[hamradio-commits] [dream] 01/01: Imported Upstream version 2.1.1

Julian Cable jcable-guest at moszumanska.debian.org
Sat Nov 8 13:04:27 UTC 2014


This is an automated email from the git hooks/post-receive script.

jcable-guest pushed a commit to branch master
in repository dream.

commit d44b227659ac4da0270d32f37e35ede9c16a6e59
Author: Julian Cable <julian.cable at yahoo.com>
Date:   Fri Nov 7 21:44:43 2014 +0000

    Imported Upstream version 2.1.1
---
 AUTHORS                                           |   18 +
 COPYING                                           |  280 +
 ChangeLog                                         |  173 +
 Desktop.ini                                       |  Bin 0 -> 186 bytes
 INSTALL                                           |   21 +
 NEWS                                              |   19 +
 README                                            |  171 +
 TODO                                              |    1 +
 android/AndroidManifest.xml                       |   40 +
 android/res/drawable-hdpi/icon.png                |  Bin 0 -> 644 bytes
 android/res/drawable-ldpi/icon.png                |  Bin 0 -> 544 bytes
 android/res/drawable-mdpi/icon.png                |  Bin 0 -> 298 bytes
 android/strings.xml                               |    4 +
 dream.pro                                         |  750 ++
 include/DIRINFO.txt                               |    1 +
 lib/DIRINFO.txt                                   |    1 +
 linux/dream.1                                     |  153 +
 linux/dreamtr.ts                                  | 2321 +++++
 linux/make_shadow_build.sh                        |   21 +
 linux/test/.cvsignore                             |    2 +
 linux/test/plotsimres.m                           |  482 ++
 macx/deploy.sh                                    |   29 +
 src/AMDemodulation.cpp                            |  988 +++
 src/AMDemodulation.h                              |  397 +
 src/AMSSDemodulation.cpp                          | 1007 +++
 src/AMSSDemodulation.h                            |  297 +
 src/DRMSignalIO.cpp                               | 1069 +++
 src/DRMSignalIO.h                                 |  245 +
 src/DataIO.cpp                                    |  971 +++
 src/DataIO.h                                      |  340 +
 src/DrmReceiver.cpp                               | 1912 +++++
 src/DrmReceiver.h                                 |  450 +
 src/DrmSimulation.cpp                             |  362 +
 src/DrmSimulation.h                               |  157 +
 src/DrmTransceiver.h                              |   93 +
 src/DrmTransmitter.cpp                            |  681 ++
 src/DrmTransmitter.h                              |  118 +
 src/FAC/FAC.cpp                                   |  645 ++
 src/FAC/FAC.h                                     |   73 +
 src/GUI-QT/AMMainWindow.ui                        |  671 ++
 src/GUI-QT/AMSSDlgbase.ui                         | 3704 ++++++++
 src/GUI-QT/AboutDlgbase.ui                        |  192 +
 src/GUI-QT/AnalogDemDlg.cpp                       | 1138 +++
 src/GUI-QT/AnalogDemDlg.h                         |  137 +
 src/GUI-QT/BWSViewer.cpp                          |  472 ++
 src/GUI-QT/BWSViewer.h                            |  103 +
 src/GUI-QT/BWSViewer.ui                           |  419 +
 src/GUI-QT/CWindow.cpp                            |  305 +
 src/GUI-QT/CWindow.h                              |  134 +
 src/GUI-QT/CodecParams.cpp                        |  305 +
 src/GUI-QT/CodecParams.h                          |   62 +
 src/GUI-QT/CodecParams.ui                         |  493 ++
 src/GUI-QT/DRMMainWindow.ui                       | 9432 +++++++++++++++++++++
 src/GUI-QT/DRMPlot.cpp                            | 1752 ++++
 src/GUI-QT/DRMPlot.h                              |  249 +
 src/GUI-QT/DialogUtil.cpp                         |  459 +
 src/GUI-QT/DialogUtil.h                           |  139 +
 src/GUI-QT/EPGDlg.cpp                             |  347 +
 src/GUI-QT/EPGDlg.h                               |   96 +
 src/GUI-QT/EPGDlgbase.ui                          |  264 +
 src/GUI-QT/EvaluationDlg.cpp                      | 1381 +++
 src/GUI-QT/EvaluationDlg.h                        |  119 +
 src/GUI-QT/GeneralSettingsDlg.cpp                 |  330 +
 src/GUI-QT/GeneralSettingsDlg.h                   |   73 +
 src/GUI-QT/GeneralSettingsDlgbase.ui              |  523 ++
 src/GUI-QT/JLViewer.cpp                           |  176 +
 src/GUI-QT/JLViewer.h                             |   63 +
 src/GUI-QT/JLViewer.ui                            |  194 +
 src/GUI-QT/LiveScheduleDlg.cpp                    | 1001 +++
 src/GUI-QT/LiveScheduleDlg.h                      |  202 +
 src/GUI-QT/LiveScheduleWindow.ui                  |  272 +
 src/GUI-QT/Logging.cpp                            |  124 +
 src/GUI-QT/Logging.h                              |   72 +
 src/GUI-QT/MultColorLED.cpp                       |  183 +
 src/GUI-QT/MultColorLED.h                         |   93 +
 src/GUI-QT/MultSettingsDlg.cpp                    |  169 +
 src/GUI-QT/MultSettingsDlg.h                      |   74 +
 src/GUI-QT/MultSettingsDlgbase.ui                 |  340 +
 src/GUI-QT/RigDlg.cpp                             |  217 +
 src/GUI-QT/RigDlg.h                               |   72 +
 src/GUI-QT/RigDlg.ui                              |  128 +
 src/GUI-QT/Schedule.cpp                           |  561 ++
 src/GUI-QT/Schedule.h                             |  151 +
 src/GUI-QT/SlideShowViewer.cpp                    |  299 +
 src/GUI-QT/SlideShowViewer.h                      |   73 +
 src/GUI-QT/SlideShowViewer.ui                     |  380 +
 src/GUI-QT/SoundCardSelMenu.cpp                   |  400 +
 src/GUI-QT/SoundCardSelMenu.h                     |  114 +
 src/GUI-QT/StationsDlg.cpp                        |  631 ++
 src/GUI-QT/StationsDlg.h                          |  132 +
 src/GUI-QT/StationsDlgbase.ui                     |  421 +
 src/GUI-QT/ThemeCustomizer.cpp                    |  315 +
 src/GUI-QT/ThemeCustomizer.h                      |   43 +
 src/GUI-QT/TransmDlg.cpp                          | 1538 ++++
 src/GUI-QT/TransmDlg.h                            |  161 +
 src/GUI-QT/TransmDlgbase.ui                       | 1478 ++++
 src/GUI-QT/afswidget.cpp                          |   80 +
 src/GUI-QT/afswidget.h                            |   21 +
 src/GUI-QT/amwidget.cpp                           |  345 +
 src/GUI-QT/amwidget.h                             |   57 +
 src/GUI-QT/amwidget.ui                            |  423 +
 src/GUI-QT/audiodetailwidget.cpp                  |  148 +
 src/GUI-QT/audiodetailwidget.h                    |   47 +
 src/GUI-QT/audiodetailwidget.ui                   |  177 +
 src/GUI-QT/bwsviewerwidget.cpp                    |  635 ++
 src/GUI-QT/bwsviewerwidget.h                      |  174 +
 src/GUI-QT/bwsviewerwidget.ui                     |  351 +
 src/GUI-QT/channelwidget.cpp                      |  200 +
 src/GUI-QT/channelwidget.h                        |   61 +
 src/GUI-QT/channelwidget.ui                       |  330 +
 src/GUI-QT/dreamtabwidget.cpp                     |  250 +
 src/GUI-QT/dreamtabwidget.h                       |   35 +
 src/GUI-QT/drmdetail.cpp                          |  504 ++
 src/GUI-QT/drmdetail.h                            |   45 +
 src/GUI-QT/drmdetail.ui                           |  881 ++
 src/GUI-QT/drmdisplay.cpp                         |  350 +
 src/GUI-QT/drmdisplay.h                           |   33 +
 src/GUI-QT/drmdisplay.ui                          | 9073 ++++++++++++++++++++
 src/GUI-QT/drmoptions.cpp                         |  258 +
 src/GUI-QT/drmoptions.h                           |   46 +
 src/GUI-QT/drmoptions.ui                          |  364 +
 src/GUI-QT/engineeringtabwidget.cpp               |   17 +
 src/GUI-QT/engineeringtabwidget.h                 |   20 +
 src/GUI-QT/fdrmdialog.cpp                         | 1293 +++
 src/GUI-QT/fdrmdialog.h                           |  172 +
 src/GUI-QT/gpswidget.cpp                          |   59 +
 src/GUI-QT/gpswidget.h                            |   33 +
 src/GUI-QT/gpswidget.ui                           |  609 ++
 src/GUI-QT/jlbrowser.cpp                          |  154 +
 src/GUI-QT/jlbrowser.h                            |   55 +
 src/GUI-QT/journalineviewer.cpp                   |   88 +
 src/GUI-QT/journalineviewer.h                     |   38 +
 src/GUI-QT/journalineviewer.ui                    |  147 +
 src/GUI-QT/languages/README.txt                   |   71 +
 src/GUI-QT/languages/dreamtr.es.qm                |  Bin 0 -> 99841 bytes
 src/GUI-QT/languages/dreamtr.es.ts                | 2298 +++++
 src/GUI-QT/languages/drm.fr.ts                    | 2391 ++++++
 src/GUI-QT/liveschedulewidget.ui                  |  252 +
 src/GUI-QT/main.cpp                               |  339 +
 src/GUI-QT/receivercontroller.cpp                 |  315 +
 src/GUI-QT/receivercontroller.h                   |  106 +
 src/GUI-QT/res/CSAudSNRHist.png                   |  Bin 0 -> 233 bytes
 src/GUI-QT/res/CSChannel.png                      |  Bin 0 -> 494 bytes
 src/GUI-QT/res/CSConstellation.png                |  Bin 0 -> 888 bytes
 src/GUI-QT/res/CSFAC.png                          |  Bin 0 -> 374 bytes
 src/GUI-QT/res/CSHistory.png                      |  Bin 0 -> 430 bytes
 src/GUI-QT/res/CSHistoryDelDopp.png               |  Bin 0 -> 331 bytes
 src/GUI-QT/res/CSHistoryFreqSam.png               |  Bin 0 -> 574 bytes
 src/GUI-QT/res/CSIR.png                           |  Bin 0 -> 257 bytes
 src/GUI-QT/res/CSMSC.png                          |  Bin 0 -> 130 bytes
 src/GUI-QT/res/CSSDC.png                          |  Bin 0 -> 393 bytes
 src/GUI-QT/res/CSSpectrum.png                     |  Bin 0 -> 778 bytes
 src/GUI-QT/res/CSSpectrumAudio.png                |  Bin 0 -> 281 bytes
 src/GUI-QT/res/CSSpectrumInpPSD.png               |  Bin 0 -> 199 bytes
 src/GUI-QT/res/CSSpectrumInpSpectr.png            |  Bin 0 -> 398 bytes
 src/GUI-QT/res/CSSpectrumSNR.png                  |  Bin 0 -> 365 bytes
 src/GUI-QT/res/CSSpectrumShiftedPSD.png           |  Bin 0 -> 357 bytes
 src/GUI-QT/res/CSSpectrumWaterf.png               |  Bin 0 -> 702 bytes
 src/GUI-QT/res/CSTF.png                           |  Bin 0 -> 258 bytes
 src/GUI-QT/res/Home.png                           |  Bin 0 -> 199 bytes
 src/GUI-QT/res/JumpBegin.png                      |  Bin 0 -> 142 bytes
 src/GUI-QT/res/JumpEnd.png                        |  Bin 0 -> 137 bytes
 src/GUI-QT/res/LogoFhGIIS.png                     |  Bin 0 -> 1012 bytes
 src/GUI-QT/res/LogoJournaline.png                 |  Bin 0 -> 4113 bytes
 src/GUI-QT/res/LogoOpus.png                       |  Bin 0 -> 2676 bytes
 src/GUI-QT/res/LogoSmall.png                      |  Bin 0 -> 3701 bytes
 src/GUI-QT/res/LogoSmallOrig.png                  |  Bin 0 -> 2275 bytes
 src/GUI-QT/res/MainIcon.ico                       |  Bin 0 -> 2550 bytes
 src/GUI-QT/res/MainIcon.png                       |  Bin 0 -> 544 bytes
 src/GUI-QT/res/MainIcon.svg                       |   69 +
 src/GUI-QT/res/MainIconOrig.png                   |  Bin 0 -> 319 bytes
 src/GUI-QT/res/MainIconTx.svg                     |   69 +
 src/GUI-QT/res/Refresh.png                        |  Bin 0 -> 182 bytes
 src/GUI-QT/res/StepBack.png                       |  Bin 0 -> 142 bytes
 src/GUI-QT/res/StepForw.png                       |  Bin 0 -> 139 bytes
 src/GUI-QT/res/Stop.png                           |  Bin 0 -> 198 bytes
 src/GUI-QT/res/greenCube.png                      |  Bin 0 -> 621 bytes
 src/GUI-QT/res/icons.qrc                          |   40 +
 src/GUI-QT/res/macicons.icns                      |  Bin 0 -> 34482 bytes
 src/GUI-QT/res/orangeCube.png                     |  Bin 0 -> 771 bytes
 src/GUI-QT/res/pinkCube.png                       |  Bin 0 -> 800 bytes
 src/GUI-QT/res/redCube.png                        |  Bin 0 -> 614 bytes
 src/GUI-QT/res/smallGreenCube.png                 |  Bin 0 -> 273 bytes
 src/GUI-QT/serviceselector.cpp                    |  145 +
 src/GUI-QT/serviceselector.h                      |   35 +
 src/GUI-QT/serviceselector.ui                     |  351 +
 src/GUI-QT/slideshowwidget.cpp                    |  261 +
 src/GUI-QT/slideshowwidget.h                      |   53 +
 src/GUI-QT/slideshowwidget.ui                     |  312 +
 src/GUI-QT/stationswidget.cpp                     |  350 +
 src/GUI-QT/stationswidget.h                       |   86 +
 src/GUI-QT/stationswidget.ui                      |  141 +
 src/GUI-QT/streamwidget.cpp                       |  101 +
 src/GUI-QT/streamwidget.h                         |   41 +
 src/GUI-QT/streamwidget.ui                        |   30 +
 src/GUI-QT/systemevalDlgbase.ui                   | 1739 ++++
 src/GUI-QT/waterfallwidget.cpp                    |  181 +
 src/GUI-QT/waterfallwidget.h                      |   45 +
 src/GlobalDefinitions.h                           |  356 +
 src/IQInputFilter.cpp                             |  287 +
 src/IQInputFilter.h                               |   21 +
 src/IQInputFilter.octave                          |  109 +
 src/InputResample.cpp                             |   87 +
 src/InputResample.h                               |   62 +
 src/MDI/AFPacketGenerator.cpp                     |  150 +
 src/MDI/AFPacketGenerator.h                       |   51 +
 src/MDI/MDIDecode.cpp                             |  237 +
 src/MDI/MDIDecode.h                               |   54 +
 src/MDI/MDIDefinitions.h                          |   64 +
 src/MDI/MDIInBuffer.cpp                           |   76 +
 src/MDI/MDIInBuffer.h                             |   51 +
 src/MDI/MDIRSCI.cpp                               |  653 ++
 src/MDI/MDIRSCI.h                                 |  208 +
 src/MDI/MDITagItemDecoders.cpp                    |  355 +
 src/MDI/MDITagItemDecoders.h                      |  136 +
 src/MDI/MDITagItems.cpp                           | 1448 ++++
 src/MDI/MDITagItems.h                             |  365 +
 src/MDI/PacketInOut.h                             |   82 +
 src/MDI/PacketSinkFile.cpp                        |  279 +
 src/MDI/PacketSinkFile.h                          |   95 +
 src/MDI/PacketSocket.cpp                          |  427 +
 src/MDI/PacketSocket.h                            |   84 +
 src/MDI/PacketSocketNull.cpp                      |   67 +
 src/MDI/PacketSocketNull.h                        |   54 +
 src/MDI/PacketSourceFile.cpp                      |  388 +
 src/MDI/PacketSourceFile.h                        |   69 +
 src/MDI/Pft.cpp                                   |  202 +
 src/MDI/Pft.h                                     |   61 +
 src/MDI/RCITagItems.cpp                           |   86 +
 src/MDI/RCITagItems.h                             |   52 +
 src/MDI/RSCITagItemDecoders.cpp                   |  368 +
 src/MDI/RSCITagItemDecoders.h                     |  158 +
 src/MDI/RSISubscriber.cpp                         |  229 +
 src/MDI/RSISubscriber.h                           |  128 +
 src/MDI/TagItemDecoder.h                          |   82 +
 src/MDI/TagPacketDecoder.cpp                      |  225 +
 src/MDI/TagPacketDecoder.h                        |   64 +
 src/MDI/TagPacketDecoderMDI.cpp                   |  124 +
 src/MDI/TagPacketDecoderMDI.h                     |   75 +
 src/MDI/TagPacketDecoderRSCIControl.cpp           |   71 +
 src/MDI/TagPacketDecoderRSCIControl.h             |   62 +
 src/MDI/TagPacketGenerator.cpp                    |  111 +
 src/MDI/TagPacketGenerator.h                      |   70 +
 src/MSCMultiplexer.cpp                            |  173 +
 src/MSCMultiplexer.h                              |   65 +
 src/OFDM.cpp                                      |  398 +
 src/OFDM.h                                        |  135 +
 src/Parameter.cpp                                 | 1377 +++
 src/Parameter.h                                   | 1307 +++
 src/PlotManager.cpp                               |  358 +
 src/PlotManager.h                                 |  108 +
 src/ReceptLog.cpp                                 |  526 ++
 src/ReceptLog.h                                   |  118 +
 src/SDC/SDC.h                                     |  129 +
 src/SDC/SDCReceive.cpp                            | 1388 +++
 src/SDC/SDCTransmit.cpp                           |  698 ++
 src/Scheduler.cpp                                 |  168 +
 src/Scheduler.h                                   |   64 +
 src/ServiceInformation.cpp                        |   31 +
 src/ServiceInformation.h                          |   43 +
 src/SimulationParameters.cpp                      |  477 ++
 src/TextMessage.cpp                               |  539 ++
 src/TextMessage.h                                 |  147 +
 src/UpsampleFilter.h                              |  318 +
 src/UpsampleFilter.octave                         |   68 +
 src/Version.cpp                                   |   47 +
 src/Version.h                                     |   39 +
 src/android/platform_util.cpp                     |   14 +
 src/android/platform_util.h                       |    8 +
 src/android/soundin.cpp                           | 1235 +++
 src/android/soundin.h                             |   26 +
 src/android/soundout.cpp                          |   79 +
 src/android/soundout.h                            |   26 +
 src/chanest/ChanEstTime.cpp                       |   58 +
 src/chanest/ChanEstTime.h                         |   74 +
 src/chanest/ChannelEstimation.cpp                 | 1364 +++
 src/chanest/ChannelEstimation.h                   |  272 +
 src/chanest/IdealChannelEstimation.cpp            |  169 +
 src/chanest/IdealChannelEstimation.h              |   70 +
 src/chanest/TimeLinear.cpp                        |  141 +
 src/chanest/TimeLinear.h                          |   70 +
 src/chanest/TimeWiener.cpp                        |  691 ++
 src/chanest/TimeWiener.h                          |  174 +
 src/datadecoding/DABMOT.cpp                       | 1716 ++++
 src/datadecoding/DABMOT.h                         |  606 ++
 src/datadecoding/DataDecoder.cpp                  |  569 ++
 src/datadecoding/DataDecoder.h                    |  130 +
 src/datadecoding/DataEncoder.cpp                  |  179 +
 src/datadecoding/DataEncoder.h                    |   69 +
 src/datadecoding/Experiment.cpp                   |   71 +
 src/datadecoding/Experiment.h                     |   55 +
 src/datadecoding/Journaline.cpp                   |  200 +
 src/datadecoding/Journaline.h                     |   86 +
 src/datadecoding/MOTSlideShow.cpp                 |  181 +
 src/datadecoding/MOTSlideShow.h                   |   75 +
 src/datadecoding/epgutil.cpp                      |  125 +
 src/datadecoding/epgutil.h                        |   47 +
 src/datadecoding/journaline/NML.cpp               |  884 ++
 src/datadecoding/journaline/NML.h                 |  379 +
 src/datadecoding/journaline/Splitter.cpp          |  141 +
 src/datadecoding/journaline/Splitter.h            |  114 +
 src/datadecoding/journaline/cpplog.h              |   74 +
 src/datadecoding/journaline/crc_8_16.c            |  403 +
 src/datadecoding/journaline/crc_8_16.h            |  100 +
 src/datadecoding/journaline/dabdatagroupdecoder.h |  218 +
 src/datadecoding/journaline/dabdgdec_impl.c       |  320 +
 src/datadecoding/journaline/dabdgdec_impl.h       |   95 +
 src/datadecoding/journaline/log.c                 |   64 +
 src/datadecoding/journaline/log.h                 |   81 +
 src/datadecoding/journaline/newsobject.cpp        |  174 +
 src/datadecoding/journaline/newsobject.h          |  121 +
 src/datadecoding/journaline/newssvcdec.h          |  352 +
 src/datadecoding/journaline/newssvcdec_impl.cpp   |  665 ++
 src/datadecoding/journaline/newssvcdec_impl.h     |  137 +
 src/drmchannel/ChannelSimulation.cpp              |  623 ++
 src/drmchannel/ChannelSimulation.h                |  118 +
 src/interleaver/BlockInterleaver.cpp              |   69 +
 src/interleaver/BlockInterleaver.h                |   48 +
 src/interleaver/SymbolInterleaver.cpp             |  216 +
 src/interleaver/SymbolInterleaver.h               |   85 +
 src/linux/ConsoleIO.cpp                           |  443 +
 src/linux/ConsoleIO.h                             |   51 +
 src/linux/Pacer.cpp                               |   60 +
 src/linux/alsa.cpp                                |  460 +
 src/linux/alsa.h                                  |   73 +
 src/linux/jack.cpp                                |  599 ++
 src/linux/jack.h                                  |  114 +
 src/linux/oss.cpp                                 |  302 +
 src/linux/pa_shm_ringbuffer.c                     |  284 +
 src/linux/pa_shm_ringbuffer.h                     |  197 +
 src/linux/shmsoundin.cpp                          |  159 +
 src/linux/shmsoundin.h                            |   72 +
 src/linux/sound.h                                 |   60 +
 src/linux/soundcommon.cpp                         |  352 +
 src/linux/soundcommon.h                           |  118 +
 src/linux/soundin.cpp                             |  502 ++
 src/linux/soundin.h                               |   94 +
 src/linux/soundout.cpp                            |  489 ++
 src/linux/soundout.h                              |   93 +
 src/matlib/Matlib.h                               |  867 ++
 src/matlib/MatlibSigProToolbox.cpp                |  606 ++
 src/matlib/MatlibSigProToolbox.h                  |  136 +
 src/matlib/MatlibStdToolbox.cpp                   |  799 ++
 src/matlib/MatlibStdToolbox.h                     |  294 +
 src/mlc/BitInterleaver.cpp                        |  145 +
 src/mlc/BitInterleaver.h                          |   75 +
 src/mlc/ChannelCode.cpp                           |  189 +
 src/mlc/ChannelCode.h                             |   70 +
 src/mlc/ConvEncoder.cpp                           |  236 +
 src/mlc/ConvEncoder.h                             |   71 +
 src/mlc/EnergyDispersal.cpp                       |   90 +
 src/mlc/EnergyDispersal.h                         |   55 +
 src/mlc/MLC.cpp                                   | 1013 +++
 src/mlc/MLC.h                                     |  229 +
 src/mlc/Metric.cpp                                | 1096 +++
 src/mlc/Metric.h                                  |  232 +
 src/mlc/QAMMapping.cpp                            |  175 +
 src/mlc/QAMMapping.h                              |   60 +
 src/mlc/TrellisUpdateMMX.cpp                      |  380 +
 src/mlc/TrellisUpdateSSE2.cpp                     |  329 +
 src/mlc/ViterbiDecoder.cpp                        |  658 ++
 src/mlc/ViterbiDecoder.h                          |  143 +
 src/ofdmcellmapping/CellMappingTable.cpp          |  727 ++
 src/ofdmcellmapping/CellMappingTable.h            |  148 +
 src/ofdmcellmapping/OFDMCellMapping.cpp           |  329 +
 src/ofdmcellmapping/OFDMCellMapping.h             |   80 +
 src/resample/Resample.cpp                         |  384 +
 src/resample/Resample.h                           |  104 +
 src/resample/ResampleFilter.cpp                   |  149 +
 src/resample/ResampleFilter.h                     |   14 +
 src/resample/ResampleFilter.m                     |   77 +
 src/resample/ResampleFilter.octave                |   86 +
 src/sound/LatencyFilter.h                         |   46 +
 src/sound/LatencyFilter.octave                    |   64 +
 src/sound/audiofilein.cpp                         |  388 +
 src/sound/audiofilein.h                           |   72 +
 src/sound/drm_portaudio.cpp                       |  426 +
 src/sound/drm_portaudio.h                         |  118 +
 src/sound/drm_pulseaudio.cpp                      | 1014 +++
 src/sound/drm_pulseaudio.h                        |  186 +
 src/sound/pa_ringbuffer.c                         |  284 +
 src/sound/pa_ringbuffer.h                         |  205 +
 src/sound/qtaudio.cpp                             |  452 +
 src/sound/qtaudio.h                               |   98 +
 src/sound/selectioninterface.h                    |   79 +
 src/sound/sound.h                                 |   86 +
 src/sound/soundinterface.h                        |   58 +
 src/sound/soundnull.h                             |   85 +
 src/sourcedecoders/AudioCodec.cpp                 |   91 +
 src/sourcedecoders/AudioCodec.h                   |   69 +
 src/sourcedecoders/AudioSourceDecoder.cpp         | 1164 +++
 src/sourcedecoders/AudioSourceDecoder.h           |  239 +
 src/sourcedecoders/AudioSourceEncoder.cpp         |  656 ++
 src/sourcedecoders/AudioSourceEncoder.h           |  172 +
 src/sourcedecoders/aac_codec.cpp                  |  324 +
 src/sourcedecoders/aac_codec.h                    |   69 +
 src/sourcedecoders/faac_dll.h                     |  143 +
 src/sourcedecoders/neaacdec_dll.h                 |   63 +
 src/sourcedecoders/null_codec.cpp                 |  145 +
 src/sourcedecoders/null_codec.h                   |   56 +
 src/sourcedecoders/opus_codec.cpp                 |  671 ++
 src/sourcedecoders/opus_codec.h                   |  168 +
 src/sourcedecoders/opus_dll.h                     | 1426 ++++
 src/sync/FreqSyncAcq.cpp                          |  509 ++
 src/sync/FreqSyncAcq.h                            |  147 +
 src/sync/SyncUsingPil.cpp                         |  452 +
 src/sync/SyncUsingPil.h                           |  135 +
 src/sync/TimeSync.cpp                             |  946 +++
 src/sync/TimeSync.h                               |  185 +
 src/sync/TimeSyncFilter.cpp                       | 2552 ++++++
 src/sync/TimeSyncFilter.h                         |   52 +
 src/sync/TimeSyncFilter.octave                    |  176 +
 src/sync/TimeSyncTrack.cpp                        |  759 ++
 src/sync/TimeSyncTrack.h                          |  167 +
 src/tables/TableAMSS.h                            |   52 +
 src/tables/TableCarMap.cpp                        |  381 +
 src/tables/TableCarMap.h                          |  141 +
 src/tables/TableDRMGlobal.h                       |  104 +
 src/tables/TableFAC.cpp                           |  990 +++
 src/tables/TableFAC.h                             |  101 +
 src/tables/TableMLC.h                             |  511 ++
 src/tables/TableQAMMapping.h                      |  316 +
 src/tables/TableStations.cpp                      | 1239 +++
 src/tables/TableStations.h                        |   50 +
 src/util-QT/EPG.cpp                               | 1629 ++++
 src/util-QT/EPG.h                                 |   82 +
 src/util-QT/PacketSocketQT.cpp                    |  358 +
 src/util-QT/PacketSocketQT.h                      |   90 +
 src/util-QT/Rig.cpp                               |  118 +
 src/util-QT/Rig.h                                 |   77 +
 src/util-QT/Util.cpp                              |  549 ++
 src/util-QT/Util.h                                |   68 +
 src/util-QT/epgdec.cpp                            |  637 ++
 src/util-QT/epgdec.h                              |   67 +
 src/util-QT/scheduleloader.cpp                    |   53 +
 src/util-QT/scheduleloader.h                      |   25 +
 src/util/AudioFile.h                              |  116 +
 src/util/Buffer.h                                 |  333 +
 src/util/CRC.cpp                                  |  120 +
 src/util/CRC.h                                    |   57 +
 src/util/FileTyper.cpp                            |   89 +
 src/util/FileTyper.h                              |   41 +
 src/util/Hamlib.cpp                               |  758 ++
 src/util/Hamlib.h                                 |  138 +
 src/util/LibraryLoader.h                          |   98 +
 src/util/LogPrint.cpp                             |  187 +
 src/util/LogPrint.h                               |  124 +
 src/util/Modul.h                                  | 1303 +++
 src/util/Pacer.h                                  |   28 +
 src/util/Reassemble.cpp                           |  170 +
 src/util/Reassemble.h                             |  201 +
 src/util/Settings.cpp                             |  903 ++
 src/util/Settings.h                               |  183 +
 src/util/Utilities.cpp                            |  462 +
 src/util/Utilities.h                              |  184 +
 src/util/Vector.h                                 |  515 ++
 src/windows/Pacer.cpp                             |   57 +
 src/windows/Sound.cpp                             |  650 ++
 src/windows/Sound.h                               |  122 +
 src/windows/platform_util.cpp                     |   23 +
 src/windows/platform_util.h                       |    8 +
 windows/dream.iss                                 |   35 +
 windows/dream.rc                                  |    1 +
 windows/faadconfig.h                              |    4 +
 windows/libfaac.sln                               |   20 +
 windows/libfaac.vcproj                            |  331 +
 windows/libfaad.sln                               |   20 +
 windows/libfaad.vcproj                            |  577 ++
 windows/libfftw.vcproj                            |  763 ++
 windows/qwt.vcproj                                | 1076 +++
 470 files changed, 153427 insertions(+)

diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..cd58951
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,18 @@
+Alexander Kurpiers 
+Andrea Russo 
+Andrew Murphy
+Cesco
+Doyle Richard
+Gian C. Pascutto
+Josh Moore
+Julian Cable
+Marek Peca
+Mark J. Fine
+Menno Bakker
+Oliver Haffenden
+Rafael Diniz
+Robert Kesterson
+Robert Turnbull
+Stephane Fillod
+Tomi Manninen
+Volker Fischer 
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..c7aea18
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,280 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                          675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+

+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+

+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+

+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+

+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 0000000..cc006f1
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,173 @@
+1.14
+  - allows building with Qt4
+
+1.13
+ 
+  - change name of faac and faad libraries to permit cooexistance of normal and drm versions
+  - support run-time loading of faac and faad libraries to enable binary dream downloads
+  - support of WinRadio G313 on linux
+  - new FM mode
+  - New "experimental" data mode
+  - don't assume audio is scaled to 32768 peak
+  - improved Mutex locking on CParameter
+  - move signal strength monitoring from CDrmReceiver
+  - PSD Measurements are configurable in the ini file
+  - improved termination state machine (CParameter.bRunThread replaced by CParameter.eRunState)
+  - Make sure frequency gets in the log file when retuning
+  - improved code for version numbers, especially in rinf RSCI tag
+  - ability to send now/next EPG data to an external program via UDP
+  - improved Journaline decoding from Fraunhofer
+  - save Tx/Rx mode in ini file
+  - better use of Qt I18N features
+  - Don't send sdc_ tag if tag packet is empty
+  - tcp mode for RSCI/MDI subscription
+  -prefix source/destination with t
+  - Power Impulse response tag in RSCI
+  - # suffix in pcap file name should allow filtering on UDP port (does this work yet?)
+  - report AF sequence number discontinuities with print statements
+  - handle ETSI filenames for EPG files as well as the old dream ones.
+ 
+1.12
+
+  - Fixed problem where users directories being cleared when clearing cache
+  - Fixed timezone problems with EPG
+  - Fixed problem when EPG is 4th service
+
+1.11
+
+  - Fix log file to add header when retuning
+  - Improvements to EPG Decoding
+
+1.10.9
+
+  - Implementation of the ETSI Receiver Status and Control Interface (RSCI)
+  - Fully integrated ETSI compliant Journaline Decoding from Fraunhofer IIS
+  - Decoding and display of AM Signalling System (AMSS) data
+  - Filters added to Station Dialogue
+  - Signalstrength added to GUI and logfiles (RXL)
+  - Support of mobile logging via an interface to gpsd
+  - Support for building and running on OSX
+  - Support for Code::Blocks on Microsoft Windows
+  - Support for Visual Studio Express 2008 on Microsoft Windows
+  - Optional Support of libsndfile for reading different audio file formats
+  - Improvement to MOT decoding when directory is divided into more segments
+
+1.6.25
+
+  - Decoding and display of ETSI Electronic Programme Guide (EPG)
+  - Display of Alternative Frequency (AFS) data
+  - Support for receiving multicast MDI/RSCI for reception
+  - Optional support for reading pcap capture files for MDI/RSCI reception
+  - Support for Dev-C++/MinGW on Microsoft Windows
+
+1.2.4
+
+  - added reverbration effect for masking audio drop-outs. A switch was
+    added to the evaluation dialog to enable or disable this feature.
+  - added error detection for SDC channel (show yellow light (LED) if SDC data seems to be corrupted)
+  - bug fix: when SDC data was used completley the CRC was read as length
+    of entity data which was wrong. Now, the length of data read is checked
+    whether it has reached the total number of bits available
+  - do not show bit-rate in service selector label if bit-rate is zero
+  - apply hanning window to input spectrum plot
+  - use lower value of Doppler for initialization phase of Wiener filter in
+    time direction (aliasing peaks in impulse response are lower now are
+    re-synchronization)
+  - use shorter filter lengths for Wiener filtering for channel estimation
+    in time direction
+  - improved initialization phase for DRM frame synchronization
+  - Only use DRM frame synchronization based on time pilots since the
+    algorithm based on the impulse response does not perform well in
+    case of a very long IR
+  - added waterfall display for input spectrum
+  - use smaller buffers to speed up audio output after re-synchronization
+  - for long symbol interleaving, try to decode data before the whole
+    interleaver buffer is filled by setting the uninitialized symbols
+    to erasure
+  - bug fix for time-sync-acquisition initialization
+  - moved bandpass-filter and frequency offset correction from OFDM
+    module in Frequency-Sync-Acquisition module,
+  - improved bandpass filter for receiver -> better interfere rejection
+    BUT: under normal conditions, this filter will degrade the performance
+    a little bit since it attenuates the OFDM carriers at the borders a bit
+  - store input data vector which is used for frequency offset acquisition
+    and output entire data vector when acquisition was successful -> speeds
+    up audio output when re-synchronization is needed
+  - fixed problem with high CPU utilization when no DRM signal was received
+  - WINDOWS: make the software more robust against high CPU utilization by
+    other applications by increasing the thread priority of the Dream signal
+    processing thread
+  - bug fix: time sync Hilbert filter must be shifted to virtual intermediate
+    frequency
+  - added informations about robustness mode, MSC scheme, protection
+    levels in log long (a log file which is generated parallel to the
+    standard log file (compatible to the DRM software radio))
+  - display sample rate offset in ppm, too
+  - do not show mode , protection levels and MSC constellation in log long
+    until FAC CRC was correct
+  - resize windows fix for Linux by Andrea Russo
+  - add name of picture in tool-tip (in case a MOTSlideShow picture is shown).
+    The tool-tip is shown when the user moves the mouse over the picture
+  - Journaline pages can be saved as HTML (patch from Andrea Russo)
+  - added preview for stations dialog, thanks to Andrea Russo for his patch!
+    A new menu was added for setting the preview time. If a DRM transmitter
+    will transmit no later than the preview time but is not active, an orange
+    marker is shown next to this transmission (in the list)
+  - improved averaging of estimation of impulse response: the time shift is
+    considered more exactly (sample rate offset estimation should be
+    improved, too)
+  - added new column to stations list showing the days the transmission is
+    active. This code is based on a patch by Andrea Russo
+  - added Weighted Modulation Error Ratio (WMER) and MER calculation based
+    on the MSC cells. The values are shown in the evaluation dialog
+  - added SDC data entity type 3 (information is not used right now) and some
+    more error checking
+  - added SDC data entity type 4 (information is not used right now)
+  - added SDC type 7 (not used right now)
+  - added class for storing alternative frequencies transmitted in SDC type 3
+  - store plot type selection for evaluation dialog
+
+1.2.2
+  - Lots of changes for AM demodulation: a separate main window for AM, noise reduction,
+    PLL and CW demodulation, changed AM bandpass filter
+  - SNR spectrum plot implemented in DRM-mode, which information is used to improve
+    reception under interference situations
+  - Added history plots for SNR/Audio, Delay/Doppler and Frequency/Sample Rate
+  - Small improvements and bug fixes
+
+1.1
+  - AAC encoder for Dream TX (using faac library)
+  - jpg-support for Windows version (using Freeimage library)
+  - including Hamlib library for front-end remote control
+  - Journaline library
+  - Dream init file, storing some settings and window sizes/positions
+
+1.0.6
+  - Improved AM demodulation (introduced new window) -> AM, USB, LSB; different filters
+  - Stations dialog with update function (using DRM schedule powered by Klaus Schneider www.drm-dx.de)
+  - Remote control for different front-ends (e.g., Winradio, AOR7030, Elektor)
+  - GUI for DRM transmitter (start with command line flag '-t')
+  - MOT Slide Show encoder + lots of fixes for DRM transmitter
+
+1.0
+  - New SNR estimation
+  - New algorithm for sample rate offset estimation
+  - I/O interface indicator
+
+0.9.3
+  - SBR support (needs new faad2 library)
+  - AM mode  (analog demodulation)
+  - MOT Slide Show decoding (DAB)
+  - improved log file
+  - command line parameters
+
+0.9.2
+  - Time synchronization acquisition algorithm improved
+  - Channel estimation: wiener filter with adaptation
+  - Log file support
+  - Improved metric for MLC decoder
+  - Improved (sample) frequency offset tracking, better averaging functions
+  - Bug fix in Windows sound interface
+
+0.9.1
+  Initial version
diff --git a/Desktop.ini b/Desktop.ini
new file mode 100644
index 0000000..ae60713
Binary files /dev/null and b/Desktop.ini differ
diff --git a/INSTALL b/INSTALL
new file mode 100644
index 0000000..dcf071c
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,21 @@
+Installation Instructions for the Dream Software
+------------------------------------------------
+
+This version of Dream can be built using any of the following:
+
+* Windows
+
+ * Microsoft Visual Studio 6.0
+ * Microsoft Visual Studio Express 2008
+ * MinGW + Dev-C++
+ * MinGW + Code::Blocks
+ 
+* Linux
+
+ * g++
+
+* OSX
+
+ * XCode
+
+Detailed build instructions are available at drm.sourceforce.net.
\ No newline at end of file
diff --git a/NEWS b/NEWS
new file mode 100644
index 0000000..906d029
--- /dev/null
+++ b/NEWS
@@ -0,0 +1,19 @@
+The Dream development team today releases Dream version 1.12.
+
+Dream is a DRM (Digital Radio Mondiale) software receiver and decoder.
+It is a very complete receiver, featuring compliant decoding of HE AAC v2
+audio streams, journaline decoding, a feature rich statistics section
+providing invaluable information about the streams being received, and automatic
+update of available stations from the web, among several other features.
+
+It also features a limited transmission mode, that uses the FAAC AAC encoder.
+
+Dream is multi-platform and has been tested on OSX, Win32 and Linux.
+
+Changes since version 1.11:
+
+  - Fixed problem where users directories being cleared when clearing cache
+  - Fixed timezone problems with EPG
+  - Fixed problem when EPG is 4th service
+
+The source files are available here: http://drm.sourceforge.net
diff --git a/README b/README
new file mode 100644
index 0000000..29081e9
--- /dev/null
+++ b/README
@@ -0,0 +1,171 @@
+/******************************************************************************\
+ * Parts (c) 2001-2003 Technische Universitaet Darmstadt, Institut fuer 
+ * Nachrichtentechnik Fachbereich Uebertragungstechnik
+ * Parts Copyright (c) 2003, 2004 Fraunhofer IIS, Erlangen, Germany
+ * Parts Copyright (c) 2004 - 2009 British Broadcasting Corporation
+ *
+ * Originally written by:
+ *  Volker Fischer, Alexander Kurpiers
+ *
+ * Additional contributions by:
+ * Stephane Fillod, Andrea Russo, Julian Cable, Andrew Murphy, Oliver Haffenden,
+ * Tomi Manninen, Robert Kesterson
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+
+Introduction
+------------
+
+Digital Radio Mondiale (DRM) is the digital radio standard for the long-,
+medium- and short-wave bands. The system is defined by ES 201 980 which
+is freely downloadable from the European Telecommunications Standards Insitute
+(ETSI). The system was designed by a consortium in co-operation with the 
+International Telecommunication Union (ITU). It offers radio stations and
+new service providers access to the multimedia age with small bit rates for 
+large target areas and long distances.
+
+For more information, visit www.drm.org. 
+
+
+The bandwidth of a DRM bandpass signal is less than 20 kHz and the number of 
+carriers used in the OFDM-modulation is relatively small (max. 460). These
+features motivate a real-time software implementation of a DRM-receiver on a 
+conventional personal computer (PC) using the sound card as the input and output 
+device. A long, medium and short wave front-end with an intermediate frequency 
+(IF) between 5 kHz and 15 kHz is used to receive the DRM signal. Any commercial 
+front-end with an IF of 455 kHz should be usable by adding a 455 kHz to 12 kHz 
+adaptor (asumed the receiver bandwith is sufficient for a DRM signal). 
+Documentation of receiver modifications for DRM reception can be found at 
+www.drmrx.org. 
+
+
+With this software project we intend to implement a working software receiver 
+with, at least, the basic features. Since this project is created at a university 
+and the fundamental idea of such an institution is to teach and stimulate the 
+creativity, this source-code is free under the GNU-General Public License (GPL). 
+Dream is a development project which uses the open source model to improve DRM 
+technology. The main aim of this project is to implement and test new research 
+results on an existing system, whereby the synchronization and channel 
+estimation is of special interest. 
+
+
+The programming-language is C++. Start of the project was June 2001. The
+software runs on Microsoft Windows, Linux and OSX
+
+
+Although this software is distributed as free software under the terms of the
+GPL this does not mean that its use is free of rights of others. The use may
+infringe third party IP and thus may not be legal in some countries.
+
+
+The intended audience of the Dream software are people who are interested in
+how to decode a DRM stream and want to learn from the algorithms used in this
+software and people who want to help us improving the performance of the receiver
+and the source code.
+
+
+Homepage:
+http://drm.sourceforge.net
+
+
+
+
+Dream code Code-Style definitions
+---------------------------------
+
+# GENERAL CONVENTIONS
+
+- tab size: 4 (taps are NOT replaced by spaces)
+- maximum line width: 80 characters
+
+
+
+# USAGE OF BRACKETS
+
+- if, while, do commands:
+
+[command1]
+{
+	/* Code 1 */
+
+	[command2]
+	{
+		/* Code 2 (more than one line) */
+	}
+}
+
+- exception: if only one line of code, do not use brackets:
+
+[command1]
+	/* Code (only one line) */
+
+- switch command:
+
+switch ([variable])
+{
+case [condition1]:
+	/* Code for condition 1 */
+	break;
+
+case [condition2]:
+	/* Code for condition 2 */
+	break;
+}
+
+
+
+# COMMENTS
+
+- Comments start with capital letters
+- regular comments shall be placed in front of the command:
+
+/* This is the comment for the next line */
+[command]
+
+- short comments can be placed right after the command:
+
+[command] /* Short comment (1 space between command and comment) */
+
+- long comments (e.g. a function description):
+
+/*
+	This is a long description for the following section of code. The text is
+	written with increased indent whereby the indent is realized with tabs.
+*/
+
+- sections comments (there are always two empty lines before a section):
+
+/******************************************************************************\
+* This is a section                                                            *
+\******************************************************************************/
+
+/* This is a subsection *******************************************************/
+
+/* This is a subsubsection -------------------------------------------------- */
+
+
+
+# PREPROCESSOR DIRECTIVES
+
+- insert spaces if preprocessor directives are in if condition:
+
+#ifdef HAVE_CONFIG_H
+# include "config.h" /* Here, a space is included between # and the command */
+#endif
diff --git a/TODO b/TODO
new file mode 100644
index 0000000..d2fe972
--- /dev/null
+++ b/TODO
@@ -0,0 +1 @@
+when starting in AM mode. The display is very sluggish, and different from when changing to AM from DRM.
diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml
new file mode 100644
index 0000000..3847544
--- /dev/null
+++ b/android/AndroidManifest.xml
@@ -0,0 +1,40 @@
+<?xml version='1.0' encoding='utf-8'?>
+<manifest android:versionName="2.2" android:versionCode="2" package="net.sourceforge.drm.dream" xmlns:android="http://schemas.android.com/apk/res/android" android:installLocation="auto">
+    <application android:name="org.qtproject.qt5.android.bindings.QtApplication" android:icon="@drawable/icon" android:label="@string/app_name">
+        <activity android:name="org.qtproject.qt5.android.bindings.QtActivity" android:label="@string/app_name" android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|locale|fontScale|keyboard|keyboardHidden|navigation" android:screenOrientation="unspecified">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.LAUNCHER"/>
+            </intent-filter>
+            <meta-data android:value="dream" android:name="android.app.lib_name"/>
+            <meta-data android:name="android.app.qt_sources_resource_id" android:resource="@array/qt_sources"/>
+            <meta-data android:value="default" android:name="android.app.repository"/>
+            <meta-data android:name="android.app.qt_libs_resource_id" android:resource="@array/qt_libs"/>
+            <meta-data android:name="android.app.bundled_libs_resource_id" android:resource="@array/bundled_libs"/>
+            <!-- Deploy Qt libs as part of package -->
+            <meta-data android:value="1" android:name="android.app.bundle_local_qt_libs"/>
+            <meta-data android:name="android.app.bundled_in_lib_resource_id" android:resource="@array/bundled_in_lib"/>
+            <meta-data android:name="android.app.bundled_in_assets_resource_id" android:resource="@array/bundled_in_assets"/>
+            <!-- Run with local libs -->
+            <meta-data android:value="1" android:name="android.app.use_local_qt_libs"/>
+            <meta-data android:value="/data/local/tmp/qt/" android:name="android.app.libs_prefix"/>
+            <meta-data android:value="plugins/platforms/android/libqtforandroid.so:lib/libQt5Xml.so:plugins/mediaservice/libqtmedia_android.so:lib/libQt5MultimediaQuick_p.so" android:name="android.app.load_local_libs"/>
+            <meta-data android:value="jar/QtAndroid.jar:jar/QtAndroidAccessibility.jar:jar/QtAndroid-bundled.jar:jar/QtAndroidAccessibility-bundled.jar:jar/QtMultimedia.jar:jar/QtMultimedia-bundled.jar" android:name="android.app.load_local_jars"/>
+            <meta-data android:value="org.qtproject.qt5.android.multimedia.QtMultimediaUtils:org.qtproject.qt5.android.multimedia.QtMultimediaUtils" android:name="android.app.static_init_classes"/>
+            <!--  Messages maps -->
+            <meta-data android:value="@string/ministro_not_found_msg" android:name="android.app.ministro_not_found_msg"/>
+            <meta-data android:value="@string/ministro_needed_msg" android:name="android.app.ministro_needed_msg"/>
+            <meta-data android:value="@string/fatal_error_msg" android:name="android.app.fatal_error_msg"/>
+            <!--  Messages maps -->
+            <!-- Splash screen -->
+            <meta-data android:name="android.app.splash_screen" android:resource="@layout/splash"/>
+            <!-- Splash screen -->
+        </activity>
+    </application>
+    <uses-sdk android:targetSdkVersion="14" android:minSdkVersion="9"/>
+    <supports-screens android:largeScreens="true" android:anyDensity="true" android:normalScreens="true" android:smallScreens="true"/>
+    <uses-permission android:name="android.permission.INTERNET"/>
+    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
+    <uses-permission android:name="android.permission.RECORD_AUDIO"/>
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
+</manifest>
diff --git a/android/res/drawable-hdpi/icon.png b/android/res/drawable-hdpi/icon.png
new file mode 100644
index 0000000..9a17c02
Binary files /dev/null and b/android/res/drawable-hdpi/icon.png differ
diff --git a/android/res/drawable-ldpi/icon.png b/android/res/drawable-ldpi/icon.png
new file mode 100644
index 0000000..a6cba48
Binary files /dev/null and b/android/res/drawable-ldpi/icon.png differ
diff --git a/android/res/drawable-mdpi/icon.png b/android/res/drawable-mdpi/icon.png
new file mode 100644
index 0000000..8bb72ed
Binary files /dev/null and b/android/res/drawable-mdpi/icon.png differ
diff --git a/android/strings.xml b/android/strings.xml
new file mode 100644
index 0000000..ff4ea8f
--- /dev/null
+++ b/android/strings.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string name="app_name">Dream</string>
+</resources>
diff --git a/dream.pro b/dream.pro
new file mode 100644
index 0000000..68e0e81
--- /dev/null
+++ b/dream.pro
@@ -0,0 +1,750 @@
+TEMPLATE = app
+CONFIG += warn_on
+TARGET = dream
+OBJECTS_DIR = obj
+DEFINES += EXECUTABLE_NAME=$$TARGET
+LIBS += -L$$OUT_PWD/lib
+INCLUDEPATH += $$OUT_PWD/include
+contains(QT_VERSION, ^4\\..*) {
+    CONFIG += qt qt4
+    VERSION_MESSAGE = Qt $$QT_VERSION
+}
+contains(QT_VERSION, ^5\\..*) {
+    CONFIG += qt qt5
+    VERSION_MESSAGE = Qt $$QT_VERSION
+}
+CONFIG(debug, debug|release) {
+    DEBUG_MESSAGE = debug
+}
+else {
+    DEBUG_MESSAGE = release
+}
+console {
+    QT -= core gui
+    CONFIG -= qt qt4 qt5
+    UI_MESSAGE = console mode
+    VERSION_MESSAGE = No Qt
+}
+qtconsole {
+    QT -= gui
+    QT += xml
+    UI_MESSAGE = console mode
+}
+!console:!qtconsole {
+    CONFIG += gui
+    UI_MESSAGE = GUI mode
+}
+gui {
+    RESOURCES = src/GUI-QT/res/icons.qrc
+    QT += network xml
+    qt4:QT += webkit
+    qt5:QT += widgets webkitwidgets
+    INCLUDEPATH += src/GUI-QT
+    VPATH += src/GUI-QT
+    win32:RC_FILE = windows/dream.rc
+    macx:RC_FILE = src/GUI-QT/res/macicons.icns
+    CONFIG += qwt
+    UI_DIR = ui
+    MOC_DIR = moc
+}
+message($$VERSION_MESSAGE $$DEBUG_MESSAGE $$UI_MESSAGE)
+qt:multimedia {
+    CONFIG += qtaudio sound
+}
+unix:!cross_compile {
+    UNAME = $$system(uname -s)
+    message(building on $$UNAME)
+}
+macx {
+    INCLUDEPATH += /opt/local/include
+    LIBS += -L/opt/local/lib
+    LIBS += -framework CoreFoundation -framework CoreServices
+    LIBS += -framework CoreAudio -framework AudioToolbox -framework AudioUnit
+    CONFIG += pcap
+    !sound:CONFIG += portaudio sound
+    !qt5:!contains(QT_VERSION, ^4\\.8.*) {
+      exists(/opt/local/include/sndfile.h) {
+        CONFIG += sndfile
+      }
+      exists(/opt/local/include/speex/speex_preprocess.h) {
+        CONFIG += speexdsp
+      }
+      exists(/opt/local/include/hamlib/rig.h) {
+        CONFIG += hamlib
+      }
+      contains(QT_VERSION, ^4\\.7.*) {
+        QT += phonon opengl svg
+        DEFINES -= QWT_NO_SVG
+        QMAKE_LFLAGS += -bind_at_load
+      }
+    }
+}
+linux-* {
+    LIBS += -ldl -lrt
+}
+android {
+    ANDROID_PACKAGE_SOURCE_DIR=$$PWD/android
+    SOURCES += src/android/platform_util.cpp
+    HEADERS += src/android/platform_util.h
+    QT -= webkitwidgets
+    QT += svg
+    #CONFIG += openSL sound
+    CONFIG += qtaudio sound
+    CONFIG += crosscompile
+}
+unix {
+    target.path = /usr/bin
+    documentation.path = /usr/share/man/man1
+    documentation.files = linux/dream.1
+    INSTALLS += documentation
+    INSTALLS += target
+    CONFIG += link_pkgconfig
+    tui:console {
+      CONFIG += consoleio
+    }
+    LIBS += -lz -lfftw3
+    SOURCES += src/linux/Pacer.cpp
+    DEFINES += HAVE_DLFCN_H \
+               HAVE_MEMORY_H \
+               HAVE_STDINT_H \
+               HAVE_STDLIB_H
+    DEFINES += HAVE_STRINGS_H \
+               HAVE_STRING_H \
+               STDC_HEADERS
+    DEFINES += HAVE_INTTYPES_H \
+               HAVE_STDINT_H \
+               HAVE_SYS_STAT_H \
+               HAVE_SYS_TYPES_H \
+               HAVE_UNISTD_H
+    DEFINES += HAVE_LIBZ
+}
+unix:!cross_compile {
+    !sound {
+         # check for pulseaudio before portaudio
+         exists(/usr/include/pulse/pulseaudio.h) | \
+         exists(/usr/local/include/pulse/pulseaudio.h) {
+         #packagesExist(libpulse)
+          CONFIG += pulseaudio sound
+         }
+         else {
+           exists(/usr/include/portaudio.h) | \
+           exists(/usr/local/include/portaudio.h) {
+           #packagesExist(portaudio-2.0)
+              CONFIG += portaudio sound
+           }
+        }
+    }
+    qt5|contains(QT_VERSION, ^4\\.8.*) {
+      packagesExist(sndfile) {
+        CONFIG += sndfile
+      }
+      packagesExist(hamlib) {
+        CONFIG += hamlib
+      }
+#      packagesExist(gpsd) { ### proper package name ??? ###
+      packagesExist(libgps) {
+        CONFIG += gps
+      }
+      packagesExist(pcap) {
+        CONFIG += pcap
+      }
+      packagesExist(opus) {
+        CONFIG += opus
+      }
+      packagesExist(speexdsp) {
+        CONFIG += speexdsp
+      }
+    }
+    else {
+      exists(/usr/include/sndfile.h) | \
+      exists(/usr/local/include/sndfile.h) {
+        CONFIG += sndfile
+      }
+      exists(/usr/include/hamlib/rig.h) | \
+      exists(/usr/local/include/hamlib/rig.h) {
+          CONFIG += hamlib
+      }
+      exists(/usr/include/gps.h) | \
+      exists(/usr/local/include/gps.h) {
+        CONFIG += gps
+      }
+      exists(/usr/include/pcap.h) | \
+      exists(/usr/local/include/pcap.h) {
+        CONFIG += pcap
+      }
+      exists(/usr/include/opus/opus.h) | \
+      exists(/usr/local/include/opus/opus.h) {
+       CONFIG += opus
+      }
+      exists(/usr/include/speex/speex_preprocess.h) | \
+      exists(/usr/local/include/speex/speex_preprocess.h) {
+       CONFIG += speexdsp
+      }
+    }
+}
+win32 {
+    LIBS += -lfftw3-3
+    OTHER_FILES += windows/dream.iss windows/dream.rc
+    !sound {
+        exists($$OUT_PWD/include/portaudio.h) {
+          CONFIG += portaudio sound
+        }
+        else {
+          CONFIG += mmsystem sound
+        }
+    }
+    LIBS += -lsetupapi -lwsock32 -lws2_32 -lzdll -ladvapi32 -luser32
+    DEFINES += HAVE_SETUPAPI \
+    HAVE_LIBZ _CRT_SECURE_NO_WARNINGS
+    DEFINES -= UNICODE
+    SOURCES += src/windows/Pacer.cpp src/windows/platform_util.cpp
+    HEADERS += src/windows/platform_util.h
+    msvc* {
+        TEMPLATE = vcapp
+        DEFINES += NOMINMAX
+        QMAKE_CXXFLAGS += /wd"4996" /wd"4521"
+        QMAKE_LFLAGS_RELEASE += /NODEFAULTLIB:libcmt.lib
+        QMAKE_LFLAGS_DEBUG += /NODEFAULTLIB:libcmtd.lib
+        LIB += zdll.lib
+    }
+    g++ {
+         DEFINES += HAVE_STDINT_H
+         LIBS += -lz
+    }
+}
+win32|crosscompile {
+    exists($$OUT_PWD/include/speex/speex_preprocess.h) {
+      CONFIG += speexdsp
+    }
+    exists($$OUT_PWD/include/hamlib/rig.h) {
+      CONFIG += hamlib
+    }
+    exists($$OUT_PWD/include/pcap.h) {
+      CONFIG += pcap
+    }
+    exists($$OUT_PWD/include/sndfile.h) {
+        CONFIG += sndfile
+    }
+    exists($$OUT_PWD/include/opus/opus.h) {
+        CONFIG += opus
+    }
+}
+exists($$OUT_PWD/include/neaacdec.h) {
+     DEFINES += HAVE_LIBFAAD \
+     USE_FAAD2_LIBRARY
+     LIBS += -lfaad_drm
+     message("with FAAD2")
+}
+exists($$OUT_PWD/include/faac.h) {
+     DEFINES += HAVE_LIBFAAC \
+     USE_FAAC_LIBRARY
+     LIBS += -lfaac_drm
+     message("with FAAC")
+}
+opus {
+     DEFINES += HAVE_LIBOPUS \
+     USE_OPUS_LIBRARY
+     unix:LIBS += -lopus
+     win32:LIBS += libopus.lib
+     message("with opus")
+}
+sndfile {
+     DEFINES += HAVE_LIBSNDFILE
+     unix:LIBS += -lsndfile
+     win32-msvc*:LIBS += libsndfile-1.lib
+     win32-g++:LIBS += -lsndfile-1
+     android:LIBS += -lvorbis -lvorbisenc -lvorbisfile -lFLAC -logg
+     message("with libsndfile")
+}
+speexdsp {
+     DEFINES += HAVE_SPEEX
+     unix:LIBS += -lspeexdsp
+     win32:LIBS += libspeexdsp.lib
+     message("with libspeexdsp")
+}
+gps {
+     DEFINES += HAVE_LIBGPS
+     unix:LIBS += -lgps
+     message("with gps")
+}
+pcap {
+     DEFINES += HAVE_LIBPCAP
+     unix:LIBS += -lpcap
+     win32-msvc*:LIBS += wpcap.lib packet.lib
+     win32-g++:LIBS += -lwpcap -lpacket
+     message("with pcap")
+}
+hamlib {
+     DEFINES += HAVE_LIBHAMLIB
+     macx:LIBS += -framework IOKit
+     unix:LIBS += -lhamlib
+     win32:LIBS += libhamlib-2.lib
+     HEADERS += src/util/Hamlib.h
+     SOURCES += src/util/Hamlib.cpp
+     qt {
+       HEADERS += src/util-QT/Rig.h
+       SOURCES += src/util-QT/Rig.cpp
+     }
+     gui {
+         HEADERS += src/GUI-QT/RigDlg.h
+         SOURCES += src/GUI-QT/RigDlg.cpp
+         FORMS += RigDlg.ui
+     }
+     message("with hamlib")
+}
+qwt {
+    #DEFINES += QWT_NO_SVG
+    QT += svg
+    macx {
+        LIBS += -framework qwt
+   }
+   else {
+        win32:CONFIG(debug, debug|release) {
+            # win debug
+            LIBS += -lqwtd
+        } else {
+            # unix | win release
+            LIBS += -lqwt
+        }
+   }
+   !crosscompile {
+        macx {
+          exists(/opt/local/Library/Frameworks/qwt.framework) {
+            INCLUDEPATH += /opt/local/Library/Frameworks/qwt.framework/Versions/6/Headers
+          }
+          exists(/Library/Frameworks/qwt.framework) {
+            INCLUDEPATH += /Library/Frameworks/qwt.framework/Versions/6/Headers
+          }
+        }
+        exists(/usr/include/qwt/qwt.h) {
+            INCLUDEPATH += /usr/include/qwt
+        }
+        exists(/usr/local/include/qwt/qwt.h) {
+            INCLUDEPATH += /usr/local/include/qwt
+        }
+        qt4 {
+            exists(/usr/include/qwt5/qwt.h) {
+                INCLUDEPATH += /usr/include/qwt5
+            }
+            exists(/usr/include/qwt-qt4/qwt.h) {
+                INCLUDEPATH += /usr/include/qwt-qt4
+                LIBS -= -lqwt
+                LIBS += -lqwt-qt4
+            }
+        }
+    }
+    exists($$OUT_PWD/include/qwt/qwt.h) {
+        INCLUDEPATH += $$OUT_PWD/include/qwt
+    }
+}
+alsa {
+    DEFINES += USE_ALSA
+    HEADERS += src/linux/soundsrc.h \
+               src/linux/soundin.h \
+               src/linux/soundout.h
+    SOURCES += src/linux/alsa.cpp \
+               src/linux/soundsrc.cpp
+    message("with alsa")
+}
+mmsystem {
+    HEADERS += src/windows/Sound.h
+    SOURCES += src/windows/Sound.cpp
+    LIBS += -lwinmm
+    message("with mmsystem")
+}
+portaudio {
+    DEFINES += USE_PORTAUDIO
+    HEADERS += src/sound/pa_ringbuffer.h \
+               src/sound/drm_portaudio.h
+    SOURCES += src/sound/drm_portaudio.cpp \
+               src/sound/pa_ringbuffer.c
+    LIBS += -lportaudio
+    unix:PKGCONFIG += portaudio-2.0
+    message("with portaudio")
+}
+pulseaudio {
+    DEFINES += USE_PULSEAUDIO
+    HEADERS += src/sound/drm_pulseaudio.h
+    SOURCES += src/sound/drm_pulseaudio.cpp
+    LIBS += -lpulse
+    unix:PKGCONFIG += libpulse
+    message("with pulseaudio")
+}
+openSL {
+    DEFINES += USE_OPENSL
+    HEADERS += src/android/soundin.h \
+               src/android/soundout.h
+    SOURCES += src/android/soundin.cpp \
+               src/android/soundout.cpp
+    LIBS += -lOpenSLES
+    message("with openSL")
+}
+qtaudio {
+    DEFINES += USE_QTAUDIO
+    HEADERS += src/sound/qtaudio.h
+    SOURCES += src/sound/qtaudio.cpp
+    QT += multimedia
+    message("with Qt audio")
+}
+consoleio {
+    DEFINES += USE_CONSOLEIO
+    HEADERS += src/linux/ConsoleIO.h
+    SOURCES += src/linux/ConsoleIO.cpp
+    LIBS += -lpthread
+    message("with terminal user interface")
+}
+HEADERS += \
+    src/AMDemodulation.h \
+    src/AMSSDemodulation.h \
+    src/chanest/ChanEstTime.h \
+    src/chanest/ChannelEstimation.h \
+    src/chanest/IdealChannelEstimation.h \
+    src/chanest/TimeLinear.h \
+    src/chanest/TimeWiener.h \
+    src/datadecoding/DABMOT.h \
+    src/datadecoding/DataDecoder.h \
+    src/datadecoding/DataEncoder.h \
+    src/datadecoding/epgutil.h \
+    src/datadecoding/Experiment.h \
+    src/datadecoding/journaline/cpplog.h \
+    src/datadecoding/journaline/crc_8_16.h \
+    src/datadecoding/journaline/dabdatagroupdecoder.h \
+    src/datadecoding/journaline/dabdgdec_impl.h \
+    src/datadecoding/Journaline.h \
+    src/datadecoding/journaline/log.h \
+    src/datadecoding/journaline/newsobject.h \
+    src/datadecoding/journaline/newssvcdec.h \
+    src/datadecoding/journaline/newssvcdec_impl.h \
+    src/datadecoding/journaline/NML.h \
+    src/datadecoding/journaline/Splitter.h \
+    src/datadecoding/MOTSlideShow.h \
+    src/DataIO.h \
+    src/drmchannel/ChannelSimulation.h \
+    src/DrmReceiver.h \
+    src/DRMSignalIO.h \
+    src/DrmSimulation.h \
+    src/DrmTransceiver.h \
+    src/DrmTransmitter.h \
+    src/FAC/FAC.h \
+    src/GlobalDefinitions.h \
+    src/InputResample.h \
+    src/interleaver/BlockInterleaver.h \
+    src/interleaver/SymbolInterleaver.h \
+    src/IQInputFilter.h \
+    src/matlib/Matlib.h \
+    src/matlib/MatlibSigProToolbox.h \
+    src/matlib/MatlibStdToolbox.h \
+    src/MDI/AFPacketGenerator.h \
+    src/MDI/MDIDecode.h \
+    src/MDI/MDIDefinitions.h \
+    src/MDI/MDIInBuffer.h \
+    src/MDI/MDIRSCI.h \
+    src/MDI/MDITagItemDecoders.h \
+    src/MDI/MDITagItems.h \
+    src/MDI/PacketInOut.h \
+    src/MDI/PacketSinkFile.h \
+    src/MDI/PacketSocket.h \
+    src/MDI/PacketSourceFile.h \
+    src/MDI/Pft.h \
+    src/MDI/RCITagItems.h \
+    src/MDI/RSCITagItemDecoders.h \
+    src/MDI/RSISubscriber.h \
+    src/MDI/TagItemDecoder.h \
+    src/MDI/TagPacketDecoder.h \
+    src/MDI/TagPacketDecoderMDI.h \
+    src/MDI/TagPacketDecoderRSCIControl.h \
+    src/MDI/TagPacketGenerator.h \
+    src/mlc/BitInterleaver.h \
+    src/mlc/ChannelCode.h \
+    src/mlc/ConvEncoder.h \
+    src/mlc/EnergyDispersal.h \
+    src/mlc/Metric.h \
+    src/mlc/MLC.h \
+    src/mlc/QAMMapping.h \
+    src/mlc/ViterbiDecoder.h \
+    src/MSCMultiplexer.h \
+    src/ofdmcellmapping/CellMappingTable.h \
+    src/ofdmcellmapping/OFDMCellMapping.h \
+    src/OFDM.h \
+    src/Parameter.h \
+    src/PlotManager.h \
+    src/ReceptLog.h \
+    src/resample/ResampleFilter.h \
+    src/resample/Resample.h \
+    src/Scheduler.h \
+    src/SDC/SDC.h \
+    src/ServiceInformation.h \
+    src/sound/audiofilein.h \
+    src/sound/selectioninterface.h \
+    src/sound/sound.h \
+    src/sound/soundinterface.h \
+    src/sound/soundnull.h \
+    src/sourcedecoders/aac_codec.h \
+    src/sourcedecoders/AudioCodec.h \
+    src/sourcedecoders/AudioSourceDecoder.h \
+    src/sourcedecoders/AudioSourceEncoder.h \
+    src/sourcedecoders/null_codec.h \
+    src/sourcedecoders/opus_codec.h \
+    src/sync/FreqSyncAcq.h \
+    src/sync/SyncUsingPil.h \
+    src/sync/TimeSyncFilter.h \
+    src/sync/TimeSync.h \
+    src/sync/TimeSyncTrack.h \
+    src/tables/TableAMSS.h \
+    src/tables/TableCarMap.h \
+    src/tables/TableDRMGlobal.h \
+    src/tables/TableFAC.h \
+    src/tables/TableMLC.h \
+    src/tables/TableQAMMapping.h \
+    src/tables/TableStations.h \
+    src/TextMessage.h \
+    src/UpsampleFilter.h \
+    src/util/AudioFile.h \
+    src/util/Buffer.h \
+    src/util/CRC.h \
+    src/util/FileTyper.h \
+    src/util/LibraryLoader.h \
+    src/util/LogPrint.h \
+    src/util/Modul.h \
+    src/util/Pacer.h \
+    src/util/Reassemble.h \
+    src/util/Settings.h \
+    src/util/Utilities.h \
+    src/util/Vector.h \
+    src/Version.h
+
+SOURCES += \
+    src/AMDemodulation.cpp \
+    src/AMSSDemodulation.cpp \
+    src/chanest/ChanEstTime.cpp \
+    src/chanest/ChannelEstimation.cpp \
+    src/chanest/IdealChannelEstimation.cpp \
+    src/chanest/TimeLinear.cpp \
+    src/chanest/TimeWiener.cpp \
+    src/datadecoding/DABMOT.cpp \
+    src/datadecoding/DataDecoder.cpp \
+    src/datadecoding/DataEncoder.cpp \
+    src/datadecoding/epgutil.cpp \
+    src/datadecoding/Experiment.cpp \
+    src/datadecoding/Journaline.cpp \
+    src/datadecoding/journaline/crc_8_16.c \
+    src/datadecoding/journaline/dabdgdec_impl.c \
+    src/datadecoding/journaline/log.c \
+    src/datadecoding/journaline/newsobject.cpp \
+    src/datadecoding/journaline/newssvcdec_impl.cpp \
+    src/datadecoding/journaline/NML.cpp \
+    src/datadecoding/journaline/Splitter.cpp \
+    src/datadecoding/MOTSlideShow.cpp \
+    src/DataIO.cpp \
+    src/drmchannel/ChannelSimulation.cpp \
+    src/DrmReceiver.cpp \
+    src/DRMSignalIO.cpp \
+    src/DrmSimulation.cpp \
+    src/DrmTransmitter.cpp \
+    src/FAC/FAC.cpp \
+    src/GUI-QT/main.cpp \
+    src/InputResample.cpp \
+    src/interleaver/BlockInterleaver.cpp \
+    src/interleaver/SymbolInterleaver.cpp \
+    src/IQInputFilter.cpp \
+    src/matlib/MatlibSigProToolbox.cpp \
+    src/matlib/MatlibStdToolbox.cpp \
+    src/MDI/AFPacketGenerator.cpp \
+    src/MDI/MDIDecode.cpp \
+    src/MDI/MDIInBuffer.cpp \
+    src/MDI/MDIRSCI.cpp \
+    src/MDI/MDITagItemDecoders.cpp \
+    src/MDI/MDITagItems.cpp \
+    src/MDI/PacketSinkFile.cpp \
+    src/MDI/PacketSocket.cpp \
+    src/MDI/PacketSourceFile.cpp \
+    src/MDI/Pft.cpp \
+    src/MDI/RCITagItems.cpp \
+    src/MDI/RSCITagItemDecoders.cpp \
+    src/MDI/RSISubscriber.cpp \
+    src/MDI/TagPacketDecoder.cpp \
+    src/MDI/TagPacketDecoderMDI.cpp \
+    src/MDI/TagPacketDecoderRSCIControl.cpp \
+    src/MDI/TagPacketGenerator.cpp \
+    src/mlc/BitInterleaver.cpp \
+    src/mlc/ChannelCode.cpp \
+    src/mlc/ConvEncoder.cpp \
+    src/mlc/EnergyDispersal.cpp \
+    src/mlc/Metric.cpp \
+    src/mlc/MLC.cpp \
+    src/mlc/QAMMapping.cpp \
+    src/mlc/TrellisUpdateMMX.cpp \
+    src/mlc/TrellisUpdateSSE2.cpp \
+    src/mlc/ViterbiDecoder.cpp \
+    src/MSCMultiplexer.cpp \
+    src/ofdmcellmapping/CellMappingTable.cpp \
+    src/ofdmcellmapping/OFDMCellMapping.cpp \
+    src/OFDM.cpp \
+    src/Parameter.cpp \
+    src/PlotManager.cpp \
+    src/ReceptLog.cpp \
+    src/resample/Resample.cpp \
+    src/resample/ResampleFilter.cpp \
+    src/Scheduler.cpp \
+    src/SDC/SDCReceive.cpp \
+    src/SDC/SDCTransmit.cpp \
+    src/ServiceInformation.cpp \
+    src/SimulationParameters.cpp \
+    src/sound/audiofilein.cpp \
+    src/sourcedecoders/aac_codec.cpp \
+    src/sourcedecoders/AudioCodec.cpp \
+    src/sourcedecoders/AudioSourceDecoder.cpp \
+    src/sourcedecoders/AudioSourceEncoder.cpp \
+    src/sourcedecoders/null_codec.cpp \
+    src/sourcedecoders/opus_codec.cpp \
+    src/sync/FreqSyncAcq.cpp \
+    src/sync/SyncUsingPil.cpp \
+    src/sync/TimeSync.cpp \
+    src/sync/TimeSyncFilter.cpp \
+    src/sync/TimeSyncTrack.cpp \
+    src/tables/TableCarMap.cpp \
+    src/tables/TableFAC.cpp \
+    src/tables/TableStations.cpp \
+    src/TextMessage.cpp \
+    src/util/CRC.cpp \
+    src/util/FileTyper.cpp \
+    src/util/LogPrint.cpp \
+    src/util/Reassemble.cpp \
+    src/util/Settings.cpp \
+    src/util/Utilities.cpp \
+    src/Version.cpp
+
+!console {
+HEADERS += \
+    src/GUI-QT/Logging.h \
+    src/util-QT/epgdec.h \
+    src/util-QT/EPG.h \
+    src/util-QT/Util.h
+SOURCES += \
+    src/GUI-QT/Logging.cpp \
+    src/util-QT/EPG.cpp \
+    src/util-QT/epgdec.cpp \
+    src/util-QT/Util.cpp
+}
+gui {
+    contains(QT, webkitwidgets)|contains(QT,webkit) {
+        FORMS += BWSViewer.ui bwsviewerwidget.ui
+        HEADERS += src/GUI-QT/BWSViewer.h src/GUI-QT/bwsviewerwidget.h
+        SOURCES += src/GUI-QT/BWSViewer.cpp src/GUI-QT/bwsviewerwidget.cpp
+        DEFINES += HAVE_QTWEBKIT
+    }
+FORMS += \
+    AboutDlgbase.ui \
+    AMMainWindow.ui \
+    AMSSDlgbase.ui \
+    CodecParams.ui \
+    DRMMainWindow.ui \
+    EPGDlgbase.ui \
+    GeneralSettingsDlgbase.ui \
+    JLViewer.ui \
+    LiveScheduleWindow.ui \
+    MultSettingsDlgbase.ui \
+    SlideShowViewer.ui \
+    StationsDlgbase.ui \
+    systemevalDlgbase.ui \
+    TransmDlgbase.ui \
+    serviceselector.ui \
+    channelwidget.ui \
+    audiodetailwidget.ui \
+    drmoptions.ui \
+    drmdisplay.ui \
+    drmdetail.ui \
+    liveschedulewidget.ui \
+    journalineviewer.ui \
+    slideshowwidget.ui \
+    stationswidget.ui \
+    gpswidget.ui \
+    amwidget.ui \
+    streamwidget.ui
+
+HEADERS += \
+    src/GUI-QT/AnalogDemDlg.h \
+    src/GUI-QT/CodecParams.h \
+    src/GUI-QT/CWindow.h \
+    src/GUI-QT/DialogUtil.h \
+    src/GUI-QT/DRMPlot.h \
+    src/GUI-QT/EPGDlg.h \
+    src/GUI-QT/EvaluationDlg.h \
+    src/GUI-QT/fdrmdialog.h \
+    src/GUI-QT/GeneralSettingsDlg.h \
+    src/GUI-QT/jlbrowser.h \
+    src/GUI-QT/JLViewer.h \
+    src/GUI-QT/LiveScheduleDlg.h \
+    src/GUI-QT/MultColorLED.h \
+    src/GUI-QT/MultSettingsDlg.h \
+    src/GUI-QT/Schedule.h \
+    src/GUI-QT/SlideShowViewer.h \
+    src/GUI-QT/SoundCardSelMenu.h \
+    src/GUI-QT/StationsDlg.h \
+    src/GUI-QT/TransmDlg.h \
+    src/GUI-QT/waterfallwidget.h \
+    src/GUI-QT/serviceselector.h \
+    src/GUI-QT/dreamtabwidget.h \
+    src/GUI-QT/channelwidget.h \
+    src/GUI-QT/audiodetailwidget.h \
+    src/GUI-QT/drmoptions.h \
+    src/GUI-QT/drmdisplay.h \
+    src/GUI-QT/drmdetail.h \
+    src/GUI-QT/journalineviewer.h \
+    src/GUI-QT/slideshowwidget.h \
+    src/GUI-QT/engineeringtabwidget.h \
+    src/GUI-QT/receivercontroller.h \
+    src/GUI-QT/stationswidget.h \
+    src/GUI-QT/gpswidget.h \
+    src/GUI-QT/afswidget.h \
+    src/util-QT/scheduleloader.h \
+    src/GUI-QT/amwidget.h \
+    src/GUI-QT/streamwidget.h \
+    src/GUI-QT/ThemeCustomizer.h
+
+SOURCES += \
+    src/GUI-QT/AnalogDemDlg.cpp \
+    src/GUI-QT/CodecParams.cpp \
+    src/GUI-QT/CWindow.cpp \
+    src/GUI-QT/DialogUtil.cpp \
+    src/GUI-QT/DRMPlot.cpp \
+    src/GUI-QT/EPGDlg.cpp \
+    src/GUI-QT/EvaluationDlg.cpp \
+    src/GUI-QT/fdrmdialog.cpp \
+    src/GUI-QT/GeneralSettingsDlg.cpp \
+    src/GUI-QT/jlbrowser.cpp \
+    src/GUI-QT/JLViewer.cpp \
+    src/GUI-QT/LiveScheduleDlg.cpp \
+    src/GUI-QT/MultColorLED.cpp \
+    src/GUI-QT/MultSettingsDlg.cpp \
+    src/GUI-QT/Schedule.cpp \
+    src/GUI-QT/SlideShowViewer.cpp \
+    src/GUI-QT/SoundCardSelMenu.cpp \
+    src/GUI-QT/StationsDlg.cpp \
+    src/GUI-QT/TransmDlg.cpp \
+    src/GUI-QT/waterfallwidget.cpp \
+    src/GUI-QT/serviceselector.cpp \
+    src/GUI-QT/dreamtabwidget.cpp \
+    src/GUI-QT/channelwidget.cpp \
+    src/GUI-QT/audiodetailwidget.cpp \
+    src/GUI-QT/drmoptions.cpp \
+    src/GUI-QT/drmdisplay.cpp \
+    src/GUI-QT/drmdetail.cpp \
+    src/GUI-QT/journalineviewer.cpp \
+    src/GUI-QT/slideshowwidget.cpp \
+    src/GUI-QT/engineeringtabwidget.cpp \
+    src/GUI-QT/receivercontroller.cpp \
+    src/util-QT/scheduleloader.cpp \
+    src/GUI-QT/stationswidget.cpp \
+    src/GUI-QT/gpswidget.cpp \
+    src/GUI-QT/afswidget.cpp \
+    src/GUI-QT/amwidget.cpp \
+    src/GUI-QT/streamwidget.cpp \
+    src/GUI-QT/ThemeCustomizer.cpp
+}
+
+!isEmpty(QT):message(With Qt components: $$QT)
+!sound:error("no usable audio interface found - install pulseaudio or portaudio dev package")
+
+OTHER_FILES += \
+    android/AndroidManifest.xml
diff --git a/include/DIRINFO.txt b/include/DIRINFO.txt
new file mode 100644
index 0000000..7f8eb7f
--- /dev/null
+++ b/include/DIRINFO.txt
@@ -0,0 +1 @@
+If you are building Dream on Windows and not shadow building, put the .h files for fftw3, qwt and any optional libraries you are using in this folder before running qmake.
diff --git a/lib/DIRINFO.txt b/lib/DIRINFO.txt
new file mode 100644
index 0000000..a31354e
--- /dev/null
+++ b/lib/DIRINFO.txt
@@ -0,0 +1 @@
+If you are building Dream on Windows and not shadow building, put the .lib files for fftw3, qwt and any optional libraries you are using in this folder before running qmake.
diff --git a/linux/dream.1 b/linux/dream.1
new file mode 100644
index 0000000..a2018ed
--- /dev/null
+++ b/linux/dream.1
@@ -0,0 +1,153 @@
+.TH DREAM 1 LOCAL
+.SH NAME 
+
+dream - Digital Radio Mondiale and AM software defined radio
+
+.SH SYNTAX 
+
+.B dream <options>
+
+.SH AVAILABILITY 
+
+Tested on Debian, Ubuntu, Windows and OSX Snow Leopard
+
+.SH DESCRIPTION 
+
+Description: a DRM (Digital Radio Mondiale) and AM Software Defined Radio
+Digital Radio Mondiale (DRM) is the digital radio standard for the
+long-, medium- and short-wave ranges. The standard was formed by a
+consortium in co-operation with the International Telecommunication
+Union (ITU).  For more information visit www.drm.org.  Dream uses the
+sound card as the input and output device. A long, medium and short wave
+front-end with an intermediate frequency (IF) between 5 kHz and 15 kHz
+is used to receive the DRM signal. Any commercial front-end with an IF
+of 455 kHz should be usable by adding a 455 kHz to 12 kHz adaptor
+(assuming the receiver bandwidth is sufficient for a DRM signal).
+
+.SH OPTIONS 
+
+.IP "-t, --transmitter"
+DRM transmitter mode
+.IP "-p, --flipspectrum"
+flip input spectrum
+.IP "-i <n>, --mlciter <n>"
+number of MLC iterations (allowed range: 0...4 default: 1)
+.IP "-s <r>, --sampleoff <r>"
+sample rate offset initial value [Hz] (allowed range: -200.0...200.0)
+.IP "-m, --muteaudio"
+mute audio output
+.IP "-f <s>, --fileio <s>"
+disable sound card, use file <s> instead
+.IP "-w <s>, --writewav <s>"
+write output to wave file
+.IP "-S <r>, --fracwinsize <r>"
+freq. acqu. search window size [Hz]
+.IP "-E <r>, --fracwincent <r>"
+freq. acqu. search window center [Hz]
+.IP "-F, --filter"
+apply bandpass filter
+.IP "-D, --modmetric"
+enable modified metrics
+.IP "-c <n>, --inchansel <n>"
+input channel selection
+.nf
+0: left channel; 1: right channel;   2: mix both channels (default)
+3: I / Q input positive;             4: I / Q input negative
+5: I / Q input positive (0 Hz IF);   6: I / Q input negative (0 Hz IF)
+.fi
+.IP "-u <n>, --outchansel <n>"
+output channel selection
+.nf
+0: L -> L, R -> R (default);   1: L -> L, R muted;   2: L muted, R -> R
+3: mix -> L, R muted;          4: L muted, mix -> R
+.fi
+.IP "-e <n>, --decodeepg <n>"
+enable/disable epg decoding (0: off; 1: on)
+.IP "-g <n>, --enablelog <n>"
+enable/disable logging (0: no logging; 1: logging
+.IP "-r <n>, --frequency <n>"
+set frequency [kHz] for log file
+.IP "-l <n>, --logdelay <n>"
+delay start of logging by <n> seconds, allowed range: 0...3600)
+.IP "-L <s>, --schedule <s>"
+read DRMLogger style ini file and obey it
+.IP "-y <n>, --sysevplotstyle <n>"
+set style for main plot
+.br
+0: blue-white (default);   1: green-black;   2: black-grey
+.IP "--enablepsd <n>"
+if 0 then only measure PSD when RSCI in use otherwise always measure it
+.IP "--mdiout <s>"
+MDI out address format [IP#:]IP#:port (for Content Server)
+.IP "--mdiin  <s>"
+MDI in address (for modulator) [[IP#:]IP:]port
+.IP "--rsioutprofile <s>"
+MDI/RSCI output profile: A|B|C|D|Q|M
+.IP "--rsiout <s>"
+MDI/RSCI output address format [IP#:]IP#:port (prefix address with 'p' to enable the simple PFT)
+.IP "--rsiin <s>"
+RSCI/MDI status input address format [[IP#:]IP#:]port
+.IP "--rciout <s>"
+RSCI Control output format IP#:port
+.IP "--rciin <s>"
+RSCI Control input address number format [IP#:]port
+.IP "--rsirecordprofile <s>"
+RSCI recording profile: A|B|C|D|Q|M
+.IP "--rsirecordtype <s>"
+RSCI recording file type: raw|ff|pcap
+.IP "--recordiq <n>"
+enable/disable recording an I/Q file
+.IP "--permissive <b>"
+enable decoding of bad RSCI frames (0: off; 1: on)
+.IP "-R <n>, --samplerate <n>"
+set audio and signal sound card sample rate [Hz]
+.IP "--audsrate <n>"
+set audio sample rate for playback [Hz], allowed range 8000 - 192000)
+.IP "--sigsrate <n>"
+set sample rate for I/F and IQ signal processing [Hz], allowed values 24000, 48000, 96000, 192000)
+.IP "-I <s>, --snddevin <s>"
+set sound in device
+.IP "-O <s>, --snddevout <s>"
+set sound out device
+.IP "-M <n>, --hamlib-model <n>"
+set Hamlib radio model ID
+.IP "-C <s>, --hamlib-config <s>"
+set Hamlib config parameter
+.IP "-T, --ensmeter"
+enable S-Meter
+.IP "--test <n>"
+if 1 then some test setup will be done
+.IP "-h, -?, --help"
+this help text
+
+.SH EXAMPLES 
+
+dream -p --sampleoff -0.23 -i 2 -r 6140 --rsiout 127.0.0.1:3002
+
+dream -t
+
+.SH AUTHOR 
+
+Dream is maintained by David Flamand and Julian Cable.
+
+Quality Assurance and user testing is provided by Simone Stoeppler
+
+This man page by Julian Cable
+
+.SH HISTORY 
+The Dream software development was started at
+.I "Darmstadt University of Technology"
+at the Institute of Communication Technology by
+.I "Volker Fischer"
+and
+.I "Alexander Kurpiers"
+in 2001-2005. The core digital signal processing and most of the GUI were the result of this development.
+
+.SH FILES 
+
+Dream creates an ini file in the directory it is run from. Sub folders for AFS, EPG and MOT files are also created.
+
+.SH BUGS 
+
+Probably
+
diff --git a/linux/dreamtr.ts b/linux/dreamtr.ts
new file mode 100644
index 0000000..a2092ea
--- /dev/null
+++ b/linux/dreamtr.ts
@@ -0,0 +1,2321 @@
+<!DOCTYPE TS><TS>
+<context>
+    <name>AnalogDemDlg</name>
+    <message>
+        <source>S&tations Dialog...</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>E&xit</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>&Sound Card Selection</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>&DRM (digital)</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>New &AM Acquisition</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>&View</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>&Settings</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>&?</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Click on the plot to set the demodulation frequency</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source> Hz</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Carrier<br>Frequency:<b><br></source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Noise Reduction:</b> The noise suppression is a frequency domain optimal filter design based algorithm. The noise PSD is estimated utilizing a minimum statistic. A problem of this type of algorithm is that it produces the so called "musical tones". The noise becomes colored and sounds a bit strange. At the same time, the useful signal (which might be speech or music) is also distorted by the algorithm. By selecting the level of noise reduction, a  [...]
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>AGC (Automatic Gain Control):</b> Input signals can have a large variation in power due to channel impairments. To compensate for that, an automatic gain control can be applied. The AGC has four settings: Off, Slow, Medium and Fast.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Filter Bandwidth:</b> A band-pass filter is applied before the actual demodulation process. With this filter, adjacent signals are attenuated. The bandwidth of this filter can be chosen in steps of 1 Hz by using the slider bar. Clicking on the right or left side of the slider leveler will increase/decrease the bandwidth by 1 kHz. <br>The current filter bandwidth is indicated in the spectrum plot by a selection bar.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Demodulation Type:</b> The following analog demodulation types are available:<ul><li><b>AM:</b> This analog demodulation type is used in most of the hardware radios. The envelope of the complex base-band signal is used followed by a high-pass filter to remove the DC offset. Additionally, a low pass filter with the same bandwidth as the pass-band filter is applied to reduce the noise caused by non-linear distortions.</li><li& [...]
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Mute Audio:</b> The audio can be muted by checking this box. The reaction of checking or unchecking this box is delayed by approx. 1 second due to the audio buffers.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Save Audio as WAV:</b> Save the audio signal as stereo, 16-bit, 48 kHz sample rate PCM wave file. Checking this box will let the user choose a file name for the recording.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Carrier Frequency:</b> The (estimated) carrier frequency of the analog signal is shown. (The estimation of this parameter can be done by the Autom Frequency Acquisition which uses the estimated PSD of the input signal and applies a maximum search.)</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>PLL:</b> The Phase-Lock-Loop (PLL) tracks the carrier of the modulated received signal. The resulting phase offset between the reference oscillator and the received carrier is displayed in a dial control. If the pointer is almost steady, the PLL is locked. If the pointer of the dial control turns quickly, the PLL is out of lock. To get the PLL locked, the frequency offset to the true carrier frequency must not exceed a few Hz.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Auto Frequency Acquisition:</b> Clicking on the input spectrum plot changes the mixing frequency for demodulation. If the Auto Frequency Acquisition is enabled, the largest peak near the curser is selected.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>&Live Schedule Dialog...</source>
+        <translation type="unfinished"></translation>
+    </message>
+</context>
+<context>
+    <name>AnalogDemDlgBase</name>
+    <message>
+        <source>System Evaluation</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Indicators</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>&Waterfall</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>TextFreqOffset</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>PLL
+Phase Offset</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Filter Bandwidth</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>TextLabelBandWidth</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Demodulation</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>AM</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>LSB</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>USB</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>CW</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>FM</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>AGC</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Off</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Slow</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Med</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Fast</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Noise Reduction</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Low</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>High</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Audio</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Mute Audio</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Save Audio</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>PLL</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Enable</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Auto Frequency Acquisition</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>&AMSS</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>&DRM</source>
+        <translation type="unfinished"></translation>
+    </message>
+</context>
+<context>
+    <name>CAMSSDlg</name>
+    <message>
+        <source></source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>No AMSS detected</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Awaiting AMSS data...</source>
+        <translation type="unfinished"></translation>
+    </message>
+</context>
+<context>
+    <name>CAMSSDlgBase</name>
+    <message>
+        <source>AMSS</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>AMSS Decoding</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>ServiceLabelAMSS</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>AMSSInfo</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Block:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Bits:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>SDC:  </source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>................</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>AFS:  </source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>AMSS Offset</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>AMSSAMCarrierMode</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>AMSSServiceID</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>AMSSLanguage</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>AMSSCountryCode</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>AMSSTimeDate</source>
+        <translation type="unfinished"></translation>
+    </message>
+</context>
+<context>
+    <name>CAboutDlg</name>
+    <message>
+        <source>is a software implementation of a Digital Radio Mondiale (DRM) receiver. With Dream, DRM broadcasts can be received with a modified analog receiver (SW, MW, LW) and a PC with a sound card.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Although this software is going to be distributed as free software under the terms of the GPL this does not mean that its use is free of rights of others. The use may infringe third party IP and thus may not be legal in some countries.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>This compilation of Dream uses the following libraries:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Dream, Version </source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Open-Source Software Implementation of a DRM-Receiver</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Under the GNU General Public License (GPL)</source>
+        <translation type="unfinished"></translation>
+    </message>
+</context>
+<context>
+    <name>CAboutDlgBase</name>
+    <message>
+        <source>About Dream</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>TextLabelVersion</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>TextViewCredits</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>&OK</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Volker Fischer, Alexander Kurpiers, Andrea Russo
+Julian Cable, Andrew Murphy, Oliver Haffenden</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Copyright (C) 2001 - 2007</source>
+        <translation type="unfinished"></translation>
+    </message>
+</context>
+<context>
+    <name>CDRMPlot</name>
+    <message>
+        <source>Channel Impulse Response</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Time [ms]</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>IR [dB]</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Guard-interval beginning</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Guard-interval end</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Estimated begin of impulse response</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Estimated end of impulse response</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Higher Bound</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Lower bound</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Channel Transfer Function / Group Delay</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Carrier Index</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>TF [dB]</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Group Delay [ms]</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Transf. Fct.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Group Del.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Audio Spectrum</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Frequency [kHz]</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Rel. Frequency Offset / Sample Rate Offset History</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Time [s]</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Sample Rate Offset [Hz]</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Freq.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Samp.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Freq. Offset [Hz] rel. to </source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Delay / Doppler History</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Time [min]</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Delay [ms]</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Doppler [Hz]</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Delay</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Doppler</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>SNR / Correctly Decoded Audio History</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>SNR [dB]</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Corr. Dec. Audio / DRM-Frame</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Shifted Power Spectral Density of Input Signal</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>PSD [dB]</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>DC carrier</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Shifted PSD</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>SNR Spectrum (Weighted MER on MSC Cells)</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>WMER [dB]</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>SNR Spectrum</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Input Spectrum</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Input Spectrum [dB]</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Input spectrum</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Input PSD</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Input PSD [dB]</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Filter bandwidth</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>My Grid</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Waterfall Input Spectrum</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>FAC Constellation</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Real</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Imaginary</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>SDC Constellation</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>MSC Constellation</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>MSC / SDC / FAC Constellation</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Impulse Response:</b> This plot shows the estimated Impulse Response (IR) of the channel based on the channel estimation. It is the averaged, Hamming Window weighted Fourier back transformation of the transfer function. The length of PDS estimation and time synchronization tracking is based on this function. The two red dashed vertical lines show the beginning and the end of the guard-interval. The two black dashed vertical lines show the estimated beginnin [...]
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Transfer Function / Group Delay:</b> This plot shows the squared magnitude and the group delay of the estimated channel at each sub-carrier.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>FAC, SDC, MSC:</b> The plots show the constellations of the FAC, SDC and MSC logical channel of the DRM stream. Depending on the current transmitter settings, the SDC and MSC can have 4-QAM, 16-QAM or 64-QAM modulation.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Shifted PSD:</b> This plot shows the estimated Power Spectrum Density (PSD) of the input signal. The DC frequency (red dashed vertical line) is fixed at 6 kHz. If the frequency offset acquisition was successful, the rectangular DRM spectrum should show up with a center frequency of 6 kHz. This plot represents the frequency synchronized OFDM spectrum. If the frequency synchronization was successful, the useful signal really shows up only inside the actual DR [...]
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>SNR Spectrum (Weighted MER on MSC Cells):</b> This plot shows the Weighted MER on MSC cells for each carrier separately.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Input Spectrum:</b> This plot shows the Fast Fourier Transformation (FFT) of the input signal. This plot is active in both modes, analog and digital. There is no averaging applied. The screen shot of the Evaluation Dialog shows the significant shape of a DRM signal (almost rectangular). The dashed vertical line shows the estimated DC frequency. This line is very important for the analog AM demodulation. Each time a new carrier frequency is acquired, the red [...]
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Input PSD:</b> This plot shows the estimated power spectral density (PSD) of the input signal. The PSD is estimated by averaging some Hamming Window weighted Fourier transformed blocks of the input signal samples. The dashed vertical line shows the estimated DC frequency.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Audio Spectrum:</b> This plot shows the averaged audio spectrum of the currently played audio. With this plot the actual audio bandwidth can easily determined. Since a linear scale is used for the frequency axis, most of the energy of the signal is usually concentrated on the far left side of the spectrum.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Frequency Offset / Sample Rate Offset History:</b> The history of the values for frequency offset and sample rate offset estimation is shown. If the frequency offset drift is very small, this is an indication that the analog front end is of high quality.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Doppler / Delay History:</b> The history of the values for the Doppler and Impulse response length is shown. Large Doppler values might be responsable for audio drop-outs.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>SNR History:</b> The history of the values for the SNR and correctly decoded audio blocks is shown. The maximum achievable number of correctly decoded audio blocks per DRM frame is 10 or 5 depending on the audio sample rate (24 kHz or 12 kHz AAC core bandwidth).</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Waterfall Display of Input Spectrum:</b> The input spectrum is displayed as a waterfall type. The different colors represent different levels.</source>
+        <translation type="unfinished"></translation>
+    </message>
+</context>
+<context>
+    <name>CDreamHelpMenu</name>
+    <message>
+        <source>What's &This</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>&About...</source>
+        <translation type="unfinished"></translation>
+    </message>
+</context>
+<context>
+    <name>CEPGDlgbase</name>
+    <message>
+        <source>Programme Guide</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Guide</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Name</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Description</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Genre</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>New Item</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Basic Profile Data</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Advanced Profile Data</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>EPG decoding is disabled</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Time [UTC]</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>&Close</source>
+        <translation type="unfinished"></translation>
+    </message>
+</context>
+<context>
+    <name>CGeneralSettingsDlgBase</name>
+    <message>
+        <source>General settings</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>&OK</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Receiver coordinates</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Latitude   </source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message encoding="UTF-8">
+        <source>°</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>'</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>N/S</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Longitude</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>E/W</source>
+        <translation type="unfinished"></translation>
+    </message>
+</context>
+<context>
+    <name>CLiveScheduleDlgBase</name>
+    <message>
+        <source>Live Schedule</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Column 1</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>New Item</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>TextLabelUTCTime</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>&Close</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>F&reeze</source>
+        <translation type="unfinished"></translation>
+    </message>
+</context>
+<context>
+    <name>CMultSettingsDlgBase</name>
+    <message>
+        <source>Multimedia settings</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>MOT Broadcast Web Site</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Add refresh header of seconds</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Clear cache</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>EPG - Electronic Programme Guide</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>&Close</source>
+        <translation type="unfinished"></translation>
+    </message>
+</context>
+<context>
+    <name>CSoundCardSelMenu</name>
+    <message>
+        <source>Sound &In</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Sound &Out</source>
+        <translation type="unfinished"></translation>
+    </message>
+</context>
+<context>
+    <name>CStationsDlgBase</name>
+    <message>
+        <source>Stations</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Column 1</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>New Item</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>TextLabelUTCTime</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>kHz</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>S-Meter [dB]
+(relative to S9):</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>&Close</source>
+        <translation type="unfinished"></translation>
+    </message>
+</context>
+<context>
+    <name>EPGDlg</name>
+    <message>
+        <source>no basic profile data</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>no advanced profile data</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>no data</source>
+        <translation type="unfinished"></translation>
+    </message>
+</context>
+<context>
+    <name>FDRMDialog</name>
+    <message>
+        <source>&Evaluation Dialog...</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>M&ultimedia Dialog...</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>S&tations Dialog...</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>&Live Schedule Dialog...</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>&Programme Guide...</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>E&xit</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>&Sound Card Selection</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>&AM (analog)</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>New &DRM Acquisition</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Set D&isplay Color...</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>&Blue / White</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>&Green / Black</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>B&lack / Grey</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>&Plot Style</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>&View</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>&Settings</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>&?</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Stations</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Live Schedule</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Programme Guide</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>System Evaluation</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Multimedia</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source> kbps</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>No Service</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source> + EPG</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source> + MM</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source> + AFS</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Scanning...</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Text Message:</b> On the top right the text message label is shown. This label only appears when an actual text message is transmitted. If the current service does not transmit a text message, the label will be disabled.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Input Level:</b> The input level meter shows the relative input signal peak level in dB. If the level is too high, the meter turns from green to red. The red region should be avoided since overload causes distortions which degrade the reception performance. Too low levels should be avoided too, since in this case the Signal-to-Noise Ratio (SNR) degrades.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Status LEDs:</b> The three status LEDs show the current CRC status of the three logical channels of a DRM stream. These LEDs are the same as the top LEDs on the Evaluation Dialog.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Station Label and Info Display:</b> In the big label with the black background the station label and some other information about the current selected service is displayed. The magenta text on the top shows the bit-rate of the current selected service (The abbreviations EEP and UEP stand for Equal Error Protection and Unequal Error Protection. UEP is a feature of DRM for a graceful degradation of the decoded audio signal in case of a bad reception situation [...]
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Service Selectors:</b> In a DRM stream up to four services can be carried. The service can be an audio service, a data service or an audio service with data. Audio services can have associated text messages, in addition to any data component. If a Multimedia data service is selected, the Multimedia Dialog will automatically show up. On the right of each service selection button a short description of the service is shown. If an audio service has associated  [...]
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>&Multimedia settings...</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Multimedia settings</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>&General settings...</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>General settings</source>
+        <translation type="unfinished"></translation>
+    </message>
+</context>
+<context>
+    <name>FDRMDialogBase</name>
+    <message>
+        <source>Dream</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Level [dB]</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>15 kbps</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>AAC+</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Stereo</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Deutsche Welle</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>German</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>DE</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Information</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>1001</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>TextTextMessage</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>1</source>
+        <comment>Selects the first service</comment>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>TextMiniService1</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>2</source>
+        <comment>Selects the second service</comment>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>TextMiniService2</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>3</source>
+        <comment>Selects the third service</comment>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>TextMiniService3</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>4</source>
+        <comment>Selects the fourth service</comment>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>TextMiniService4</source>
+        <translation type="unfinished"></translation>
+    </message>
+</context>
+<context>
+    <name>GeneralSettingsDlg</name>
+    <message>
+        <source>Latitude value must be in the range 0 to 90</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Longitude value must be in the range 0 to 180</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Minutes value must be in the range 0 to 59</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Compile all fields on receiver coordinates</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Receiver coordinates:</b> Are used on Live Schedule Dialog to show a little green cube on the left of the target column if the receiver coordinates (latitude and longitude) are inside the target area of this transmission.<br>Receiver coordinates are also saved into the Log file.</source>
+        <translation type="unfinished"></translation>
+    </message>
+</context>
+<context>
+    <name>LiveScheduleDlg</name>
+    <message>
+        <source>System</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Time [UTC]</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Target</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Show &only active stations</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Show &all stations</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>&Disabled</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>&5 minutes</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>&15 minutes</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>&30 minutes</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Stations &preview</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>&Save...</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>&File</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>&View</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>AFS Live Schedule</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>UTC Time:</b> Shows the current Coordinated Universal Time (UTC) which is also known as Greenwich Mean Time (GMT).</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Frequency [kHz/MHz]</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Start day</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Live Schedule</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Freeze:</b> If this check box is selectd the live schedule is freezed.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Live Schedule List:</b> In the live schedule list it's possible to view AFS (Alternative Frequency Signalling) informations trasmitted with the current DRM or AMSS signal.</b>It is possible to show only active stations by changing a setting in the 'view' menu.<br>The color of the cube on the left of the frequency shows the current status of the transmission.<br>A green box shows that the transmission takes place right now a  [...]
+        <translation type="unfinished"></translation>
+    </message>
+</context>
+<context>
+    <name>MultimediaDlg</name>
+    <message>
+        <source>C&lear all</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>&Save...</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Save &all...</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>&Close</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Set &Font...</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>&File</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>&Settings</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>MOT Broadcast Web Site</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>The home page is available</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Image could not be loaded, </source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>-format not supported by this version of QT!</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>If you want to view the image, save it to file and use an external viewer</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>MOT Slideshow Viewer</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>No data service or data service not supported.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>The homepage is available.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Press the button to open it in the default browser.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Multimedia</source>
+        <translation type="unfinished"></translation>
+    </message>
+</context>
+<context>
+    <name>MultimediaDlgBase</name>
+    <message>
+        <source>Dream Multimedia</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Receiving Status:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>0/0</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>&Close</source>
+        <translation type="unfinished"></translation>
+    </message>
+</context>
+<context>
+    <name>QObject</name>
+    <message>
+        <source>Sun</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Mon</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Tue</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Wed</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Thu</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Fri</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Sat</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>irregular</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>daily</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>from Sun to Thu</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>from Sun to Fri</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>from Mon to Fri</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>from Mon to Sat</source>
+        <translation type="unfinished"></translation>
+    </message>
+</context>
+<context>
+    <name>StationsDlg</name>
+    <message>
+        <source>Station Name</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Time [UTC]</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Frequency [kHz]</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Target</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Power [kW]</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Country</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Site</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Language</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Days</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Show &only active stations</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Show &all stations</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>&Disabled</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>&5 minutes</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>&15 minutes</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>&30 minutes</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Stations &preview</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>None</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Other</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Enable S-Meter</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>With DRM Modification</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>&Get Update...</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>&View</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>&Remote</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>&Update</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Dream Schedule Update</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Dream tries to download the newest DRM schedule
+from www.drm-dx.de (powered by Klaus Schneider).
+Your computer must be connected to the internet.
+
+The current file DRMSchedule.ini will be overwritten.
+Do you want to continue?</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Update failed. The following things may caused the failure:
+<byte value="x9"/>- the internet connection was not set up properly
+<byte value="x9"/>- the server www.drm-dx.de is currently not available
+<byte value="x9"/>- the file 'DRMSchedule.ini' could not be written</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Update successful.
+Due to network problems with the Windows version of QT, the Dream software must be restarted after a DRMSchedule update.
+Please exit Dream now.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Ok</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Update successful.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Frequency Counter:</b> The current frequency value can be changed by using this counter. The tuning steps are 100 kHz for the  buttons with three arrows, 10 kHz for the buttons with two arrows and 1 kHz for the buttons having only one arrow. By keeping the button pressed, the values are increased / decreased automatically.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>UTC Time:</b> Shows the current Coordinated Universal Time (UTC) which is also known as Greenwich Mean Time (GMT).</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Signal-Meter:</b> Shows the signal strength level in dB relative to S9.<br>Note that not all front-ends controlled by hamlib support this feature. If the s-meter is not available, the controls are disabled.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source> (last update: </source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>&Get Update</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Stations List:</b> In the stations list view all DRM stations which are stored in the DRMSchedule.ini file are shown. It is possible to show only active stations by changing a setting in the 'view' menu. The color of the cube on the left of a menu item shows the current status of the DRM transmission. A green box shows that the transmission takes place right now, a yellow cube shows that this is a test transmission and with a red cube it is shown  [...]
+        <translation type="unfinished"></translation>
+    </message>
+</context>
+<context>
+    <name>TransmDialog</name>
+    <message>
+        <source>new</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>&Start</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>2 s (Long Interleaving)</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>400 ms (Short Interleaving)</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>SM 16-QAM</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>SM 64-QAM</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>4-QAM</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>16-QAM</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Dream DRM Transmitter<byte value="xb"/>
+This is a test transmission</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>&Sound Card Selection</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>&Settings</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>&?</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>&Stop</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Image Files (*.png *.jpg *.jpeg *.jfif)</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Dream Logo:</b> This is the official logo of the Dream software.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Input Level:</b> The input level meter shows the relative input signal peak level in dB. If the level is too high, the meter turns from green to red.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>DRM Robustness Mode:</b> In a DRM system, four possible robustness modes are defined to adapt the system to different channel conditions. According to the DRM standard:<ul><li><i>Mode A:</i> Gaussian channels, with minor fading</li><li><i>Mode B:</i> Time and frequency selective channels, with longer delay spread</li><li><i>Mode C:</i> As robustness mode B, but with higher Doppler sprea [...]
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>DRM Bandwidth:</b> The bandwith is the gross bandwidth of the generated DRM signal. Not all DRM robustness mode / bandwidth constellations are possible, e.g., DRM robustness mode D and C are only defined for the bandwidths 10 kHz and 20 kHz.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Output intermediate frequency of DRM signal:</b> Set the output intermediate frequency (IF) of generated DRM signal in the 'sound-card pass-band'. In some DRM modes, the IF is located at the edge of the DRM signal, in other modes it is centered. The IF should be chosen that the DRM signal lies entirely inside the sound-card bandwidth.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Output format:</b> Since the sound-card outputs signals in stereo format, it is possible to output the DRM signal in three formats:<ul><li><b>real valued</b> output on both, left and right, sound-card channels</li><li><b>I / Q</b> output which is the in-phase and quadrature component of the complex base-band signal at the desired IF. In-phase is output on the left channel and quadrature on the right channel.&l [...]
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>MSC interleaver mode:</b> The symbol interleaver depth can be either short (approx. 400 ms) or long (approx. 2 s). The longer the interleaver the better the channel decoder can correct errors from slow fading signals. But the longer the interleaver length the longer the delay until (after a re-synchronization) audio can be heard.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Dream DRM Transmitter</source>
+        <translation type="unfinished"></translation>
+    </message>
+</context>
+<context>
+    <name>TransmDlgBase</name>
+    <message>
+        <source>Dream DRM Transmitter</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Volker Fischer, Alexander Kurpiers</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Darmstadt University of Technology
+Institute for Communication Technology</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Indicators</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Audio Level [dB]:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>TextLabelCurPict</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Channel Parameters</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Robustness Mode</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>A</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>B</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>C</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>D</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Bandwidth</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>4,5 kHz</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>9 kHz</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>18 kHz</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>5 kHz</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>10 kHz</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>20 kHz</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>MSC Constellation Scheme:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>MSC Protection Level:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>SDC Constellation Scheme:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>MSC Interleaver Mode:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Output</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>IF:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source> Hz</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Real val.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>I / Q (pos)</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>I / Q (neg)</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>E / P</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Service 1</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Enable</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Label:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Service ID:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Language:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Audio</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Program Type:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Text Message</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>&Clear All</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>&Add / Modify</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Data (SlideShow Application)</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Column 1</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>New Item</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>&Add</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Service 2</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Service 3</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Service 4</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>&Start</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>&Close</source>
+        <translation type="unfinished"></translation>
+    </message>
+</context>
+<context>
+    <name>systemevalDlg</name>
+    <message>
+        <source>MLC: Number of Iterations: </source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>History</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Constellation</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Channel</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Spectrum</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>SNR Spectrum</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Audio Spectrum</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Shifted PSD</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Waterfall Input Spectrum</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Input Spectrum</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Input PSD</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>MSC</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>SDC</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>FAC</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>FAC / SDC / MSC</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Frequency / Sample Rate</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Delay / Doppler</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>SNR / Audio</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Transfer Function</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Impulse Response</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>ListView context menu</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>&Open in separate window</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Chart Window</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Metrics [dB]: MSC: </source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>2 s (Long Interleaving)</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>400 ms (Short Interleaving)</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Interleaver Depth:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>SDC / MSC Mode:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Prot. Level (B / A):</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Audio: </source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source> / Data: </source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Number of Services:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Service not available</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Received time - date:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>DreamOut.wav</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Label            </source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>
+Bitrate          </source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>
+Mode             </source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>
+Bandwidth        </source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>DC Frequency Offset:</b> This is the estimation of the DC frequency offset. This offset corresponds to the resulting sound card intermedia frequency of the front-end. This frequency is not restricted to a certain value. The only restriction is that the DRM spectrum must be completely inside the bandwidth of the sound card.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Sample Frequency Offset:</b> This is the estimation of the sample rate offset between the sound card sample rate of the local computer and the sample rate of the D / A (digital to analog) converter in the transmitter. Usually the sample rate offset is very constant for a given sound card. Therefore it is useful to inform the Dream software about this value at application startup to increase the acquisition speed and reliability.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Doppler / Delay:</b> The Doppler frequency of the channel is estimated for the Wiener filter design of channel estimation in time direction. If linear interpolation is set for channel estimation in time direction, this estimation is not updated. The Doppler frequency is an indication of how fast the channel varies with time. The higher the frequency, the faster the channel changes are.<br>The total delay of the Power Delay Spectrum (PDS) is estimated  [...]
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>I / O Interface LED:</b> This LED shows the current status of the sound card interface. The yellow light shows that the audio output was corrected. Since the sample rate of the transmitter and local computer are different, from time to time the audio buffers will overflow or under run and a correction is necessary. When a correction occurs, a "click" sound can be heard. The red light shows that a buffer was lost in the sound card input stream. Thi [...]
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Time Sync Acq LED:</b> This LED shows the state of the timing acquisition (search for the beginning of an OFDM symbol). If the acquisition is done, this LED will stay green.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Frame Sync LED:</b> The DRM frame synchronization status is shown with this LED. This LED is also only active during acquisition state of the Dream receiver. In tracking mode, this LED is always green.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>FAC CRC LED:</b> This LED shows the Cyclic Redundancy Check (CRC) of the Fast Access Channel (FAC) of DRM. FAC is one of the three logical channels and is always modulated with a 4-QAM. If the FAC CRC check was successful, the receiver changes to tracking mode. The FAC LED is the indication whether the receiver is synchronized to a DRM transmission or not.<br>The bandwidth of the DRM signal, the constellation scheme of MSC and SDC channels and the int [...]
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>SDC CRC LED:</b> This LED shows the CRC check result of the Service Description Channel (SDC) which is one logical channel of the DRM stream. This data is transmitted in approx. 1 second intervals and contains information about station label, audio and data format, etc. The error protection is normally lower than the protection of the FAC. Therefore this LED will turn to red earlier than the FAC LED in general.<br>If the CRC check is ok but errors in  [...]
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>MSC CRC LED:</b> This LED shows the status of the Main Service Channel (MSC). This channel contains the actual audio and data bits. The LED shows the CRC check of the AAC core decoder. The SBR has a separate CRC, but this status is not shown with this LED. If SBR CRC is wrong but the AAC CRC is ok one can still hear something (of course, the high frequencies are not there in this case). If this LED turns red, interruptions of the audio are heard. The yellow [...]
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>MLC, Number of Iterations:</b> In DRM, a multilevel channel coder is used. With this code it is possible to iterate the decoding process in the decoder to improve the decoding result. The more iterations are used the better the result will be. But switching to more iterations will increase the CPU load. Simulations showed that the first iteration (number of iterations = 1) gives the most improvement (approx. 1.5 dB at a BER of 10-4 on a Gaussian channel, Mo [...]
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Flip Input Spectrum:</b> Checking this box will flip or invert the input spectrum. This is necessary if the mixer in the front-end uses the lower side band.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Mute Audio:</b> The audio can be muted by checking this box. The reaction of checking or unchecking this box is delayed by approx. 1 second due to the audio buffers.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Reverberation Effect:</b> If this check box is checked, a reverberation effect is applied each time an audio drop-out occurs. With this effect it is possible to mask short drop-outs.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Freq:</b> In this edit control, the current selected frequency on the front-end can be specified. This frequency will be written into the log file.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Channel Estimation Settings:</b> With these settings, the channel estimation method in time and frequency direction can be selected. The default values use the most powerful algorithms. For more detailed information about the estimation algorithms there are a lot of papers and books available.<br><b>Wiener:</b> Wiener interpolation method uses estimation of the statistics of the channel to design an optimal filter for noise reduction.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Channel Estimation Settings:</b> With these settings, the channel estimation method in time and frequency direction can be selected. The default values use the most powerful algorithms. For more detailed information about the estimation algorithms there are a lot of papers and books available.<br><b>Linear:</b> Simple linear interpolation method to get the channel estimate. The real and imaginary parts of the estimated channel at the pilot [...]
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Channel Estimation Settings:</b> With these settings, the channel estimation method in time and frequency direction can be selected. The default values use the most powerful algorithms. For more detailed information about the estimation algorithms there are a lot of papers and books available.<br><b>DFT Zero Pad:</b> Channel estimation method for the frequency direction using Discrete Fourier Transformation (DFT) to transform the channel e [...]
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Guard Energy:</b> Time synchronization tracking algorithm utilizes the estimation of the impulse response. This method tries to maximize the energy in the guard-interval to set the correct timing.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>First Peak:</b> This algorithms searches for the first peak in the estimated impulse response and moves this peak to the beginning of the guard-interval (timing tracking algorithm).</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>SNR:</b> Signal to Noise Ratio (SNR) estimation based on FAC cells. Since the FAC cells are only located approximately in the region 0-5 kHz relative to the DRM DC frequency, it may happen that the SNR value is very high although the DRM spectrum on the left side of the DRM DC frequency is heavily distorted or disturbed by an interferer so that the true overall SNR is lower as indicated by the SNR value. Similarly, the SNR value might show a very low value  [...]
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>MSC WMER / MSC MER:</b> Modulation Error Ratio (MER) and weighted MER (WMER) calculated on the MSC cells is shown. The MER is calculated as follows: For each equalized MSC cell (only MSC cells, no FAC cells, no SDC cells, no pilot cells), the error vector from the nearest ideal point of the constellation diagram is measured. The squared magnitude of this error is found, and a mean of the squared errors is calculated (over one frame). The MER is the ratio in [...]
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>DRM Mode / Bandwidth:</b> In a DRM system, four possible robustness modes are defined to adapt the system to different channel conditions. According to the DRM standard:<ul><li><i>Mode A:</i> Gaussian channels, with minor fading</li><li><i>Mode B:</i> Time and frequency selective channels, with longer delay spread</li><li><i>Mode C:</i> As robustness mode B, but with higher Doppler spre [...]
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Interleaver Depth:</b> The symbol interleaver depth can be either short (approx. 400 ms) or long (approx. 2 s). The longer the interleaver the better the channel decoder can correct errors from slow fading signals. But the longer the interleaver length the longer the delay until (after a re-synchronization) audio can be heard.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>SDC / MSC Mode:</b> Shows the modulation type of the SDC and MSC channel. For the MSC channel, some hierarchical modes are defined which can provide a very strong protected service channel.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Prot. Level (B/A):</b> The error protection level of the channel coder. For 64-QAM, there are four protection levels defined in the DRM standard. Protection level 0 has the highest protection whereas level 3 has the lowest protection. The letters A and B are the names of the higher and lower protected parts of a DRM block when Unequal Error Protection (UEP) is used. If Equal Error Protection (EEP) is used, only the protection level of part B is valid.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Number of Services:</b> This shows the number of audio and data services transmitted in the DRM stream. The maximum number of streams is four.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Received time - date:</b> This label shows the received time and date in UTC. This information is carried in the SDC channel.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Save Audio as WAV:</b> Save the audio signal as stereo, 16-bit, 48 kHz sample rate PCM wave file. Checking this box will let the user choose a file name for the recording.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Chart Selector:</b> With the chart selector different types of graphical display of parameters and receiver states can be chosen. The different plot types are sorted in different groups. To open a group just double-click on the group or click on the plus left of the group name. After clicking on an item it is possible to choose other items by using the up / down arrow keys. With these keys it is also possible to open and close the groups by using the left / [...]
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Interferer Rejection:</b> There are two algorithms available to reject interferers:<ul><li><b>Bandpass Filter (BP-Filter):</b> The bandpass filter is designed to have the same bandwidth as the DRM signal. If, e.g., a strong signal is close to the border of the actual DRM signal, under some conditions this signal will produce interference in the useful bandwidth of the DRM signal although it is not on the same frequency as the DRM sig [...]
+        <translation type="unfinished"></translation>
+    </message>
+</context>
+<context>
+    <name>systemevalDlgBase</name>
+    <message>
+        <source>System Evaluation</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>SNR:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>MSC WMER / MSC MER:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>DC Frequency of DRM Signal:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Sample Frequency Offset:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Doppler / Delay:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>SNR</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>MER</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>FreqOffset</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>SampFreqOffset</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Wiener</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>MSC CRC:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>SDC CRC:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>FAC CRC:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Frame Sync:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Time Sync Acq:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>I/O Interface:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>FACDRMModeBWL</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>FACInterleaverDepthL</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>FACSDCMSCModeL</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>FACCodeRateL</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>FACNumServicesL</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>FACTimeDateL</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>FACDRMModeBWV</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>FACInterleaverDepthV</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>FACSDCMSCModeV</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>FACCodeRateV</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>FACNumServicesV</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>FACTimeDateV</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Chart Selector</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>D-Spectrum</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>D-InpPSD</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>D-InpSpectr</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>D-Waterfall</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>D-ShiftedPSD</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>D-AudSpectr</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>D-SNRSpectr</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>D-Channel</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>D-IR</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>D-TF</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>D-Constellation</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>D-FAC</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>D-SDC</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>D-MSC</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>D-History</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>D-SNRAudiHist</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>D-DelDopp</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>D-FreqSam</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Channel Estimation: Frequency Interpolation</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Linear</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>DFT Zero Pad.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Channel Estimation: Time Interpolation</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Time Sync Tracking</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Guard Energy</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>First Peak</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Misc Settings</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>TextNumOfIterations</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Log File, Audio</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>kHz</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Interferer Rejection</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>&Close</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>&Flip Input Spectrum</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Mute &Audio</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>&Log File, Freq:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>&Save Audio as WAV</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>&Reverberation</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>&Bandpass Filter</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Modified &Metrics</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>GPS</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message encoding="UTF-8">
+        <source>Lat: 53.123°   Long: 00.456°</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>24/01/2007 15:14.33 UTC</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message encoding="UTF-8">
+        <source>10.0 m/s  151°</source>
+        <translation type="unfinished"></translation>
+    </message>
+</context>
+</TS>
diff --git a/linux/make_shadow_build.sh b/linux/make_shadow_build.sh
new file mode 100755
index 0000000..09c47ba
--- /dev/null
+++ b/linux/make_shadow_build.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+cd ..
+mkdir dream-qt4 dream-qt3 dream-qt2
+cd dream-qt4
+mkdir moc obj
+qmake-qt4 ../dream/dream.pro
+cd ../dream-qt3
+mkdir moc obj
+qmake-qt3 ../dream/dream.pro
+cd ../dream-qt2
+mkdir moc obj
+cp ../dream-qt3/Makefile .
+sed -i -f - Makefile <<EOT
+/^CC/i QTDIR = /usr/src/qt-2.3.2
+s:/usr/share/qt3:\$(QTDIR):
+/^Makefile/,+3d
+s/dream-qt3/dream-qt2/g
+s:\.\./\.\./\.\./\.\./include/qt3:\$(QTDIR)/include:g
+s:/usr/lib/libqwt.so.4:/usr/lib/qt2/libqwt.so.4:
+EOT
+cd ../dream
diff --git a/linux/test/.cvsignore b/linux/test/.cvsignore
new file mode 100644
index 0000000..beb1bff
--- /dev/null
+++ b/linux/test/.cvsignore
@@ -0,0 +1,2 @@
+*.dat
+
diff --git a/linux/test/plotsimres.m b/linux/test/plotsimres.m
new file mode 100644
index 0000000..3bf09a3
--- /dev/null
+++ b/linux/test/plotsimres.m
@@ -0,0 +1,482 @@
+%******************************************************************************\
+%* Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+%* Copyright (c) 2005
+%*
+%* Author:
+%*	Volker Fischer
+%*
+%* Description:
+%* 	This file automatically reads all relevant simulation results
+%*	Note: for correct outputs/plots this script needs Matlab >= R14
+%*
+%******************************************************************************
+%*
+%* This program is free software; you can redistribute it and/or modify it under
+%* the terms of the GNU General Public License as published by the Free Software
+%* Foundation; either version 2 of the License, or (at your option) any later 
+%* version.
+%*
+%* This program is distributed in the hope that it will be useful, but WITHOUT 
+%* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+%* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 
+%* details.
+%*
+%* You should have received a copy of the GNU General Public License along with
+%* this program; if not, write to the Free Software Foundation, Inc., 
+%* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+%*
+%******************************************************************************/
+
+function [] = plotsimres(doremcompnamein)
+global plotcolors;
+global LW;
+global figstretch;
+global doremcompname;
+	
+	% Check parameters
+	if nargin < 1
+        doremcompname = 0; % do not remove by default
+    else
+        doremcompname = doremcompnamein;
+	end
+
+	close all;
+	
+	% definitions
+	plotcolors = {'b-' 'g-' 'r-' 'k-' 'm-' 'y-' 'c-' ...
+        'b--' 'g--' 'r--' 'k--' 'm--' 'y--' 'c--' ...
+        'bd-' 'gd-' 'rd-' 'kd-' 'md-' 'yd-' 'cd-' ...
+		'b+-' 'g+-' 'r+-' 'k+-' 'm+-' 'y+-' 'c+-' ...
+		'b*-' 'g*-' 'r*-' 'k*-' 'm*-' 'y*-' 'c*-'};
+	LW = 2; % line width
+	figstretch = 1.6;
+
+
+	% Get file names of simulation results files
+	files = dir('*.dat');
+	if (length(files) == 0)
+		disp('no simulation output files found');
+		return;
+	end
+
+	% sort files by date
+	filedates = [];
+	for i = 1:length(files)
+        filesdates(i) = datenum(files(i).date);
+	end
+	[dummy, sortdateidxs] = sort(filesdates);
+	files = files(sortdateidxs);
+
+
+	% sort files
+	simresBERIDEAL = struct([]);
+	simresMSE = struct([]);
+	simresBER = struct([]);
+	simresSYNC = struct([]);
+	simrescntBERIDEAL = 1;
+	simrescntMSE = 1;
+	simrescntBER = 1;
+	simrescntSYNC = 1;
+    newestfile = -1;
+	for i = 1:length(files)
+        % sort out SIMTIME files
+        if isempty(findstr(files(i).name, '_SIMTIME'))
+            % sort out BERIDEAL files
+            if ~isempty(findstr(files(i).name, 'BERIDEAL_'))
+                simresBERIDEAL(simrescntBERIDEAL).name = files(i).name;
+                simrescntBERIDEAL = simrescntBERIDEAL + 1;
+                newestfile = 0;
+            end
+
+            % sort out BER files
+            if ~isempty(findstr(files(i).name, 'BER_'))
+                simresBER(simrescntBER).name = files(i).name;
+                simrescntBER = simrescntBER + 1;
+                newestfile = 1;             
+            end
+
+            % sort out MSE files
+            if ~isempty(findstr(files(i).name, 'MSE_'))
+                simresMSE(simrescntMSE).name = files(i).name;
+                simrescntMSE = simrescntMSE + 1;
+                newestfile = 2;               
+            end
+
+            % sort out SYNC files
+            if ~isempty(findstr(files(i).name, 'SYNC_'))
+                simresSYNC(simrescntSYNC).name = files(i).name;
+                simrescntSYNC = simrescntSYNC + 1;
+                newestfile = 3;            
+            end        
+        end
+	end
+
+    % plot results in that order that the newest file is plotted at last so
+    % that this plot is upmost
+    switch newestfile
+        case {0}
+            plotBERresults(simresBER);
+			plotMSEresults(simresMSE);
+            plotSYNCresults(simresSYNC);
+            plotBERIDEALresults(simresBERIDEAL);
+        case {1}
+			plotMSEresults(simresMSE);
+            plotSYNCresults(simresSYNC);
+            plotBERIDEALresults(simresBERIDEAL);
+            plotBERresults(simresBER);
+        case {2}
+            plotSYNCresults(simresSYNC);
+            plotBERIDEALresults(simresBERIDEAL);
+            plotBERresults(simresBER);
+			plotMSEresults(simresMSE);
+        otherwise
+            plotBERIDEALresults(simresBERIDEAL);
+            plotBERresults(simresBER);
+			plotMSEresults(simresMSE);
+            plotSYNCresults(simresSYNC);
+    end
+return;
+
+
+
+% *******************************************************************
+% BERIDEAL results **************************************************
+% *******************************************************************
+function [] = plotBERIDEALresults(simresBERIDEAL)
+global doremcompname;
+
+    numdataBERIDEAL = length(simresBERIDEAL);
+	if (numdataBERIDEAL > 0)
+        figure;
+
+        % load data
+        for i = 1:numdataBERIDEAL
+            resBERIDEAL(i).data = load(simresBERIDEAL(i).name);
+        end
+
+        % plot results
+        [handles simresBERIDEAL] = plotresults(resBERIDEAL, simresBERIDEAL);    
+        numdataBERIDEAL= length(simresBERIDEAL); % update length (might have changed if data was empty)
+
+        % generate legend
+        for i = 1:numdataBERIDEAL
+            % remove underscores
+            simresBERIDEAL(i).name = replaceunderscores(simresBERIDEAL(i).name);
+
+            % remove ".dat"
+            simresBERIDEAL(i).name = removedat(simresBERIDEAL(i).name);        
+
+            % remove BERIDEAL
+            simresBERIDEAL(i).name = removesimtype(simresBERIDEAL(i).name);             
+
+            % remove length of simulation
+            simresBERIDEAL(i).name = removelenofsim(simresBERIDEAL(i).name, 5);
+
+            % remove computer name if requested
+            if doremcompname ~= 0
+                simresBERIDEAL(i).name = removecompname(simresBERIDEAL(i).name);
+            end
+        end
+
+        setlegend(simresBERIDEAL, handles);
+
+        title('Bit-Error-Rate Results (BERIDEAL)');
+        xlabel('SNR [dB]');
+        ylabel('BER');
+	end
+return;
+
+
+
+% *******************************************************************
+% BER results *******************************************************
+% *******************************************************************
+function [] = plotBERresults(simresBER)
+global doremcompname;
+
+	numdataBER= length(simresBER);
+	if (numdataBER > 0)
+        figure;
+
+        % load data
+        for i = 1:numdataBER
+            resBER(i).data = load(simresBER(i).name);
+        end
+
+        % plot results
+        [handles simresBER] = plotresults(resBER, simresBER);    
+        numdataBER= length(simresBER); % update length (might have changed if data was empty)
+
+        % generate legend
+        for i = 1:numdataBER
+            % remove underscores
+            simresBER(i).name = replaceunderscores(simresBER(i).name);
+
+            % remove ".dat"
+            simresBER(i).name = removedat(simresBER(i).name);
+
+            % remove BER
+            simresBER(i).name = removesimtype(simresBER(i).name);        
+
+            % remove length of simulation
+            simresBER(i).name = removelenofsim(simresBER(i).name, 6); 
+
+            % remove computer name if requested
+            if doremcompname ~= 0
+                simresBER(i).name = removecompname(simresBER(i).name);
+            end        
+        end
+
+        setlegend(simresBER, handles);
+
+        title('Bit-Error-Rate Results (BER)');
+        xlabel('SNR [dB]');
+        ylabel('BER');
+	end
+return;
+
+
+
+% *******************************************************************
+% SYNC results ******************************************************
+% *******************************************************************
+function [] = plotSYNCresults(simresSYNC)
+global doremcompname;
+
+	numdataSYNC= length(simresSYNC);
+	if (numdataSYNC > 0)
+        figure;
+
+        % load data
+        for i = 1:numdataSYNC
+            resSYNC(i).data = load(simresSYNC(i).name);
+        end
+
+        % plot results
+        [handles simresSYNC] = plotresults(resSYNC, simresSYNC);    
+        numdataSYNC= length(simresSYNC); % update length (might have changed if data was empty)
+
+        % generate legend
+        for i = 1:numdataSYNC
+            % remove underscores
+            simresSYNC(i).name = replaceunderscores(simresSYNC(i).name);
+
+            % remove ".dat"
+            simresSYNC(i).name = removedat(simresSYNC(i).name);
+
+            % remove BER
+            simresSYNC(i).name = removesimtype(simresSYNC(i).name);        
+
+            % remove length of simulation
+            simresSYNC(i).name = removelenofsim(simresSYNC(i).name, 5);   
+
+            % remove computer name if requested
+            if doremcompname ~= 0
+                simresSYNC(i).name = removecompname(simresSYNC(i).name);
+            end        
+        end
+
+        setlegend(simresSYNC, handles);
+
+        title('Synchronization Results');
+        xlabel('SNR [dB]');
+        ylabel('user defined');
+	end
+return;
+
+
+
+% *******************************************************************
+% MSE results *******************************************************
+% *******************************************************************
+function [] = plotMSEresults(simresMSE)
+global doremcompname;
+global plotcolors;
+global LW;
+
+    numdataMSE = length(simresMSE);
+	if (numdataMSE > 0)
+        figure;
+
+        % load data
+        for i = 1:numdataMSE
+            resMSE(i).data = load(simresMSE(i).name).';
+        end
+
+        % plot results
+        [handles simresMSE] = plotresults(resMSE, simresMSE, 1);    
+        numdataMSE= length(simresMSE); % update length (might have changed if data was empty)
+
+        % generate legend
+        for i = 1:numdataMSE
+            % remove underscores
+            simresMSE(i).name = replaceunderscores(simresMSE(i).name);
+
+            % remove ".dat"
+            simresMSE(i).name = removedat(simresMSE(i).name);
+
+            % remove MSE
+            simresMSE(i).name = removesimtype(simresMSE(i).name);
+
+            % remove length of simulation
+            simresMSE(i).name = removelenofsim(simresMSE(i).name, 5);
+
+            % remove computer name if requested
+            if doremcompname ~= 0
+                simresMSE(i).name = removecompname(simresMSE(i).name);
+            end
+        end
+
+        setlegend(simresMSE, handles);
+
+        title('MSE of Channel Estimation Results');
+        xlabel('subcarrier index');
+        ylabel('MSE [dB]');
+	end
+return;
+
+
+
+% *******************************************************************
+% Utility functions *************************************************
+% function for removing underscores and replacing them by spaces
+function [x] = replaceunderscores(x)
+    underscoridxs = findstr(x, '_');
+
+    % replace underscores with spaces
+    x(underscoridxs) = ' ';
+return;
+
+% function for removing the ".dat" at the end of the file names
+function [x] = removedat(x)
+    datidx = findstr(x, '.dat');
+
+    % remove ".dat"
+    x = x(1:datidx - 1);
+return;
+
+% function for removing simulation type (at the beginning of file name)
+function [x] = removesimtype(x)
+    [token x] = strtok(x);
+
+    x = x(2:end); % remove space
+return;
+
+% function for removing the length of simulation token
+function [x] = removelenofsim(x, numtoken)
+    [token remtoken] = strtok(x);
+    if (~isempty(findstr(x, 'CH8')))
+        numtoken = numtoken + 1; % for CH8 the Doppler is shown
+    end
+
+    for j = 1:numtoken
+        [token remtoken] = strtok(remtoken);
+    end
+    
+    % actual cut
+    tokenidx = findstr(x, token) - 1;
+    x = [x(1:tokenidx) x(tokenidx + length(token) + 2:end)];
+return;
+
+% remove computer name
+function [x] = removecompname(x)
+    [token remtoken] = strtok(x);
+    while ~isempty(remtoken)
+        [token remtoken] = strtok(remtoken);
+    end
+    tokenidx = findstr(x, token) - 1;
+    x = [x(1:tokenidx) x(tokenidx + length(token) + 2:end)];    
+return;
+
+% plot results
+function [handles, simnames] = plotresults(simres, simnames, isMSEplot)
+global plotcolors;
+global LW;
+
+    % no MSE is default
+    if nargin ~= 3
+        isMSEplot = 0;
+    end
+
+    % remove empty data
+    simresnew = struct([]);
+    simnamesnew = struct([]);
+    for i = 1:length(simres)
+        if length(simres(i).data) > 0
+            simresnew = [simresnew simres(i)];
+            simnamesnew = [simnamesnew simnames(i)];
+        end
+    end
+    simnames = simnamesnew; % make sure we get the correct labels!
+    
+    numdata = length(simresnew);
+    handles = [];
+    if (numdata > 0)
+        % first curve
+        if isMSEplot ~= 0
+            handtmp = plot(10 * log10(simresnew(1).data), char(plotcolors(1)), 'LineWidth', LW);
+            handles = handtmp(1);            
+		else
+			% if only one data point is available, use marker
+			optstr = char(plotcolors(1));
+			if length(simresnew(1).data(:, 1)) < 2
+				optstr = [optstr '*'];
+			end
+
+            handles = semilogy(simresnew(1).data(:, 1), simresnew(1).data(:, 2), ...
+                optstr, 'LineWidth', LW);
+        end
+
+        grid on;
+
+        if (numdata > 1)
+            % plot rest of the curves
+            hold on;
+            for i = 2:numdata
+                if isMSEplot ~= 0
+                    handtmp = plot(10 * log10(simresnew(i).data), char(plotcolors(i)), 'LineWidth', LW);
+                    handles = [handles handtmp(1)];
+				else
+					% if only one data point is available, use marker
+					optstr = char(plotcolors(i));
+					if length(simresnew(i).data(:, 1)) < 2
+						optstr = [optstr '*'];
+					end
+
+                    handles = [handles ...
+                        semilogy(simresnew(i).data(:, 1), simresnew(i).data(:, 2), ...
+                        optstr, 'LineWidth', LW)];
+                end
+            end
+        end
+    end
+return;
+
+% set legend
+function [] = setlegend(simres, handles)
+global figstretch;
+	
+	if (length(handles) > 0)
+	    legend(handles, simres.name, 'Location', 'NorthEastOutside');
+
+	    % stretch figure since we want to have the legend outside on the right
+	    figpos = get(gcf, 'Position');
+	    set(gcf, 'Position', [figpos(1) figpos(2) figpos(3) * figstretch figpos(4)]);
+	end
+return;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/macx/deploy.sh b/macx/deploy.sh
new file mode 100755
index 0000000..ec1be94
--- /dev/null
+++ b/macx/deploy.sh
@@ -0,0 +1,29 @@
+#!/bin/sh
+mkdir -p dream
+rm -rf dream/dream.app
+cp -r dream.app dream
+cd dream
+mkdir dream.app/Contents/Frameworks
+cp /usr/local/lib/libhamlib.2.dylib dream.app/Contents/Frameworks/
+cp /opt/local/lib/libportaudio.2.dylib dream.app/Contents/Frameworks/
+cp /opt/local/lib/libsndfile.1.dylib dream.app/Contents/Frameworks/
+cp /opt/local/lib/libFLAC.8.dylib dream.app/Contents/Frameworks/
+cp /opt/local/lib/libvorbis.0.dylib dream.app/Contents/Frameworks/
+cp /opt/local/lib/libvorbisenc.2.dylib dream.app/Contents/Frameworks/
+cp /opt/local/lib/libogg.0.dylib dream.app/Contents/Frameworks/
+
+macdeployqt dream.app
+
+install_name_tool -change /usr/local/lib/libhamlib.2.dylib @executable_path/../Frameworks/libhamlib.2.dylib dream.app/Contents/MacOS/dream 
+install_name_tool -change /opt/local/lib/libportaudio.2.dylib @executable_path/../Frameworks/libportaudio.2.dylib dream.app/Contents/MacOS/dream 
+install_name_tool -change /opt/local/lib/libsndfile.1.dylib @executable_path/../Frameworks/libsndfile.1.dylib dream.app/Contents/MacOS/dream 
+
+install_name_tool -change /opt/local/lib/libogg.0.dylib @executable_path/../Frameworks/libogg.0.dylib dream.app/Contents/Frameworks/libsndfile.1.dylib 
+install_name_tool -change /opt/local/lib/libvorbis.0.dylib @executable_path/../Frameworks/libvorbis.0.dylib dream.app/Contents/Frameworks/libsndfile.1.dylib 
+install_name_tool -change /opt/local/lib/libvorbisenc.2.dylib @executable_path/../Frameworks/libvorbisenc.2.dylib dream.app/Contents/Frameworks/libsndfile.1.dylib 
+install_name_tool -change /opt/local/lib/libFLAC.8.dylib @executable_path/../Frameworks/libFLAC.8.dylib dream.app/Contents/Frameworks/libsndfile.1.dylib 
+install_name_tool -change /opt/local/lib/libogg.0.dylib @executable_path/../Frameworks/libogg.0.dylib dream.app/Contents/Frameworks/libvorbisenc.2.dylib 
+install_name_tool -change /opt/local/lib/libvorbis.0.dylib @executable_path/../Frameworks/libvorbis.0.dylib dream.app/Contents/Frameworks/libvorbisenc.2.dylib 
+
+cd ..
+hdiutil create dream.dmg -srcfolder dream/ -ov
diff --git a/src/AMDemodulation.cpp b/src/AMDemodulation.cpp
new file mode 100644
index 0000000..ca7595a
--- /dev/null
+++ b/src/AMDemodulation.cpp
@@ -0,0 +1,988 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *	Implementation of an analog AM demodulation
+ *
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "AMDemodulation.h"
+
+
+/* Implementation *************************************************************/
+
+CAMDemodulation::CAMDemodulation() :
+    cvecBReal(), cvecBImag(), rvecZReal(), rvecZImag(),
+    cvecBAMAfterDem(), rvecZAMAfterDem(), rvecInpTmp(),
+    cvecHilbert(),
+    iHilFiltBlLen(0),
+    FftPlansHilFilt(),
+    rBPNormBW(0.0),
+    rNormCurMixFreqOffs((CReal) 0.0),
+    rBPNormCentOffsTot(0.0),
+    rvecZAM(), rvecADC(), rvecBDC(), rvecZFM(), rvecAFM(), rvecBFM(),
+    iSymbolBlockSize(0),
+    bPLLIsEnabled(FALSE), bAutoFreqAcquIsEnabled(FALSE), eDemodType(DT_AM),
+    cOldVal(), eNoiRedType(NR_OFF), iNoiRedLevel(-12),
+    PLL(), Mixer(), FreqOffsAcq(), AGC(), NoiseReduction(),
+    iFreeSymbolCounter(0), iAudSampleRate(0), iSigSampleRate(0), iBandwidth(0),
+    iResOutBlockSize(0)
+{
+}
+
+void CAMDemodulation::ProcessDataInternal(CParameter& Parameters)
+{
+    int i;
+
+    /* OPH: update free-running symbol counter */
+    Parameters.Lock();
+    iFreeSymbolCounter++;
+    if (iFreeSymbolCounter >= Parameters.CellMappingTable.iNumSymPerFrame)
+    {
+        iFreeSymbolCounter = 0;
+    }
+    Parameters.Unlock();
+
+
+    /* Frequency offset estimation if requested */
+    if (FreqOffsAcq.Run(*pvecInputData))
+        SetNormCurMixFreqOffs(FreqOffsAcq.GetCurResult());
+
+
+    /* Band-pass filter and mixer ------------------------------------------- */
+    /* Copy CVector data in CMatlibVector */
+    for (i = 0; i < iInputBlockSize; i++)
+        rvecInpTmp[i] = (*pvecInputData)[i];
+
+    /* Cut out a spectrum part of desired bandwidth */
+    cvecHilbert = CComplexVector(
+                      FftFilt(cvecBReal, rvecInpTmp, rvecZReal, FftPlansHilFilt),
+                      FftFilt(cvecBImag, rvecInpTmp, rvecZImag, FftPlansHilFilt));
+
+    /* Mix it down to zero frequency */
+    Mixer.Process(cvecHilbert);
+
+
+    /* Phase lock loop (PLL) ------------------------------------------------ */
+    if (bPLLIsEnabled == TRUE)
+    {
+        PLL.Process(rvecInpTmp);
+
+        /* Update mixer frequency with tracking result from PLL. Special case
+           here since we change the mixer frequency but do not update the
+           band-pass filter. We can do this because the frequency changes by the
+           PLL are usually small */
+        Mixer.SetMixFreq(PLL.GetCurNormFreqOffs());
+        rNormCurMixFreqOffs = PLL.GetCurNormFreqOffs(); /* For GUI */
+    }
+
+
+    /* Analog demodulation -------------------------------------------------- */
+    /* Actual demodulation. Reuse temp buffer "rvecInpTmp" for output
+       signal */
+    switch (eDemodType)
+    {
+    case DT_AM:
+        /* Use envelope of signal and apply low-pass filter */
+        rvecInpTmp = FftFilt(cvecBAMAfterDem, Abs(cvecHilbert),
+                             rvecZAMAfterDem, FftPlansHilFilt);
+
+        /* Apply DC filter (high-pass filter) */
+        rvecInpTmp = Filter(rvecBDC, rvecADC, rvecInpTmp, rvecZAM);
+        break;
+
+    case DT_LSB:
+    case DT_USB:
+    case DT_CW:
+        /* Make signal real and compensate for removed spectrum part */
+        rvecInpTmp = Real(cvecHilbert) * (CReal) 2.0;
+        break;
+
+    case DT_FM:
+        /* Get phase of complex signal and apply differentiation */
+        for (i = 0; i < iInputBlockSize; i++)
+        {
+            /* Back-rotate new input sample by old value to get
+               differentiation operation, get angle of complex signal and
+               amplify result */
+            rvecInpTmp[i] = Angle(cvecHilbert[i] * Conj(cOldVal)) *
+                            _MAXSHORT / ((CReal) 4.0 * crPi);
+
+            /* Store old value */
+            cOldVal = cvecHilbert[i];
+        }
+
+        /* Low-pass filter */
+        rvecInpTmp = Filter(rvecBFM, rvecAFM, rvecInpTmp, rvecZFM);
+    }
+
+
+    /* Noise reduction -------------------------------------------------- */
+    if (eNoiRedType != NR_OFF)
+        NoiseReduction.Process(rvecInpTmp);
+
+
+    /* AGC -------------------------------------------------------------- */
+    AGC.Process(rvecInpTmp);
+
+
+    /* Resampling audio ------------------------------------------------- */
+    /* Change type of data (short -> real) */
+    for (i = 0; i < iSymbolBlockSize; i++)
+        vecTempResBufIn[i] = rvecInpTmp[i];
+
+    /* Resample data */
+    ResampleObj.Resample(vecTempResBufIn, vecTempResBufOut);
+
+    /* Write mono signal in both channels (left and right) */
+    for (i = 0; i < iResOutBlockSize; i++)
+        (*pvecOutputData)[2 * i] = (*pvecOutputData)[2 * i + 1] =
+            Real2Sample(vecTempResBufOut[i]);
+}
+
+void CAMDemodulation::InitInternal(CParameter& Parameters)
+{
+    /* Get parameters from info class */
+    Parameters.Lock();
+    iSymbolBlockSize = Parameters.CellMappingTable.iSymbolBlockSize;
+    iAudSampleRate = Parameters.GetAudSampleRate();
+    iSigSampleRate = Parameters.GetSigSampleRate();
+    Parameters.Unlock();
+
+    /* SetFilterBW() can be called before InitInternal() and iSigSampleRate is defined,
+       so we need to recalculate the bandwidth here */
+    rBPNormBW = (CReal) iBandwidth / iSigSampleRate;
+
+    /* Init temporary vector for filter input and output */
+    rvecInpTmp.Init(iSymbolBlockSize);
+    cvecHilbert.Init(iSymbolBlockSize);
+
+    /* Init old value needed for differentiation */
+    cOldVal = (CReal) 0.0;
+
+    /* Init noise reduction object */
+    NoiseReduction.Init(iSigSampleRate, iSymbolBlockSize);
+
+    /* Init frequency offset acquisition (start new acquisition) */
+    FreqOffsAcq.Init(iSymbolBlockSize);
+    FreqOffsAcq.Start((CReal) 0.0); /* Search entire bandwidth */
+
+    /* Init AGC */
+    AGC.Init(iSigSampleRate, iSymbolBlockSize);
+
+    /* Init mixer */
+    Mixer.Init(iSymbolBlockSize);
+
+    /* Init PLL */
+    PLL.Init(iSymbolBlockSize);
+
+    /* Inits for Hilbert and DC filter -------------------------------------- */
+    /* Hilbert filter block length is the same as input block length */
+    iHilFiltBlLen = iSymbolBlockSize;
+
+    /* Init state vector for filtering with zeros */
+    rvecZReal.Init(iHilFiltBlLen, (CReal) 0.0);
+    rvecZImag.Init(iHilFiltBlLen, (CReal) 0.0);
+    rvecZAMAfterDem.Init(iHilFiltBlLen, (CReal) 0.0);
+
+    /* "+ 1" because of the Nyquist frequency (filter in frequency domain) */
+    cvecBReal.Init(iHilFiltBlLen + 1);
+    cvecBImag.Init(iHilFiltBlLen + 1);
+    cvecBAMAfterDem.Init(iHilFiltBlLen + 1);
+
+    /* FFT plans are initialized with the long length */
+    FftPlansHilFilt.Init(iHilFiltBlLen * 2);
+
+    /* Init DC filter */
+    /* IIR filter: H(Z) = (1 - z^{-1}) / (1 - lamDC * z^{-1}) */
+    rvecZAM.Init(2, (CReal) 0.0); /* Memory */
+    rvecBDC.Init(2);
+    rvecADC.Init(2);
+    rvecBDC[0] = (CReal) 1.0;
+    rvecBDC[1] = (CReal) -1.0;
+    rvecADC[0] = (CReal) 1.0;
+    rvecADC[1] = -DC_IIR_FILTER_LAMBDA;
+
+    /* Init FM audio filter. This is a butterworth IIR filter with cut-off
+       of 3 kHz. It was generated in Matlab with
+       [b, a] = butter(4, 3000 / 24000); */
+    rvecZFM.Init(5, (CReal) 0.0); /* Memory */
+    rvecBFM.Init(5);
+    rvecAFM.Init(5);
+    rvecBFM[0] = (CReal) 0.00093349861295;
+    rvecBFM[1] = (CReal) 0.00373399445182;
+    rvecBFM[2] = (CReal) 0.00560099167773;
+    rvecBFM[3] = (CReal) 0.00373399445182;
+    rvecBFM[4] = (CReal) 0.00093349861295;
+    rvecAFM[0] = (CReal) 1.0;
+    rvecAFM[1] = (CReal) -2.97684433369673;
+    rvecAFM[2] = (CReal) 3.42230952937764;
+    rvecAFM[3] = (CReal) -1.78610660021804;
+    rvecAFM[4] = (CReal) 0.35557738234441;
+
+
+    /* Init band-pass filter */
+    SetNormCurMixFreqOffs(rNormCurMixFreqOffs);
+
+
+    /* Define block-sizes for input and output */
+    /* The output buffer is a cyclic buffer, we have to specify the total
+       buffer size */
+    iMaxOutputBlockSize = (int) ((_REAL) iAudSampleRate *
+                                 (_REAL) 0.4 /* 400ms */ * 2 /* for stereo */);
+
+    iInputBlockSize = iSymbolBlockSize;
+
+    iResOutBlockSize = (int) ((_REAL) iSymbolBlockSize *
+                              iAudSampleRate / iSigSampleRate);
+
+    iOutputBlockSize = 2 * iResOutBlockSize; /* Stereo */
+
+
+    /* Init audio resampler */
+    ResampleObj.Init(iSymbolBlockSize,
+        (_REAL) iAudSampleRate / iSigSampleRate);
+    vecTempResBufIn.Init(iSymbolBlockSize, (_REAL) 0.0);
+    vecTempResBufOut.Init(iResOutBlockSize, (_REAL) 0.0);
+
+    /* OPH: init free-running symbol counter */
+    iFreeSymbolCounter = 0;
+
+}
+
+void CAMDemodulation::SetNormCurMixFreqOffs(const CReal rNewNormCurMixFreqOffs)
+{
+    /* In case CW demodulation is used, set mixer frequency so that the center
+       of the band-pass filter is at the selected frequency */
+    if (eDemodType == DT_CW)
+    {
+        rNormCurMixFreqOffs =
+            rNewNormCurMixFreqOffs - FREQ_OFFS_CW_DEMOD / iSigSampleRate;
+    }
+    else
+        rNormCurMixFreqOffs = rNewNormCurMixFreqOffs;
+
+    /* Generate filter taps and set mixing frequency */
+    SetBPFilter(rBPNormBW, rNormCurMixFreqOffs, eDemodType);
+    Mixer.SetMixFreq(rNormCurMixFreqOffs);
+
+    /* Tell the PLL object the new frequency (we do not care here if it is
+       enabled or not) */
+    PLL.SetRefNormFreq(rNormCurMixFreqOffs);
+}
+
+void CAMDemodulation::SetBPFilter(const CReal rNewBPNormBW,
+                                  const CReal rNewNormFreqOffset,
+                                  const EDemodType eDemodType)
+{
+    /* Set internal parameter */
+    rBPNormBW = rNewBPNormBW;
+
+    /* Actual prototype filter design */
+    CRealVector vecrFilter(iHilFiltBlLen);
+    vecrFilter = FirLP(rBPNormBW, Nuttallwin(iHilFiltBlLen));
+
+    /* Adjust center of filter for respective demodulation types */
+    CReal rBPNormFreqOffset = (CReal) 0.0;
+    const CReal rSSBMargin = SSB_DC_MARGIN_HZ / iSigSampleRate;
+    switch (eDemodType)
+    {
+    case DT_AM:
+    case DT_FM:
+        /* No offset */
+        rBPNormFreqOffset = (CReal) 0.0;
+        break;
+
+    case DT_LSB:
+        /* Shift filter to the left side of the carrier. Add a small offset
+          to the filter bandwidht because of the filter slope */
+        rBPNormFreqOffset = - rBPNormBW / 2 - rSSBMargin;
+        break;
+
+    case DT_USB:
+        /* Shift filter to the right side of the carrier. Add a small offset
+          to the filter bandwidht because of the filter slope */
+        rBPNormFreqOffset = rBPNormBW / 2 + rSSBMargin;
+        break;
+
+    case DT_CW:
+        /* Shift filter to the right side of the carrier according to the
+           special CW demodulation shift */
+        rBPNormFreqOffset = FREQ_OFFS_CW_DEMOD / iSigSampleRate;
+        break;
+    }
+
+    /* Actual band-pass filter offset is the demodulation frequency plus the
+       additional offset for the demodulation type */
+    rBPNormCentOffsTot = rNewNormFreqOffset + rBPNormFreqOffset;
+
+
+    /* Set filter coefficients ---------------------------------------------- */
+    /* Make sure that the phase in the middle of the filter is always the same
+       to avaoid clicks when the filter coefficients are changed */
+    const CReal rStartPhase = (CReal) iHilFiltBlLen * crPi * rBPNormCentOffsTot;
+
+    /* Copy actual filter coefficients. It is important to initialize the
+       vectors with zeros because we also do a zero-padding */
+    CRealVector rvecBReal(2 * iHilFiltBlLen, (CReal) 0.0);
+    CRealVector rvecBImag(2 * iHilFiltBlLen, (CReal) 0.0);
+    for (int i = 0; i < iHilFiltBlLen; i++)
+    {
+        rvecBReal[i] = vecrFilter[i] *
+                       Cos((CReal) 2.0 * crPi * rBPNormCentOffsTot * i - rStartPhase);
+
+        rvecBImag[i] = vecrFilter[i] *
+                       Sin((CReal) 2.0 * crPi * rBPNormCentOffsTot * i - rStartPhase);
+    }
+
+    /* Transformation in frequency domain for fft filter */
+    cvecBReal = rfft(rvecBReal, FftPlansHilFilt);
+    cvecBImag = rfft(rvecBImag, FftPlansHilFilt);
+
+    /* Set filter coefficients for AM filter after demodulation (use same low-
+       pass design as for the bandpass filter) */
+    CRealVector rvecBAMAfterDem(2 * iHilFiltBlLen, (CReal) 0.0);
+    rvecBAMAfterDem.PutIn(1, iHilFiltBlLen, vecrFilter);
+    cvecBAMAfterDem = rfft(rvecBAMAfterDem, FftPlansHilFilt);
+}
+
+
+/* Interface functions ------------------------------------------------------ */
+void CAMDemodulation::SetAcqFreq(const CReal rNewNormCenter)
+{
+    /* Lock resources */
+    Lock();
+    {
+        if (bAutoFreqAcquIsEnabled == TRUE)
+            FreqOffsAcq.Start(rNewNormCenter);
+        else
+            SetNormCurMixFreqOffs(rNewNormCenter / 2);
+    }
+    Unlock();
+}
+
+void CAMDemodulation::SetDemodType(const EDemodType eNewType)
+{
+    /* Lock resources */
+    Lock();
+    {
+        /* Set internal demodulation type flag */
+        eDemodType = eNewType;
+
+        /* Init band-pass filter according to new demodulation method */
+        if (iSigSampleRate != 0)
+            SetBPFilter(rBPNormBW, rNormCurMixFreqOffs, eDemodType);
+    }
+    Unlock();
+}
+
+void CAMDemodulation::SetFilterBW(const int iNewBW)
+{
+    /* Lock resources */
+    Lock();
+    {
+        /* Set internal bandwidth value */
+        iBandwidth = iNewBW;
+
+        /* Init band-pass filter according to new bandwidth value */
+        if (iSigSampleRate != 0)
+            SetBPFilter((CReal) iNewBW / iSigSampleRate, rNormCurMixFreqOffs,
+                        eDemodType);
+    }
+    Unlock();
+}
+
+void CAMDemodulation::SetAGCType(const CAGC::EType eNewType)
+{
+    /* Lock resources */
+    Lock();
+    {
+        AGC.SetType(eNewType);
+    }
+    Unlock();
+}
+
+void CAMDemodulation::SetNoiRedType(const ENoiRedType eNewType)
+{
+    /* Lock resources */
+    Lock();
+    {
+        eNoiRedType = eNewType;
+
+        switch (eNoiRedType)
+        {
+        case NR_OFF:
+            break;
+
+        case NR_LOW:
+            NoiseReduction.SetNoiRedDegree(CNoiseReduction::NR_LOW);
+            break;
+
+        case NR_MEDIUM:
+            NoiseReduction.SetNoiRedDegree(CNoiseReduction::NR_MEDIUM);
+            break;
+
+        case NR_HIGH:
+            NoiseReduction.SetNoiRedDegree(CNoiseReduction::NR_HIGH);
+            break;
+
+        case NR_SPEEX:
+            NoiseReduction.SetNoiRedDegree((CNoiseReduction::ENoiRedDegree)iNoiRedLevel);
+            break;
+        }
+    }
+    Unlock();
+}
+
+void CAMDemodulation::SetNoiRedLevel(const int iNewLevel)
+{
+    /* Lock resources */
+    Lock();
+    {
+        iNoiRedLevel = iNewLevel;
+        if (eNoiRedType == NR_SPEEX)
+            NoiseReduction.SetNoiRedDegree((CNoiseReduction::ENoiRedDegree)iNoiRedLevel);
+    }
+    Unlock();
+}
+
+_BOOLEAN CAMDemodulation::GetPLLPhase(CReal& rPhaseOut)
+{
+    _BOOLEAN bReturn;
+
+    /* Lock resources */
+    Lock();
+    {
+        /* Phase is only valid if PLL is enabled. Return status */
+        rPhaseOut = PLL.GetCurPhase();
+        bReturn = bPLLIsEnabled;
+    }
+    Unlock();
+
+    return bReturn;
+}
+
+
+/******************************************************************************\
+* Mixer                                                                        *
+\******************************************************************************/
+void CMixer::Process(CComplexVector& veccIn /* in/out */)
+{
+    for (int i = 0; i < iBlockSize; i++)
+    {
+        veccIn[i] *= cCurExp;
+
+        /* Rotate exp-pointer one step further by complex multiplication
+           with precalculated rotation vector cExpStep. This saves us from
+           calling sin() and cos() functions all the time (iterative
+           calculation of these functions) */
+        cCurExp *= cExpStep;
+    }
+}
+
+void CMixer::Init(const int iNewBlockSize)
+{
+    /* Set internal parameter */
+    iBlockSize = iNewBlockSize;
+}
+
+void CMixer::SetMixFreq(const CReal rNewNormMixFreq)
+{
+    /* Set mixing constant */
+    cExpStep = CComplex(Cos((CReal) 2.0 * crPi * rNewNormMixFreq),
+                        -Sin((CReal) 2.0 * crPi * rNewNormMixFreq));
+}
+
+
+/******************************************************************************\
+* Phase lock loop (PLL)                                                        *
+\******************************************************************************/
+void CPLL::Process(CRealVector& vecrIn /* in/out */)
+{
+    /* Mix it down to zero frequency */
+    cvecLow = vecrIn;
+    Mixer.Process(cvecLow);
+
+    /* Complex loop filter */
+    rvecRealTmp = Filter(rvecB, rvecA, Real(cvecLow), rvecZReal);
+    rvecImagTmp = Filter(rvecB, rvecA, Imag(cvecLow), rvecZImag);
+
+    /* Calculate current phase for GUI */
+    rCurPhase = Angle(CComplex(Mean(rvecRealTmp), Mean(rvecImagTmp)));
+
+    /* Average over entire block (only real part) */
+    const CReal rOffsEst = Mean(rvecRealTmp);
+
+    /* Close loop */
+    rNormCurFreqOffsetAdd = PLL_LOOP_GAIN * rOffsEst;
+
+    /* Update mixer */
+    Mixer.SetMixFreq(rNormCurFreqOffset + rNormCurFreqOffsetAdd);
+}
+
+void CPLL::Init(const int iNewBlockSize)
+{
+    /* Set internal parameter */
+    iBlockSize = iNewBlockSize;
+
+    /* Init mixer object */
+    Mixer.Init(iBlockSize);
+
+    /* Init buffers */
+    cvecLow.Init(iBlockSize);
+    rvecRealTmp.Init(iBlockSize);
+    rvecImagTmp.Init(iBlockSize);
+
+    /* Init loop filter (low-pass filter design) */
+    /* IIR filter: H(Z) = (-(1 - lam) * z^{-1}) / (1 - lam * z^{-1}) */
+    rvecZReal.Init(2, (CReal) 0.0); /* Memory */
+    rvecZImag.Init(2, (CReal) 0.0);
+    rvecB.Init(2);
+    rvecA.Init(2);
+    rvecB[0] = (CReal) 0.0;
+    rvecB[1] = -((CReal) 1.0 - PLL_LOOP_FILTER_LAMBDA);
+    rvecA[0] = (CReal) 1.0;
+    rvecA[1] = -PLL_LOOP_FILTER_LAMBDA;
+}
+
+void CPLL::SetRefNormFreq(const CReal rNewNormFreq)
+{
+    /* Store new reference frequency */
+    rNormCurFreqOffset = rNewNormFreq;
+
+    /* Reset offset and phase */
+    rNormCurFreqOffsetAdd = (CReal) 0.0;
+    rCurPhase = (CReal) 0.0;
+}
+
+
+/******************************************************************************\
+* Automatic gain control (AGC)                                                 *
+\******************************************************************************/
+void CAGC::Process(CRealVector& vecrIn)
+{
+    if (eType == AT_NO_AGC)
+    {
+        /* No modification of the signal (except of an amplitude
+           correction factor) */
+        vecrIn *= AM_AMPL_CORR_FACTOR;
+    }
+    else
+    {
+        for (int i = 0; i < iBlockSize; i++)
+        {
+            /* Two sided one-pole recursion for average amplitude
+               estimation */
+            IIR1TwoSided(rAvAmplEst, Abs(vecrIn[i]), rAttack, rDecay);
+
+            /* Lower bound for estimated average amplitude */
+            if (rAvAmplEst < LOWER_BOUND_AMP_LEVEL)
+                rAvAmplEst = LOWER_BOUND_AMP_LEVEL;
+
+            /* Normalize to average amplitude and then amplify to the
+               desired level */
+            vecrIn[i] *= DES_AV_AMPL_AM_SIGNAL / rAvAmplEst;
+        }
+    }
+}
+
+void CAGC::Init(int iNewSampleRate, int iNewBlockSize)
+{
+    /* Set internal parameter */
+    iSampleRate = iNewSampleRate;
+    iBlockSize = iNewBlockSize;
+
+    /* Init filters */
+    SetType(eType);
+
+    /* Init average amplitude estimation with desired amplitude */
+    rAvAmplEst = DES_AV_AMPL_AM_SIGNAL / AM_AMPL_CORR_FACTOR;
+}
+
+void CAGC::SetType(const EType eNewType)
+{
+    /* Set internal parameter */
+    eType = eNewType;
+
+    /*          Slow     Medium   Fast    */
+    /* Attack: 0.025 s, 0.015 s, 0.005 s  */
+    /* Decay : 4.000 s, 2.000 s, 0.200 s  */
+    switch (eType)
+    {
+    case AT_SLOW:
+        rAttack = IIR1Lam(0.025, iSampleRate);
+        rDecay = IIR1Lam(4.000, iSampleRate);
+        break;
+
+    case AT_MEDIUM:
+        rAttack = IIR1Lam(0.015, iSampleRate);
+        rDecay = IIR1Lam(2.000, iSampleRate);
+        break;
+
+    case AT_FAST:
+        rAttack = IIR1Lam(0.005, iSampleRate);
+        rDecay = IIR1Lam(0.200, iSampleRate);
+        break;
+
+    case AT_NO_AGC:
+        break;
+    }
+}
+
+
+/******************************************************************************\
+* Frequency offset acquisition                                                 *
+\******************************************************************************/
+_BOOLEAN CFreqOffsAcq::Run(const CVector<_REAL>& vecrInpData)
+{
+    /* Init return flag */
+    _BOOLEAN bNewAcqResAvailable = FALSE;
+
+    /* Only do new acquisition if requested */
+    if (bAcquisition == TRUE)
+    {
+        /* Add new symbol in history (shift register) */
+        vecrFFTHistory.AddEnd(vecrInpData, iBlockSize);
+
+        if (iAquisitionCounter > 0)
+        {
+            /* Decrease counter */
+            iAquisitionCounter--;
+        }
+        else
+        {
+            /* Copy vector to matlib vector and calculate real-valued FFT */
+            for (int i = 0; i < iTotalBufferSize; i++)
+                vecrFFTInput[i] = vecrFFTHistory[i];
+
+            /* Calculate power spectrum (X = real(F) ^ 2 + imag(F) ^ 2) */
+            vecrPSD = SqMag(rfft(vecrFFTInput, FftPlanAcq));
+
+            /* Calculate frequency from maximum peak in spectrum */
+            CReal rMaxPeak; /* Not needed, dummy */
+            int iIndMaxPeak;
+            Max(rMaxPeak, iIndMaxPeak /* out */,
+                vecrPSD(iSearchWinStart + 1, iSearchWinEnd));
+
+            /* Calculate estimated relative frequency offset */
+            rCurNormFreqOffset =
+                (CReal) (iIndMaxPeak + iSearchWinStart) / iHalfBuffer / 2;
+
+            /* Reset acquisition flag and Set return flag to show that new
+               result is available*/
+            bAcquisition = FALSE;
+            bNewAcqResAvailable = TRUE;
+        }
+    }
+
+    return bNewAcqResAvailable;
+}
+
+void CFreqOffsAcq::Init(const int iNewBlockSize)
+{
+    /* Set internal parameter */
+    iBlockSize = iNewBlockSize;
+
+    /* Total buffer size */
+    iTotalBufferSize = NUM_BLOCKS_CARR_ACQUISITION * iBlockSize;
+
+    /* Length of the half of the spectrum of real input signal (the other half
+       is the same because of the real input signal). We have to consider the
+       Nyquist frequency ("iTotalBufferSize" is always even!) */
+    iHalfBuffer = iTotalBufferSize / 2 + 1;
+
+    /* Allocate memory for FFT-histories and init with zeros */
+    vecrFFTHistory.Init(iTotalBufferSize, (CReal) 0.0);
+    vecrFFTInput.Init(iTotalBufferSize);
+    vecrPSD.Init(iHalfBuffer);
+
+    /* Init plans for FFT (faster processing of Fft and Ifft commands) */
+    FftPlanAcq.Init(iTotalBufferSize);
+}
+
+void CFreqOffsAcq::Start(const CReal rNewNormCenter)
+{
+    /* Search window indices for aquisition. If input parameter is
+       zero, we use the entire bandwidth for acquisition (per definition) */
+    if (rNewNormCenter == (CReal) 0.0)
+    {
+        iSearchWinStart = 1; /* Do not use DC */
+        iSearchWinEnd = iHalfBuffer;
+    }
+    else
+    {
+        const int iWinCenter = (int) (rNewNormCenter * iHalfBuffer);
+        const int iHalfWidth = (int) (PERC_SEARCH_WIN_HALF_SIZE * iHalfBuffer);
+
+        iSearchWinStart = iWinCenter - iHalfWidth;
+        iSearchWinEnd = iWinCenter + iHalfWidth;
+
+        /* Check the values that they are within the valid range */
+        if (iSearchWinStart < 1) /* Do not use DC */
+            iSearchWinStart = 1;
+
+        if (iSearchWinEnd > iHalfBuffer)
+            iSearchWinEnd = iHalfBuffer;
+    }
+
+    /* Set flag for aquisition */
+    bAcquisition = TRUE;
+    iAquisitionCounter = NUM_BLOCKS_CARR_ACQUISITION;
+}
+
+
+/******************************************************************************\
+* Noise reduction                                                              *
+\******************************************************************************/
+/*
+	The original Dream noise reduction algorithm is based on optimal filters, whereas the
+	PDS of the noise is estimated with a minimum statistic.
+	We use an overlap and add method to avoid clicks caused by fast changing
+	optimal filters between successive blocks.
+
+	[Ref] A. Engel: "Transformationsbasierte Systeme zur einkanaligen
+		Stoerunterdrueckung bei Sprachsignalen", PhD Thesis, Christian-
+		Albrechts-Universitaet zu Kiel, 1998
+
+	Robert Turnbull added the capability to use the one from the SPEEX codec
+*/
+
+CNoiseReduction::~CNoiseReduction()
+{
+#ifdef HAVE_SPEEX
+    if (preprocess_state)
+        speex_preprocess_state_destroy(preprocess_state);
+    if (speex_data)
+        free(speex_data);
+#endif
+}
+
+void CNoiseReduction::SetNoiRedDegree(const ENoiRedDegree eNND)
+{
+    eNoiRedDegree = eNND;
+#ifdef HAVE_SPEEX
+    supression_level = (spx_int32_t)eNND;
+#endif
+}
+
+void CNoiseReduction::Process(CRealVector& vecrIn)
+{
+#ifdef HAVE_SPEEX
+    if ((int)eNoiRedDegree <= 0) {
+        int i;
+        CReal* vectorData = &vecrIn[0];
+        int vectorSz = vecrIn.GetSize();
+        if (sample_rate)
+        {
+            if (preprocess_state)
+                speex_preprocess_state_destroy(preprocess_state);
+            if (speex_data)
+                free(speex_data);
+            preprocess_state = speex_preprocess_state_init(vectorSz, sample_rate);
+            speex_data = (spx_int16_t*)malloc(vectorSz*sizeof(spx_int16_t));
+            supression_level = (spx_int32_t)eNoiRedDegree;
+            sample_rate = 0;
+        }
+        if (supression_level)
+        {
+            speex_preprocess_ctl(preprocess_state, SPEEX_PREPROCESS_SET_NOISE_SUPPRESS, &supression_level);
+            supression_level = 0;
+        }
+        for (i=0; i<vectorSz; i++)
+        {
+            speex_data[i] = (spx_int16_t)vectorData[i];
+        }
+        speex_preprocess(preprocess_state, speex_data, NULL);
+        for (i=0; i<vectorSz; i++)
+        {
+            vectorData[i] = (CReal)speex_data[i];
+        }
+    } else {
+#endif
+        /* Regular block (updates the noise estimate) --------------------------- */
+        /* Update history of input signal */
+        vecrLongSignal.Merge(vecrOldSignal, vecrIn);
+
+        /* Update signal PSD estimation */
+        veccSigFreq = rfft(vecrLongSignal, FftPlan);
+        vecrSqMagSigFreq = SqMag(veccSigFreq);
+
+        /* Update minimum statistic for noise PSD estimation. This update is made
+           only once a regular (non-shited) block */
+        UpdateNoiseEst(vecrNoisePSD, vecrSqMagSigFreq, eNoiRedDegree);
+
+        /* Actual noise reducation filtering based on the noise PSD estimation and
+           the current squared magnitude of the input signal */
+        vecrFiltResult = OptimalFilter(veccSigFreq, vecrSqMagSigFreq, vecrNoisePSD);
+
+        /* Apply windowing */
+        vecrFiltResult *= vecrTriangWin;
+
+        /* Build output signal vector with old half and new half */
+        vecrOutSig1.Merge(vecrOldOutSignal, vecrFiltResult(1, iHalfBlockLen));
+
+        /* Save second half of output signal for next block (for overlap and add) */
+        vecrOldOutSignal = vecrFiltResult(iHalfBlockLen + 1, iBlockLen);
+
+
+        /* "Half-shifted" block for overlap and add ----------------------------- */
+        /* Build input vector for filtering the "half-shifted" blocks. It is the
+           second half of the very old signal plus the complete old signal and the
+           first half of the current signal */
+        vecrLongSignal.Merge(vecrVeryOldSignal(iHalfBlockLen + 1, iBlockLen),
+                             vecrOldSignal, vecrIn(1, iHalfBlockLen));
+
+        /* Store old input signal blocks */
+        vecrVeryOldSignal = vecrOldSignal;
+        vecrOldSignal = vecrIn;
+
+        /* Update signal PSD estimation for "half-shifted" block and calculate
+           optimal filter */
+        veccSigFreq = rfft(vecrLongSignal, FftPlan);
+        vecrSqMagSigFreq = SqMag(veccSigFreq);
+
+        vecrFiltResult = OptimalFilter(veccSigFreq, vecrSqMagSigFreq, vecrNoisePSD);
+
+        /* Apply windowing */
+        vecrFiltResult *= vecrTriangWin;
+
+        /* Overlap and add operation */
+        vecrIn = vecrFiltResult + vecrOutSig1;
+#ifdef HAVE_SPEEX
+    }
+#endif
+}
+
+CRealVector CNoiseReduction::OptimalFilter(const CComplexVector& veccSigFreq,
+        const CRealVector& vecrSqMagSigFreq,
+        const CRealVector& vecrNoisePSD)
+{
+    CRealVector vecrReturn(iBlockLenLong);
+
+    /* Calculate optimal filter coefficients in the frequency domain:
+       G_opt = max(1 - S_nn(n) / S_xx(n), 0) */
+    veccOptFilt = Max(Zeros(iFreqBlLen), Ones(iFreqBlLen) -
+                      vecrNoisePSD / vecrSqMagSigFreq);
+
+    /* Constrain the optimal filter in time domain to avoid aliasing */
+    vecrOptFiltTime = rifft(veccOptFilt, FftPlan);
+    vecrOptFiltTime.Merge(vecrOptFiltTime(1, iBlockLen), Zeros(iBlockLen));
+    veccOptFilt = rfft(vecrOptFiltTime, FftPlan);
+
+    /* Actual filtering in frequency domain */
+    vecrReturn = rifft(veccSigFreq * veccOptFilt, FftPlan);
+
+    /* Cut out correct samples (to get from cyclic convolution to linear
+       convolution) */
+    return vecrReturn(iBlockLen + 1, iBlockLenLong);
+}
+
+void CNoiseReduction::UpdateNoiseEst(CRealVector& vecrNoisePSD,
+                                     const CRealVector& vecrSqMagSigFreq,
+                                     const ENoiRedDegree eNoiRedDegree)
+{
+    /*
+    	Implements a mimium statistic proposed by R. Martin
+    */
+    /* Set weighting factor for minimum statistic */
+    CReal rWeiFact = MIN_STAT_WEIGHT_FACTOR_MED;
+    switch (eNoiRedDegree)
+    {
+    case NR_LOW:
+        rWeiFact = MIN_STAT_WEIGHT_FACTOR_LOW;
+        break;
+
+    case NR_MEDIUM:
+        rWeiFact = MIN_STAT_WEIGHT_FACTOR_MED;
+        break;
+
+    case NR_HIGH:
+        rWeiFact = MIN_STAT_WEIGHT_FACTOR_HIGH;
+        break;
+    }
+
+    /* Update signal PSD estimation (first order IIR filter) */
+    IIR1(vecrSigPSD, vecrSqMagSigFreq, rLamPSD);
+
+    for (int i = 0; i < iFreqBlLen; i++)
+    {
+// TODO: Update of minimum statistic can be done much more efficient
+        /* Update history */
+        matrMinimumStatHist[i].Merge(
+            matrMinimumStatHist[i](2, iMinStatHistLen), vecrSigPSD[i]);
+
+        /* Minimum values in history are taken for noise estimation */
+        vecrNoisePSD[i] = Min(matrMinimumStatHist[i]) * rWeiFact;
+    }
+}
+
+void CNoiseReduction::Init(int iSampleRate, int iNewBlockLen)
+{
+    iBlockLen = iNewBlockLen;
+    iHalfBlockLen = iBlockLen / 2;
+    iBlockLenLong = 2 * iBlockLen;
+
+    /* Block length of signal in frequency domain. "+ 1" because of the Nyquist
+       frequency */
+    iFreqBlLen = iBlockLen + 1;
+
+    /* Length of the minimum statistic history */
+    iMinStatHistLen = (int) (MIN_STAT_HIST_LENGTH_SEC * (CReal) iSampleRate / iBlockLen);
+
+    /* Lambda for IIR filter */
+    rLamPSD = IIR1Lam(TICONST_PSD_EST_SIG_NOISE_RED,
+                      (CReal) iSampleRate / iBlockLen);
+
+    /* Init vectors storing time series signals */
+    vecrOldSignal.Init(iBlockLen, (CReal) 0.0);
+    vecrVeryOldSignal.Init(iBlockLen, (CReal) 0.0);
+    vecrFiltResult.Init(iBlockLen);
+    vecrOutSig1.Init(iBlockLen);
+    vecrLongSignal.Init(iBlockLenLong);
+    vecrOptFiltTime.Init(iBlockLenLong);
+    vecrOldOutSignal.Init(iHalfBlockLen, (CReal) 0.0);
+
+    /* Init plans for FFT (faster processing of Fft and Ifft commands). FFT
+       plans are initialized with the long length */
+    FftPlan.Init(iBlockLenLong);
+
+    /* Init vectors storing data in frequency domain */
+    veccOptFilt.Init(iFreqBlLen);
+
+    /* Init signal and noise PDS estimation vectors */
+    veccSigFreq.Init(iFreqBlLen);
+    vecrSqMagSigFreq.Init(iFreqBlLen);
+    vecrSigPSD.Init(iFreqBlLen, (CReal) 0.0);
+    vecrNoisePSD.Init(iFreqBlLen, (CReal) 0.0);
+
+    matrMinimumStatHist.Init(iFreqBlLen, iMinStatHistLen, (CReal) 0.0);
+
+    /* Init window for overlap and add */
+    vecrTriangWin.Init(iBlockLen);
+    vecrTriangWin = Triang(iBlockLen);
+
+#ifdef HAVE_SPEEX
+    sample_rate = iSampleRate;
+#endif
+}
diff --git a/src/AMDemodulation.h b/src/AMDemodulation.h
new file mode 100644
index 0000000..bbc24a0
--- /dev/null
+++ b/src/AMDemodulation.h
@@ -0,0 +1,397 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *	See AMDemodulation.cpp
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#if !defined(AMDEMOD_H__3B0BEVJBN8LKH2934BGF4344_BB27912__INCLUDED_)
+#define AMDEMOD_H__3B0BEVJBN8LKH2934BGF4344_BB27912__INCLUDED_
+
+#include "Parameter.h"
+#include "util/Modul.h"
+#include "util/Vector.h"
+#include "matlib/Matlib.h"
+#include "resample/Resample.h"
+#ifdef HAVE_SPEEX
+# include <speex/speex_preprocess.h>
+#endif
+
+
+/* Definitions ****************************************************************/
+/* Set value for desired amplitude for AM signal, controlled by the AGC. Maximum
+   value is the range for short variables (16 bit) -> 32768 */
+#define DES_AV_AMPL_AM_SIGNAL				((CReal) 8000.0)
+
+/* Lower bound for estimated average amplitude. That is needed, since we
+   devide by this estimate so it must not be zero */
+#define LOWER_BOUND_AMP_LEVEL				((CReal) 10.0)
+
+/* Amplitude correction factor for demodulation */
+#define AM_AMPL_CORR_FACTOR					((CReal) 5.0)
+
+/* Lambda for IIR filter for DC-filter */
+#define DC_IIR_FILTER_LAMBDA				((CReal) 0.999)
+
+/* Margin at the DC frequency in case of SSB demodulation */
+#define SSB_DC_MARGIN_HZ					((CReal) 100.0) /* Hz */
+
+/* Frequency offset for CW demodulation */
+#define FREQ_OFFS_CW_DEMOD					((CReal) 1000.0) /* Hz */
+
+
+/* Parameters for frequency offset estimation algorithm --------------------- */
+/* Set the number of blocks used for carrier frequency acquisition */
+#define NUM_BLOCKS_CARR_ACQUISITION			20
+
+/* Percentage of aquisition search window half size relative to the useful
+   spectrum bandwidth */
+#define PERC_SEARCH_WIN_HALF_SIZE			((CReal) 5.0 /* % */ / 100)
+
+
+/* Parameters for noise reduction algorithm --------------------------------- */
+/* Length of minimum statistic estimation history */
+#define MIN_STAT_HIST_LENGTH_SEC			((CReal) 1.5) /* sec */
+
+/* Minimum statistic weightning factors. With this value the degree of noise
+   reduction can be adjusted. We use three settings here */
+#define MIN_STAT_WEIGHT_FACTOR_LOW			((CReal) 0.4)
+#define MIN_STAT_WEIGHT_FACTOR_MED			((CReal) 1.0)
+#define MIN_STAT_WEIGHT_FACTOR_HIGH			((CReal) 2.0)
+
+/* Time constant for IIR averaging of PSD estimation */
+#define TICONST_PSD_EST_SIG_NOISE_RED		((CReal) 1.0) /* sec */
+
+
+/* Parameters for PLL ------------------------------------------------------- */
+#define PLL_LOOP_GAIN						((CReal) 0.0000001)
+
+/* Lambda for IIR filter for loop filter */
+#define PLL_LOOP_FILTER_LAMBDA				((CReal) 0.99)
+
+
+/* Classes ********************************************************************/
+/* Noise reduction ---------------------------------------------------------- */
+class CNoiseReduction
+{
+public:
+    CNoiseReduction() : eNoiRedDegree(NR_MEDIUM)
+#ifdef HAVE_SPEEX
+    , preprocess_state(NULL), speex_data(NULL)
+    , supression_level(0), sample_rate(0)
+#endif
+    {}
+    virtual ~CNoiseReduction();
+
+    enum ENoiRedDegree {NR_LOW=1, NR_MEDIUM=2, NR_HIGH=3};
+
+    void Init(int iSampleRate, int iNewBlockLen);
+    void Process(CRealVector& vecrIn /* in/out */);
+    void SetNoiRedDegree(const ENoiRedDegree eNND);
+
+protected:
+    void UpdateNoiseEst(CRealVector& vecrNoisePSD,
+                        const CRealVector& vecrSqMagSigFreq, const ENoiRedDegree eNoiRedDegree);
+    CRealVector OptimalFilter(const CComplexVector& vecrSigFreq,
+                              const CRealVector& vecrSqMagSigFreq, const CRealVector& vecrNoisePSD);
+
+    int				iBlockLen;
+    int				iHalfBlockLen;
+    int				iBlockLenLong;
+    int				iFreqBlLen;
+    int				iMinStatHistLen;
+    CReal			rLamPSD;
+    CRealMatrix		matrMinimumStatHist;
+    CComplexVector	veccSigFreq;
+    CRealVector		vecrSqMagSigFreq;
+    CRealVector		vecrSigPSD;
+    CRealVector		vecrNoisePSD;
+    CFftPlans		FftPlan;
+    CComplexVector	veccOptFilt;
+    CRealVector		vecrOldSignal;
+    CRealVector		vecrVeryOldSignal;
+    CRealVector		vecrLongSignal;
+    CRealVector		vecrOldOutSignal;
+    CRealVector		vecrOutSig1;
+    CRealVector		vecrTriangWin;
+    CRealVector		vecrOptFiltTime;
+    CRealVector		vecrFiltResult;
+
+    ENoiRedDegree	eNoiRedDegree;
+#ifdef HAVE_SPEEX
+    SpeexPreprocessState *preprocess_state;
+    spx_int16_t*	speex_data;
+    spx_int32_t		supression_level;
+    int				sample_rate;
+#endif
+};
+
+
+/* Frequency offset acquisition --------------------------------------------- */
+class CFreqOffsAcq
+{
+public:
+    CFreqOffsAcq() : bAcquisition(FALSE), rCurNormFreqOffset((CReal) 0.0) {}
+    void Init(const int iNewBlockSize);
+    _BOOLEAN Run(const CVector<_REAL>& vecrInpData);
+
+    void Start(const CReal rNewNormCenter);
+    CReal GetCurResult() {
+        return rCurNormFreqOffset;
+    }
+
+protected:
+    int						iBlockSize;
+    CFftPlans				FftPlanAcq;
+    CRealVector				vecrFFTInput;
+    int						iTotalBufferSize;
+    int						iHalfBuffer;
+    int						iAquisitionCounter;
+    CShiftRegister<_REAL>	vecrFFTHistory;
+    CRealVector				vecrPSD;
+    int						iSearchWinStart;
+    int						iSearchWinEnd;
+    _BOOLEAN				bAcquisition;
+
+    CReal					rNormCenter;
+    CReal					rCurNormFreqOffset;
+};
+
+
+/* Automatic gain control --------------------------------------------------- */
+class CAGC
+{
+public:
+    enum EType {AT_NO_AGC, AT_SLOW, AT_MEDIUM, AT_FAST};
+
+    CAGC() : eType(AT_MEDIUM) {}
+    void Init(int iSampleRate, int iNewBlockSize);
+    void Process(CRealVector& vecrIn /* in/out */);
+
+    void SetType(const EType eNewType);
+    EType GetType() {
+        return eType;
+    }
+
+protected:
+    int		iSampleRate;
+    int		iBlockSize;
+    EType	eType;
+    CReal	rAttack, rDecay;
+    CReal	rAvAmplEst;
+};
+
+
+/* Mixer -------------------------------------------------------------------- */
+class CMixer
+{
+public:
+    CMixer() : cCurExp((CReal) 1.0), cExpStep((CReal) 1.0) {}
+    void Init(const int iNewBlockSize);
+    void Process(CComplexVector& veccIn /* in/out */);
+
+    void SetMixFreq(const CReal rNewNormMixFreq);
+
+protected:
+    int			iBlockSize;
+    CComplex	cCurExp, cExpStep;
+};
+
+
+/* Phase lock loop ---------------------------------------------------------- */
+class CPLL
+{
+public:
+    CPLL() : rCurPhase((CReal) 0.0) {}
+    void Init(const int iNewBlockSize);
+    void Process(CRealVector& vecrIn /* in/out */);
+
+    void SetRefNormFreq(const CReal rNewNormFreq);
+    CReal GetCurPhase() {
+        return rCurPhase;
+    }
+    CReal GetCurNormFreqOffs()
+    {
+        return rNormCurFreqOffset + rNormCurFreqOffsetAdd;
+    }
+
+protected:
+    CMixer			Mixer;
+    int				iBlockSize;
+    CRealVector		rvecRealTmp;
+    CRealVector		rvecImagTmp;
+    CComplexVector	cvecLow;
+    CReal			rNormCurFreqOffset;
+    CReal			rNormCurFreqOffsetAdd;
+    CReal			rCurPhase;
+
+    CRealVector		rvecZReal;
+    CRealVector		rvecZImag;
+    CRealVector		rvecA;
+    CRealVector		rvecB;
+};
+
+/* AM demodulation module --------------------------------------------------- */
+class CAMDemodulation : public CReceiverModul<_REAL, _SAMPLE>
+{
+public:
+    CAMDemodulation();
+    virtual ~CAMDemodulation() {}
+
+    enum EDemodType {DT_AM, DT_LSB, DT_USB, DT_CW, DT_FM};
+    enum ENoiRedType {NR_OFF, NR_LOW, NR_MEDIUM, NR_HIGH, NR_SPEEX};
+
+    void SetAcqFreq(const CReal rNewNormCenter);
+
+    void EnableAutoFreqAcq(const _BOOLEAN bNewEn)
+    {
+        bAutoFreqAcquIsEnabled = bNewEn;
+    }
+    _BOOLEAN AutoFreqAcqEnabled() {
+        return bAutoFreqAcquIsEnabled;
+    }
+
+    void EnablePLL(const _BOOLEAN bNewEn) {
+        bPLLIsEnabled = bNewEn;
+    }
+    _BOOLEAN PLLEnabled() {
+        return bPLLIsEnabled;
+    }
+
+    void SetDemodType(const EDemodType eNewType);
+    EDemodType GetDemodType() {
+        return eDemodType;
+    }
+
+    void SetFilterBW(const int iNewBW);
+    int GetFilterBW() {
+        return (int) (rBPNormBW * iSigSampleRate);
+    }
+
+    void SetAGCType(const CAGC::EType eNewType);
+    CAGC::EType GetAGCType() {
+        return AGC.GetType();
+    }
+
+    void SetNoiRedType(const ENoiRedType eNewType);
+    ENoiRedType GetNoiRedType() {
+        return eNoiRedType;
+    }
+
+    void SetNoiRedLevel(const int iNewLevel);
+    int GetNoiRedLevel() {
+        return iNoiRedLevel;
+    }
+
+    _BOOLEAN haveSpeex() {
+#ifdef HAVE_SPEEX
+        return TRUE;
+#else
+        return FALSE;
+#endif
+    }
+
+    void GetBWParameters(CReal& rCenterFreq, CReal& rBW)
+    {
+        rCenterFreq = rBPNormCentOffsTot;
+        rBW = rBPNormBW;
+    }
+
+    _BOOLEAN GetPLLPhase(CReal& rPhaseOut);
+    CReal GetCurMixFreqOffs() const
+    {
+        return rNormCurMixFreqOffs * iSigSampleRate;
+    }
+
+    _BOOLEAN GetFrameBoundary() {
+        return iFreeSymbolCounter==0;
+    }
+
+
+protected:
+    void SetBPFilter(const CReal rNewBPNormBW, const CReal rNewNormFreqOffset,
+                     const EDemodType eDemodType);
+    void SetNormCurMixFreqOffs(const CReal rNewNormCurMixFreqOffs);
+
+    CComplexVector				cvecBReal;
+    CComplexVector				cvecBImag;
+    CRealVector					rvecZReal;
+    CRealVector					rvecZImag;
+    CComplexVector				cvecBAMAfterDem;
+    CRealVector					rvecZAMAfterDem;
+
+    CRealVector					rvecInpTmp;
+    CComplexVector				cvecHilbert;
+    int							iHilFiltBlLen;
+    CFftPlans					FftPlansHilFilt;
+
+    CReal						rBPNormBW;
+    CReal						rNormCurMixFreqOffs;
+    CReal						rBPNormCentOffsTot;
+
+    CRealVector					rvecZAM;
+    CRealVector					rvecADC;
+    CRealVector					rvecBDC;
+    CRealVector					rvecZFM;
+    CRealVector					rvecAFM;
+    CRealVector					rvecBFM;
+
+    int							iSymbolBlockSize;
+
+    _BOOLEAN					bPLLIsEnabled;
+    _BOOLEAN					bAutoFreqAcquIsEnabled;
+
+    EDemodType					eDemodType;
+
+    CComplex					cOldVal;
+
+    CVector<_REAL>				vecTempResBufIn;
+    CVector<_REAL>				vecTempResBufOut;
+
+    ENoiRedType					eNoiRedType;
+    int							iNoiRedLevel;
+
+    /* Objects */
+    CPLL						PLL;
+    CMixer						Mixer;
+    CFreqOffsAcq				FreqOffsAcq;
+    CAGC						AGC;
+    CNoiseReduction				NoiseReduction;
+    CAudioResample				ResampleObj;
+
+    /* OPH: counter to count symbols within a frame in order to generate */
+    /* RSCI output */
+    int							iFreeSymbolCounter;
+    int							iAudSampleRate;
+    int							iSigSampleRate;
+    int							iBandwidth;
+    int							iResOutBlockSize;
+
+
+    virtual void InitInternal(CParameter& Parameters);
+    virtual void ProcessDataInternal(CParameter& Parameters);
+};
+
+
+#endif // !defined(AMDEMOD_H__3B0BEVJBN8LKH2934BGF4344_BB27912__INCLUDED_)
diff --git a/src/AMSSDemodulation.cpp b/src/AMSSDemodulation.cpp
new file mode 100644
index 0000000..020d9db
--- /dev/null
+++ b/src/AMSSDemodulation.cpp
@@ -0,0 +1,1007 @@
+/******************************************************************************\
+ * BBC Research & Development
+ * Copyright (c) 2005
+ *
+ * Author(s):
+ *	Andrew Murphy
+ *
+ * Description:
+ *	Implementation of an AMSS demodulator
+ *
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "AMDemodulation.h"
+#include "AMSSDemodulation.h"
+
+#include <fstream>
+using namespace std;
+
+/* Implementation *************************************************************/
+void CAMSSPhaseDemod::ProcessDataInternal(CParameter&)
+{
+    int i;
+
+    /* Frequency offset estimation */
+    if (FreqOffsAcq.Run(*pvecInputData))
+        SetNormCurMixFreqOffs(FreqOffsAcq.GetCurResult());
+
+    /* Band-pass filter and mixer ------------------------------------------- */
+    /* Copy CVector data in CMatlibVector */
+    for (i = 0; i < iInputBlockSize; i++)
+        rvecInpTmp[i] = (*pvecInputData)[i];
+
+    /* Cut out a spectrum part of desired bandwidth */
+    cvecHilbert = CComplexVector(
+                      FftFilt(cvecBReal, rvecInpTmp, rvecZReal, FftPlansHilFilt),
+                      FftFilt(cvecBImag, rvecInpTmp, rvecZImag, FftPlansHilFilt));
+
+    // in AM demod there's a mixer here - this is included in PLL that follows
+    /* Track carrier using freq-locked loop */
+    AMSSPLL.Process(cvecHilbert, rvecPhase);
+
+    //Apply low-pass filter
+    rvecPhase = Filter(rvecB, rvecA, rvecPhase, rvecZPhase);
+
+    for (i=0; i < iInputBlockSize; i++)
+    {
+        (*pvecOutputData)[i] = rvecPhase[i];
+    }
+
+
+    iOutputBlockSize = iInputBlockSize;
+}
+
+void CAMSSPhaseDemod::InitInternal(CParameter& Parameters)
+{
+    /* Get parameters from info class */
+    Parameters.Lock();
+    iSymbolBlockSize = Parameters.CellMappingTable.iSymbolBlockSize;
+    rBPNormBW = CReal(AMSS_IF_FILTER_BW) / Parameters.GetSigSampleRate();
+    Parameters.Unlock();
+
+    /* Define block-sizes for input and output */
+    /* The output buffer is a cyclic buffer, we have to specify the total
+       buffer size */
+    iInputBlockSize = iSymbolBlockSize;
+
+    iMaxOutputBlockSize = iInputBlockSize;
+    iOutputBlockSize = iMaxOutputBlockSize;
+
+    /* Init temporary vector for filter input and output */
+    rvecInpTmp.Init(iSymbolBlockSize);
+    rvecPhase.Init(iSymbolBlockSize);
+    cvecHilbert.Init(iSymbolBlockSize);
+
+    /* Init frequency offset acquisition (start new acquisition) */
+    FreqOffsAcq.Init(iSymbolBlockSize);
+    FreqOffsAcq.Start((CReal) 0.0); /* Search entire bandwidth */
+
+    /* Init loop filter (low-pass filter design) */
+    /* andrewm - changed so gain _not_ negative */
+    /* IIR filter: H(Z) = ((1 - lam) * z^{-1}) / (1 - lam * z^{-1}) */
+    rvecZPhase.Init(2, (CReal) 0.0); /* Memory */
+    rvecB.Init(2);
+    rvecA.Init(2);
+    rvecB[0] = (CReal) 0.0;
+    rvecB[1] = ((CReal) 1.0 - AMSS_FILTER_LAMBDA);
+    rvecA[0] = (CReal) 1.0;
+    rvecA[1] = -AMSS_FILTER_LAMBDA;
+
+    /* Init PLL */
+    AMSSPLL.Init(iSymbolBlockSize);
+
+    /* Inits for Hilbert and DC filter -------------------------------------- */
+    /* Hilbert filter block length is the same as input block length */
+    iHilFiltBlLen = iSymbolBlockSize;
+
+
+    /* Init state vector for filtering with zeros */
+    rvecZReal.Init(iHilFiltBlLen, (CReal) 0.0);
+    rvecZImag.Init(iHilFiltBlLen, (CReal) 0.0);
+
+    /* "+ 1" because of the Nyquist frequency (filter in frequency domain) */
+    cvecBReal.Init(iHilFiltBlLen + 1);
+    cvecBImag.Init(iHilFiltBlLen + 1);
+
+    /* FFT plans are initialized with the long length */
+    FftPlansHilFilt.Init(iHilFiltBlLen * 2);
+
+    /* Init band-pass filter */
+    SetNormCurMixFreqOffs(rNormCurMixFreqOffs);
+}
+
+void CAMSSPhaseDemod::SetNormCurMixFreqOffs(const CReal rNewNormCurMixFreqOffs)
+{
+    rNormCurMixFreqOffs = rNewNormCurMixFreqOffs;
+
+    /* Generate filter taps */
+    SetBPFilter(rBPNormBW, rNormCurMixFreqOffs);
+
+    /* Tell the PLL object the new frequency (we do not care here if it is
+       enabled or not) */
+    AMSSPLL.SetRefNormFreq(rNormCurMixFreqOffs);
+}
+
+void CAMSSPhaseDemod::SetBPFilter(const CReal rNewBPNormBW,
+                                  const CReal rNewNormFreqOffset)
+{
+    /* Set internal parameter */
+    rBPNormBW = rNewBPNormBW;
+
+    /* Actual prototype filter design */
+    CRealVector vecrFilter(iHilFiltBlLen);
+    vecrFilter = FirLP(rBPNormBW, Nuttallwin(iHilFiltBlLen));
+
+    /* Actual band-pass filter offset is the demodulation frequency plus the
+       additional offset for the demodulation type */
+    rBPNormCentOffsTot = rNewNormFreqOffset;
+
+
+    /* Set filter coefficients ---------------------------------------------- */
+    /* Make sure that the phase in the middle of the filter is always the same
+       to avoid clicks when the filter coefficients are changed */
+    const CReal rStartPhase = (CReal) iHilFiltBlLen * crPi * rBPNormCentOffsTot;
+
+    /* Copy actual filter coefficients. It is important to initialize the
+       vectors with zeros because we also do a zero-padding */
+    CRealVector rvecBReal(2 * iHilFiltBlLen, (CReal) 0.0);
+    CRealVector rvecBImag(2 * iHilFiltBlLen, (CReal) 0.0);
+    for (int i = 0; i < iHilFiltBlLen; i++)
+    {
+        rvecBReal[i] = vecrFilter[i] *
+                       Cos((CReal) 2.0 * crPi * rBPNormCentOffsTot * i - rStartPhase);
+
+        rvecBImag[i] = vecrFilter[i] *
+                       Sin((CReal) 2.0 * crPi * rBPNormCentOffsTot * i - rStartPhase);
+    }
+
+    /* Transformation in frequency domain for fft filter */
+    cvecBReal = rfft(rvecBReal, FftPlansHilFilt);
+    cvecBImag = rfft(rvecBImag, FftPlansHilFilt);
+}
+
+_BOOLEAN CAMSSPhaseDemod::GetPLLPhase(CReal& rPhaseOut)
+{
+    _BOOLEAN bReturn;
+
+    /* Lock resources */
+    Lock();
+    {
+        /* Phase is only valid if PLL is enabled. Return status */
+        rPhaseOut = AMSSPLL.GetCurPhase();
+        bReturn = TRUE;
+    }
+    Unlock();
+
+    return bReturn;
+}
+
+
+/* Interface functions ------------------------------------------------------ */
+void CAMSSPhaseDemod::SetAcqFreq(const CReal rNewNormCenter)
+{
+    /* Lock resources */
+    Lock();
+    {
+        FreqOffsAcq.Start(rNewNormCenter);
+    }
+    Unlock();
+}
+
+/* Implementation *************************************************************/
+void CAMSSExtractBits::ProcessDataInternal(CParameter& Parameters)
+{
+    int i;
+
+    /* Decimate 4 to 1 to get 12kHz (approx) samples (AMSS is well oversampled and has already been filtered) */
+    for (i = 0; i < iInputBlockSize/4; i++)
+    {
+        rvecInpTmp[i] = (*pvecInputData)[i*4];
+    }
+
+    /* Differentiate over bi-phase bit period */
+    for (i = 0; i < iInputBlockSize/4; i++)
+    {
+        iDiffInSamplePos = iDiffStorePos;
+
+        iDiffStorePos++;
+        if (iDiffStorePos >= (AMSS_12kHz_SAMPLES_PER_BIT/2))
+            iDiffStorePos = 0;
+
+        rvecDiffStore[iDiffInSamplePos] = rvecInpTmp[i];
+
+        rvecInpTmp[i] = rvecInpTmp[i] - rvecDiffStore[iDiffStorePos];
+    }
+
+    rvecInpTmpAbs = Abs(rvecInpTmp);
+
+    RecursiveFilter.Process(rvecInpTmpAbs);
+    Parameters.Lock();
+    Parameters.rResampleOffset = AMSS_RESAMPLER_LOOP_GAIN * ( (signed) (RecursiveFilter.GetPeakPos() - (AMSS_12kHz_SAMPLES_PER_BIT/2)) );
+    Parameters.Unlock();
+
+    int iBitCount = 0;
+
+    for (i = 0; i < iInputBlockSize/4; i++)
+    {
+        if (iBitSyncSampleCount == iBitSyncSliceOffset)
+        {
+            if (rvecInpTmp[i] < 0)
+                (*pvecOutputData)[iBitCount] = TRUE;
+            else
+                (*pvecOutputData)[iBitCount] = FALSE;
+
+            iBitCount++;
+        }
+
+        if (iBitSyncSampleCount >= (AMSS_12kHz_SAMPLES_PER_BIT-1))
+        {
+            //fprintf(stderr, "pos: %d\n", m_bit_sync_slice_offset);
+            iBitSyncSliceOffset = RecursiveFilter.GetPeakPos();
+            iBitSyncSampleCount = 0;
+        }
+        else
+            iBitSyncSampleCount++;
+    }
+
+    iOutputBlockSize = iBitCount;
+}
+
+
+void CAMSSExtractBits::InitInternal(CParameter& Parameters)
+{
+    /* Get parameters from info class */
+    Parameters.Lock();
+    iSymbolBlockSize = Parameters.CellMappingTable.iSymbolBlockSize;
+    Parameters.Unlock();
+
+    /* Define block-sizes for input and output */
+    /* The output buffer is a cyclic buffer, we have to specify the total
+       buffer size */
+    iMaxOutputBlockSize = (iSymbolBlockSize/AMSS_12kHz_SAMPLES_PER_BIT) + 2;
+
+    iInputBlockSize = iSymbolBlockSize;
+    iOutputBlockSize = 0;
+
+    /* Init recursive filter */
+    RecursiveFilter.Init(iSymbolBlockSize/4);
+
+    /* Init temporary vector for filter input and output */
+    rvecInpTmp.Init(iSymbolBlockSize/4);	// stores 12kHz samples (not 48)
+    rvecInpTmpAbs.Init(iSymbolBlockSize/4);	// stores 12kHz samples (not 48)
+
+    rvecDiffStore.Init(AMSS_12kHz_SAMPLES_PER_BIT/2);
+
+}
+
+
+void CAMSSDecode::InitInternal(CParameter& Parameters)
+{
+    iInputBlockSize = 2;
+
+    iMaxOutputBlockSize = AMSS_MAX_DATA_ENTITY_GROUP_LENGTH;		// max length of SDC carried as one data entity group
+
+    bAMSSBits.Init(AMSS_BLOCK_SIZE_BITS);
+    iIntakeBufferPos = 0;
+
+    bBitsBlock1.Init(AMSS_BLOCK_SIZE_BITS);
+    bBitsBlock2.Init(AMSS_BLOCK_SIZE_BITS);
+
+    eAMSSBlockLockStatus = NO_SYNC;
+
+    bOffsetBlock1.Init(AMSS_OFFSET_SIZE_BITS);
+    bOffsetBlock1[0] = 0;
+    bOffsetBlock1[1] = 1;
+    bOffsetBlock1[2] = 0;
+    bOffsetBlock1[3] = 1;
+    bOffsetBlock1[4] = 1;
+    bOffsetBlock1[5] = 0;
+    bOffsetBlock1[6] = 1;
+    bOffsetBlock1[7] = 0;
+    bOffsetBlock1[8] = 1;
+    bOffsetBlock1[9] = 0;
+    bOffsetBlock1[10] = 1;
+
+    bOffsetBlock2.Init(AMSS_OFFSET_SIZE_BITS);
+    bOffsetBlock2[0] = 1;
+    bOffsetBlock2[1] = 0;
+    bOffsetBlock2[2] = 1;
+    bOffsetBlock2[3] = 1;
+    bOffsetBlock2[4] = 0;
+    bOffsetBlock2[5] = 1;
+    bOffsetBlock2[6] = 0;
+    bOffsetBlock2[7] = 1;
+    bOffsetBlock2[8] = 0;
+    bOffsetBlock2[9] = 1;
+    bOffsetBlock2[10] = 1;
+
+    bGP.Init(AMSS_GP_SIZE_BITS);
+    bGP[0] = 1;
+    bGP[1] = 0;
+    bGP[2] = 0;
+    bGP[3] = 1;
+    bGP[4] = 0;
+    bGP[5] = 1;
+    bGP[6] = 0;
+    bGP[7] = 0;
+    bGP[8] = 0;
+    bGP[9] = 0;
+    bGP[10] = 0;
+    bGP[11] =1;
+
+
+    bBlock1Store.Init(AMSS_BLOCK_SIZE_BITS);
+    bBlock2Store.Init(AMSS_BLOCK_SIZE_BITS);
+
+    bDataEntityGroup.Init(AMSS_MAX_DATA_ENTITY_GROUP_LENGTH, 0);
+
+    blDataEntityGroupSegmentsReceived.Init(MAX_DATA_ENTITY_GROUP_SEGMENTS, 0);
+
+    bVersionFlag = FALSE;
+
+    Parameters.Lock();
+    ResetStatus(Parameters);
+    Parameters.Unlock();
+}
+
+void CAMSSDecode::ProcessDataInternal(CParameter& Parameters)
+{
+    int i = 0;
+    int j = 0;
+    /* Copy CVector data into bits*/;
+    Parameters.Lock();
+    for (i = 0; i < iInputBlockSize; i++)
+    {
+        bAMSSBits[iIntakeBufferPos] = (*pvecInputData)[i];
+        iIntakeBufferPos++;
+
+        if (iIntakeBufferPos >= AMSS_BLOCK_SIZE_BITS)
+        {
+            DecodeBlock(bAMSSBits, Parameters);
+
+            /* Shift everything down by one bit */
+            for (j = 1; j < AMSS_BLOCK_SIZE_BITS; j++)
+                bAMSSBits[j-1] = bAMSSBits[j];
+
+            /* next bit goes on the end of the array */
+            iIntakeBufferPos = AMSS_BLOCK_SIZE_BITS-1;
+        }
+    }
+
+
+    if (iPercentageDataEntityGroupComplete >= 100)
+    {
+        for (j=0; j < iTotalDataEntityGroupSegments * DATA_ENTITY_GROUP_SEGMENT_SIZE_BITS; j++)
+            (*pvecOutputData)[j] = bDataEntityGroup[j];
+
+        Parameters.SetNumDecodedBitsSDC(iTotalDataEntityGroupSegments * DATA_ENTITY_GROUP_SEGMENT_SIZE_BITS);
+        iOutputBlockSize = iTotalDataEntityGroupSegments * DATA_ENTITY_GROUP_SEGMENT_SIZE_BITS;
+    }
+    else
+        iOutputBlockSize = 0;
+    Parameters.Unlock();
+}
+
+void CAMSSDecode::DecodeBlock1(CVector<_BINARY>& bBits, CParameter& Parameters)
+{
+    _BOOLEAN	bLocalVersionFlag;
+    int			i;
+
+    uint32_t	iServiceID;
+    int			iAMSSCarrierMode;
+    int			iLanguage;
+
+    bBits.ResetBitAccess();
+
+    /* Version flag */
+    if (bBits.Separate(1) == 0)
+        bLocalVersionFlag = FALSE;
+    else
+        bLocalVersionFlag = TRUE;
+
+    iAMSSCarrierMode = bBits.Separate(3);
+    iTotalDataEntityGroupSegments = bBits.Separate(4) + 1;
+
+    iLanguage = bBits.Separate(4);
+    iServiceID = bBits.Separate(24);
+
+    if (iServiceID != Parameters.Service[0].iServiceID)
+    {
+        Parameters.ResetServicesStreams();
+    }
+
+    Parameters.iAMSSCarrierMode = iAMSSCarrierMode;
+    Parameters.Service[0].iLanguage = iLanguage;
+    Parameters.Service[0].iServiceID = iServiceID;
+
+    if ( (bVersionFlag != bLocalVersionFlag) || blFirstEverBlock1)	// discard entire current data entity group
+    {
+        if (!blFirstEverBlock1)		// give benefit of doubt to any block 2 already received unless outside the total num we expect
+            blDataEntityGroupSegmentsReceived.Reset(0);
+        else
+        {
+            for (i=iTotalDataEntityGroupSegments; i < MAX_DATA_ENTITY_GROUP_SEGMENTS; i++)
+            {
+                blDataEntityGroupSegmentsReceived[i] = 0;
+            }
+        }
+
+        iPercentageDataEntityGroupComplete = 0;
+
+        for (i=0; i < MAX_DATA_ENTITY_GROUP_SEGMENTS; i++)
+        {
+            if (i < iTotalDataEntityGroupSegments)
+            {
+                if (blDataEntityGroupSegmentsReceived[i] == 0)
+                    cDataEntityGroupStatus[i] = '#';
+            }
+            else
+                cDataEntityGroupStatus[i] = '_';
+        }
+        cDataEntityGroupStatus[MAX_DATA_ENTITY_GROUP_SEGMENTS] = '\0';
+        bVersionFlag = bLocalVersionFlag;
+    }
+
+    if (blFirstEverBlock1)
+        blFirstEverBlock1 = FALSE;
+
+    blBlock1DataValid = TRUE;
+}
+
+void CAMSSDecode::DecodeBlock2(CVector<_BINARY>& bBits)
+{
+    int iSegmentNumber;
+    int i;
+
+    bBits.ResetBitAccess();
+    iSegmentNumber = bBits.Separate(4);
+
+    for (i=0; i < DATA_ENTITY_GROUP_SEGMENT_SIZE_BITS; i++)
+    {
+        bDataEntityGroup[i + (iSegmentNumber*DATA_ENTITY_GROUP_SEGMENT_SIZE_BITS)] = bBits[4+i];
+    }
+
+    blDataEntityGroupSegmentsReceived[iSegmentNumber] = 1;
+
+    if (cDataEntityGroupStatus[iSegmentNumber] == 'C')
+        cDataEntityGroupStatus[iSegmentNumber] = 'c';
+    else
+        cDataEntityGroupStatus[iSegmentNumber] = 'C';
+
+    int iReceivedSegments=0;
+
+    for (i=0; i < MAX_DATA_ENTITY_GROUP_SEGMENTS; i++)
+    {
+        if (blDataEntityGroupSegmentsReceived[i])
+            iReceivedSegments++;
+    }
+
+    if (iTotalDataEntityGroupSegments != 0)
+        iPercentageDataEntityGroupComplete = (int) (((float) iReceivedSegments/iTotalDataEntityGroupSegments) * 100.0);
+    else
+        iPercentageDataEntityGroupComplete = 0;
+}
+
+int CAMSSDecode::DecodeBlock(CVector<_BINARY>& bBits, CParameter& Parameters)
+{
+    int i;
+
+    //Take local copies for CRC calcuations
+    bBitsBlock1 = bBits;
+    bBitsBlock2 = bBits;
+
+    //Apply offset to both
+    ApplyOffsetWord(bBitsBlock1, bOffsetBlock1);
+    ApplyOffsetWord(bBitsBlock2, bOffsetBlock2);
+
+    _BOOLEAN bBlock1Test = CheckCRC(bBitsBlock1);
+    _BOOLEAN bBlock2Test = CheckCRC(bBitsBlock2);
+
+    if (bBlock1Test)
+        iCurrentBlock =  1;
+    else if (bBlock2Test)
+        iCurrentBlock = 2;
+
+    if (bBlock1Test || bBlock2Test)
+    {
+        //Parameters.Service[0].iServiceID++;
+        for (i=0; i < AMSS_BLOCK_SIZE_BITS; i++)
+            cCurrentBlockBits[i] = bBits[i] == 1 ? '1' : '0';
+    }
+
+    switch (eAMSSBlockLockStatus)
+    {
+    case NO_SYNC:
+        blBlock1DataValid = FALSE;
+
+        if (bBlock1Test)
+        {
+            //take a local copy for later comparison
+            bBlock1Store = bBits;
+            eAMSSBlockLockStatus = RE_SYNC;
+        }
+        if (bBlock2Test)
+        {
+            // might as well store it anyway just in case it's useful data
+            DecodeBlock2(bBits);
+            eAMSSBlockLockStatus = RE_SYNC;
+        }
+
+        iBitsSinceLastBlock1Pass = 0;
+        iBitsSinceLastBlock2Pass = 0;
+        iBlock1FailCount = 0;
+        iBlock2FailCount = 0;
+        break;
+
+    case RE_SYNC:
+        iBitsSinceLastBlock1Pass++;
+        iBitsSinceLastBlock2Pass++;
+
+        if (bBlock1Test)
+        {
+            if (iBitsSinceLastBlock1Pass >= (AMSS_BLOCK_SIZE_BITS*2))
+            {
+                //compare the bits
+                if (bBits == bBlock1Store)
+                {
+                    // definitely a reliable block 1
+                    DecodeBlock1(bBits, Parameters);
+                    eAMSSBlockLockStatus = DEF_SYNC;
+                }
+                else
+                {
+                    //take local copy of the bits
+                    bBlock1Store = bBits;
+
+                    // not really sync'ed but still possible
+                    eAMSSBlockLockStatus = RE_SYNC;
+                }
+
+                iBlock1FailCount = 0;
+            }
+            else
+            {
+                //take local copy of the bits;
+                bBlock1Store = bBits;
+
+                // might not be really sync'ed but still possible
+                eAMSSBlockLockStatus = RE_SYNC;
+            }
+
+            iBitsSinceLastBlock1Pass = 0;
+        }
+        if (bBlock2Test)
+        {
+            if (iBitsSinceLastBlock2Pass >= (AMSS_BLOCK_SIZE_BITS*2))	// probably a block 2
+            {
+                DecodeBlock2(bBits);
+                eAMSSBlockLockStatus = RE_SYNC;
+                iBlock2FailCount = 0;
+            }
+            else
+                eAMSSBlockLockStatus = RE_SYNC;		// stay put in this state
+
+            iBitsSinceLastBlock2Pass = 0;
+        }
+
+        if ((iBlock1FailCount > MAX_BLOCK_FAIL_COUNT_BEFORE_SYNC_LOSS) || (iBlock2FailCount > MAX_BLOCK_FAIL_COUNT_BEFORE_SYNC_LOSS) )
+        {
+            ResetStatus(Parameters);
+            eAMSSBlockLockStatus = NO_SYNC;
+        }
+
+        break;
+
+    case DEF_SYNC:
+        iBitsSinceLastBlock1Pass++;
+        iBitsSinceLastBlock2Pass++;
+
+        if (bBlock1Test)
+        {
+            if (iBitsSinceLastBlock1Pass >= (AMSS_BLOCK_SIZE_BITS*2))	// definitely a block 1
+            {
+                if (bBlock1Store == bBits)
+                {
+                    eAMSSBlockLockStatus = DEF_SYNC;
+                    DecodeBlock1(bBits, Parameters);
+                }
+                else
+                {
+                    // data could have changed, but get a couple just to be sure!
+                    bBlock1Store = bBits;
+                    eAMSSBlockLockStatus = DEF_SYNC_BUT_DATA_CHANGED;
+                }
+
+                iBitsSinceLastBlock1Pass = 0;
+                iBlock1FailCount = 0;
+            }
+            else
+                eAMSSBlockLockStatus = POSSIBLE_LOSS_OF_SYNC;
+        }
+        if (bBlock2Test)
+        {
+            if (iBitsSinceLastBlock2Pass >= (AMSS_BLOCK_SIZE_BITS*2))	// probably a block 2
+            {
+                DecodeBlock2(bBits);
+
+                iBitsSinceLastBlock2Pass = 0;
+                eAMSSBlockLockStatus = DEF_SYNC;
+
+                iBlock2FailCount = 0;
+            }
+            else
+                eAMSSBlockLockStatus = POSSIBLE_LOSS_OF_SYNC;
+        }
+
+        if ((iBlock1FailCount > MAX_BLOCK_FAIL_COUNT_BEFORE_SYNC_LOSS) || (iBlock2FailCount > MAX_BLOCK_FAIL_COUNT_BEFORE_SYNC_LOSS) )
+        {
+            ResetStatus(Parameters);
+            eAMSSBlockLockStatus = NO_SYNC;
+        }
+
+        break;
+
+    case DEF_SYNC_BUT_DATA_CHANGED:
+        iBitsSinceLastBlock1Pass++;
+        iBitsSinceLastBlock2Pass++;
+
+        if (bBlock1Test)
+        {
+            if (iBitsSinceLastBlock1Pass >= (AMSS_BLOCK_SIZE_BITS*2))	// definitely a block 1
+            {
+                if (bBlock1Store == bBits)		// data has definitely changed - go to def sync
+                {
+                    eAMSSBlockLockStatus = DEF_SYNC;
+                    DecodeBlock1(bBits, Parameters);
+
+                    //last block 2 was from this new data entity group so decode that.
+                    if (blStoredBlock2Valid == TRUE)
+                    {
+                        DecodeBlock2(bBlock2Store);
+                        blStoredBlock2Valid = FALSE;
+                    }
+                }
+                else
+                {
+                    // data different again, go to RE_SYNC
+                    bBlock1Store = bBits;
+                    eAMSSBlockLockStatus = RE_SYNC;
+                }
+
+                iBitsSinceLastBlock1Pass = 0;
+                iBlock1FailCount = 0;
+            }
+            else
+                eAMSSBlockLockStatus = POSSIBLE_LOSS_OF_SYNC;
+        }
+        if (bBlock2Test)
+        {
+            if (iBitsSinceLastBlock2Pass >= (AMSS_BLOCK_SIZE_BITS*2))	// probably a block 2
+            {
+                DecodeBlock2(bBits);
+
+                //also store the block 2 - may belong to next data entity group
+                blStoredBlock2Valid = TRUE;
+                bBlock2Store = bBits;
+
+                iBitsSinceLastBlock2Pass = 0;
+                eAMSSBlockLockStatus = DEF_SYNC_BUT_DATA_CHANGED;
+
+                iBlock2FailCount = 0;
+            }
+            else
+                eAMSSBlockLockStatus = POSSIBLE_LOSS_OF_SYNC;
+        }
+
+        if ((iBlock1FailCount > MAX_BLOCK_FAIL_COUNT_BEFORE_SYNC_LOSS) || (iBlock2FailCount > MAX_BLOCK_FAIL_COUNT_BEFORE_SYNC_LOSS) )
+        {
+            ResetStatus(Parameters);
+            eAMSSBlockLockStatus = NO_SYNC;
+        }
+
+        break;
+
+    case POSSIBLE_LOSS_OF_SYNC:
+        iBitsSinceLastBlock1Pass++;
+        iBitsSinceLastBlock2Pass++;
+
+        if (bBlock1Test)
+        {
+            // definitely a block 1
+            if (iBitsSinceLastBlock1Pass >= (AMSS_BLOCK_SIZE_BITS*2))
+            {
+                if (bBlock1Store == bBits)		// data has definitely changed - go to def sync
+                {
+                    eAMSSBlockLockStatus = DEF_SYNC;
+                }
+                else
+                {
+                    // data could have changed, but get a couple just to be sure!
+                    bBlock1Store = bBits;
+                    eAMSSBlockLockStatus = RE_SYNC;
+                }
+
+                iBitsSinceLastBlock1Pass = 0;
+                iBlock1FailCount = 0;
+            }
+            else if (iBlock1FailCount > 0) // Found one in an unexpected place and missed it in the expected place
+            {
+                iBlock1FailCount = 0;
+                iBitsSinceLastBlock1Pass = 0;
+                eAMSSBlockLockStatus = POSSIBLE_LOSS_OF_SYNC;
+            }
+            else
+                eAMSSBlockLockStatus = POSSIBLE_LOSS_OF_SYNC;
+        }
+
+        if (bBlock2Test)
+        {
+            if (iBitsSinceLastBlock2Pass >= (AMSS_BLOCK_SIZE_BITS*2))	// probably a block 2
+            {
+                DecodeBlock2(bBits);
+
+                iBitsSinceLastBlock2Pass = 0;
+                eAMSSBlockLockStatus = DEF_SYNC;
+
+                iBlock2FailCount = 0;
+            }
+            else if (iBlock2FailCount > 0) // Found one in an unexpected place and missed it in the expected place
+            {
+                iBlock2FailCount = 0;
+                iBitsSinceLastBlock2Pass = 0;
+                eAMSSBlockLockStatus = POSSIBLE_LOSS_OF_SYNC;
+            }
+            else
+                eAMSSBlockLockStatus = POSSIBLE_LOSS_OF_SYNC;
+        }
+
+        if ((iBlock1FailCount > MAX_BLOCK_FAIL_COUNT_BEFORE_SYNC_LOSS) || (iBlock2FailCount > MAX_BLOCK_FAIL_COUNT_BEFORE_SYNC_LOSS) )
+        {
+            ResetStatus(Parameters);
+            eAMSSBlockLockStatus = NO_SYNC;
+        }
+
+        break;
+    }
+
+    if (iBitsSinceLastBlock1Pass >= (AMSS_BLOCK_SIZE_BITS*2))
+    {
+        iBlock1FailCount++;
+        iBitsSinceLastBlock1Pass = 0;
+    }
+
+    if (iBitsSinceLastBlock2Pass >= (AMSS_BLOCK_SIZE_BITS*2))
+    {
+        iBlock2FailCount++;
+        iBitsSinceLastBlock2Pass = 0;
+    }
+
+    if (bBlock1Test)
+        return 1;
+    else if (bBlock2Test)
+        return 2;
+    else
+        return 0;
+}
+
+_BOOLEAN CAMSSDecode::CheckCRC(CVector<_BINARY>& bBits)
+{
+    int i=0;
+    int j=0;
+    for (i=0; i < ( AMSS_BLOCK_SIZE_BITS - (AMSS_GP_SIZE_BITS-1) ); i++)
+    {
+        if (bBits[i])
+            for (j=0; j < AMSS_GP_SIZE_BITS; j++)
+                bBits[i+j] ^= bGP[j];
+    }
+
+    int iCRCTrueBits=0;
+    for (i=AMSS_BLOCK_SIZE_BITS - (AMSS_GP_SIZE_BITS-1); i < AMSS_BLOCK_SIZE_BITS; i++)
+    {
+        if (bBits[i])
+            iCRCTrueBits++;
+    }
+
+    if (iCRCTrueBits == 0)
+        return TRUE;
+    else
+        return FALSE;
+}
+
+
+
+void CAMSSDecode::ApplyOffsetWord(CVector<_BINARY>& bBlockBits, CVector<_BINARY>& bOffset)
+{
+    for (unsigned short i=0; i < bOffset.Size(); i++)
+        bBlockBits[(AMSS_BLOCK_SIZE_BITS-bOffset.Size())+i] ^= bOffset[i];		// XOR with offset work
+}
+
+void CRecursiveFilter::Process(CRealVector& vecrIn)
+{
+    for (int i=0; i < iBlockSize; i++)
+    {
+        rOut = (AMSS_RECURSIVE_FILTER_GAIN*vecrIn[i]) + ( (1.0F-AMSS_RECURSIVE_FILTER_GAIN)*vecrStore[iCurPos] );
+        vecrStore[iCurPos] = rOut;
+        //vecrIn[i] = rOut;
+
+        iCurPos++;
+
+        if (iCurPos >= AMSS_12kHz_SAMPLES_PER_BIT)
+            iCurPos = 0;
+    }
+}
+
+void CRecursiveFilter::Init(const int iNewBlockSize)
+{
+    /* Set internal parameter */
+    vecrStore.Init(AMSS_12kHz_SAMPLES_PER_BIT);
+
+    iBlockSize = iNewBlockSize;
+}
+
+int CRecursiveFilter::GetPeakPos()
+{
+    rPeakVal = 0.0;
+    iPeakPos = 0;
+
+    for (int i=0; i < AMSS_12kHz_SAMPLES_PER_BIT; i++)
+    {
+        if (vecrStore[i] > rPeakVal)
+        {
+            rPeakVal = vecrStore[i];
+            iPeakPos = i;
+        }
+    }
+
+    return iPeakPos;
+}
+
+_REAL CRecursiveFilter::GetPeakVal()
+{
+    rPeakVal = 0.0;
+
+    for (int i=0; i < AMSS_12kHz_SAMPLES_PER_BIT; i++)
+    {
+        if (vecrStore[i] > rPeakVal)
+            rPeakVal = vecrStore[i];
+    }
+
+    return rPeakVal;
+}
+
+void CAMSSDecode::ResetStatus(CParameter& Parameters)
+{
+    int i;
+
+    blStoredBlock2Valid = FALSE;
+    blFirstEverBlock1 = TRUE;
+
+    iTotalDataEntityGroupSegments = 0;
+
+    iBitsSinceLastBlock1Pass = 0;
+    iBitsSinceLastBlock2Pass = 0;
+    iBlock1FailCount = 0;
+    iBlock2FailCount = 0;
+
+    blBlock1DataValid = FALSE;
+
+    iCurrentBlock = 0;
+
+    for (i=0; i < MAX_DATA_ENTITY_GROUP_SEGMENTS; i++)
+        cDataEntityGroupStatus[i] = '_';
+
+    cDataEntityGroupStatus[MAX_DATA_ENTITY_GROUP_SEGMENTS] = '\0';
+
+    for (i=0; i < AMSS_BLOCK_SIZE_BITS; i++)
+        cCurrentBlockBits[i] = ' ';
+
+    cCurrentBlockBits[AMSS_BLOCK_SIZE_BITS] = '\0';
+
+    iPercentageDataEntityGroupComplete = 0;
+
+    bDataEntityGroup.Reset(FALSE);
+    blDataEntityGroupSegmentsReceived.Reset(0);
+
+    Parameters.ResetServicesStreams();
+}
+
+
+/******************************************************************************\
+* AMSS Phase lock loop (PLL)
+\******************************************************************************/
+void CAMSSPLL::Process(CComplexVector& veccIn, CRealVector& vecrOut)
+{
+    CReal rPhaseDiff;
+
+    /* Mix it down to zero frequency */
+    cvecLow = veccIn;
+    Mixer.Process(cvecLow);
+
+    int i;
+
+    for (i=0; i < iBlockSize; i++)
+    {
+        rvecPhaseTmp[i] = Angle(CComplex(Real(cvecLow[i]), Imag(cvecLow[i])));
+    }
+
+    //check for 2PI wrapping
+    for (i=0; i < iBlockSize; i++)
+    {
+        rPhaseDiff = rvecPhaseTmp[i] - rPreviousPhaseSample;
+
+        if (rPhaseDiff >= (crPi))
+            rPhaseOffset -=(2.0*crPi);
+        else if (rPhaseDiff < (-crPi))
+            rPhaseOffset += (2.0*crPi);
+
+        rPreviousPhaseSample = rvecPhaseTmp[i];
+        rvecPhaseTmp[i] += rPhaseOffset;
+
+        vecrOut[i] = rvecPhaseTmp[i];
+    }
+
+    rvecPhaseTmp = Filter(rvecB, rvecA, rvecPhaseTmp, rvecZPhase);
+
+    /* Calculate current phase for GUI */
+    rCurPhase = Mean(rvecPhaseTmp);
+    const CReal rOffsEst = rCurPhase;
+
+    rNormCurFreqOffsetAdd = AMSS_PLL_LOOP_GAIN * rOffsEst;
+
+    /* Update mixer */
+    Mixer.SetMixFreq(rNormCurFreqOffset + rNormCurFreqOffsetAdd);
+}
+
+void CAMSSPLL::Init(const int iNewBlockSize)
+{
+    /* Set internal parameter */
+    iBlockSize = iNewBlockSize;
+
+    /* Init mixer object */
+    Mixer.Init(iBlockSize);
+
+    /* Init buffers */
+    cvecLow.Init(iBlockSize);
+    rvecPhaseTmp.Init(iBlockSize);
+
+    /* Init loop filter (low-pass filter design) */
+    /* andrewm - changed so _not_ negative gain! */
+    /* IIR filter: H(Z) = ((1 - lam) * z^{-1}) / (1 - lam * z^{-1}) */
+    rvecZPhase.Init(2, (CReal) 0.0); /* Memory */
+    rvecB.Init(2);
+    rvecA.Init(2);
+    rvecB[0] = (CReal) 0.0;
+    rvecB[1] = ((CReal) 1.0 - AMSS_PLL_LOOP_FILTER_LAMBDA);
+    rvecA[0] = (CReal) 1.0;
+    rvecA[1] = -AMSS_PLL_LOOP_FILTER_LAMBDA;
+
+    rPreviousPhaseSample = 0;
+    rPhaseOffset = 0;
+}
+
+void CAMSSPLL::SetRefNormFreq(const CReal rNewNormFreq)
+{
+    /* Store new reference frequency */
+    rNormCurFreqOffset = rNewNormFreq;
+
+    /* Reset offset and phase */
+    rNormCurFreqOffsetAdd = (CReal) 0.0;
+    rCurPhase = (CReal) 0.0;
+}
diff --git a/src/AMSSDemodulation.h b/src/AMSSDemodulation.h
new file mode 100644
index 0000000..f76ef50
--- /dev/null
+++ b/src/AMSSDemodulation.h
@@ -0,0 +1,297 @@
+/******************************************************************************\
+ * BBC Research & Development
+ * Copyright (c) 2005
+ *
+ * Author(s):
+ *	Andrew Murphy
+ *
+ * Description:
+ *	See AMSSDemodulation.cpp
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#if !defined(_AMSSDEMODULATION_H_)
+#define _AMSSDEMODULATION_H_
+
+#include "Parameter.h"
+#include "util/Modul.h"
+#include "util/Vector.h"
+#include "matlib/Matlib.h"
+#include "resample/Resample.h"
+
+#define AMSS_PLL_LOOP_GAIN						((CReal) 0.00015)
+#define AMSS_PLL_LOOP_FILTER_LAMBDA				((CReal) 0.99)
+
+#define AMSS_FILTER_LAMBDA						((CReal) 0.9876)
+
+#define AMSS_IF_FILTER_BW						((CReal) 300.0)
+
+#define AMSS_RESAMPLER_LOOP_GAIN				((CReal) 0.00001)
+#define	AMSS_RECURSIVE_FILTER_GAIN				((CReal) 0.05)
+#define	AMSS_12kHz_SAMPLES_PER_BIT				256
+#define AMSS_BLOCK_SIZE_BITS					47
+#define	AMSS_GP_SIZE_BITS						12
+#define AMSS_OFFSET_SIZE_BITS					11
+#define MAX_BLOCK_FAIL_COUNT_BEFORE_SYNC_LOSS	10
+#define	MAX_DATA_ENTITY_GROUP_SEGMENTS			16
+#define DATA_ENTITY_GROUP_SEGMENT_SIZE_BITS		32
+#define AMSS_MAX_DATA_ENTITY_GROUP_LENGTH		(MAX_DATA_ENTITY_GROUP_SEGMENTS * DATA_ENTITY_GROUP_SEGMENT_SIZE_BITS)
+
+/* Phase lock loop ---------------------------------------------------------- */
+class CAMSSPLL
+{
+public:
+    CAMSSPLL() : rCurPhase((CReal) 0.0) {}
+    void Init(const int iNewBlockSize);
+    void Process(CComplexVector& veccIn, CRealVector& vecrOut);
+
+    void SetRefNormFreq(const CReal rNewNormFreq);
+    CReal GetCurPhase() const {
+        return rCurPhase;
+    }
+    CReal GetCurNormFreqOffs() const
+    {
+        return rNormCurFreqOffset + rNormCurFreqOffsetAdd;
+    }
+
+protected:
+    CMixer			Mixer;
+    int				iBlockSize;
+    CRealVector		rvecPhaseTmp;
+    CComplexVector	cvecLow;
+    CReal			rNormCurFreqOffset;
+    CReal			rNormCurFreqOffsetAdd;
+    CReal			rCurPhase;
+
+    CRealVector		rvecZPhase;
+    CRealVector		rvecA;
+    CRealVector		rvecB;
+
+    CReal rPreviousPhaseSample;
+    CReal rPhaseOffset;
+};
+
+/* Recursive filter  -------------------------------------------------------------------- */
+class CRecursiveFilter
+{
+public:
+    CRecursiveFilter() {
+        iPeakPos = 0;
+        iCurPos = 0;
+    }
+    ~CRecursiveFilter() {}
+    void Init(const int iNewBlockSize);
+    void Process(CRealVector& vecrIn /* in/out */);
+
+    int GetPeakPos();
+    _REAL GetPeakVal();
+
+
+protected:
+    int				iBlockSize;
+    CRealVector		vecrStore;
+
+    CReal			rOut;
+    CReal			rPeakVal;
+    int				iPeakPos;
+    int				iCurPos;
+
+};
+
+
+/* AMSS phase demodulation module --------------------------------------------------- */
+class CAMSSPhaseDemod : public CReceiverModul<_REAL, _REAL>
+{
+public:
+    CAMSSPhaseDemod() :
+        rBPNormBW((CReal) 0.0), rNormCurMixFreqOffs((CReal) 0.0),
+        rPreviousPhaseSample((CReal) 0.0), rPhaseOffset((CReal) 0.0) {}
+    virtual ~CAMSSPhaseDemod() {}
+
+    void SetAcqFreq(const CReal rNewNormCenter);
+    _BOOLEAN GetPLLPhase(CReal& rPhaseOut);
+
+protected:
+    virtual void InitInternal(CParameter& Parameters);
+    virtual void ProcessDataInternal(CParameter& Parameters);
+
+    int			iSymbolBlockSize;
+
+    void SetBPFilter(const CReal rNewBPNormBW, const CReal rNewNormFreqOffset);
+    void SetNormCurMixFreqOffs(const CReal rNewNormCurMixFreqOffs);
+
+    CComplexVector				cvecBReal;
+    CComplexVector				cvecBImag;
+    CRealVector					rvecZReal;
+    CRealVector					rvecZImag;
+
+    CRealVector					rvecInpTmp;
+    CRealVector					rvecPhase;
+    CComplexVector				cvecHilbert;
+    int							iHilFiltBlLen;
+    CFftPlans					FftPlansHilFilt;
+
+    CReal						rBPNormBW;
+    CReal						rNormCurMixFreqOffs;
+    CReal						rBPNormCentOffsTot;
+
+    CReal						rPreviousPhaseSample;
+    CReal						rPhaseOffset;
+    CReal						rPhaseDiff;
+
+
+    CRealVector		rvecZPhase;
+    CRealVector		rvecA;
+    CRealVector		rvecB;
+
+    /* Objects */
+    CAMSSPLL					AMSSPLL;
+    CFreqOffsAcq				FreqOffsAcq;
+    //CAGC						AGC;
+};
+
+
+/* AMSS decoding module --------------------------------------------------- */
+class CAMSSExtractBits : public CReceiverModul<_REAL, _BINARY>
+{
+public:
+    CAMSSExtractBits()
+    {
+        iDiffStorePos = 0;
+        iDiffInSamplePos = 0;
+        iBitSyncSampleCount = 0;
+        iBitSyncSliceOffset = 0;
+    }
+    virtual ~CAMSSExtractBits() { }
+protected:
+    virtual void InitInternal(CParameter& Parameters);
+    virtual void ProcessDataInternal(CParameter& Parameters);
+
+    int					iSymbolBlockSize;
+
+    CRealVector			rvecDiffStore;
+    int					iDiffStorePos;
+    int					iDiffInSamplePos;
+
+    CRealVector			rvecInpTmp;
+    CRealVector			rvecInpTmpAbs;
+
+    int					iBitSyncSampleCount;
+    int					iBitSyncSliceOffset;
+
+    /* Objects */
+    CRecursiveFilter	RecursiveFilter;
+};
+
+
+/* AMSS decoding module --------------------------------------------------- */
+class CAMSSDecode : public CReceiverModul<_BINARY, _BINARY>
+{
+public:
+    CAMSSDecode()
+    {
+        cDataEntityGroupStatus = new char[MAX_DATA_ENTITY_GROUP_SEGMENTS+1];
+        cCurrentBlockBits = new char[AMSS_BLOCK_SIZE_BITS+1];
+    }
+
+    virtual ~CAMSSDecode()
+    {
+        delete[] cDataEntityGroupStatus;
+        delete[] cCurrentBlockBits;
+    }
+
+    /* AMSS status */
+    enum EAMSSBlockLockStat { NO_SYNC, RE_SYNC, DEF_SYNC, DEF_SYNC_BUT_DATA_CHANGED, POSSIBLE_LOSS_OF_SYNC };
+
+
+    EAMSSBlockLockStat GetLockStatus() const {
+        return eAMSSBlockLockStatus;
+    }
+    int GetPercentageDataEntityGroupComplete() const
+    {
+        return iPercentageDataEntityGroupComplete;
+    }
+    char* GetDataEntityGroupStatus() const {
+        return cDataEntityGroupStatus;
+    }
+    int GetCurrentBlock() const {
+        return iCurrentBlock;
+    }
+    char* GetCurrentBlockBits() const {
+        return cCurrentBlockBits;
+    }
+
+    _BOOLEAN GetBlock1Status() const {
+        return blBlock1DataValid;
+    }
+
+protected:
+    virtual void InitInternal(CParameter& Parameters);
+    virtual void ProcessDataInternal(CParameter& Parameters);
+
+    EAMSSBlockLockStat	eAMSSBlockLockStatus;
+
+    int				iPercentageDataEntityGroupComplete;
+    char*			cDataEntityGroupStatus;
+    int				iCurrentBlock;
+    char*			cCurrentBlockBits;
+
+    int				iTotalDataEntityGroupSegments;
+    CVector<int>	blDataEntityGroupSegmentsReceived;
+
+    int				DecodeBlock(CVector<_BINARY>& bBits, CParameter& Parameters);
+    void			DecodeBlock1(CVector<_BINARY>& bBits, CParameter& Parameters);
+    void			DecodeBlock2(CVector<_BINARY>& bBits);
+
+    void			ApplyOffsetWord(CVector<_BINARY>& bBlockBits, CVector<_BINARY>& offset);
+    _BOOLEAN		CheckCRC(CVector<_BINARY>& bBits);
+
+    void			ResetStatus(CParameter& ReveiverParam);
+
+    CVector<_BINARY>	bAMSSBits;
+    int					iIntakeBufferPos;
+
+    CVector<_BINARY>	bBitsBlock1;
+    CVector<_BINARY>	bBitsBlock2;
+
+    CVector<_BINARY>	bOffsetBlock1;
+    CVector<_BINARY>	bOffsetBlock2;
+
+    CVector<_BINARY>	bGP;
+
+    CVector<_BINARY>	bBlock1Store;
+    CVector<_BINARY>	bBlock2Store;
+
+    _BOOLEAN			blStoredBlock2Valid;
+    _BOOLEAN			bVersionFlag;
+
+    _BOOLEAN			blFirstEverBlock1;
+
+    CVector<_BINARY>	bDataEntityGroup;
+
+    int					iBitsSinceLastBlock1Pass;
+    int					iBitsSinceLastBlock2Pass;
+    int					iBlock1FailCount;
+    int					iBlock2FailCount;
+
+    _BOOLEAN			blBlock1DataValid;
+};
+
+
+#endif // !defined(_AMSSDEMODULATION_H_)
diff --git a/src/DRMSignalIO.cpp b/src/DRMSignalIO.cpp
new file mode 100644
index 0000000..5d63cba
--- /dev/null
+++ b/src/DRMSignalIO.cpp
@@ -0,0 +1,1069 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer, Cesco (HB9TLK)
+ *
+ * Description:
+ *	Transmit and receive data
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "DRMSignalIO.h"
+#include "UpsampleFilter.h"
+#include <iostream>
+
+
+const static int SineTable[] = { 0, 1, 0, -1, 0 };
+
+
+/* Implementation *************************************************************/
+/******************************************************************************\
+* Transmitter                                                                  *
+\******************************************************************************/
+void CTransmitData::ProcessDataInternal(CParameter&)
+{
+    int i;
+
+    /* Apply bandpass filter */
+    BPFilter.Process(*pvecInputData);
+
+    /* Convert vector type. Fill vector with symbols (collect them) */
+    const int iNs2 = iInputBlockSize * 2;
+    for (i = 0; i < iNs2; i += 2)
+    {
+        const int iCurIndex = iBlockCnt * iNs2 + i;
+        _COMPLEX cInputData = (*pvecInputData)[i / 2];
+
+        if (bHighQualityIQ && eOutputFormat != OF_REAL_VAL)
+            HilbertFilt(cInputData);
+
+        /* Imaginary, real */
+        const _SAMPLE sCurOutReal =
+            Real2Sample(cInputData.real() * rNormFactor);
+        const _SAMPLE sCurOutImag =
+            Real2Sample(cInputData.imag() * rNormFactor);
+
+        /* Envelope, phase */
+        const _SAMPLE sCurOutEnv = 
+            Real2Sample(Abs(cInputData) * (_REAL) 256.0);
+        const _SAMPLE sCurOutPhase = /* 2^15 / pi / 2 -> approx. 5000 */
+            Real2Sample(Angle(cInputData) * (_REAL) 5000.0);
+
+        switch (eOutputFormat)
+        {
+        case OF_REAL_VAL:
+            /* Use real valued signal as output for both sound card channels */
+            vecsDataOut[iCurIndex] = vecsDataOut[iCurIndex + 1] = sCurOutReal;
+            break;
+
+        case OF_IQ_POS:
+            /* Send inphase and quadrature (I / Q) signal to stereo sound card
+               output. I: left channel, Q: right channel */
+            vecsDataOut[iCurIndex] = sCurOutReal;
+            vecsDataOut[iCurIndex + 1] = sCurOutImag;
+            break;
+
+        case OF_IQ_NEG:
+            /* Send inphase and quadrature (I / Q) signal to stereo sound card
+               output. I: right channel, Q: left channel */
+            vecsDataOut[iCurIndex] = sCurOutImag;
+            vecsDataOut[iCurIndex + 1] = sCurOutReal;
+            break;
+
+        case OF_EP:
+            /* Send envelope and phase signal to stereo sound card
+               output. Envelope: left channel, Phase: right channel */
+            vecsDataOut[iCurIndex] = sCurOutEnv;
+            vecsDataOut[iCurIndex + 1] = sCurOutPhase;
+            break;
+        }
+    }
+
+    iBlockCnt++;
+    if (iBlockCnt == iNumBlocks)
+        FlushData();
+}
+
+void CTransmitData::FlushData()
+{
+    int i;
+
+    /* Zero the remain of the buffer, if incomplete */
+    if (iBlockCnt != iNumBlocks)
+    {
+        const int iSize = vecsDataOut.Size();
+        const int iStart = iSize * iBlockCnt / iNumBlocks;
+        for (i = iStart; i < iSize; i++)
+            vecsDataOut[i] = 0;
+    }
+
+    iBlockCnt = 0;
+
+    if (bUseSoundcard == TRUE)
+    {
+        /* Write data to sound card. Must be a blocking function */
+        pSound->Write(vecsDataOut);
+    }
+    else
+    {
+        /* Write data to file */
+        for (i = 0; i < iBigBlockSize; i++)
+        {
+#ifdef FILE_DRM_USING_RAW_DATA
+            const short sOut = vecsDataOut[i];
+
+            /* Write 2 bytes, 1 piece */
+            fwrite((const void*) &sOut, size_t(2), size_t(1),
+                   pFileTransmitter);
+#else
+            /* This can be read with Matlab "load" command */
+            fprintf(pFileTransmitter, "%d\n", vecsDataOut[i]);
+#endif
+        }
+
+        /* Flush the file buffer */
+        fflush(pFileTransmitter);
+    }
+}
+
+void CTransmitData::InitInternal(CParameter& Parameters)
+{
+    /*
+    	float*	pCurFilt;
+    	int		iNumTapsTransmFilt;
+    	CReal	rNormCurFreqOffset;
+    */
+    /* Get signal sample rate */
+    const int iSampleRate = Parameters.GetSigSampleRate();
+    /* Define symbol block-size */
+    const int iSymbolBlockSize = Parameters.CellMappingTable.iSymbolBlockSize;
+
+    /* Init vector for storing a complete DRM frame number of OFDM symbols */
+    iBlockCnt = 0;
+    Parameters.Lock();
+    iNumBlocks = Parameters.CellMappingTable.iNumSymPerFrame;
+    ESpecOcc eSpecOcc = Parameters.GetSpectrumOccup();
+    Parameters.Unlock();
+    iBigBlockSize = iSymbolBlockSize * 2 /* Stereo */ * iNumBlocks;
+
+    /* Init I/Q history */
+    vecrReHist.Init(NUM_TAPS_IQ_INPUT_FILT_HQ, (_REAL) 0.0);
+
+    vecsDataOut.Init(iBigBlockSize);
+
+    if (pFileTransmitter != NULL)
+    {
+        fclose(pFileTransmitter);
+    }
+
+    if (bUseSoundcard == TRUE)
+    {
+        /* Init sound interface */
+        pSound->Init(iSampleRate, iBigBlockSize, TRUE);
+    }
+    else
+    {
+
+        /* Open file for writing data for transmitting */
+#ifdef FILE_DRM_USING_RAW_DATA
+        pFileTransmitter = fopen(strOutFileName.c_str(), "wb");
+#else
+        pFileTransmitter = fopen(strOutFileName.c_str(), "w");
+#endif
+
+        /* Check for error */
+        if (pFileTransmitter == NULL)
+            throw CGenErr("The file " + strOutFileName + " cannot be created.");
+    }
+
+
+    /* Init bandpass filter object */
+    BPFilter.Init(iSampleRate, iSymbolBlockSize, rDefCarOffset, eSpecOcc, CDRMBandpassFilt::FT_TRANSMITTER);
+
+    /* All robustness modes and spectrum occupancies should have the same output
+       power. Calculate the normaization factor based on the average power of
+       symbol (the number 3000 was obtained through output tests) */
+    rNormFactor = (CReal) 3000.0 / Sqrt(Parameters.CellMappingTable.rAvPowPerSymbol);
+
+    /* Apply amplification factor, 4.0 = +12dB
+       (the maximum without clipping, obtained through output tests) */
+    rNormFactor *= bAmplified ? 4.0 : 1.0;
+
+    /* Define block-size for input */
+    iInputBlockSize = iSymbolBlockSize;
+}
+
+CTransmitData::~CTransmitData()
+{
+    /* Close file */
+    if (pFileTransmitter != NULL)
+        fclose(pFileTransmitter);
+}
+
+void CTransmitData::HilbertFilt(_COMPLEX& vecData)
+{
+    int i;
+
+    /* Move old data */
+    for (i = 0; i < NUM_TAPS_IQ_INPUT_FILT_HQ - 1; i++)
+        vecrReHist[i] = vecrReHist[i + 1];
+
+    vecrReHist[NUM_TAPS_IQ_INPUT_FILT_HQ - 1] = vecData.real();
+
+    /* Filter */
+    _REAL rSum = (_REAL) 0.0;
+    for (i = 1; i < NUM_TAPS_IQ_INPUT_FILT_HQ; i += 2)
+        rSum += fHilFiltIQ_HQ[i] * vecrReHist[i];
+
+    vecData = _COMPLEX(vecrReHist[IQ_INP_HIL_FILT_DELAY_HQ], -rSum);
+}
+
+
+/******************************************************************************\
+* Receive data from the sound card                                             *
+\******************************************************************************/
+
+//inline _REAL sample2real(_SAMPLE s) { return _REAL(s)/32768.0; }
+inline _REAL sample2real(_SAMPLE s) { return _REAL(s); }
+
+void CReceiveData::ProcessDataInternal(CParameter& Parameters)
+{
+    int i;
+
+    /* OPH: update free-running symbol counter */
+    Parameters.Lock();
+
+    iFreeSymbolCounter++;
+    if (iFreeSymbolCounter >= Parameters.CellMappingTable.iNumSymPerFrame * 2) /* x2 because iOutputBlockSize=iSymbolBlockSize/2 */
+    {
+        iFreeSymbolCounter = 0;
+        /* calculate the PSD once per frame for the RSI output */
+
+        if (Parameters.bMeasurePSD)
+            PutPSD(Parameters);
+
+    }
+    Parameters.Unlock();
+
+
+    /* Get data from sound interface. The read function must be a
+       blocking function! */
+    bool bBad = true;
+    bool bError = false;
+    if (pSound)
+        bBad = pSound->Read(vecsSoundBuffer);
+    else
+        bError = true;
+    Parameters.Lock();
+    Parameters.ReceiveStatus.InterfaceI.SetStatus(bBad || bError ? CRC_ERROR : RX_OK); /* Red light */
+    Parameters.Unlock();
+    if (bError)
+        return;
+
+    /* Upscale if ratio greater than one */
+    if (iUpscaleRatio > 1)
+    {
+        /* The actual upscaling, currently only 2X is supported */
+        InterpFIR_2X(2, &vecsSoundBuffer[0], vecf_ZL, vecf_YL, vecf_B);
+        InterpFIR_2X(2, &vecsSoundBuffer[1], vecf_ZR, vecf_YR, vecf_B);
+
+        /* Write data to output buffer. Do not set the switch command inside
+           the for-loop for efficiency reasons */
+        switch (eInChanSelection)
+        {
+        case CS_LEFT_CHAN:
+            for (i = 0; i < iOutputBlockSize; i++)
+                (*pvecOutputData)[i] = vecf_YL[i];
+            break;
+
+        case CS_RIGHT_CHAN:
+            for (i = 0; i < iOutputBlockSize; i++)
+                (*pvecOutputData)[i] = vecf_YR[i];
+            break;
+
+        case CS_MIX_CHAN:
+            for (i = 0; i < iOutputBlockSize; i++)
+            {
+                /* Mix left and right channel together */
+                (*pvecOutputData)[i] = (vecf_YL[i] + vecf_YR[i]) / 2;
+            }
+            break;
+
+        case CS_SUB_CHAN:
+            for (i = 0; i < iOutputBlockSize; i++)
+            {
+                /* Subtract right channel from left */
+                (*pvecOutputData)[i] = (vecf_YL[i] - vecf_YR[i]) / 2;
+            }
+            break;
+
+            /* I / Q input */
+        case CS_IQ_POS:
+            for (i = 0; i < iOutputBlockSize; i++)
+            {
+                (*pvecOutputData)[i] =
+                    HilbertFilt(vecf_YL[i], vecf_YR[i]);
+            }
+            break;
+
+        case CS_IQ_NEG:
+            for (i = 0; i < iOutputBlockSize; i++)
+            {
+                (*pvecOutputData)[i] =
+                    HilbertFilt(vecf_YR[i], vecf_YL[i]);
+            }
+            break;
+
+        case CS_IQ_POS_ZERO:
+            for (i = 0; i < iOutputBlockSize; i++)
+            {
+                /* Shift signal to vitual intermediate frequency before applying
+                   the Hilbert filtering */
+                _COMPLEX cCurSig = _COMPLEX(vecf_YL[i], vecf_YR[i]);
+
+                cCurSig *= cCurExp;
+
+                /* Rotate exp-pointer on step further by complex multiplication
+                   with precalculated rotation vector cExpStep */
+                cCurExp *= cExpStep;
+
+                (*pvecOutputData)[i] =
+                    HilbertFilt(cCurSig.real(), cCurSig.imag());
+            }
+            break;
+
+        case CS_IQ_NEG_ZERO:
+            for (i = 0; i < iOutputBlockSize; i++)
+            {
+                /* Shift signal to vitual intermediate frequency before applying
+                   the Hilbert filtering */
+                _COMPLEX cCurSig = _COMPLEX(vecf_YR[i], vecf_YL[i]);
+
+                cCurSig *= cCurExp;
+
+                /* Rotate exp-pointer on step further by complex multiplication
+                   with precalculated rotation vector cExpStep */
+                cCurExp *= cExpStep;
+
+                (*pvecOutputData)[i] =
+                    HilbertFilt(cCurSig.real(), cCurSig.imag());
+            }
+            break;
+
+        case CS_IQ_POS_SPLIT:
+            for (i = 0; i < iOutputBlockSize; i += 4)
+            {
+                (*pvecOutputData)[i + 0] =  vecf_YL[i + 0];
+                (*pvecOutputData)[i + 1] = -vecf_YR[i + 1];
+                (*pvecOutputData)[i + 2] = -vecf_YL[i + 2];
+                (*pvecOutputData)[i + 3] =  vecf_YR[i + 3];
+            }
+            break;
+
+        case CS_IQ_NEG_SPLIT:
+            for (i = 0; i < iOutputBlockSize; i += 4)
+            {
+                (*pvecOutputData)[i + 0] =  vecf_YR[i + 0];
+                (*pvecOutputData)[i + 1] = -vecf_YL[i + 1];
+                (*pvecOutputData)[i + 2] = -vecf_YR[i + 2];
+                (*pvecOutputData)[i + 3] =  vecf_YL[i + 3];
+            }
+            break;
+        }
+    }
+
+    /* Upscale ratio equal to one */
+	else {
+    /* Write data to output buffer. Do not set the switch command inside
+       the for-loop for efficiency reasons */
+        switch (eInChanSelection)
+        {
+        case CS_LEFT_CHAN:
+            for (i = 0; i < iOutputBlockSize; i++)
+                (*pvecOutputData)[i] = sample2real(vecsSoundBuffer[2 * i]);
+            break;
+
+        case CS_RIGHT_CHAN:
+            for (i = 0; i < iOutputBlockSize; i++)
+                (*pvecOutputData)[i] = sample2real(vecsSoundBuffer[2 * i + 1]);
+            break;
+
+        case CS_MIX_CHAN:
+            for (i = 0; i < iOutputBlockSize; i++)
+            {
+                /* Mix left and right channel together */
+                const _REAL rLeftChan = sample2real(vecsSoundBuffer[2 * i]);
+                const _REAL rRightChan = sample2real(vecsSoundBuffer[2 * i + 1]);
+                (*pvecOutputData)[i] = (rLeftChan + rRightChan) / 2;
+            }
+            break;
+
+        case CS_SUB_CHAN:
+            for (i = 0; i < iOutputBlockSize; i++)
+            {
+                /* Subtract right channel from left */
+                const _REAL rLeftChan = sample2real(vecsSoundBuffer[2 * i]);
+                const _REAL rRightChan = sample2real(vecsSoundBuffer[2 * i + 1]);
+                (*pvecOutputData)[i] = (rLeftChan - rRightChan) / 2;
+            }
+            break;
+
+            /* I / Q input */
+        case CS_IQ_POS:
+            for (i = 0; i < iOutputBlockSize; i++)
+            {
+                (*pvecOutputData)[i] =
+                    HilbertFilt(sample2real(vecsSoundBuffer[2 * i]),
+                                sample2real(vecsSoundBuffer[2 * i + 1]));
+            }
+            break;
+
+        case CS_IQ_NEG:
+            for (i = 0; i < iOutputBlockSize; i++)
+            {
+                (*pvecOutputData)[i] =
+                    HilbertFilt(sample2real(vecsSoundBuffer[2 * i + 1]),
+                                sample2real(vecsSoundBuffer[2 * i]));
+            }
+            break;
+
+        case CS_IQ_POS_ZERO:
+            for (i = 0; i < iOutputBlockSize; i++)
+            {
+                /* Shift signal to vitual intermediate frequency before applying
+                   the Hilbert filtering */
+                _COMPLEX cCurSig = _COMPLEX(sample2real(vecsSoundBuffer[2 * i]),
+                                            sample2real(vecsSoundBuffer[2 * i + 1]));
+
+                cCurSig *= cCurExp;
+
+                /* Rotate exp-pointer on step further by complex multiplication
+                   with precalculated rotation vector cExpStep */
+                cCurExp *= cExpStep;
+
+                (*pvecOutputData)[i] =
+                    HilbertFilt(cCurSig.real(), cCurSig.imag());
+            }
+            break;
+
+        case CS_IQ_NEG_ZERO:
+            for (i = 0; i < iOutputBlockSize; i++)
+            {
+                /* Shift signal to vitual intermediate frequency before applying
+                   the Hilbert filtering */
+                _COMPLEX cCurSig = _COMPLEX(sample2real(vecsSoundBuffer[2 * i + 1]),
+                                            sample2real(vecsSoundBuffer[2 * i]));
+
+                cCurSig *= cCurExp;
+
+                /* Rotate exp-pointer on step further by complex multiplication
+                   with precalculated rotation vector cExpStep */
+                cCurExp *= cExpStep;
+
+                (*pvecOutputData)[i] =
+                    HilbertFilt(cCurSig.real(), cCurSig.imag());
+            }
+            break;
+
+        case CS_IQ_POS_SPLIT: /* Require twice the bandwidth */
+            for (i = 0; i < iOutputBlockSize; i++)
+            {
+                iPhase = (iPhase + 1) & 3;
+                _REAL rValue = vecsSoundBuffer[2 * i]     * /*COS*/SineTable[iPhase + 1] -
+                               vecsSoundBuffer[2 * i + 1] * /*SIN*/SineTable[iPhase];
+                (*pvecOutputData)[i] = sample2real(rValue);
+            }
+            break;
+
+        case CS_IQ_NEG_SPLIT: /* Require twice the bandwidth */
+            for (i = 0; i < iOutputBlockSize; i++)
+            {
+                iPhase = (iPhase + 1) & 3;
+                _REAL rValue = vecsSoundBuffer[2 * i + 1] * /*COS*/SineTable[iPhase + 1] -
+                               vecsSoundBuffer[2 * i]     * /*SIN*/SineTable[iPhase];
+                (*pvecOutputData)[i] = sample2real(rValue);
+            }
+            break;
+        }
+	}
+
+    /* Flip spectrum if necessary ------------------------------------------- */
+    if (bFippedSpectrum == TRUE)
+    {
+        /* Since iOutputBlockSize is always even we can do some opt. here */
+        for (i = 0; i < iOutputBlockSize; i+=2)
+        {
+            /* We flip the spectrum by using the mirror spectrum at the negative
+               frequencys. If we shift by half of the sample frequency, we can
+               do the shift without the need of a Hilbert transformation */
+            (*pvecOutputData)[i] = -(*pvecOutputData)[i];
+        }
+    }
+
+    /* Copy data in buffer for spectrum calculation */
+    mutexInpData.Lock();
+    vecrInpData.AddEnd((*pvecOutputData), iOutputBlockSize);
+    mutexInpData.Unlock();
+
+    /* Update level meter */
+    SignalLevelMeter.Update((*pvecOutputData));
+    Parameters.Lock();
+    Parameters.SetIFSignalLevel(SignalLevelMeter.Level());
+    Parameters.Unlock();
+
+}
+
+void CReceiveData::InitInternal(CParameter& Parameters)
+{
+    /* Init sound interface. Set it to one symbol. The sound card interface
+    	   has to taken care about the buffering data of a whole MSC block.
+    	   Use stereo input (* 2) */
+
+    if (pSound == NULL)
+        return;
+
+    Parameters.Lock();
+    /* We define iOutputBlockSize as half the iSymbolBlockSize because
+       if a positive frequency offset is present in drm signal,
+       after some time a buffer overflow occur in the output buffer of
+       InputResample.ProcessData() */
+    /* Define output block-size */
+    iOutputBlockSize = Parameters.CellMappingTable.iSymbolBlockSize / 2;
+    iMaxOutputBlockSize = iOutputBlockSize * 2;
+    /* Get signal sample rate */
+    iSampleRate = Parameters.GetSigSampleRate();
+    iUpscaleRatio = Parameters.GetSigUpscaleRatio();
+    Parameters.Unlock();
+
+    const int iOutputBlockAlignment = iOutputBlockSize & 3;
+    if (iOutputBlockAlignment)
+        fprintf(stderr, "CReceiveData::InitInternal(): iOutputBlockAlignment = %i\n", iOutputBlockAlignment);
+
+	try {
+		const _BOOLEAN bChanged = pSound->Init(iSampleRate / iUpscaleRatio, iOutputBlockSize * 2 / iUpscaleRatio, TRUE);
+
+		/* Clear input data buffer on change samplerate change */
+		if (bChanged)
+			ClearInputData();
+
+		/* Init 2X upscaler if enabled */
+		if (iUpscaleRatio > 1)
+		{
+			const int taps = (NUM_TAPS_UPSAMPLE_FILT + 3) & ~3;
+			vecf_B.resize(taps, 0.0f);
+			for (int i = 0; i < NUM_TAPS_UPSAMPLE_FILT; i++)
+				vecf_B[i] = dUpsampleFilt[i] * iUpscaleRatio;
+			if (bChanged)
+			{
+				vecf_ZL.resize(0);
+				vecf_ZR.resize(0);
+			}
+			vecf_ZL.resize((iOutputBlockSize + taps) / 2, 0.0f);
+			vecf_ZR.resize((iOutputBlockSize + taps) / 2, 0.0f);
+			vecf_YL.resize(iOutputBlockSize);
+			vecf_YR.resize(iOutputBlockSize);
+		}
+		else
+		{
+			vecf_B.resize(0);
+			vecf_YL.resize(0);
+			vecf_YR.resize(0);
+			vecf_ZL.resize(0);
+			vecf_ZR.resize(0);
+		}
+
+		/* Init buffer size for taking stereo input */
+		vecsSoundBuffer.Init(iOutputBlockSize * 2 / iUpscaleRatio);
+
+		/* Init signal meter */
+		SignalLevelMeter.Init(0);
+
+		/* Inits for I / Q input, only if it is not already
+		   to keep the history intact */
+		if (vecrReHist.Size() != NUM_TAPS_IQ_INPUT_FILT || bChanged)
+		{
+			vecrReHist.Init(NUM_TAPS_IQ_INPUT_FILT, (_REAL) 0.0);
+			vecrImHist.Init(NUM_TAPS_IQ_INPUT_FILT, (_REAL) 0.0);
+		}
+
+		/* Start with phase null (can be arbitrarily chosen) */
+		cCurExp = (_REAL) 1.0;
+
+		/* Set rotation vector to mix signal from zero frequency to virtual
+		   intermediate frequency */
+		const _REAL rNormCurFreqOffsetIQ =
+			(_REAL) 2.0 * crPi * ((_REAL) VIRTUAL_INTERMED_FREQ / iSampleRate);
+
+		cExpStep = _COMPLEX(cos(rNormCurFreqOffsetIQ), sin(rNormCurFreqOffsetIQ));
+
+
+		/* OPH: init free-running symbol counter */
+		iFreeSymbolCounter = 0;
+
+	}
+    catch (CGenErr GenErr)
+    {
+		pSound = NULL;
+    }
+    catch (string strError)
+    {
+		pSound = NULL;
+    }
+}
+
+_REAL CReceiveData::HilbertFilt(const _REAL rRe, const _REAL rIm)
+{
+    /*
+    	Hilbert filter for I / Q input data. This code is based on code written
+    	by Cesco (HB9TLK)
+    */
+    int i;
+
+    /* Move old data */
+    for (i = 0; i < NUM_TAPS_IQ_INPUT_FILT - 1; i++)
+    {
+        vecrReHist[i] = vecrReHist[i + 1];
+        vecrImHist[i] = vecrImHist[i + 1];
+    }
+
+    vecrReHist[NUM_TAPS_IQ_INPUT_FILT - 1] = rRe;
+    vecrImHist[NUM_TAPS_IQ_INPUT_FILT - 1] = rIm;
+
+    /* Filter */
+    _REAL rSum = (_REAL) 0.0;
+    for (i = 1; i < NUM_TAPS_IQ_INPUT_FILT; i += 2)
+        rSum += fHilFiltIQ[i] * vecrImHist[i];
+
+    return (rSum + vecrReHist[IQ_INP_HIL_FILT_DELAY]) / 2;
+}
+
+void CReceiveData::InterpFIR_2X(const int channels, _SAMPLE* X, vector<float>& Z, vector<float>& Y, vector<float>& B)
+{
+	/*
+	    2X interpolating filter. When combined with CS_IQ_POS_SPLIT or CS_IQ_NEG_SPLIT
+	    input data mode, convert I/Q input to full bandwidth, code by David Flamand
+	*/
+	int i, j;
+	const int B_len = B.size();
+	const int Z_len = Z.size();
+	const int Y_len = Y.size();
+	const int Y_len_2 = Y_len / 2;
+	float *B_beg_ptr = &B[0];
+	float *Z_beg_ptr = &Z[0];
+	float *Y_ptr = &Y[0];
+	float *B_end_ptr, *B_ptr, *Z_ptr;
+	float y0, y1, y2, y3;
+
+	/* Check for size and alignment requirement */
+	if ((B_len & 3) || (Z_len != (B_len/2 + Y_len_2)) || (Y_len & 1))
+		return;
+
+	/* Copy the old history at the end */
+	for (i = B_len/2-1; i >= 0; i--)
+		Z_beg_ptr[Y_len_2 + i] = Z_beg_ptr[i];
+
+	/* Copy the new sample at the beginning of the history */
+	for (i = 0, j = 0; i < Y_len_2; i++, j+=channels)
+		Z_beg_ptr[Y_len_2 - i - 1] = X[j];
+
+	/* The actual lowpass filtering using FIR */
+	for (i = Y_len_2-1; i >= 0; i--)
+	{
+		B_end_ptr  = B_beg_ptr + B_len;
+		B_ptr      = B_beg_ptr;
+		Z_ptr      = Z_beg_ptr + i;
+		y0 = y1 = y2 = y3 = 0.0f;
+		while (B_ptr != B_end_ptr)
+		{
+			y0 = y0 + B_ptr[0] * Z_ptr[0];
+			y1 = y1 + B_ptr[1] * Z_ptr[0];
+			y2 = y2 + B_ptr[2] * Z_ptr[1];
+			y3 = y3 + B_ptr[3] * Z_ptr[1];
+			B_ptr += 4;
+			Z_ptr += 2;
+		}
+		*Y_ptr++ = y0 + y2;
+		*Y_ptr++ = y1 + y3;
+	}
+}
+
+CReceiveData::~CReceiveData()
+{
+}
+
+/*
+    Convert Real to I/Q frequency when bInvert is FALSE
+    Convert I/Q to Real frequency when bInvert is TRUE
+*/
+_REAL CReceiveData::ConvertFrequency(_REAL rFrequency, _BOOLEAN bInvert) const
+{
+    const int iInvert = bInvert ? -1 : 1;
+
+    if (eInChanSelection == CReceiveData::CS_IQ_POS_SPLIT ||
+        eInChanSelection == CReceiveData::CS_IQ_NEG_SPLIT)
+        rFrequency -= iSampleRate / 4 * iInvert;
+    else
+        if (eInChanSelection == CReceiveData::CS_IQ_POS_ZERO ||
+            eInChanSelection == CReceiveData::CS_IQ_NEG_ZERO)
+            rFrequency -= VIRTUAL_INTERMED_FREQ * iInvert;
+
+    return rFrequency;
+}
+
+void CReceiveData::GetInputSpec(CVector<_REAL>& vecrData,
+                                CVector<_REAL>& vecrScale)
+{
+    int i;
+
+    /* Length of spectrum vector including Nyquist frequency */
+    const int iLenSpecWithNyFreq = NUM_SMPLS_4_INPUT_SPECTRUM / 2 + 1;
+
+    /* Init input and output vectors */
+    vecrData.Init(iLenSpecWithNyFreq, (_REAL) 0.0);
+    vecrScale.Init(iLenSpecWithNyFreq, (_REAL) 0.0);
+
+    /* Init the constants for scale and normalization */
+    const _BOOLEAN bNegativeFreq = 
+        eInChanSelection == CReceiveData::CS_IQ_POS_SPLIT ||
+		eInChanSelection == CReceiveData::CS_IQ_NEG_SPLIT;
+
+    const _BOOLEAN bOffsetFreq = 
+        eInChanSelection == CReceiveData::CS_IQ_POS_ZERO ||
+		eInChanSelection == CReceiveData::CS_IQ_NEG_ZERO;
+
+    const int iOffsetScale =
+        bNegativeFreq ? iLenSpecWithNyFreq / 2 :
+        (bOffsetFreq ? iLenSpecWithNyFreq * VIRTUAL_INTERMED_FREQ
+            / (iSampleRate / 2) : 0);
+
+    const _REAL rFactorScale =
+        (_REAL) iSampleRate / iLenSpecWithNyFreq / 2000;
+
+    /* The calibration factor was determined experimentaly,
+       give 0 dB for a full scale sine wave input (0 dBFS) */
+    const _REAL rDataCalibrationFactor = 18.49;
+
+    const _REAL rNormData = rDataCalibrationFactor /
+                            ((_REAL) _MAXSHORT * _MAXSHORT *
+                            NUM_SMPLS_4_INPUT_SPECTRUM *
+                            NUM_SMPLS_4_INPUT_SPECTRUM);
+
+    /* Copy data from shift register in Matlib vector */
+    CRealVector vecrFFTInput(NUM_SMPLS_4_INPUT_SPECTRUM);
+    mutexInpData.Lock();
+    for (i = 0; i < NUM_SMPLS_4_INPUT_SPECTRUM; i++)
+        vecrFFTInput[i] = vecrInpData[i];
+    mutexInpData.Unlock();
+
+    /* Get squared magnitude of spectrum */
+    CRealVector vecrSqMagSpect(iLenSpecWithNyFreq);
+    CFftPlans FftPlans;
+    vecrSqMagSpect =
+        SqMag(rfft(vecrFFTInput * Hann(NUM_SMPLS_4_INPUT_SPECTRUM), FftPlans));
+
+    /* Log power spectrum data */
+    for (i = 0; i < iLenSpecWithNyFreq; i++)
+    {
+        const _REAL rNormSqMag = vecrSqMagSpect[i] * rNormData;
+
+        if (rNormSqMag > 0)
+            vecrData[i] = (_REAL) 10.0 * log10(rNormSqMag);
+        else
+            vecrData[i] = RET_VAL_LOG_0;
+
+        vecrScale[i] = (_REAL) (i - iOffsetScale) * rFactorScale;
+    }
+
+}
+
+void CReceiveData::GetInputPSD(CVector<_REAL>& vecrData,
+                               CVector<_REAL>& vecrScale,
+                               const int iLenPSDAvEachBlock,
+                               const int iNumAvBlocksPSD,
+                               const int iPSDOverlap)
+{
+    CalculatePSD(vecrData, vecrScale, iLenPSDAvEachBlock,iNumAvBlocksPSD,iPSDOverlap);
+}
+
+void CReceiveData::CalculatePSD(CVector<_REAL>& vecrData,
+                                CVector<_REAL>& vecrScale,
+                                const int iLenPSDAvEachBlock,
+                                const int iNumAvBlocksPSD,
+                                const int iPSDOverlap)
+{
+    /* Length of spectrum vector including Nyquist frequency */
+    const int iLenSpecWithNyFreq = iLenPSDAvEachBlock / 2 + 1;
+
+    /* Init input and output vectors */
+    vecrData.Init(iLenSpecWithNyFreq, (_REAL) 0.0);
+    vecrScale.Init(iLenSpecWithNyFreq, (_REAL) 0.0);
+
+    /* Init the constants for scale and normalization */
+    const _BOOLEAN bNegativeFreq = 
+        eInChanSelection == CReceiveData::CS_IQ_POS_SPLIT ||
+		eInChanSelection == CReceiveData::CS_IQ_NEG_SPLIT;
+
+    const _BOOLEAN bOffsetFreq = 
+        eInChanSelection == CReceiveData::CS_IQ_POS_ZERO ||
+		eInChanSelection == CReceiveData::CS_IQ_NEG_ZERO;
+
+    const int iOffsetScale =
+        bNegativeFreq ? iLenSpecWithNyFreq / 2 :
+        (bOffsetFreq ? iLenSpecWithNyFreq * VIRTUAL_INTERMED_FREQ
+            / (iSampleRate / 2) : 0);
+
+    const _REAL rFactorScale =
+        (_REAL) iSampleRate / iLenSpecWithNyFreq / 2000;
+
+    const _REAL rNormData = (_REAL) _MAXSHORT * _MAXSHORT *
+                            iLenPSDAvEachBlock * iLenPSDAvEachBlock *
+                            iNumAvBlocksPSD * _REAL(PSD_WINDOW_GAIN);
+
+    /* Init intermediate vectors */
+    CRealVector vecrAvSqMagSpect(iLenSpecWithNyFreq, (CReal) 0.0);
+    CRealVector vecrFFTInput(iLenPSDAvEachBlock);
+
+    /* Init Hamming window */
+    CRealVector vecrHammWin(Hamming(iLenPSDAvEachBlock));
+
+    /* Calculate FFT of each small block and average results (estimation
+       of PSD of input signal) */
+    CFftPlans FftPlans; int i;
+    mutexInpData.Lock();
+    for (i = 0; i < iNumAvBlocksPSD; i++)
+    {
+        /* Copy data from shift register in Matlib vector */
+        for (int j = 0; j < iLenPSDAvEachBlock; j++)
+            vecrFFTInput[j] = vecrInpData[j + i * (iLenPSDAvEachBlock - iPSDOverlap)];
+
+        /* Apply Hamming window */
+        vecrFFTInput *= vecrHammWin;
+
+        /* Calculate squared magnitude of spectrum and average results */
+        vecrAvSqMagSpect += SqMag(rfft(vecrFFTInput, FftPlans));
+    }
+    mutexInpData.Unlock();
+
+    /* Log power spectrum data */
+    for (i = 0; i <iLenSpecWithNyFreq; i++)
+    {
+        const _REAL rNormSqMag = vecrAvSqMagSpect[i] / rNormData;
+
+        if (rNormSqMag > 0)
+            vecrData[i] = (_REAL) 10.0 * log10(rNormSqMag);
+        else
+            vecrData[i] = RET_VAL_LOG_0;
+
+        vecrScale[i] = (_REAL) (i - iOffsetScale) * rFactorScale;
+    }
+}
+
+/* Calculate PSD and put it into the CParameter class.
+ * The data will be used by the rsi output.
+ * This function is called in a context where the Parameters structure is Locked.
+ */
+void CReceiveData::PutPSD(CParameter &Parameters)
+{
+    int i, j;
+
+    CVector<_REAL>		vecrData;
+    CVector<_REAL>		vecrScale;
+
+    CalculatePSD(vecrData, vecrScale, LEN_PSD_AV_EACH_BLOCK_RSI, NUM_AV_BLOCKS_PSD_RSI, PSD_OVERLAP_RSI);
+
+    /* Data required for rpsd tag */
+    /* extract the values from -8kHz to +8kHz/18kHz relative to 12kHz, i.e. 4kHz to 20kHz */
+    /*const int startBin = 4000.0 * LEN_PSD_AV_EACH_BLOCK_RSI /iSampleRate;
+    const int endBin = 20000.0 * LEN_PSD_AV_EACH_BLOCK_RSI /iSampleRate;*/
+    /* The above calculation doesn't round in the way FhG expect. Probably better to specify directly */
+
+    /* For 20k mode, we need -8/+18, which is more than the Nyquist rate of 24kHz. */
+    /* Assume nominal freq = 7kHz (i.e. 2k to 22k) and pad with zeroes (roughly 1kHz each side) */
+
+    int iStartBin = 22;
+    int iEndBin = 106;
+    int iVecSize = iEndBin - iStartBin + 1; //85
+
+    //_REAL rIFCentreFrequency = Parameters.FrontEndParameters.rIFCentreFreq;
+
+    ESpecOcc eSpecOcc = Parameters.GetSpectrumOccup();
+    if (eSpecOcc == SO_4 || eSpecOcc == SO_5)
+    {
+        iStartBin = 0;
+        iEndBin = 127;
+        iVecSize = 139;
+    }
+    /* Line up the the middle of the vector with the quarter-Nyquist bin of FFT */
+    int iStartIndex = iStartBin - (LEN_PSD_AV_EACH_BLOCK_RSI/4) + (iVecSize-1)/2;
+
+    /* Fill with zeros to start with */
+    Parameters.vecrPSD.Init(iVecSize, (_REAL) 0.0);
+
+    for (i=iStartIndex, j=iStartBin; j<=iEndBin; i++,j++)
+        Parameters.vecrPSD[i] = vecrData[j];
+
+    CalculateSigStrengthCorrection(Parameters, vecrData);
+
+    CalculatePSDInterferenceTag(Parameters, vecrData);
+
+}
+
+/*
+ * This function is called in a context where the Parameters structure is Locked.
+ */
+void CReceiveData::CalculateSigStrengthCorrection(CParameter &Parameters, CVector<_REAL> &vecrPSD)
+{
+
+    _REAL rCorrection = _REAL(0.0);
+
+    /* Calculate signal power in measurement bandwidth */
+
+    _REAL rFreqKmin, rFreqKmax;
+
+    _REAL rIFCentreFrequency = Parameters.FrontEndParameters.rIFCentreFreq;
+
+    if (Parameters.GetAcquiState() == AS_WITH_SIGNAL &&
+            Parameters.FrontEndParameters.bAutoMeasurementBandwidth)
+    {
+        // Receiver is locked, so measure in the current DRM signal bandwidth Kmin to Kmax
+        _REAL rDCFrequency = Parameters.GetDCFrequency();
+        rFreqKmin = rDCFrequency + _REAL(Parameters.CellMappingTable.iCarrierKmin)/Parameters.CellMappingTable.iFFTSizeN * iSampleRate;
+        rFreqKmax = rDCFrequency + _REAL(Parameters.CellMappingTable.iCarrierKmax)/Parameters.CellMappingTable.iFFTSizeN * iSampleRate;
+    }
+    else
+    {
+        // Receiver unlocked, or measurement is requested in fixed bandwidth
+        _REAL rMeasBandwidth = Parameters.FrontEndParameters.rDefaultMeasurementBandwidth;
+        rFreqKmin = rIFCentreFrequency - rMeasBandwidth/_REAL(2.0);
+        rFreqKmax = rIFCentreFrequency + rMeasBandwidth/_REAL(2.0);
+    }
+
+    _REAL rSigPower = CalcTotalPower(vecrPSD, FreqToBin(rFreqKmin), FreqToBin(rFreqKmax));
+
+    if (Parameters.FrontEndParameters.eSMeterCorrectionType == CFrontEndParameters::S_METER_CORRECTION_TYPE_AGC_ONLY)
+    {
+        /* Write it to the receiver params to help with calculating the signal strength */
+        rCorrection += _REAL(10.0) * log10(rSigPower);
+    }
+    else if (Parameters.FrontEndParameters.eSMeterCorrectionType == CFrontEndParameters::S_METER_CORRECTION_TYPE_AGC_RSSI)
+    {
+        _REAL rSMeterBandwidth = Parameters.FrontEndParameters.rSMeterBandwidth;
+
+        _REAL rFreqSMeterMin = _REAL(rIFCentreFrequency - rSMeterBandwidth / _REAL(2.0));
+        _REAL rFreqSMeterMax = _REAL(rIFCentreFrequency + rSMeterBandwidth / _REAL(2.0));
+
+        _REAL rPowerInSMeterBW = CalcTotalPower(vecrPSD, FreqToBin(rFreqSMeterMin), FreqToBin(rFreqSMeterMax));
+
+        /* Write it to the receiver params to help with calculating the signal strength */
+
+        rCorrection += _REAL(10.0) * log10(rSigPower/rPowerInSMeterBW);
+    }
+
+    /* Add on the calibration factor for the current mode */
+    if (Parameters.GetReceiverMode() == RM_DRM)
+        rCorrection += Parameters.FrontEndParameters.rCalFactorDRM;
+    else if (Parameters.GetReceiverMode() == RM_AM)
+        rCorrection += Parameters.FrontEndParameters.rCalFactorAM;
+
+    Parameters.rSigStrengthCorrection = rCorrection;
+
+    return;
+}
+
+/*
+ * This function is called in a context where the Parameters structure is Locked.
+ */
+void CReceiveData::CalculatePSDInterferenceTag(CParameter &Parameters, CVector<_REAL> &vecrPSD)
+{
+
+    /* Interference tag (rnip) */
+
+    // Calculate search range: defined as +/-5.1kHz except if locked and in 20k
+    _REAL rIFCentreFrequency = Parameters.FrontEndParameters.rIFCentreFreq;
+
+    _REAL rFreqSearchMin = rIFCentreFrequency - _REAL(RNIP_SEARCH_RANGE_NARROW);
+    _REAL rFreqSearchMax = rIFCentreFrequency + _REAL(RNIP_SEARCH_RANGE_NARROW);
+
+    ESpecOcc eSpecOcc = Parameters.GetSpectrumOccup();
+
+    if (Parameters.GetAcquiState() == AS_WITH_SIGNAL &&
+            (eSpecOcc == SO_4 || eSpecOcc == SO_5) )
+    {
+        rFreqSearchMax = rIFCentreFrequency + _REAL(RNIP_SEARCH_RANGE_WIDE);
+    }
+    int iSearchStartBin = FreqToBin(rFreqSearchMin);
+    int iSearchEndBin = FreqToBin(rFreqSearchMax);
+
+    if (iSearchStartBin < 0) iSearchStartBin = 0;
+    if (iSearchEndBin > LEN_PSD_AV_EACH_BLOCK_RSI/2)
+        iSearchEndBin = LEN_PSD_AV_EACH_BLOCK_RSI/2;
+
+    _REAL rMaxPSD = _REAL(-1000.0);
+    int iMaxPSDBin = 0;
+
+    for (int i=iSearchStartBin; i<=iSearchEndBin; i++)
+    {
+        _REAL rPSD = _REAL(2.0) * pow(_REAL(10.0), vecrPSD[i]/_REAL(10.0));
+        if (rPSD > rMaxPSD)
+        {
+            rMaxPSD = rPSD;
+            iMaxPSDBin = i;
+        }
+    }
+
+    // For total signal power, exclude the biggest one and e.g. 2 either side
+    int iExcludeStartBin = iMaxPSDBin - RNIP_EXCLUDE_BINS;
+    int iExcludeEndBin = iMaxPSDBin + RNIP_EXCLUDE_BINS;
+
+    // Calculate power. TotalPower() function will deal with start>end correctly
+    _REAL rSigPowerExcludingInterferer = CalcTotalPower(vecrPSD, iSearchStartBin, iExcludeStartBin-1) +
+                                         CalcTotalPower(vecrPSD, iExcludeEndBin+1, iSearchEndBin);
+
+    /* interferer level wrt signal power */
+    Parameters.rMaxPSDwrtSig = _REAL(10.0) * log10(rMaxPSD / rSigPowerExcludingInterferer);
+
+    /* interferer frequency */
+    Parameters.rMaxPSDFreq = _REAL(iMaxPSDBin) * _REAL(iSampleRate) / _REAL(LEN_PSD_AV_EACH_BLOCK_RSI) - rIFCentreFrequency;
+
+}
+
+
+int CReceiveData::FreqToBin(_REAL rFreq)
+{
+    return int(rFreq/iSampleRate * LEN_PSD_AV_EACH_BLOCK_RSI);
+}
+
+_REAL CReceiveData::CalcTotalPower(CVector<_REAL> &vecrData, int iStartBin, int iEndBin)
+{
+    if (iStartBin < 0) iStartBin = 0;
+    if (iEndBin > LEN_PSD_AV_EACH_BLOCK_RSI/2)
+        iEndBin = LEN_PSD_AV_EACH_BLOCK_RSI/2;
+
+    _REAL rSigPower = _REAL(0.0);
+    for (int i=iStartBin; i<=iEndBin; i++)
+    {
+        _REAL rPSD = pow(_REAL(10.0), vecrData[i]/_REAL(10.0));
+        // The factor of 2 below is needed because half of the power is in the negative frequencies
+        rSigPower += rPSD * _REAL(2.0);
+    }
+
+    return rSigPower;
+}
diff --git a/src/DRMSignalIO.h b/src/DRMSignalIO.h
new file mode 100644
index 0000000..679c52f
--- /dev/null
+++ b/src/DRMSignalIO.h
@@ -0,0 +1,245 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *	See DRMSignalIO.cpp
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#if !defined(DRMSIGNALIO_H__3B0BA660_CA63_4344_B_23E7A0D31912__INCLUDED_)
+#define DRMSIGNALIO_H__3B0BA660_CA63_4344_B_23E7A0D31912__INCLUDED_
+
+#include "sound/soundinterface.h"
+#include "Parameter.h"
+#include "matlib/Matlib.h"
+#include "IQInputFilter.h"
+#include "util/Modul.h"
+#include "util/Utilities.h"
+#include <math.h>
+#include <vector>
+
+/* Definitions ****************************************************************/
+/* Number of FFT blocks used for averaging. See next definition
+   ("NUM_SMPLS_4_INPUT_SPECTRUM") for how to set the parameters */
+#define NUM_AV_BLOCKS_PSD			16
+#define LEN_PSD_AV_EACH_BLOCK		512
+
+/* same but for the rpsd tag */
+#define NUM_AV_BLOCKS_PSD_RSI	150
+#define LEN_PSD_AV_EACH_BLOCK_RSI		256
+#define PSD_OVERLAP_RSI	128
+
+/* power gain of the Hamming window */
+#define PSD_WINDOW_GAIN 0.39638
+
+/* Length of vector for input spectrum. We use approx. 0.2 sec
+   of sampled data for spectrum calculation, this is 2^13 = 8192 to
+   make the FFT work more efficient. Make sure that this number is not smaller
+   than the symbol lenght in 48 khz domain of longest mode (which is mode A/B:
+   1280) */
+#define NUM_SMPLS_4_INPUT_SPECTRUM (NUM_AV_BLOCKS_PSD * LEN_PSD_AV_EACH_BLOCK)
+
+/* The RSI output needs 400ms with a 50% overlap, so this needs more space
+   I think the RSCI spec is slightly wrong - using 150 windows consumes just over 400ms, 149 would be exact */
+#define INPUT_DATA_VECTOR_SIZE (NUM_AV_BLOCKS_PSD_RSI * (LEN_PSD_AV_EACH_BLOCK_RSI-PSD_OVERLAP_RSI)+PSD_OVERLAP_RSI)
+
+#define RNIP_SEARCH_RANGE_NARROW 5100.0
+#define RNIP_SEARCH_RANGE_WIDE 15100.0
+#define RNIP_EXCLUDE_BINS 2 // either side of the peak
+
+/* Use raw 16 bit data or in text form for file format for DRM data. Defining
+   the following macro will enable the raw data option */
+#define FILE_DRM_USING_RAW_DATA
+
+
+/* Classes ********************************************************************/
+class CTransmitData : public CTransmitterModul<_COMPLEX, _COMPLEX>
+{
+public:
+    enum EOutFormat {OF_REAL_VAL /* real valued */, OF_IQ_POS,
+                     OF_IQ_NEG /* I / Q */, OF_EP /* envelope / phase */
+                    };
+
+    CTransmitData(CSoundOutInterface* pNS) : pFileTransmitter(NULL), pSound(pNS),
+            eOutputFormat(OF_REAL_VAL), rDefCarOffset((_REAL) VIRTUAL_INTERMED_FREQ),
+            strOutFileName("test/TransmittedData.txt"), bUseSoundcard(TRUE),
+            bAmplified(FALSE), bHighQualityIQ(FALSE) {}
+    virtual ~CTransmitData();
+
+    void SetIQOutput(const EOutFormat eFormat) {
+        eOutputFormat = eFormat;
+    }
+    EOutFormat GetIQOutput() {
+        return eOutputFormat;
+    }
+
+    void SetAmplifiedOutput(_BOOLEAN bEnable) {
+        bAmplified = bEnable;
+    }
+    _BOOLEAN GetAmplifiedOutput() {
+        return bAmplified;
+    }
+
+    void SetHighQualityIQ(_BOOLEAN bEnable) {
+        bHighQualityIQ = bEnable;
+    }
+    _BOOLEAN GetHighQualityIQ() {
+        return bHighQualityIQ;
+    }
+
+    void SetCarOffset(const CReal rNewCarOffset)
+    {
+        rDefCarOffset = rNewCarOffset;
+    }
+
+    void SetWriteToFile(const string strNFN)
+    {
+        strOutFileName = strNFN;
+        bUseSoundcard = FALSE;
+    }
+
+    void FlushData();
+
+protected:
+    FILE*				pFileTransmitter;
+    CSoundOutInterface*	pSound;
+    CVector<short>		vecsDataOut;
+    int					iBlockCnt;
+    int					iNumBlocks;
+    EOutFormat			eOutputFormat;
+
+    CDRMBandpassFilt	BPFilter;
+    CReal				rDefCarOffset;
+
+    CReal				rNormFactor;
+
+    int					iBigBlockSize;
+
+    string				strOutFileName;
+    _BOOLEAN			bUseSoundcard;
+
+    _BOOLEAN			bAmplified;
+    _BOOLEAN			bHighQualityIQ;
+    CVector<_REAL>		vecrReHist;
+
+    void HilbertFilt(_COMPLEX& vecData);
+
+    virtual void InitInternal(CParameter& TransmParam);
+    virtual void ProcessDataInternal(CParameter& Parameter);
+};
+
+class CReceiveData : public CReceiverModul<_REAL, _REAL>
+{
+public:
+    enum EInChanSel {CS_LEFT_CHAN, CS_RIGHT_CHAN, CS_MIX_CHAN, CS_SUB_CHAN, CS_IQ_POS,
+                     CS_IQ_NEG, CS_IQ_POS_ZERO, CS_IQ_NEG_ZERO, CS_IQ_POS_SPLIT, CS_IQ_NEG_SPLIT
+                    };
+
+    CReceiveData() :
+        pSound(NULL), vecrInpData(INPUT_DATA_VECTOR_SIZE, (_REAL) 0.0),
+        bFippedSpectrum(FALSE), eInChanSelection(CS_MIX_CHAN), iPhase(0)
+    {}
+    virtual ~CReceiveData();
+
+    _REAL ConvertFrequency(_REAL rFrequency, _BOOLEAN bInvert=FALSE) const;
+
+    void GetInputSpec(CVector<_REAL>& vecrData, CVector<_REAL>& vecrScale);
+    void GetInputPSD(CVector<_REAL>& vecrData, CVector<_REAL>& vecrScale,
+                     const int iLenPSDAvEachBlock = LEN_PSD_AV_EACH_BLOCK,
+                     const int iNumAvBlocksPSD = NUM_AV_BLOCKS_PSD,
+                     const int iPSDOverlap = 0);
+
+    void SetFlippedSpectrum(const _BOOLEAN bNewF) {
+        bFippedSpectrum = bNewF;
+    }
+    _BOOLEAN GetFlippedSpectrum() {
+        return bFippedSpectrum;
+    }
+
+    void ClearInputData() {
+        mutexInpData.Lock();
+        vecrInpData.Init(INPUT_DATA_VECTOR_SIZE, (_REAL) 0.0);
+        mutexInpData.Unlock();
+    }
+
+    void SetSoundInterface(CSoundInInterface* pS) {
+        pSound = pS;
+    }
+    void SetInChanSel(const EInChanSel eNS) {
+        eInChanSelection = eNS;
+    }
+    EInChanSel GetInChanSel() {
+        return eInChanSelection;
+    }
+
+protected:
+    CSignalLevelMeter		SignalLevelMeter;
+
+    CSoundInInterface*		pSound;
+    CVector<_SAMPLE>		vecsSoundBuffer;
+
+    /* Access to vecrInpData buffer must be done 
+       inside mutexInpData mutex */
+    CShiftRegister<_REAL>	vecrInpData;
+    CMutex                  mutexInpData;
+
+    int					iSampleRate;
+    _BOOLEAN			bFippedSpectrum;
+
+    int					iUpscaleRatio;
+    vector<float>		vecf_B, vecf_YL, vecf_YR, vecf_ZL, vecf_ZR;
+
+    EInChanSel			eInChanSelection;
+
+    CVector<_REAL>		vecrReHist;
+    CVector<_REAL>		vecrImHist;
+    _COMPLEX			cCurExp;
+    _COMPLEX			cExpStep;
+    int					iPhase;
+
+    _REAL HilbertFilt(const _REAL rRe, const _REAL rIm);
+
+    /* OPH: counter to count symbols within a frame in order to generate */
+    /* RSCI output */
+    int							iFreeSymbolCounter;
+
+    virtual void InitInternal(CParameter& Parameters);
+    virtual void ProcessDataInternal(CParameter& Parameters);
+
+    void PutPSD(CParameter& Parameters);
+    void CalculatePSD(CVector<_REAL>& vecrData, CVector<_REAL>& vecrScale,
+                      const int iLenPSDAvEachBlock = LEN_PSD_AV_EACH_BLOCK,
+                      const int iNumAvBlocksPSD = NUM_AV_BLOCKS_PSD,
+                      const int iPSDOverlap = 0);
+
+    void CalculateSigStrengthCorrection(CParameter &Parameters, CVector<_REAL> &vecrPSD);
+    void CalculatePSDInterferenceTag(CParameter &Parameters, CVector<_REAL> &vecrPSD);
+
+    int FreqToBin(_REAL rFreq);
+    _REAL CalcTotalPower(CVector<_REAL> &vecrData, int iStartBin, int iEndBin);
+
+    void InterpFIR_2X(const int channels, _SAMPLE* X, vector<float>& Z, vector<float>& Y, vector<float>& B);
+};
+
+
+#endif // !defined(DRMSIGNALIO_H__3B0BA660_CA63_4344_B_23E7A0D31912__INCLUDED_)
diff --git a/src/DataIO.cpp b/src/DataIO.cpp
new file mode 100644
index 0000000..5915558
--- /dev/null
+++ b/src/DataIO.cpp
@@ -0,0 +1,971 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "DataIO.h"
+#include <iomanip>
+#include <time.h>
+
+/* Implementation *************************************************************/
+/******************************************************************************\
+* MSC data																	   *
+\******************************************************************************/
+/* Transmitter -------------------------------------------------------------- */
+void CReadData::ProcessDataInternal(CParameter&)
+{
+    /* Get data from sound interface */
+    pSound->Read(vecsSoundBuffer);
+
+    /* Write data to output buffer */
+    for (int i = 0; i < iOutputBlockSize; i++)
+        (*pvecOutputData)[i] = vecsSoundBuffer[i];
+
+    /* Update level meter */
+    SignalLevelMeter.Update((*pvecOutputData));
+}
+
+void CReadData::InitInternal(CParameter& Parameters)
+{
+    /* Get audio sample rate */
+    const int iSampleRate = Parameters.GetAudSampleRate();
+
+    /* Define block-size for output, an audio frame always corresponds
+       to 400 ms. We use always stereo blocks */
+    iOutputBlockSize = (int) ((_REAL) iSampleRate *
+                              (_REAL) 0.4 /* 400 ms */ * 2 /* stereo */);
+
+    /* Init sound interface and intermediate buffer */
+    pSound->Init(iSampleRate, iOutputBlockSize, FALSE);
+    vecsSoundBuffer.Init(iOutputBlockSize);
+
+    /* Init level meter */
+    SignalLevelMeter.Init(0);
+}
+
+/* Receiver ----------------------------------------------------------------- */
+
+void CWriteData::ProcessDataInternal(CParameter& Parameters)
+{
+    int i;
+
+    /* Calculate size of each individual audio channel */
+    const int iHalfBlSi = iInputBlockSize / 2;
+
+    switch (eOutChanSel)
+    {
+    case CS_BOTH_BOTH:
+        /* left -> left, right -> right (vector sizes might not be the
+           same -> use for-loop for copying) */
+        for (i = 0; i < iInputBlockSize; i++)
+            vecsTmpAudData[i] = (*pvecInputData)[i]; /* Just copy data */
+        break;
+
+    case CS_LEFT_LEFT:
+        /* left -> left, right muted */
+        for (i = 0; i < iHalfBlSi; i++)
+        {
+            vecsTmpAudData[2 * i] = (*pvecInputData)[2 * i];
+            vecsTmpAudData[2 * i + 1] = 0; /* mute */
+        }
+        break;
+
+    case CS_RIGHT_RIGHT:
+        /* left muted, right -> right */
+        for (i = 0; i < iHalfBlSi; i++)
+        {
+            vecsTmpAudData[2 * i] = 0; /* mute */
+            vecsTmpAudData[2 * i + 1] = (*pvecInputData)[2 * i + 1];
+        }
+        break;
+
+    case CS_LEFT_MIX:
+        /* left -> mix, right muted */
+        for (i = 0; i < iHalfBlSi; i++)
+        {
+            /* Mix left and right channel together. Prevent overflow! First,
+               copy recorded data from "short" in "_REAL" type variables */
+            const _REAL rLeftChan = (*pvecInputData)[2 * i];
+            const _REAL rRightChan = (*pvecInputData)[2 * i + 1];
+
+            vecsTmpAudData[2 * i] =
+                Real2Sample((rLeftChan + rRightChan) * rMixNormConst);
+
+            vecsTmpAudData[2 * i + 1] = 0; /* mute */
+        }
+        break;
+
+    case CS_RIGHT_MIX:
+        /* left muted, right -> mix */
+        for (i = 0; i < iHalfBlSi; i++)
+        {
+            /* Mix left and right channel together. Prevent overflow! First,
+               copy recorded data from "short" in "_REAL" type variables */
+            const _REAL rLeftChan = (*pvecInputData)[2 * i];
+            const _REAL rRightChan = (*pvecInputData)[2 * i + 1];
+
+            vecsTmpAudData[2 * i] = 0; /* mute */
+            vecsTmpAudData[2 * i + 1] =
+                Real2Sample((rLeftChan + rRightChan) * rMixNormConst);
+        }
+        break;
+    }
+
+    if (bMuteAudio == TRUE)
+    {
+        /* Clear both channels if muted */
+        for (i = 0; i < iInputBlockSize; i++)
+            vecsTmpAudData[i] = 0;
+    }
+
+    /* Put data to sound card interface. Show sound card state on GUI */
+
+    const _BOOLEAN bBad = pSound->Write(vecsTmpAudData);
+    Parameters.Lock();
+    Parameters.ReceiveStatus.InterfaceO.SetStatus(bBad ? DATA_ERROR : RX_OK); /* Yellow light */
+    Parameters.Unlock();
+
+    /* Write data as wave in file */
+    if (bDoWriteWaveFile == TRUE)
+    {
+        /* Write audio data to file only if it is not zero */
+        _BOOLEAN bDoNotWrite = TRUE;
+        for (i = 0; i < iInputBlockSize; i++)
+        {
+            if ((*pvecInputData)[i] != 0)
+                bDoNotWrite = FALSE;
+        }
+
+        if (bDoNotWrite == FALSE)
+        {
+            for (i = 0; i < iInputBlockSize; i += 2)
+            {
+                WaveFileAudio.AddStereoSample((*pvecInputData)[i] /* left */,
+                                              (*pvecInputData)[i + 1] /* right */);
+            }
+        }
+    }
+
+    /* Store data in buffer for spectrum calculation */
+    vecsOutputData.AddEnd((*pvecInputData), iInputBlockSize);
+}
+
+void CWriteData::InitInternal(CParameter& Parameters)
+{
+    /* Get audio sample rate */
+    iAudSampleRate = Parameters.GetAudSampleRate();
+
+    /* Set maximum audio frequency */
+	iMaxAudioFrequency = MAX_SPEC_AUDIO_FREQUENCY;
+	if (iMaxAudioFrequency > iAudSampleRate/2)
+		iMaxAudioFrequency = iAudSampleRate/2;
+
+    /* Length of vector for audio spectrum. We use a power-of-two length to
+       make the FFT work more efficient, need to be scaled from sample rate to
+       keep the same frequency resolution */
+    iNumSmpls4AudioSprectrum = ADJ_FOR_SRATE(1024, iAudSampleRate);
+
+    /* Number of blocks for averaging the audio spectrum */
+    iNumBlocksAvAudioSpec = Ceil(((_REAL) iAudSampleRate *
+        TIME_AV_AUDIO_SPECT_MS / 1000 / iNumSmpls4AudioSprectrum));
+
+    /* Inits for audio spectrum plotting */
+    vecsOutputData.Init((int) iNumBlocksAvAudioSpec * iNumSmpls4AudioSprectrum *
+                   2 /* stereo */, 0); /* Init with zeros */
+    FftPlan.Init(iNumSmpls4AudioSprectrum);
+    veccFFTInput.Init(iNumSmpls4AudioSprectrum);
+    veccFFTOutput.Init(iNumSmpls4AudioSprectrum);
+    vecrAudioWindowFunction.Init(iNumSmpls4AudioSprectrum);
+
+    /* An audio frame always corresponds to 400 ms.
+       We use always stereo blocks */
+    const int iAudFrameSize = (int) ((_REAL) iAudSampleRate *
+                                     (_REAL) 0.4 /* 400 ms */);
+
+    /* Check if blocking behaviour of sound interface shall be changed */
+    if (bNewSoundBlocking != bSoundBlocking)
+        bSoundBlocking = bNewSoundBlocking;
+
+    /* Init sound interface with blocking or non-blocking behaviour */
+    pSound->Init(iAudSampleRate, iAudFrameSize * 2 /* stereo */, bSoundBlocking);
+
+    /* Init intermediate buffer needed for different channel selections */
+    vecsTmpAudData.Init(iAudFrameSize * 2 /* stereo */);
+
+    /* Inits for audio spectrum plot */
+    vecrAudioWindowFunction = Hann(iNumSmpls4AudioSprectrum);
+    vecsOutputData.Reset(0); /* Reset audio data storage vector */
+
+    /* Define block-size for input (stereo input) */
+    iInputBlockSize = iAudFrameSize * 2 /* stereo */;
+}
+
+CWriteData::CWriteData(CSoundOutInterface* pNS) :
+        pSound(pNS), /* Sound interface */
+        bMuteAudio(FALSE), bDoWriteWaveFile(FALSE),
+        bSoundBlocking(FALSE), bNewSoundBlocking(FALSE),
+        eOutChanSel(CS_BOTH_BOTH), rMixNormConst(MIX_OUT_CHAN_NORM_CONST),
+        iAudSampleRate(0), iNumSmpls4AudioSprectrum(0), iNumBlocksAvAudioSpec(0),
+        iMaxAudioFrequency(MAX_SPEC_AUDIO_FREQUENCY)
+{
+    /* Constructor */
+}
+
+void CWriteData::StartWriteWaveFile(const string& strFileName)
+{
+    /* No Lock(), Unlock() needed here */
+    if (bDoWriteWaveFile == FALSE)
+    {
+        WaveFileAudio.Open(strFileName, iAudSampleRate);
+        bDoWriteWaveFile = TRUE;
+    }
+}
+
+void CWriteData::StopWriteWaveFile()
+{
+    Lock();
+
+    WaveFileAudio.Close();
+    bDoWriteWaveFile = FALSE;
+
+    Unlock();
+}
+
+void CWriteData::GetAudioSpec(CVector<_REAL>& vecrData,
+                              CVector<_REAL>& vecrScale)
+{
+    if (iAudSampleRate == 0)
+    {
+        /* Init output vectors to zero data */
+        vecrData.Init(0, (_REAL) 0.0);
+        vecrScale.Init(0, (_REAL) 0.0);
+        return;
+    }
+
+    /* Real input signal -> symmetrical spectrum -> use only half of spectrum */
+    const _REAL rLenPowSpec = _REAL(iNumSmpls4AudioSprectrum) * iMaxAudioFrequency / iAudSampleRate;
+    const int iLenPowSpec = int(rLenPowSpec);
+
+    /* Init output vectors */
+    vecrData.Init(iLenPowSpec, (_REAL) 0.0);
+    vecrScale.Init(iLenPowSpec, (_REAL) 0.0);
+
+    int i;
+
+    /* Lock resources */
+    Lock();
+
+    /* Init vector storing the average spectrum with zeros */
+    CVector<_REAL> veccAvSpectrum(iLenPowSpec, (_REAL) 0.0);
+
+    int iCurPosInStream = 0;
+    for (i = 0; i < iNumBlocksAvAudioSpec; i++)
+    {
+        int j;
+
+        /* Mix both channels */
+        for (j = 0; j < iNumSmpls4AudioSprectrum; j++)
+        {
+            int jj =  2*(iCurPosInStream + j);
+            veccFFTInput[j] = _REAL(vecsOutputData[jj] + vecsOutputData[jj + 1]) / 2;
+        }
+
+        /* Apply window function */
+        veccFFTInput *= vecrAudioWindowFunction;
+
+        /* Calculate Fourier transformation to get the spectrum */
+        veccFFTOutput = Fft(veccFFTInput, FftPlan);
+
+        /* Average power (using power of this tap) */
+        for (j = 0; j < iLenPowSpec; j++)
+            veccAvSpectrum[j] += SqMag(veccFFTOutput[j]);
+
+        iCurPosInStream += iNumSmpls4AudioSprectrum;
+    }
+
+    /* Calculate norm constant and scale factor */
+    const _REAL rNormData = (_REAL) iNumSmpls4AudioSprectrum *
+                            iNumSmpls4AudioSprectrum * _MAXSHORT * _MAXSHORT *
+                            iNumBlocksAvAudioSpec;
+
+    /* Define scale factor for audio data */
+    const _REAL rFactorScale = _REAL(iMaxAudioFrequency) / iLenPowSpec / 1000;
+
+    /* Apply the normalization (due to the FFT) */
+    for (i = 0; i < iLenPowSpec; i++)
+    {
+        const _REAL rNormPowSpec = veccAvSpectrum[i] / rNormData;
+
+        if (rNormPowSpec > 0)
+            vecrData[i] = (_REAL) 10.0 * log10(rNormPowSpec);
+        else
+            vecrData[i] = RET_VAL_LOG_0;
+
+        vecrScale[i] = (_REAL) i * rFactorScale;
+    }
+
+    /* Release resources */
+    Unlock();
+}
+
+
+/* Simulation --------------------------------------------------------------- */
+void CGenSimData::ProcessDataInternal(CParameter& TransmParam)
+{
+    int			i;
+    uint32_t	iTempShiftRegister1;
+    _BINARY		biPRBSbit;
+    uint32_t	iShiftRegister;
+    FILE*		pFileCurPos;
+    time_t		tiElTi;
+    long int	lReTi;
+    _REAL		rReDays;
+
+    /* Get elapsed time since this run was started (seconds) */
+    tiElTi = time(NULL) - tiStartTime;
+
+    /* Stop simulation if stop condition is true */
+    iCounter++;
+    switch (eCntType)
+    {
+    case CT_TIME:
+        try
+        {
+            /* Estimate remaining time */
+            lReTi = (long int) (((_REAL) iNumSimBlocks - iCounter) /
+                                iCounter * tiElTi);
+
+            /* Store current counter position in file */
+            pFileCurPos = fopen(strFileName.c_str(), "w");
+            if (pFileCurPos != NULL)
+            {
+                fprintf(pFileCurPos,
+                        "%d / %d (%ld min elapsed, estimated time remaining: %ld min)",
+                        iCounter, iNumSimBlocks,
+                        (long int)tiElTi / 60, lReTi / 60);
+
+                /* Write current paramter value */
+                _REAL rCurParamVal;
+                switch (TransmParam.eSimType)
+                {
+                case CParameter::ST_SYNC_PARAM:
+                    rCurParamVal = TransmParam.rSyncTestParam;
+                    break;
+
+                case CParameter::ST_SINR:
+                    rCurParamVal = TransmParam.rSINR;
+                    break;
+
+                default:
+                    rCurParamVal = TransmParam.rBitErrRate;
+                    break;
+                }
+                fprintf(pFileCurPos, "\n%e %e",
+                        TransmParam.GetNominalSNRdB(), rCurParamVal);
+
+                fclose(pFileCurPos);
+            }
+        }
+
+        catch (...)
+        {
+            /* Catch all file errors to avoid stopping the simulation */
+        }
+
+        if (iCounter == iNumSimBlocks)
+        {
+		TransmParam.eRunState = CParameter::STOP_REQUESTED;
+		iCounter = 0;
+        }
+        break;
+
+    case CT_ERRORS:
+        try
+        {
+            if (iCounter >= iMinNumBlocks)
+            {
+                /* Estimate remaining time */
+                lReTi = (long int)
+                        (((_REAL) iNumErrors - TransmParam.iNumBitErrors) /
+                         TransmParam.iNumBitErrors * tiElTi);
+
+                /* Estimated remaining days ( x / (60 * 60 * 24) ) */
+                rReDays = (_REAL) lReTi / 86400;
+
+                /* Store current counter position in file */
+                pFileCurPos = fopen(strFileName.c_str(), "w");
+                if (pFileCurPos != NULL)
+                {
+                    fprintf(pFileCurPos,
+                            "%d / %d (%ld min elapsed, estimated time remaining: %ld min [%.1f days])",
+                            TransmParam.iNumBitErrors, iNumErrors, (long int)tiElTi / 60,
+                            lReTi / 60, rReDays);
+
+                    /* Add current value of BER */
+                    fprintf(pFileCurPos, "\n%e %e", TransmParam.
+                            GetNominalSNRdB(), TransmParam.rBitErrRate);
+                    fclose(pFileCurPos);
+                }
+            }
+            else
+            {
+                /* Estimate remaining time */
+                lReTi = (long int)
+                        (((_REAL) iMinNumBlocks - iCounter) / iCounter * tiElTi);
+
+                /* Store current counter position in file */
+                pFileCurPos = fopen(strFileName.c_str(), "w");
+                if (pFileCurPos != NULL)
+                {
+                    fprintf(pFileCurPos,
+                            "%d / %d (%ld min elapsed, estimated minimum"
+                            " time remaining: %ld min)\n",
+                            iCounter, iMinNumBlocks, (long int)tiElTi / 60, lReTi / 60);
+
+                    lReTi = (long int)
+                            (((_REAL) iNumErrors - TransmParam.iNumBitErrors) /
+                             TransmParam.iNumBitErrors * tiElTi);
+                    fprintf(pFileCurPos,
+                            "%d / %d (%ld min elapsed, estimated time remaining: %ld min)",
+                            TransmParam.iNumBitErrors, iNumErrors, (long int)tiElTi / 60,
+                            lReTi / 60);
+
+                    /* Add current value of BER */
+                    fprintf(pFileCurPos, "\n%e %e", TransmParam.
+                            GetNominalSNRdB(), TransmParam.rBitErrRate);
+                    fclose(pFileCurPos);
+                }
+            }
+        }
+
+        catch (...)
+        {
+            /* Catch all file errors to avoid stopping the simulation */
+        }
+
+        if (TransmParam.iNumBitErrors >= iNumErrors)
+        {
+            /* A minimum simulation time must be elapsed */
+            if (iCounter >= iMinNumBlocks)
+            {
+		TransmParam.eRunState = CParameter::STOP_REQUESTED;
+                iCounter = 0;
+            }
+        }
+        break;
+    }
+
+    /* Generate a pseudo-noise test-signal (PRBS) */
+    /* Init shift register with an arbitrary number (Must be known at the
+       receiver AND transmitter!) */
+    iShiftRegister = (uint32_t) (time(NULL) + rand());
+    TransmParam.RawSimDa.Add(iShiftRegister);
+
+    for (i = 0; i < iOutputBlockSize; i++)
+    {
+        /* Calculate new PRBS bit */
+        iTempShiftRegister1 = iShiftRegister;
+
+        /* P(X) = X^9 + X^5 + 1,
+           in this implementation we have to shift n-1! */
+        biPRBSbit = _BINARY(((iTempShiftRegister1 >> 4) & 1) ^
+                            ((iTempShiftRegister1 >> 8) & 1));
+
+        /* Shift bits in shift register and add new bit */
+        iShiftRegister <<= 1;
+        iShiftRegister |= (biPRBSbit & 1);
+
+        /* Use PRBS output */
+        (*pvecOutputData)[i] = biPRBSbit;
+    }
+}
+
+void CGenSimData::InitInternal(CParameter& TransmParam)
+{
+    /* Define output block size */
+    iOutputBlockSize = TransmParam.iNumDecodedBitsMSC;
+
+    /* Minimum simulation time depends on the selected channel */
+    switch (TransmParam.iDRMChannelNum)
+    {
+    case 1:
+        /* AWGN: No fading */
+        iMinNumBlocks = (int) ((_REAL) 2000.0 / (_REAL) 0.4);
+        break;
+
+    case 2:
+        /* Rice with delay: 0.1 Hz */
+        iMinNumBlocks = (int) ((_REAL) 5000.0 / (_REAL) 0.4);
+        break;
+
+    case 3:
+        /* US Consortium: slowest 0.1 Hz */
+        iMinNumBlocks = (int) ((_REAL) 15000.0 / (_REAL) 0.4);
+        break;
+
+    case 4:
+        /* CCIR Poor: 1 Hz */
+        iMinNumBlocks = (int) ((_REAL) 4000.0 / (_REAL) 0.4);
+        break;
+
+    case 5:
+        /* Channel no 5: 2 Hz -> 30 sec */
+        iMinNumBlocks = (int) ((_REAL) 3000.0 / (_REAL) 0.4);
+        break;
+
+    case 6:
+        /* Channel no 6: same as case "2" */
+        iMinNumBlocks = (int) ((_REAL) 2000.0 / (_REAL) 0.4);
+        break;
+
+    default:
+        /* My own channels */
+        iMinNumBlocks = (int) ((_REAL) 2000.0 / (_REAL) 0.4);
+        break;
+    }
+
+    /* Prepare shift register used for storing the start values of the PRBS
+       shift register */
+    TransmParam.RawSimDa.Reset();
+
+    /* Init start time */
+    tiStartTime = time(NULL);
+}
+
+void CGenSimData::SetSimTime(int iNewTi, string strNewFileName)
+{
+    /* One MSC frame is 400 ms long */
+    iNumSimBlocks = (int) ((_REAL) iNewTi /* sec */ / (_REAL) 0.4);
+
+    /* Set simulation count type */
+    eCntType = CT_TIME;
+
+    /* Reset counter */
+    iCounter = 0;
+
+    /* Set file name */
+    strFileName = string(SIM_OUT_FILES_PATH) +
+                  strNewFileName + "__SIMTIME" + string(".dat");
+}
+
+void CGenSimData::SetNumErrors(int iNewNE, string strNewFileName)
+{
+    iNumErrors = iNewNE;
+
+    /* Set simulation count type */
+    eCntType = CT_ERRORS;
+
+    /* Reset counter, because we also use it at the beginning of a run */
+    iCounter = 0;
+
+    /* Set file name */
+    strFileName = string(SIM_OUT_FILES_PATH) +
+                  strNewFileName + "__SIMTIME" + string(".dat");
+}
+
+void CEvaSimData::ProcessDataInternal(CParameter& Parameters)
+{
+    uint32_t	iTempShiftRegister1;
+    _BINARY		biPRBSbit;
+    uint32_t	iShiftRegister;
+    int			iNumBitErrors;
+    int			i;
+
+    /* -------------------------------------------------------------------------
+       Generate a pseudo-noise test-signal (PRBS) for comparison with
+       received signal */
+    /* Init shift register with an arbitrary number (Must be known at the
+       receiver AND transmitter!) */
+    iShiftRegister = Parameters.RawSimDa.Get();
+
+    iNumBitErrors = 0;
+
+    for (i = 0; i < iInputBlockSize; i++)
+    {
+        /* Calculate new PRBS bit */
+        iTempShiftRegister1 = iShiftRegister;
+
+        /* P(X) = X^9 + X^5 + 1,
+           in this implementation we have to shift n-1! */
+        biPRBSbit = _BINARY(((iTempShiftRegister1 >> 4) & 1) ^
+                            ((iTempShiftRegister1 >> 8) & 1));
+
+        /* Shift bits in shift register and add new bit */
+        iShiftRegister <<= 1;
+        iShiftRegister |= (biPRBSbit & 1);
+
+        /* Count bit errors */
+        if (biPRBSbit != (*pvecInputData)[i])
+            iNumBitErrors++;
+    }
+
+    /* Save bit error rate, debar initialization blocks */
+    if (iIniCnt > 0)
+        iIniCnt--;
+    else
+    {
+        rAccBitErrRate += (_REAL) iNumBitErrors / iInputBlockSize;
+        iNumAccBitErrRate++;
+
+        Parameters.rBitErrRate = rAccBitErrRate / iNumAccBitErrRate;
+        Parameters.iNumBitErrors += iNumBitErrors;
+    }
+}
+
+void CEvaSimData::InitInternal(CParameter& Parameters)
+{
+    /* Reset bit error rate parameters */
+    rAccBitErrRate = (_REAL) 0.0;
+    iNumAccBitErrRate = 0;
+
+    /* Number of blocks at the beginning we do not want to use */
+    iIniCnt = 10;
+
+    /* Init global parameters */
+    Parameters.rBitErrRate = (_REAL) 0.0;
+    Parameters.iNumBitErrors = 0;
+
+    /* Define block-size for input */
+    iInputBlockSize = Parameters.iNumDecodedBitsMSC;
+}
+
+
+/******************************************************************************\
+* FAC data																	   *
+\******************************************************************************/
+/* Transmitter */
+void CGenerateFACData::ProcessDataInternal(CParameter& TransmParam)
+{
+    FACTransmit.FACParam(pvecOutputData, TransmParam);
+}
+
+void CGenerateFACData::InitInternal(CParameter& TransmParam)
+{
+    FACTransmit.Init(TransmParam);
+
+    /* Define block-size for output */
+    iOutputBlockSize = TransmParam.iNumFACBitsPerBlock;
+}
+
+/* Receiver */
+void CUtilizeFACData::ProcessDataInternal(CParameter& Parameters)
+{
+    /* Do not use received FAC data in case of simulation */
+    if (bSyncInput == FALSE)
+    {
+        bCRCOk = FACReceive.FACParam(pvecInputData, Parameters);
+        /* Set FAC status for RSCI, log file & GUI */
+        if (bCRCOk)
+            Parameters.ReceiveStatus.FAC.SetStatus(RX_OK);
+        else
+            Parameters.ReceiveStatus.FAC.SetStatus(CRC_ERROR);
+    }
+
+    if ((bSyncInput == TRUE) || (bCRCOk == FALSE))
+    {
+        /* If FAC CRC check failed we should increase the frame-counter
+           manually. If only FAC data was corrupted, the others can still
+           decode if they have the right frame number. In case of simulation
+           no FAC data is used, we have to increase the counter here */
+        Parameters.iFrameIDReceiv++;
+
+        if (Parameters.iFrameIDReceiv == NUM_FRAMES_IN_SUPERFRAME)
+            Parameters.iFrameIDReceiv = 0;
+    }
+}
+
+void CUtilizeFACData::InitInternal(CParameter& Parameters)
+{
+
+// This should be in FAC class in an Init() routine which has to be defined, this
+// would be cleaner code! TODO
+    /* Init frame ID so that a "0" comes after increasing the init value once */
+    Parameters.iFrameIDReceiv = NUM_FRAMES_IN_SUPERFRAME - 1;
+
+    /* Reset flag */
+    bCRCOk = FALSE;
+
+    /* Define block-size for input */
+    iInputBlockSize = Parameters.iNumFACBitsPerBlock;
+}
+
+
+/******************************************************************************\
+* SDC data																	   *
+\******************************************************************************/
+/* Transmitter */
+void CGenerateSDCData::ProcessDataInternal(CParameter& TransmParam)
+{
+    SDCTransmit.SDCParam(pvecOutputData, TransmParam);
+}
+
+void CGenerateSDCData::InitInternal(CParameter& TransmParam)
+{
+    /* Define block-size for output */
+    iOutputBlockSize = TransmParam.iNumSDCBitsPerSFrame;
+}
+
+/* Receiver */
+void CUtilizeSDCData::ProcessDataInternal(CParameter& Parameters)
+{
+//    _BOOLEAN bSDCOK = FALSE;
+
+    /* Decode SDC block and return CRC status */
+    CSDCReceive::ERetStatus eStatus = SDCReceive.SDCParam(pvecInputData, Parameters);
+
+    Parameters.Lock();
+    switch (eStatus)
+    {
+    case CSDCReceive::SR_OK:
+        Parameters.ReceiveStatus.SDC.SetStatus(RX_OK);
+//        bSDCOK = TRUE;
+        break;
+
+    case CSDCReceive::SR_BAD_CRC:
+        /* SDC block depends on only a few parameters: robustness mode,
+           DRM bandwidth and coding scheme (can be 4 or 16 QAM). If we
+           initialize these parameters with resonable parameters it might
+           be possible that these are the correct parameters. Therefore
+           try to decode SDC even in case FAC wasn't decoded. That might
+           speed up the DRM signal acqisition. But quite often it is the
+           case that the parameters are not correct. In this case do not
+           show a red light if SDC CRC was not ok */
+        if (bFirstBlock == FALSE)
+            Parameters.ReceiveStatus.SDC.SetStatus(CRC_ERROR);
+        break;
+
+    case CSDCReceive::SR_BAD_DATA:
+        /* CRC was ok but data seems to be incorrect */
+        Parameters.ReceiveStatus.SDC.SetStatus(DATA_ERROR);
+        break;
+    }
+    Parameters.Unlock();
+
+    /* Reset "first block" flag */
+    bFirstBlock = FALSE;
+}
+
+void CUtilizeSDCData::InitInternal(CParameter& Parameters)
+{
+    /* Init "first block" flag */
+    bFirstBlock = TRUE;
+
+    /* Define block-size for input */
+    iInputBlockSize = Parameters.iNumSDCBitsPerSFrame;
+}
+
+
+/* CWriteIQFile : module for writing an IQ or IF file */
+
+CWriteIQFile::CWriteIQFile() : pFile(0), iFrequency(0), bIsRecording(FALSE), bChangeReceived(FALSE)
+{
+}
+
+CWriteIQFile::~CWriteIQFile()
+{
+    if (pFile != 0)
+        fclose(pFile);
+}
+
+void CWriteIQFile::StartRecording(CParameter&)
+{
+    bIsRecording = TRUE;
+    bChangeReceived = TRUE;
+}
+
+void CWriteIQFile::OpenFile(CParameter& Parameters)
+{
+    iFrequency = Parameters.GetFrequency();
+
+    /* Get current UTC time */
+    time_t ltime;
+    time(&ltime);
+    struct tm* gmtCur = gmtime(&ltime);
+
+    stringstream filename;
+    filename << Parameters.sReceiverID << "_";
+    filename << setw(4) << setfill('0') << gmtCur->tm_year + 1900 << "-" << setw(2) << setfill('0')<< gmtCur->tm_mon + 1;
+    filename << "-" << setw(2) << setfill('0')<< gmtCur->tm_mday << "_";
+    filename << setw(2) << setfill('0') << gmtCur->tm_hour << "-" << setw(2) << setfill('0')<< gmtCur->tm_min;
+    filename << "-" << setw(2) << setfill('0')<< gmtCur->tm_sec << "_";
+    filename << setw(8) << setfill('0') << (iFrequency*1000) << ".iq" << (Parameters.GetSigSampleRate()/1000);
+
+    pFile = fopen(filename.str().c_str(), "wb");
+
+}
+
+void CWriteIQFile::StopRecording()
+{
+    bIsRecording = FALSE;
+    bChangeReceived = TRUE;
+}
+
+void CWriteIQFile::NewFrequency(CParameter &)
+{
+}
+
+void CWriteIQFile::InitInternal(CParameter& Parameters)
+{
+    /* Get parameters from info class */
+    const int iSymbolBlockSize = Parameters.CellMappingTable.iSymbolBlockSize;
+
+    iInputBlockSize = iSymbolBlockSize;
+
+    /* Init temporary vector for filter input and output */
+    rvecInpTmp.Init(iSymbolBlockSize);
+    cvecHilbert.Init(iSymbolBlockSize);
+
+    /* Init mixer */
+    Mixer.Init(iSymbolBlockSize);
+
+    /* Inits for Hilbert and DC filter -------------------------------------- */
+    /* Hilbert filter block length is the same as input block length */
+    iHilFiltBlLen = iSymbolBlockSize;
+
+    /* Init state vector for filtering with zeros */
+    rvecZReal.Init(iHilFiltBlLen, (CReal) 0.0);
+    rvecZImag.Init(iHilFiltBlLen, (CReal) 0.0);
+
+    /* "+ 1" because of the Nyquist frequency (filter in frequency domain) */
+    cvecBReal.Init(iHilFiltBlLen + 1);
+    cvecBImag.Init(iHilFiltBlLen + 1);
+
+    /* FFT plans are initialized with the long length */
+    FftPlansHilFilt.Init(iHilFiltBlLen * 2);
+
+    /* Set up the band-pass filter */
+
+    /* Set internal parameter */
+    const CReal rBPNormBW = CReal(0.4);
+
+    /* Actual prototype filter design */
+    CRealVector vecrFilter(iHilFiltBlLen);
+    vecrFilter = FirLP(rBPNormBW, Nuttallwin(iHilFiltBlLen));
+
+    /* Assume the IQ will be centred on a quarter of the soundcard sampling rate (e.g. 12kHz @ 48kHz) */
+    const CReal rBPNormCentOffset = CReal(0.25);
+
+    /* Set filter coefficients ---------------------------------------------- */
+    /* Not really necessary since bandwidth will never be changed */
+    const CReal rStartPhase = (CReal) iHilFiltBlLen * crPi * rBPNormCentOffset;
+
+    /* Copy actual filter coefficients. It is important to initialize the
+       vectors with zeros because we also do a zero-padding */
+    CRealVector rvecBReal(2 * iHilFiltBlLen, (CReal) 0.0);
+    CRealVector rvecBImag(2 * iHilFiltBlLen, (CReal) 0.0);
+    for (int i = 0; i < iHilFiltBlLen; i++)
+    {
+        rvecBReal[i] = vecrFilter[i] *
+                       Cos((CReal) 2.0 * crPi * rBPNormCentOffset * i - rStartPhase);
+
+        rvecBImag[i] = vecrFilter[i] *
+                       Sin((CReal) 2.0 * crPi * rBPNormCentOffset * i - rStartPhase);
+    }
+
+    /* Transformation in frequency domain for fft filter */
+    cvecBReal = rfft(rvecBReal, FftPlansHilFilt);
+    cvecBImag = rfft(rvecBImag, FftPlansHilFilt);
+
+}
+
+void CWriteIQFile::ProcessDataInternal(CParameter& Parameters)
+{
+    int i;
+
+    if (bChangeReceived) // file is open but we want to start a new one
+    {
+        bChangeReceived = FALSE;
+        if (pFile != NULL)
+        {
+            fclose(pFile);
+        }
+        pFile = 0;
+    }
+
+    // is recording switched on?
+    if (!bIsRecording)
+    {
+        if (pFile != NULL)
+        {
+            fclose(pFile); // close file if currently open
+            pFile = NULL;
+        }
+        return;
+    }
+
+
+    // Has the frequency changed? If so, close any open file (a new one will be opened)
+    int iNewFrequency = Parameters.GetFrequency();
+
+    if (iNewFrequency != iFrequency)
+    {
+        iFrequency = iNewFrequency;
+        // If file is currently open, close it
+        if (pFile != NULL)
+        {
+            fclose(pFile);
+            pFile = NULL;
+        }
+    }
+    // Now open the file with correct name if it isn't currently open
+    if (!pFile)
+    {
+        OpenFile(Parameters);
+    }
+
+    /* Band-pass filter and mixer ------------------------------------------- */
+    /* Copy CVector data in CMatlibVector */
+    for (i = 0; i < iInputBlockSize; i++)
+        rvecInpTmp[i] = (*pvecInputData)[i];
+
+    /* Cut out a spectrum part of desired bandwidth */
+    cvecHilbert = CComplexVector(
+                      FftFilt(cvecBReal, rvecInpTmp, rvecZReal, FftPlansHilFilt),
+                      FftFilt(cvecBImag, rvecInpTmp, rvecZImag, FftPlansHilFilt));
+
+    /* Mix it down to zero frequency */
+    Mixer.SetMixFreq(CReal(0.25));
+    Mixer.Process(cvecHilbert);
+
+    /* Write to the file */
+
+    _SAMPLE re, im;
+    _BYTE bytes[4];
+
+    CReal rScale = CReal(1.0);
+    for (i=0; i<iInputBlockSize; i++)
+    {
+        re = _SAMPLE(cvecHilbert[i].real() * rScale);
+        im = _SAMPLE(cvecHilbert[i].imag() * rScale);
+        bytes[0] = _BYTE(re & 0xFF);
+        bytes[1] = _BYTE((re>>8) & 0xFF);
+        bytes[2] = _BYTE(im & 0xFF);
+        bytes[3] = _BYTE((im>>8) & 0xFF);
+
+        fwrite(bytes, 4, sizeof(_BYTE), pFile);
+    }
+}
+
diff --git a/src/DataIO.h b/src/DataIO.h
new file mode 100644
index 0000000..015caae
--- /dev/null
+++ b/src/DataIO.h
@@ -0,0 +1,340 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer, Andrew Murphy
+ *
+ * Description:
+ *	See Data.cpp
+ *
+ * 11/21/2005 Andrew Murphy, BBC Research & Development, 2005
+ *	- Addition GetSDCReceive(), Added CSplit class
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#if !defined(DATA_H__3B0BA660_CA63_4344_BB2B_23E7A0D31912__INCLUDED_)
+#define DATA_H__3B0BA660_CA63_4344_BB2B_23E7A0D31912__INCLUDED_
+
+#include "sound/soundinterface.h"
+#include "Parameter.h"
+#include "util/Modul.h"
+#include "FAC/FAC.h"
+#include "SDC/SDC.h"
+#include "TextMessage.h"
+#include "util/AudioFile.h"
+#include "util/Utilities.h"
+#include "AMDemodulation.h" // For CMixer
+
+/* Definitions ****************************************************************/
+/* Maximum frequency for audio spectrum */
+#define MAX_SPEC_AUDIO_FREQUENCY	20000 /* Hz */
+
+/* In case of random-noise, define number of blocks */
+#define DEFAULT_NUM_SIM_BLOCKS		50
+
+/* Time span used for averaging the audio spectrum. Shall be higher than the
+   400 ms DRM audio block */
+#define TIME_AV_AUDIO_SPECT_MS		500 /* ms */
+
+/* Normalization constant for two mixed signals. If this constant is 2, no
+   overrun of the "short" variable can happen but signal has quite much lower
+   power -> compromise */
+#define MIX_OUT_CHAN_NORM_CONST		((_REAL) 1.0 / sqrt((_REAL) 2.0))
+
+
+/* Classes ********************************************************************/
+/* MSC ---------------------------------------------------------------------- */
+class CReadData : public CTransmitterModul<_SAMPLE, _SAMPLE>
+{
+public:
+    CReadData(CSoundInInterface* pNS) : pSound(pNS) {}
+    virtual ~CReadData() {}
+
+    _REAL GetLevelMeter() {
+        return SignalLevelMeter.Level();
+    }
+
+protected:
+    CSoundInInterface*	pSound;
+    CVector<_SAMPLE>	vecsSoundBuffer;
+    CSignalLevelMeter	SignalLevelMeter;
+
+    virtual void InitInternal(CParameter& TransmParam);
+    virtual void ProcessDataInternal(CParameter& TransmParam);
+};
+
+class CWriteData : public CReceiverModul<_SAMPLE, _SAMPLE>
+{
+public:
+    enum EOutChanSel {CS_BOTH_BOTH, CS_LEFT_LEFT, CS_RIGHT_RIGHT,
+                      CS_LEFT_MIX, CS_RIGHT_MIX
+                     };
+
+    CWriteData(CSoundOutInterface* pNS);
+    virtual ~CWriteData() {}
+
+    void StartWriteWaveFile(const string& strFileName);
+    _BOOLEAN GetIsWriteWaveFile() {
+        return bDoWriteWaveFile;
+    }
+    void StopWriteWaveFile();
+
+    void MuteAudio(_BOOLEAN bNewMA) {
+        bMuteAudio = bNewMA;
+    }
+    _BOOLEAN GetMuteAudio() {
+        return bMuteAudio;
+    }
+
+    void SetSoundBlocking(const _BOOLEAN bNewBl)
+    {
+        bNewSoundBlocking = bNewBl;
+        SetInitFlag();
+    }
+
+    void GetAudioSpec(CVector<_REAL>& vecrData, CVector<_REAL>& vecrScale);
+
+    void SetOutChanSel(const EOutChanSel eNS) {
+        eOutChanSel = eNS;
+    }
+    EOutChanSel GetOutChanSel() {
+        return eOutChanSel;
+    }
+
+protected:
+    CSoundOutInterface*		pSound;
+    _BOOLEAN				bMuteAudio;
+    CWaveFile				WaveFileAudio;
+    _BOOLEAN				bDoWriteWaveFile;
+    _BOOLEAN				bSoundBlocking;
+    _BOOLEAN				bNewSoundBlocking;
+    CVector<_SAMPLE>		vecsTmpAudData;
+    EOutChanSel				eOutChanSel;
+    _REAL					rMixNormConst;
+
+    CShiftRegister<_SAMPLE>	vecsOutputData;
+    CFftPlans				FftPlan;
+    CComplexVector			veccFFTInput;
+    CComplexVector			veccFFTOutput;
+    CRealVector				vecrAudioWindowFunction;
+    int						iAudSampleRate;
+    int                     iNumSmpls4AudioSprectrum;
+    int                     iNumBlocksAvAudioSpec;
+    int                     iMaxAudioFrequency;
+
+    virtual void InitInternal(CParameter& Parameters);
+    virtual void ProcessDataInternal(CParameter& Parameters);
+};
+
+class CGenSimData : public CTransmitterModul<_BINARY, _BINARY>
+{
+public:
+    CGenSimData() : eCntType(CT_TIME), iNumSimBlocks(DEFAULT_NUM_SIM_BLOCKS),
+            iNumErrors(0), iCounter(0), strFileName("SimTime.dat"), tiStartTime(0) {}
+    virtual ~CGenSimData() {}
+
+    void SetSimTime(int iNewTi, string strNewFileName);
+    void SetNumErrors(int iNewNE, string strNewFileName);
+
+protected:
+    enum ECntType {CT_TIME, CT_ERRORS};
+    ECntType	eCntType;
+    int			iNumSimBlocks;
+    int			iNumErrors;
+    int			iCounter;
+    int			iMinNumBlocks;
+    string		strFileName;
+    time_t		tiStartTime;
+
+    virtual void InitInternal(CParameter& TransmParam);
+    virtual void ProcessDataInternal(CParameter& TransmParam);
+};
+
+class CEvaSimData : public CReceiverModul<_BINARY, _BINARY>
+{
+public:
+    CEvaSimData() {}
+    virtual ~CEvaSimData() {}
+
+protected:
+    int		iIniCnt;
+    int		iNumAccBitErrRate;
+    _REAL	rAccBitErrRate;
+
+    virtual void InitInternal(CParameter& Parameters);
+    virtual void ProcessDataInternal(CParameter& Parameters);
+};
+
+
+/* FAC ---------------------------------------------------------------------- */
+class CGenerateFACData : public CTransmitterModul<_BINARY, _BINARY>
+{
+public:
+    CGenerateFACData() {}
+    virtual ~CGenerateFACData() {}
+
+protected:
+    CFACTransmit FACTransmit;
+
+    virtual void InitInternal(CParameter& TransmParam);
+    virtual void ProcessDataInternal(CParameter& TransmParam);
+};
+
+class CUtilizeFACData : public CReceiverModul<_BINARY, _BINARY>
+{
+public:
+    CUtilizeFACData() :
+            bSyncInput(FALSE), bCRCOk(FALSE) {}
+    virtual ~CUtilizeFACData() {}
+
+    /* To set the module up for synchronized DRM input data stream */
+    void SetSyncInput(_BOOLEAN bNewS) {
+        bSyncInput = bNewS;
+    }
+
+    _BOOLEAN GetCRCOk() const {
+        return bCRCOk;
+    }
+
+protected:
+    CFACReceive FACReceive;
+    _BOOLEAN	bSyncInput;
+    _BOOLEAN	bCRCOk;
+
+    virtual void InitInternal(CParameter& Parameters);
+    virtual void ProcessDataInternal(CParameter& Parameters);
+};
+
+
+/* SDC ---------------------------------------------------------------------- */
+class CGenerateSDCData : public CTransmitterModul<_BINARY, _BINARY>
+{
+public:
+    CGenerateSDCData() {}
+    virtual ~CGenerateSDCData() {}
+
+protected:
+    CSDCTransmit SDCTransmit;
+
+    virtual void InitInternal(CParameter& TransmParam);
+    virtual void ProcessDataInternal(CParameter& TransmParam);
+};
+
+class CUtilizeSDCData : public CReceiverModul<_BINARY, _BINARY>
+{
+public:
+    CUtilizeSDCData() {}
+    virtual ~CUtilizeSDCData() {}
+
+    CSDCReceive* GetSDCReceive() {
+        return &SDCReceive;
+    }
+
+protected:
+    CSDCReceive SDCReceive;
+    _BOOLEAN	bFirstBlock;
+
+    virtual void InitInternal(CParameter& Parameters);
+    virtual void ProcessDataInternal(CParameter& Parameters);
+};
+
+
+/******************************************************************************\
+* Data type conversion classes needed for simulation and AMSS decoding         *
+\******************************************************************************/
+/* Conversion from channel output to resample module input */
+class CDataConvChanResam : public CReceiverModul<CChanSimDataMod, _REAL>
+{
+protected:
+    virtual void InitInternal(CParameter& Parameters)
+    {
+        iInputBlockSize = Parameters.CellMappingTable.iSymbolBlockSize;
+        iOutputBlockSize = Parameters.CellMappingTable.iSymbolBlockSize;
+    }
+    virtual void ProcessDataInternal(CParameter&)
+    {
+        for (int i = 0; i < iOutputBlockSize; i++)
+            (*pvecOutputData)[i] = (*pvecInputData)[i].tOut;
+    }
+};
+
+/* Takes an input buffer and splits it 2 ways */
+class CSplit: public CReceiverModul<_REAL, _REAL>
+{
+protected:
+    virtual void InitInternal(CParameter& Parameters)
+    {
+        iInputBlockSize = Parameters.CellMappingTable.iSymbolBlockSize;
+        iOutputBlockSize = Parameters.CellMappingTable.iSymbolBlockSize;
+        iOutputBlockSize2 = Parameters.CellMappingTable.iSymbolBlockSize;
+    }
+    virtual void ProcessDataInternal(CParameter&)
+    {
+        for (int i = 0; i < iInputBlockSize; i++)
+        {
+            (*pvecOutputData)[i] = (*pvecInputData)[i];
+            (*pvecOutputData2)[i] = (*pvecInputData)[i];
+        }
+    }
+};
+
+
+class CWriteIQFile : public CReceiverModul<_REAL, _REAL>
+{
+public:
+    CWriteIQFile();
+    virtual ~CWriteIQFile();
+
+    void StartRecording(CParameter& Parameters);
+    void StopRecording();
+
+    void NewFrequency(CParameter &Parameters);
+
+	_BOOLEAN IsRecording() {return bIsRecording;}
+
+protected:
+    FILE *					pFile;
+    CVector<_SAMPLE>		vecsTmpAudData;
+
+    virtual void InitInternal(CParameter& Parameters);
+    virtual void ProcessDataInternal(CParameter& Parameters);
+    void		 OpenFile(CParameter& Parameters);
+
+    /* For doing the IF to IQ conversion (stolen from AM demod) */
+    CRealVector					rvecInpTmp;
+    CComplexVector				cvecHilbert;
+    int							iHilFiltBlLen;
+    CFftPlans					FftPlansHilFilt;
+
+    CComplexVector				cvecBReal;
+    CComplexVector				cvecBImag;
+    CRealVector					rvecZReal;
+    CRealVector					rvecZImag;
+
+    CMixer						Mixer;
+
+    int							iFrequency; // For use in generating filename
+    _BOOLEAN					bIsRecording;
+    _BOOLEAN					bChangeReceived;
+
+};
+
+
+#endif // !defined(DATA_H__3B0BA660_CA63_4344_BB2B_23E7A0D31912__INCLUDED_)
diff --git a/src/DrmReceiver.cpp b/src/DrmReceiver.cpp
new file mode 100644
index 0000000..5009a97
--- /dev/null
+++ b/src/DrmReceiver.cpp
@@ -0,0 +1,1912 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer, Andrew Murphy, Julian Cable
+ *
+ * Description:
+ *	DRM-receiver
+ * The hand over of data is done via an intermediate-buffer. The calling
+ * convention is always "input-buffer, output-buffer". Additionally, the
+ * DRM-parameters are fed to the function.
+ *
+ * 11/21/2005 Andrew Murphy, BBC Research & Development, 2005
+ *	- Additions to include AMSS demodulation
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "DrmReceiver.h"
+#include "util/Settings.h"
+#include "util/Utilities.h"
+#include "util/FileTyper.h"
+
+#include "sound/sound.h"
+#include "sound/soundnull.h"
+#include "sound/audiofilein.h"
+#ifdef USE_CONSOLEIO
+# include "linux/ConsoleIO.h"
+#endif
+#if 0
+#include <fcd.h>
+#endif
+const int
+CDRMReceiver::MAX_UNLOCKED_COUNT = 2;
+
+/* Implementation *************************************************************/
+CDRMReceiver::CDRMReceiver(CSettings* pSettings) : CDRMTransceiver(pSettings, new CSoundInNull, new CSoundOut),
+    ReceiveData(), WriteData(pSoundOutInterface),
+    FreqSyncAcq(),
+    ChannelEstimation(),
+    UtilizeFACData(), UtilizeSDCData(), MSCDemultiplexer(),
+    AudioSourceDecoder(),
+    pUpstreamRSCI(new CUpstreamDI()), DecodeRSIMDI(), downstreamRSCI(),
+    RSIPacketBuf(),
+    MSCDecBuf(MAX_NUM_STREAMS), MSCUseBuf(MAX_NUM_STREAMS),
+    MSCSendBuf(MAX_NUM_STREAMS), iAcquRestartCnt(0),
+    iAcquDetecCnt(0), iGoodSignCnt(0), eReceiverMode(RM_DRM),
+    eNewReceiverMode(RM_DRM), iAudioStreamID(STREAM_ID_NOT_USED),
+    iDataStreamID(STREAM_ID_NOT_USED), bRestartFlag(TRUE),
+    rInitResampleOffset((_REAL) 0.0),
+    iBwAM(10000), iBwLSB(5000), iBwUSB(5000), iBwCW(150), iBwFM(6000),
+    time_keeper(0), sfCallback(NULL), sfCallbackParam(NULL),
+    PlotManager(), iPrevSigSampleRate(0)
+{
+    Parameters.SetReceiver(this);
+    downstreamRSCI.SetReceiver(this);
+    PlotManager.SetReceiver(this);
+#ifdef HAVE_LIBGPS
+    Parameters.gps_data.gps_fd = -1;
+#endif
+}
+
+CDRMReceiver::~CDRMReceiver()
+{
+    delete pSoundInInterface;
+    delete pSoundOutInterface;
+    delete pUpstreamRSCI;
+}
+
+void
+CDRMReceiver::SetReceiverMode(ERecMode eNewMode)
+{
+    if (eReceiverMode!=eNewMode || eNewReceiverMode != RM_NONE)
+        eNewReceiverMode = eNewMode;
+}
+
+void
+CDRMReceiver::SetAMDemodType(CAMDemodulation::EDemodType eNew)
+{
+    AMDemodulation.SetDemodType(eNew);
+    switch (eNew)
+    {
+    case CAMDemodulation::DT_AM:
+        AMDemodulation.SetFilterBW(iBwAM);
+        break;
+
+    case CAMDemodulation::DT_LSB:
+        AMDemodulation.SetFilterBW(iBwLSB);
+        break;
+
+    case CAMDemodulation::DT_USB:
+        AMDemodulation.SetFilterBW(iBwUSB);
+        break;
+
+    case CAMDemodulation::DT_CW:
+        AMDemodulation.SetFilterBW(iBwCW);
+        break;
+
+    case CAMDemodulation::DT_FM:
+        AMDemodulation.SetFilterBW(iBwFM);
+        break;
+    }
+}
+
+void
+CDRMReceiver::SetAMFilterBW(int value)
+{
+    /* Store filter bandwidth for this demodulation type */
+    switch (AMDemodulation.GetDemodType())
+    {
+    case CAMDemodulation::DT_AM:
+        iBwAM = value;
+        break;
+
+    case CAMDemodulation::DT_LSB:
+        iBwLSB = value;
+        break;
+
+    case CAMDemodulation::DT_USB:
+        iBwUSB = value;
+        break;
+
+    case CAMDemodulation::DT_CW:
+        iBwCW = value;
+        break;
+
+    case CAMDemodulation::DT_FM:
+        iBwFM = value;
+        break;
+    }
+    AMDemodulation.SetFilterBW(value);
+}
+
+void
+CDRMReceiver::Run()
+{
+    _BOOLEAN bEnoughData = TRUE;
+    _BOOLEAN bFrameToSend = FALSE;
+    size_t i;
+    /* Check for parameter changes from RSCI or GUI thread --------------- */
+    /* The parameter changes are done through flags, the actual initialization
+     * is done in this (the working) thread to avoid problems with shared data */
+    if (eNewReceiverMode != RM_NONE)
+        InitReceiverMode();
+
+#ifdef HAVE_LIBGPS
+//TODO locking
+    gps_data_t* gps_data = &Parameters.gps_data;
+    int result=0;
+    if(Parameters.restart_gpsd)
+    {
+        stringstream s;
+        s <<  Parameters.gps_port;
+        if(gps_data->gps_fd != -1) (void)gps_close(gps_data);
+# if GPSD_API_MAJOR_VERSION < 5
+        result = gps_open_r(Parameters.gps_host.c_str(), s.str().c_str(), gps_data);
+        if(!result) (void)gps_stream(gps_data, WATCH_ENABLE|POLL_NONBLOCK, NULL);
+# else
+        result = gps_open(Parameters.gps_host.c_str(), s.str().c_str(), gps_data);
+        if(!result) (void)gps_stream(gps_data, WATCH_ENABLE, NULL);
+# endif
+        if(result) gps_data->gps_fd = -1;
+        Parameters.restart_gpsd = false;
+    }
+    if(gps_data->gps_fd != -1)
+    {
+        if(Parameters.use_gpsd)
+# if GPSD_API_MAJOR_VERSION < 5
+            result = gps_poll(gps_data);
+# else
+            result = gps_read(gps_data);
+# endif
+        else
+        {
+            (void)gps_close(gps_data);
+            gps_data->gps_fd = -1;
+        }
+    }
+	(void)result;
+#endif
+
+    if (bRestartFlag) /* new acquisition requested by GUI */
+    {
+        bRestartFlag = FALSE;
+        SetInStartMode();
+    }
+
+    /* Input - from upstream RSCI or input and demodulation from sound card / file */
+    if (pUpstreamRSCI->GetInEnabled() == TRUE)
+    {
+        RSIPacketBuf.Clear();
+        pUpstreamRSCI->ReadData(Parameters, RSIPacketBuf);
+        if (RSIPacketBuf.GetFillLevel() > 0)
+        {
+            time_keeper = time(NULL);
+            DecodeRSIMDI.ProcessData(Parameters, RSIPacketBuf, FACDecBuf, SDCDecBuf, MSCDecBuf);
+            // HACK until understand where it should go
+            int n = FACDecBuf.GetFillLevel();
+            if(n != Parameters.iNumFACBitsPerBlock)
+            {
+                Parameters.iNumFACBitsPerBlock = n;
+                SplitFAC.SetInitFlag();
+                UtilizeFACData.SetInitFlag();
+            }
+            PlotManager.UpdateParamHistoriesRSIIn();
+            bFrameToSend = TRUE;
+        }
+        else
+        {
+            time_t now = time(NULL);
+            if ((now - time_keeper) > 2)
+            {
+                Parameters.ReceiveStatus.InterfaceI.SetStatus(NOT_PRESENT);
+                Parameters.ReceiveStatus.InterfaceO.SetStatus(NOT_PRESENT);
+                Parameters.ReceiveStatus.TSync.SetStatus(NOT_PRESENT);
+                Parameters.ReceiveStatus.FSync.SetStatus(NOT_PRESENT);
+                Parameters.ReceiveStatus.FAC.SetStatus(NOT_PRESENT);
+                Parameters.ReceiveStatus.SDC.SetStatus(NOT_PRESENT);
+                Parameters.ReceiveStatus.SLAudio.SetStatus(NOT_PRESENT);
+            }
+        }
+    }
+    else
+    {
+
+        if (WriteIQFile.IsRecording())
+        {
+            /* Receive data in RecDataBuf */
+            ReceiveData.ReadData(Parameters, RecDataBuf);
+
+            /* Split samples, one output to the demodulation, another for IQ recording */
+            if (SplitForIQRecord.ProcessData(Parameters, RecDataBuf, DemodDataBuf, IQRecordDataBuf))
+            {
+                bEnoughData = TRUE;
+            }
+        }
+        else
+        {
+            /* No I/Q recording then receive data directly in DemodDataBuf */
+            ReceiveData.ReadData(Parameters, DemodDataBuf);
+        }
+
+        switch (eReceiverMode)
+        {
+        case RM_DRM:
+            DemodulateDRM(bEnoughData);
+            DecodeDRM(bEnoughData, bFrameToSend);
+            break;
+        case RM_AM:
+            DemodulateAM(bEnoughData);
+            DecodeAM(bEnoughData);
+            break;
+        case RM_FM:
+            DemodulateFM(bEnoughData);
+            DecodeFM(bEnoughData);
+            break;
+        case RM_NONE:
+            break;
+        }
+    }
+
+    /* Split the data for downstream RSCI and local processing. TODO make this conditional */
+    switch (eReceiverMode)
+    {
+    case RM_DRM:
+        SplitFAC.ProcessData(Parameters, FACDecBuf, FACUseBuf, FACSendBuf);
+
+        /* if we have an SDC block, make a copy and keep it until the next frame is to be sent */
+        if (SDCDecBuf.GetFillLevel() == Parameters.iNumSDCBitsPerSFrame)
+        {
+            SplitSDC.ProcessData(Parameters, SDCDecBuf, SDCUseBuf, SDCSendBuf);
+        }
+
+        for (i = 0; i < MSCDecBuf.size(); i++)
+        {
+            SplitMSC[i].ProcessData(Parameters, MSCDecBuf[i], MSCUseBuf[i], MSCSendBuf[i]);
+        }
+        break;
+    case RM_AM:
+        SplitAudio.ProcessData(Parameters, AMAudioBuf, AudSoDecBuf, AMSoEncBuf);
+        break;
+    case RM_FM:
+        SplitAudio.ProcessData(Parameters, AMAudioBuf, AudSoDecBuf, AMSoEncBuf);
+        break;
+    case RM_NONE:
+        break;
+    }
+
+    /* Decoding */
+    while (bEnoughData &&
+        (Parameters.eRunState==CParameter::RUNNING ||
+         Parameters.eRunState==CParameter::RESTART))
+    {
+        /* Init flag */
+        bEnoughData = FALSE;
+
+        // Write output I/Q file
+        if (WriteIQFile.IsRecording())
+        {
+            if (WriteIQFile.WriteData(Parameters, IQRecordDataBuf))
+            {
+                bEnoughData = TRUE;
+            }
+        }
+
+        switch (eReceiverMode)
+        {
+        case RM_DRM:
+            UtilizeDRM(bEnoughData);
+            break;
+        case RM_AM:
+            UtilizeAM(bEnoughData);
+            break;
+        case RM_FM:
+            UtilizeFM(bEnoughData);
+            break;
+        case RM_NONE:
+            break;
+        }
+    }
+
+    /* Output to downstream RSCI */
+    if (downstreamRSCI.GetOutEnabled())
+    {
+        switch (eReceiverMode)
+        {
+        case RM_DRM:
+            if (Parameters.eAcquiState == AS_NO_SIGNAL)
+            {
+                /* we will get one of these between each FAC block, and occasionally we */
+                /* might get two, so don't start generating free-wheeling RSCI until we've. */
+                /* had three in a row */
+                if (FreqSyncAcq.GetUnlockedFrameBoundary())
+                {
+                    if (iUnlockedCount < MAX_UNLOCKED_COUNT)
+                        iUnlockedCount++;
+                    else
+                        downstreamRSCI.SendUnlockedFrame(Parameters);
+                }
+            }
+            else if (bFrameToSend)
+            {
+                downstreamRSCI.SendLockedFrame(Parameters, FACSendBuf, SDCSendBuf, MSCSendBuf);
+                iUnlockedCount = 0;
+                bFrameToSend = FALSE;
+            }
+            break;
+        case RM_AM:
+        case RM_FM:
+            /* Encode audio for RSI output */
+            if (AudioSourceEncoder.ProcessData(Parameters, AMSoEncBuf, MSCSendBuf[0]))
+                bFrameToSend = TRUE;
+
+            if (bFrameToSend)
+                downstreamRSCI.SendAMFrame(Parameters, MSCSendBuf[0]);
+            break;
+        case RM_NONE:
+            break;
+        }
+    }
+    /* Check for RSCI commands */
+    if (downstreamRSCI.GetInEnabled())
+    {
+        downstreamRSCI.poll();
+    }
+
+    /* Play and/or save the audio */
+    if (iAudioStreamID != STREAM_ID_NOT_USED || (eReceiverMode == RM_AM) || (eReceiverMode == RM_FM))
+    {
+        if (WriteData.WriteData(Parameters, AudSoDecBuf))
+        {
+            bEnoughData = TRUE;
+        }
+    }
+}
+
+void
+CDRMReceiver::SetInput()
+{
+    string sSndDevIn;
+    Parameters.Lock();
+        /* Fetch new sample rate if any */
+        Parameters.FetchNewSampleRate();
+        /* Close previous sound interface */
+        if (pSoundInInterface != NULL)
+        {
+            sSndDevIn = pSoundInInterface->GetDev();
+            pSoundInInterface->Close();
+            delete pSoundInInterface;
+        }
+        /* Get a fresh CUpstreamDI interface */
+        if (pUpstreamRSCI->GetInEnabled())
+        {
+            delete pUpstreamRSCI;
+            pUpstreamRSCI = new CUpstreamDI();
+        }
+        /* Check for RSCI file */
+        if (rsiOrigin != "")
+        {
+            ReceiveData.ClearInputData();
+            pSoundInInterface = new CSoundInNull();
+            pUpstreamRSCI->SetOrigin(rsiOrigin);
+        }
+        else
+        {
+            /* SetSyncInput to FALSE, can be modified by pUpstreamRSCI */
+            InputResample.SetSyncInput(FALSE);
+            SyncUsingPil.SetSyncInput(FALSE);
+            TimeSync.SetSyncInput(FALSE);
+            /* Check for Sound file */
+            if (sSoundFile != "")
+            {
+                /* Save sample rate */
+                if (iPrevSigSampleRate == 0)
+                    iPrevSigSampleRate = Parameters.GetSoundCardSigSampleRate();
+                /* Open sound file interface */
+                CAudioFileIn* AudioFileIn = new CAudioFileIn();
+                AudioFileIn->SetFileName(sSoundFile);
+                const int iSampleRate = AudioFileIn->GetSampleRate();
+                Parameters.SetSoundCardSigSampleRate(iSampleRate);
+                pSoundInInterface = AudioFileIn;
+            }
+            else
+            {
+                /* Open sound card interface */
+                pSoundInInterface = new CSoundIn();
+            }
+        }
+        pSoundInInterface->SetDev(sSndDevIn);
+    Parameters.Unlock();
+}
+
+void
+CDRMReceiver::ResetInput()
+{
+    if (iPrevSigSampleRate != 0)
+    {
+        Parameters.SetSoundCardSigSampleRate(iPrevSigSampleRate);
+        iPrevSigSampleRate = 0;
+    }
+}
+
+void
+CDRMReceiver::SetRsciInput(const string& rsciInput)
+{
+    Parameters.Lock();
+        rsiOrigin = rsciInput;
+    Parameters.Unlock();
+}
+
+void
+CDRMReceiver::ClearRsciInput()
+{
+    Parameters.Lock();
+        rsiOrigin = "";
+    Parameters.Unlock();
+}
+
+void
+CDRMReceiver::SetSoundFile(const string& soundFile)
+{
+    Parameters.Lock();
+        sSoundFile = soundFile;
+    Parameters.Unlock();
+}
+
+void
+CDRMReceiver::ClearSoundFile()
+{
+    Parameters.Lock();
+        sSoundFile = "";
+    Parameters.Unlock();
+}
+
+void
+CDRMReceiver::SetInputFile(const string& inputFile)
+{
+    FileTyper::type t = FileTyper::resolve(inputFile);
+    if(FileTyper::is_rxstat(t))
+    {
+        SetRsciInput(inputFile);
+        ClearSoundFile();
+    }
+    else
+    {
+        SetSoundFile(inputFile);
+        ClearRsciInput();
+    }
+}
+
+void
+CDRMReceiver::ClearInputFile()
+{
+    ClearSoundFile();
+    ClearRsciInput();
+}
+
+CDRMReceiver::ESFStatus
+CDRMReceiver::GetInputStatus()
+{
+    CDRMReceiver::ESFStatus eStatus = SF_SNDCARDIN;
+    Parameters.Lock();
+        if (rsiOrigin != "")
+            eStatus = SF_RSCIMDIIN;
+        else if (sSoundFile != "")
+            eStatus = SF_SNDFILEIN;
+    Parameters.Unlock();
+    return eStatus;
+}
+
+string
+CDRMReceiver::GetInputFileName()
+{
+    string fileName;
+    Parameters.Lock();
+        fileName = rsiOrigin != "" ? rsiOrigin : sSoundFile;
+    Parameters.Unlock();
+    return fileName;
+}
+
+void
+CDRMReceiver::DemodulateDRM(_BOOLEAN& bEnoughData)
+{
+    /* Resample input DRM-stream -------------------------------- */
+    if (InputResample.ProcessData(Parameters, DemodDataBuf, InpResBuf))
+    {
+        bEnoughData = TRUE;
+    }
+
+    /* Frequency synchronization acquisition -------------------- */
+    if (FreqSyncAcq.ProcessData(Parameters, InpResBuf, FreqSyncAcqBuf))
+    {
+        bEnoughData = TRUE;
+    }
+
+    /* Time synchronization ------------------------------------- */
+    if (TimeSync.ProcessData(Parameters, FreqSyncAcqBuf, TimeSyncBuf))
+    {
+        bEnoughData = TRUE;
+        /* Use count of OFDM-symbols for detecting
+         * aquisition state for acquisition detection
+         * only if no signal was decoded before */
+        if (Parameters.eAcquiState == AS_NO_SIGNAL)
+        {
+            /* Increment symbol counter and check if bound is reached */
+            iAcquDetecCnt++;
+
+            if (iAcquDetecCnt > NUM_OFDMSYM_U_ACQ_WITHOUT)
+                SetInStartMode();
+        }
+    }
+
+    /* OFDM-demodulation ---------------------------------------- */
+    if (OFDMDemodulation.
+            ProcessData(Parameters, TimeSyncBuf, OFDMDemodBuf))
+    {
+        bEnoughData = TRUE;
+    }
+
+    /* Synchronization in the frequency domain (using pilots) --- */
+    if (SyncUsingPil.
+            ProcessData(Parameters, OFDMDemodBuf, SyncUsingPilBuf))
+    {
+        bEnoughData = TRUE;
+    }
+
+    /* Channel estimation and equalisation ---------------------- */
+    if (ChannelEstimation.
+            ProcessData(Parameters, SyncUsingPilBuf, ChanEstBuf))
+    {
+        bEnoughData = TRUE;
+
+        /* If this module has finished, all synchronization units
+           have also finished their OFDM symbol based estimates.
+           Update synchronization parameters histories */
+        PlotManager.UpdateParamHistories(eReceiverState);
+    }
+
+    /* Demapping of the MSC, FAC, SDC and pilots off the carriers */
+    if (OFDMCellDemapping.ProcessData(Parameters, ChanEstBuf,
+                                      MSCCarDemapBuf,
+                                      FACCarDemapBuf, SDCCarDemapBuf))
+    {
+        bEnoughData = TRUE;
+    }
+
+}
+
+void
+CDRMReceiver::DecodeDRM(_BOOLEAN& bEnoughData, _BOOLEAN& bFrameToSend)
+{
+    /* FAC ------------------------------------------------------ */
+    if (FACMLCDecoder.ProcessData(Parameters, FACCarDemapBuf, FACDecBuf))
+    {
+        bEnoughData = TRUE;
+        bFrameToSend = TRUE;
+    }
+
+    /* SDC ------------------------------------------------------ */
+    if (SDCMLCDecoder.ProcessData(Parameters, SDCCarDemapBuf, SDCDecBuf))
+    {
+        bEnoughData = TRUE;
+    }
+
+    /* MSC ------------------------------------------------------ */
+
+    /* Symbol de-interleaver */
+    if (SymbDeinterleaver.ProcessData(Parameters, MSCCarDemapBuf, DeintlBuf))
+    {
+        bEnoughData = TRUE;
+    }
+
+    /* MLC decoder */
+    if (MSCMLCDecoder.ProcessData(Parameters, DeintlBuf, MSCMLCDecBuf))
+    {
+        bEnoughData = TRUE;
+    }
+
+    /* MSC demultiplexer (will leave FAC & SDC alone! */
+    if (MSCDemultiplexer.ProcessData(Parameters, MSCMLCDecBuf, MSCDecBuf))
+    {
+        bEnoughData = TRUE;
+    }
+}
+
+void
+CDRMReceiver::UtilizeDRM(_BOOLEAN& bEnoughData)
+{
+    if (UtilizeFACData.WriteData(Parameters, FACUseBuf))
+    {
+        bEnoughData = TRUE;
+
+        /* Use information of FAC CRC for detecting the acquisition
+           requirement */
+        DetectAcquiFAC();
+    }
+#if 0
+        saveSDCtoFile();
+#endif
+
+    if (UtilizeSDCData.WriteData(Parameters, SDCUseBuf))
+    {
+        bEnoughData = TRUE;
+    }
+
+    /* Data decoding */
+    if (iDataStreamID != STREAM_ID_NOT_USED)
+    {
+        if (DataDecoder.WriteData(Parameters, MSCUseBuf[iDataStreamID]))
+            bEnoughData = TRUE;
+    }
+    /* Source decoding (audio) */
+    if (iAudioStreamID != STREAM_ID_NOT_USED)
+    {
+        if (AudioSourceDecoder.ProcessData(Parameters,
+                                           MSCUseBuf[iAudioStreamID],
+                                           AudSoDecBuf))
+        {
+            bEnoughData = TRUE;
+
+            /* Store the number of correctly decoded audio blocks for
+             *                            the history */
+            PlotManager.SetCurrentCDAud(AudioSourceDecoder.GetNumCorDecAudio());
+        }
+    }
+    if( (iDataStreamID == STREAM_ID_NOT_USED)
+       &&
+         (iAudioStreamID == STREAM_ID_NOT_USED)
+    ) // try and decode stream 0 as audio anyway
+    {
+        if (AudioSourceDecoder.ProcessData(Parameters,
+                                           MSCUseBuf[0],
+                                           AudSoDecBuf))
+        {
+            bEnoughData = TRUE;
+
+            /* Store the number of correctly decoded audio blocks for
+             *                            the history */
+            PlotManager.SetCurrentCDAud(AudioSourceDecoder.GetNumCorDecAudio());
+        }
+    }
+}
+
+void
+CDRMReceiver::DemodulateAM(_BOOLEAN& bEnoughData)
+{
+    /* The incoming samples are split 2 ways.
+       One set is passed to the existing AM demodulator.
+       The other set is passed to the new AMSS demodulator.
+       The AMSS and AM demodulators work completely independently
+     */
+    if (Split.ProcessData(Parameters, DemodDataBuf, AMDataBuf, AMSSDataBuf))
+    {
+        bEnoughData = TRUE;
+    }
+
+    /* AM demodulation ------------------------------------------ */
+    if (AMDemodulation.ProcessData(Parameters, AMDataBuf, AMAudioBuf))
+    {
+        bEnoughData = TRUE;
+    }
+
+    /* AMSS phase demodulation */
+    if (AMSSPhaseDemod.ProcessData(Parameters, AMSSDataBuf, AMSSPhaseBuf))
+    {
+        bEnoughData = TRUE;
+    }
+}
+
+void
+CDRMReceiver::DecodeAM(_BOOLEAN& bEnoughData)
+{
+    /* AMSS resampling */
+    if (InputResample.ProcessData(Parameters, AMSSPhaseBuf, AMSSResPhaseBuf))
+    {
+        bEnoughData = TRUE;
+    }
+
+    /* AMSS bit extraction */
+    if (AMSSExtractBits.
+            ProcessData(Parameters, AMSSResPhaseBuf, AMSSBitsBuf))
+    {
+        bEnoughData = TRUE;
+    }
+
+    /* AMSS data decoding */
+    if (AMSSDecode.ProcessData(Parameters, AMSSBitsBuf, SDCDecBuf))
+    {
+        bEnoughData = TRUE;
+    }
+}
+
+void
+CDRMReceiver::UtilizeAM(_BOOLEAN& bEnoughData)
+{
+    if (UtilizeSDCData.WriteData(Parameters, SDCDecBuf))
+    {
+        bEnoughData = TRUE;
+    }
+}
+
+void CDRMReceiver::DemodulateFM(_BOOLEAN& bEnoughData)
+{
+    if (ConvertAudio.ProcessData(Parameters, DemodDataBuf, AMAudioBuf))
+    {
+        bEnoughData = TRUE;
+        iAudioStreamID = 0; // TODO
+    }
+}
+
+void CDRMReceiver::DecodeFM(_BOOLEAN& bEnoughData)
+{
+    (void)bEnoughData;
+}
+
+void CDRMReceiver::UtilizeFM(_BOOLEAN& bEnoughData)
+{
+    (void)bEnoughData;
+}
+
+void
+CDRMReceiver::DetectAcquiFAC()
+{
+    /* If upstreamRSCI in is enabled, do not check for acquisition state because we want
+       to stay in tracking mode all the time */
+    if (pUpstreamRSCI->GetInEnabled() == TRUE)
+        return;
+
+    /* Acquisition switch */
+    if (!UtilizeFACData.GetCRCOk())
+    {
+        /* Reset "good signal" count */
+        iGoodSignCnt = 0;
+
+        iAcquRestartCnt++;
+
+        /* Check situation when receiver must be set back in start mode */
+        if ((Parameters.eAcquiState == AS_WITH_SIGNAL)
+                && (iAcquRestartCnt > NUM_FAC_FRA_U_ACQ_WITH))
+        {
+            SetInStartMode();
+        }
+    }
+    else
+    {
+        /* Set the receiver state to "with signal" not until two successive FAC
+           frames are "ok", because there is only a 8-bit CRC which is not good
+           for many bit errors. But it is very unlikely that we have two
+           successive FAC blocks "ok" if no good signal is received */
+        if (iGoodSignCnt > 0)
+        {
+            Parameters.eAcquiState = AS_WITH_SIGNAL;
+
+            /* Take care of delayed tracking mode switch */
+            if (iDelayedTrackModeCnt > 0)
+                iDelayedTrackModeCnt--;
+            else
+                SetInTrackingModeDelayed();
+        }
+        else
+        {
+            /* If one CRC was correct, reset acquisition since
+               we assume, that this was a correct detected signal */
+            iAcquRestartCnt = 0;
+            iAcquDetecCnt = 0;
+
+            /* Set in tracking mode */
+            SetInTrackingMode();
+
+            iGoodSignCnt++;
+        }
+    }
+}
+
+void
+CDRMReceiver::InitReceiverMode()
+{
+    switch (eNewReceiverMode)
+    {
+    case RM_AM:
+    case RM_FM:
+#if 0
+        if (pAMParam == NULL)
+        {
+            /* its the first time we have been in AM mode */
+            if (pDRMParam == NULL)
+            {
+                /* DRM Mode was never invoked so we get to claim the default parameter instance */
+                pAMParam = pParameters;
+            }
+            else
+            {
+                /* change from DRM to AM Mode - we better have our own copy
+                 * but make sure we inherit the initial settings of the default
+                 */
+                pAMParam = new CParameter(*pDRMParam);
+            }
+        }
+        else
+        {
+            /* we have been in AM mode before, and have our own parameters but
+             * we might need some state from the DRM mode params
+             */
+            switch (eReceiverMode)
+            {
+            case RM_AM:
+                /* AM to AM switch */
+                break;
+            case RM_FM:
+                /* AM to FM switch - re-acquisition requested - no special action */
+                break;
+            case RM_DRM:
+                /* DRM to AM switch - grab some common stuff */
+                pAMParam->rSigStrengthCorrection = pDRMParam->rSigStrengthCorrection;
+                pAMParam->bMeasurePSD = pDRMParam->bMeasurePSD;
+                pAMParam->bMeasurePSDAlways = pDRMParam->bMeasurePSDAlways;
+                pAMParam->bMeasureInterference = pDRMParam->bMeasureInterference;
+                pAMParam->FrontEndParameters = pDRMParam->FrontEndParameters;
+                pAMParam->gps_data = pDRMParam->gps_data;
+                pAMParam->use_gpsd = pDRMParam->use_gpsd;
+                pAMParam->sSerialNumber = pDRMParam->sSerialNumber;
+                pAMParam->sReceiverID  = pDRMParam->sReceiverID;
+                pAMParam->SetDataDirectory(pDRMParam->GetDataDirectory());
+                break;
+            case RM_NONE:
+                /* Start from cold in AM mode - no special action */
+                break;
+            }
+        }
+        pAMParam->eReceiverMode = eNewReceiverMode;
+        pParameters = pAMParam;
+
+        if (pParameters == NULL)
+            throw CGenErr("Something went terribly wrong in the Receiver");
+#endif
+        Parameters.eReceiverMode = eNewReceiverMode;
+
+        /* Tell the SDC decoder that it's AMSS to decode (no AFS index) */
+        UtilizeSDCData.GetSDCReceive()->SetSDCType(CSDCReceive::SDC_AMSS);
+
+        /* Set the receive status - this affects the RSI output */
+        Parameters.ReceiveStatus.TSync.SetStatus(NOT_PRESENT);
+        Parameters.ReceiveStatus.FSync.SetStatus(NOT_PRESENT);
+        Parameters.ReceiveStatus.FAC.SetStatus(NOT_PRESENT);
+        Parameters.ReceiveStatus.SDC.SetStatus(NOT_PRESENT);
+        Parameters.ReceiveStatus.SLAudio.SetStatus(NOT_PRESENT);
+        Parameters.ReceiveStatus.LLAudio.SetStatus(NOT_PRESENT);
+        break;
+    case RM_DRM:
+#if 0
+        if (pDRMParam == NULL)
+        {
+            /* its the first time we have been in DRM mode */
+            if (pAMParam == NULL)
+            {
+                /* AM Mode was never invoked so we get to claim the default parameter instance */
+                pDRMParam = pParameters;
+            }
+            else
+            {
+                /* change from AM to DRM Mode - we better have our own copy
+                 * but make sure we inherit the initial settings of the default
+                 */
+                pDRMParam = new CParameter(*pAMParam);
+            }
+        }
+        else
+        {
+            /* we have been in DRM mode before, and have our own parameters but
+             * we might need some state from the AM mode params
+             */
+            switch (eReceiverMode)
+            {
+            case RM_AM:
+            case RM_FM:
+                /* AM to DRM switch - grab some common stuff */
+                pDRMParam->rSigStrengthCorrection = pAMParam->rSigStrengthCorrection;
+                pDRMParam->bMeasurePSD = pAMParam->bMeasurePSD;
+                pDRMParam->bMeasurePSDAlways = pAMParam->bMeasurePSDAlways;
+                pDRMParam->bMeasureInterference = pAMParam->bMeasureInterference;
+                pDRMParam->FrontEndParameters = pAMParam->FrontEndParameters;
+                pDRMParam->gps_data = pAMParam->gps_data;
+                pDRMParam->use_gpsd = pAMParam->use_gpsd;
+                pDRMParam->sSerialNumber = pAMParam->sSerialNumber;
+                pDRMParam->sReceiverID  = pAMParam->sReceiverID;
+                pDRMParam->SetDataDirectory(pAMParam->GetDataDirectory());
+                break;
+            case RM_DRM:
+                /* DRM to DRM switch - re-acquisition requested - no special action */
+                break;
+            case RM_NONE:
+                /* Start from cold in DRM mode - no special action */
+                break;
+            }
+        }
+#endif
+//        pDRMParam->eReceiverMode = RM_DRM;
+//        pParameters = pDRMParam;
+
+//        if (pParameters == NULL)
+//            throw CGenErr("Something went terribly wrong in the Receiver");
+        Parameters.eReceiverMode = eNewReceiverMode;
+
+        UtilizeSDCData.GetSDCReceive()->SetSDCType(CSDCReceive::SDC_DRM);
+        break;
+    case RM_NONE:
+        return;
+    }
+
+    eReceiverMode = eNewReceiverMode;
+    /* Reset new mode flag */
+    eNewReceiverMode = RM_NONE;
+
+    /* Init all modules */
+    SetInStartMode();
+
+    if (pUpstreamRSCI->GetOutEnabled() == TRUE)
+    {
+        pUpstreamRSCI->SetReceiverMode(eReceiverMode);
+    }
+}
+
+void
+CDRMReceiver::Start()
+{
+    // set the frequency from the command line or ini file
+    int iFreqkHz = Parameters.GetFrequency();
+    if (iFreqkHz != -1)
+        SetFrequency(iFreqkHz);
+
+#ifdef USE_CONSOLEIO
+    CConsoleIO::Enter(this);
+#endif
+
+    /* Set restart flag */
+    Parameters.eRunState = CParameter::RESTART;
+    do
+    {
+        /* Setup new sound file or RSCI input if any */
+        SetInput();
+
+        /* Set new acquisition flag */
+        RequestNewAcquisition();
+
+        /* Initialisation pass */
+        Run();
+
+        /* Set run flag so that the thread can work */
+        Parameters.eRunState = CParameter::RUNNING;
+        do
+        {
+            Run();
+#ifdef USE_CONSOLEIO
+            CConsoleIO::Update();
+#endif
+        }
+        while (Parameters.eRunState == CParameter::RUNNING);
+
+        /* Restore some parameter previously set by SetInput() */
+        ResetInput();
+    }
+    while (Parameters.eRunState == CParameter::RESTART);
+
+    CloseSoundInterfaces();
+
+#ifdef USE_CONSOLEIO
+    CConsoleIO::Leave();
+#endif
+
+    Parameters.eRunState = CParameter::STOPPED;
+}
+
+void
+CDRMReceiver::CloseSoundInterfaces()
+{
+    pSoundInInterface->Close();
+    pSoundOutInterface->Close();
+}
+
+void
+CDRMReceiver::SetAMDemodAcq(_REAL rNewNorCen)
+{
+    /* Set the frequency where the AM demodulation should look for the
+       aquisition. Receiver must be in AM demodulation mode */
+    if (eReceiverMode == RM_AM)
+    {
+        AMDemodulation.SetAcqFreq(rNewNorCen);
+        AMSSPhaseDemod.SetAcqFreq(rNewNorCen);
+    }
+}
+
+void
+CDRMReceiver::SetInStartMode()
+{
+    iUnlockedCount = MAX_UNLOCKED_COUNT;
+
+    Parameters.Lock();
+    /* Load start parameters for all modules */
+
+    /* Define with which parameters the receiver should try to decode the
+       signal. If we are correct with our assumptions, the receiver does not
+       need to reinitialize */
+    Parameters.InitCellMapTable(RM_ROBUSTNESS_MODE_B, SO_3);
+
+    /* Set initial MLC parameters */
+    Parameters.SetInterleaverDepth(SI_LONG);
+    Parameters.SetMSCCodingScheme(CS_3_SM);
+    Parameters.SetSDCCodingScheme(CS_2_SM);
+
+    /* Select the service we want to decode. Always zero, because we do not
+       know how many services are transmitted in the signal we want to
+       decode */
+
+    /* TODO: if service 0 is not used but another service is the audio service
+     * we have a problem. We should check as soon as we have information about
+     * services if service 0 is really the audio service
+     */
+
+    /* Set the following parameters to zero states (initial states) --------- */
+    Parameters.ResetServicesStreams();
+    Parameters.ResetCurSelAudDatServ();
+
+    /* Protection levels */
+    Parameters.MSCPrLe.iPartA = 0;
+    Parameters.MSCPrLe.iPartB = 1;
+    Parameters.MSCPrLe.iHierarch = 0;
+
+    /* Number of audio and data services */
+    Parameters.iNumAudioService = 0;
+    Parameters.iNumDataService = 0;
+
+    /* We start with FAC ID = 0 (arbitrary) */
+    Parameters.iFrameIDReceiv = 0;
+
+    /* Set synchronization parameters */
+    Parameters.rResampleOffset = rInitResampleOffset;	/* Initial resample offset */
+    Parameters.rFreqOffsetAcqui = (_REAL) 0.0;
+    Parameters.rFreqOffsetTrack = (_REAL) 0.0;
+    Parameters.iTimingOffsTrack = 0;
+
+    Parameters.Unlock();
+
+    /* Initialization of the modules */
+    InitsForAllModules();
+
+    /* Activate acquisition */
+    FreqSyncAcq.StartAcquisition();
+    TimeSync.StartAcquisition();
+    ChannelEstimation.GetTimeSyncTrack()->StopTracking();
+    ChannelEstimation.StartSaRaOffAcq();
+    ChannelEstimation.GetTimeWiener()->StopTracking();
+
+    SyncUsingPil.StartAcquisition();
+    SyncUsingPil.StopTrackPil();
+
+    Parameters.Lock();
+    /* Set flag that no signal is currently received */
+    Parameters.eAcquiState = AS_NO_SIGNAL;
+
+    /* Set flag for receiver state */
+    eReceiverState = RS_ACQUISITION;
+
+    /* Reset counters for acquisition decision, "good signal" and delayed
+       tracking mode counter */
+    iAcquRestartCnt = 0;
+    iAcquDetecCnt = 0;
+    iGoodSignCnt = 0;
+    iDelayedTrackModeCnt = NUM_FAC_DEL_TRACK_SWITCH;
+
+    /* Reset GUI lights */
+    Parameters.ReceiveStatus.InterfaceI.SetStatus(NOT_PRESENT);
+    Parameters.ReceiveStatus.InterfaceO.SetStatus(NOT_PRESENT);
+    Parameters.ReceiveStatus.TSync.SetStatus(NOT_PRESENT);
+    Parameters.ReceiveStatus.FSync.SetStatus(NOT_PRESENT);
+    Parameters.ReceiveStatus.FAC.SetStatus(NOT_PRESENT);
+    Parameters.ReceiveStatus.SDC.SetStatus(NOT_PRESENT);
+    Parameters.ReceiveStatus.SLAudio.SetStatus(NOT_PRESENT);
+    Parameters.ReceiveStatus.LLAudio.SetStatus(NOT_PRESENT);
+
+    /* Clear audio decoder string */
+    Parameters.audiodecoder = "";
+
+    Parameters.Unlock();
+
+    /* In case upstreamRSCI is enabled, go directly to tracking mode, do not activate the
+       synchronization units */
+    if (pUpstreamRSCI->GetInEnabled() == TRUE)
+    {
+        /* We want to have as low CPU usage as possible, therefore set the
+           synchronization units in a state where they do only a minimum
+           work */
+        FreqSyncAcq.StopAcquisition();
+        TimeSync.StopTimingAcqu();
+        InputResample.SetSyncInput(TRUE);
+        SyncUsingPil.SetSyncInput(TRUE);
+
+        /* This is important so that always the same amount of module input
+           data is queried, otherwise it could be that amount of input data is
+           set to zero and the receiver gets into an infinite loop */
+        TimeSync.SetSyncInput(TRUE);
+
+        /* Always tracking mode for upstreamRSCI */
+        Parameters.Lock();
+        Parameters.eAcquiState = AS_WITH_SIGNAL;
+        Parameters.Unlock();
+
+        SetInTrackingMode();
+    }
+}
+
+void
+CDRMReceiver::SetInTrackingMode()
+{
+    /* We do this with the flag "eReceiverState" to ensure that the following
+       routines are only called once when the tracking is actually started */
+    if (eReceiverState == RS_ACQUISITION)
+    {
+        /* In case the acquisition estimation is still in progress, stop it now
+           to avoid a false estimation which could destroy synchronization */
+        TimeSync.StopRMDetAcqu();
+
+        /* Acquisition is done, deactivate it now and start tracking */
+        ChannelEstimation.GetTimeWiener()->StartTracking();
+
+        /* Reset acquisition for frame synchronization */
+        SyncUsingPil.StopAcquisition();
+        SyncUsingPil.StartTrackPil();
+
+        /* Set receiver flag to tracking */
+        eReceiverState = RS_TRACKING;
+    }
+}
+
+void
+CDRMReceiver::SetInTrackingModeDelayed()
+{
+    /* The timing tracking must be enabled delayed because it must wait until
+       the channel estimation has initialized its estimation */
+    TimeSync.StopTimingAcqu();
+    ChannelEstimation.GetTimeSyncTrack()->StartTracking();
+}
+
+void
+CDRMReceiver::InitsForAllModules()
+{
+    if (downstreamRSCI.GetOutEnabled())
+    {
+        Parameters.bMeasureDelay = TRUE;
+        Parameters.bMeasureDoppler = TRUE;
+        Parameters.bMeasureInterference = TRUE;
+        Parameters.bMeasurePSD = TRUE;
+    }
+    else
+    {
+        Parameters.bMeasureDelay = FALSE;
+        Parameters.bMeasureDoppler = FALSE;
+        Parameters.bMeasureInterference = FALSE;
+        if(Parameters.bMeasurePSDAlways)
+            Parameters.bMeasurePSD = TRUE;
+        else
+            Parameters.bMeasurePSD = FALSE;
+    }
+
+    /* Set init flags */
+    SplitSDC.SetInitFlag();
+    for (size_t i = 0; i < MSCDecBuf.size(); i++)
+    {
+        SplitMSC[i].SetStream(i);
+        SplitMSC[i].SetInitFlag();
+        MSCDecBuf[i].Clear();
+        MSCUseBuf[i].Clear();
+        MSCSendBuf[i].Clear();
+    }
+    ConvertAudio.SetInitFlag();
+
+    ReceiveData.SetSoundInterface(pSoundInInterface);
+    ReceiveData.SetInitFlag();
+    InputResample.SetInitFlag();
+    FreqSyncAcq.SetInitFlag();
+    TimeSync.SetInitFlag();
+    OFDMDemodulation.SetInitFlag();
+    SyncUsingPil.SetInitFlag();
+    ChannelEstimation.SetInitFlag();
+    OFDMCellDemapping.SetInitFlag();
+    FACMLCDecoder.SetInitFlag();
+    UtilizeFACData.SetInitFlag();
+    SplitFAC.SetInitFlag();
+    SDCMLCDecoder.SetInitFlag();
+    UtilizeSDCData.SetInitFlag();
+    SymbDeinterleaver.SetInitFlag();
+    MSCMLCDecoder.SetInitFlag();
+    DecodeRSIMDI.SetInitFlag();
+    MSCDemultiplexer.SetInitFlag();
+    AudioSourceDecoder.SetInitFlag();
+    DataDecoder.SetInitFlag();
+    WriteData.SetInitFlag();
+
+    Split.SetInitFlag();
+    SplitAudio.SetInitFlag();
+    AudioSourceEncoder.SetInitFlag();
+    AMDemodulation.SetInitFlag();
+
+    SplitForIQRecord.SetInitFlag();
+    WriteIQFile.SetInitFlag();
+    /* AMSS */
+    AMSSPhaseDemod.SetInitFlag();
+    AMSSExtractBits.SetInitFlag();
+    AMSSDecode.SetInitFlag();
+
+    pUpstreamRSCI->SetInitFlag();
+    //downstreamRSCI.SetInitFlag();
+
+    /* Clear all buffers (this is especially important for the "AudSoDecBuf"
+       buffer since AM mode and DRM mode use the same buffer. When init is
+       called or modes are switched, the buffer could have some data left which
+       lead to an overrun) */
+    RecDataBuf.Clear();
+    AMDataBuf.Clear();
+
+    DemodDataBuf.Clear();
+    IQRecordDataBuf.Clear();
+
+    AMSSDataBuf.Clear();
+    AMSSPhaseBuf.Clear();
+    AMSSResPhaseBuf.Clear();
+    AMSSBitsBuf.Clear();
+
+    InpResBuf.Clear();
+    FreqSyncAcqBuf.Clear();
+    TimeSyncBuf.Clear();
+    OFDMDemodBuf.Clear();
+    SyncUsingPilBuf.Clear();
+    ChanEstBuf.Clear();
+    MSCCarDemapBuf.Clear();
+    FACCarDemapBuf.Clear();
+    SDCCarDemapBuf.Clear();
+    DeintlBuf.Clear();
+    FACDecBuf.Clear();
+    SDCDecBuf.Clear();
+    MSCMLCDecBuf.Clear();
+    RSIPacketBuf.Clear();
+    AudSoDecBuf.Clear();
+    AMAudioBuf.Clear();
+    AMSoEncBuf.Clear();
+}
+
+/* -----------------------------------------------------------------------------
+   Initialization routines for the modules. We have to look into the modules
+   and decide on which parameters the modules depend on */
+void
+CDRMReceiver::InitsForWaveMode()
+{
+    /* Reset averaging of the parameter histories (needed, e.g., because the
+       number of OFDM symbols per DRM frame might have changed) */
+    PlotManager.Init();
+
+    /* After a new robustness mode was detected, give the time synchronization
+       a bit more time for its job */
+    iAcquDetecCnt = 0;
+
+    /* Set init flags */
+    ReceiveData.SetSoundInterface(pSoundInInterface);
+    ReceiveData.SetInitFlag();
+    InputResample.SetInitFlag();
+    FreqSyncAcq.SetInitFlag();
+    Split.SetInitFlag();
+    AMDemodulation.SetInitFlag();
+    AudioSourceEncoder.SetInitFlag();
+
+    SplitForIQRecord.SetInitFlag();
+    WriteIQFile.SetInitFlag();
+
+    AMSSPhaseDemod.SetInitFlag();
+    AMSSExtractBits.SetInitFlag();
+    AMSSDecode.SetInitFlag();
+
+    TimeSync.SetInitFlag();
+    OFDMDemodulation.SetInitFlag();
+    SyncUsingPil.SetInitFlag();
+    ChannelEstimation.SetInitFlag();
+    OFDMCellDemapping.SetInitFlag();
+    SymbDeinterleaver.SetInitFlag();	// Because of "iNumUsefMSCCellsPerFrame"
+    MSCMLCDecoder.SetInitFlag();	// Because of "iNumUsefMSCCellsPerFrame"
+    SDCMLCDecoder.SetInitFlag();	// Because of "iNumSDCCellsPerSFrame"
+}
+
+void
+CDRMReceiver::InitsForSpectrumOccup()
+{
+    /* Set init flags */
+    FreqSyncAcq.SetInitFlag();	// Because of bandpass filter
+    OFDMDemodulation.SetInitFlag();
+    SyncUsingPil.SetInitFlag();
+    ChannelEstimation.SetInitFlag();
+    OFDMCellDemapping.SetInitFlag();
+    SymbDeinterleaver.SetInitFlag();	// Because of "iNumUsefMSCCellsPerFrame"
+    MSCMLCDecoder.SetInitFlag();	// Because of "iNumUsefMSCCellsPerFrame"
+    SDCMLCDecoder.SetInitFlag();	// Because of "iNumSDCCellsPerSFrame"
+}
+
+/* SDC ---------------------------------------------------------------------- */
+void
+CDRMReceiver::InitsForSDCCodSche()
+{
+    /* Set init flags */
+    SDCMLCDecoder.SetInitFlag();
+
+#ifdef USE_DD_WIENER_FILT_TIME
+    ChannelEstimation.SetInitFlag();
+#endif
+}
+
+void
+CDRMReceiver::InitsForNoDecBitsSDC()
+{
+    /* Set init flag */
+    SplitSDC.SetInitFlag();
+    UtilizeSDCData.SetInitFlag();
+}
+
+/* MSC ---------------------------------------------------------------------- */
+void
+CDRMReceiver::InitsForInterlDepth()
+{
+    /* Can be absolutely handled seperately */
+    SymbDeinterleaver.SetInitFlag();
+}
+
+void
+CDRMReceiver::InitsForMSCCodSche()
+{
+    /* Set init flags */
+    MSCMLCDecoder.SetInitFlag();
+    MSCDemultiplexer.SetInitFlag();	// Not sure if really needed, look at code! TODO
+
+#ifdef USE_DD_WIENER_FILT_TIME
+    ChannelEstimation.SetInitFlag();
+#endif
+}
+
+void
+CDRMReceiver::InitsForMSC()
+{
+    /* Set init flags */
+    MSCMLCDecoder.SetInitFlag();
+
+    InitsForMSCDemux();
+}
+
+void
+CDRMReceiver::InitsForMSCDemux()
+{
+    /* Set init flags */
+    DecodeRSIMDI.SetInitFlag();
+    MSCDemultiplexer.SetInitFlag();
+    for (size_t i = 0; i < MSCDecBuf.size(); i++)
+    {
+        SplitMSC[i].SetStream(i);
+        SplitMSC[i].SetInitFlag();
+    }
+    InitsForAudParam();
+    InitsForDataParam();
+
+    /* Reset value used for the history because if an audio service was selected
+       but then only a data service is selected, the value would remain with the
+       last state */
+    PlotManager.SetCurrentCDAud(0);
+}
+
+void
+CDRMReceiver::InitsForAudParam()
+{
+    for (size_t i = 0; i < MSCDecBuf.size(); i++)
+    {
+        MSCDecBuf[i].Clear();
+        MSCUseBuf[i].Clear();
+        MSCSendBuf[i].Clear();
+    }
+
+    /* Set init flags */
+    DecodeRSIMDI.SetInitFlag();
+    MSCDemultiplexer.SetInitFlag();
+    int a = Parameters.GetCurSelAudioService();
+    iAudioStreamID = Parameters.GetAudioParam(a).iStreamID;
+    Parameters.SetNumAudioDecoderBits(Parameters.
+                                           GetStreamLen(iAudioStreamID) *
+                                           SIZEOF__BYTE);
+    AudioSourceDecoder.SetInitFlag();
+}
+
+void
+CDRMReceiver::InitsForDataParam()
+{
+    /* Set init flags */
+    DecodeRSIMDI.SetInitFlag();
+    MSCDemultiplexer.SetInitFlag();
+    int d = Parameters.GetCurSelDataService();
+    iDataStreamID = Parameters.GetDataParam(d).iStreamID;
+    Parameters.SetNumDataDecoderBits(Parameters.
+                                          GetStreamLen(iDataStreamID) *
+                                          SIZEOF__BYTE);
+    DataDecoder.SetInitFlag();
+}
+
+void CDRMReceiver::SetFrequency(int iNewFreqkHz)
+{
+    Parameters.Lock();
+    Parameters.SetFrequency(iNewFreqkHz);
+    /* clear out AMSS data and re-initialise AMSS acquisition */
+    if (Parameters.eReceiverMode == RM_AM)
+        Parameters.ResetServicesStreams();
+    Parameters.Unlock();
+
+    if (pUpstreamRSCI->GetOutEnabled() == TRUE)
+        pUpstreamRSCI->SetFrequency(iNewFreqkHz);
+
+    if (sfCallback)
+        sfCallback(sfCallbackParam, iNewFreqkHz);
+
+#if 0
+	{
+		FCD_MODE_ENUM fme;
+		unsigned int uFreq, rFreq;
+		int lnbOffset = 6;
+		double d = (double) (iNewFreqkHz-lnbOffset);
+
+		//d *= 1.0 + n/1000000.0;
+		uFreq = (unsigned int) d;
+
+		fme = fcdAppSetFreq(uFreq, &rFreq);
+
+		if ((fme != FCD_MODE_APP) || (uFreq != rFreq))
+		{
+			stringstream ss;
+			ss << "Error in" << __FUNCTION__ << "set:" << uFreq << "read:" << rFreq;
+			qDebug(ss.str().c_str()); 
+		}
+	}
+#endif
+    if (downstreamRSCI.GetOutEnabled() == TRUE)
+        downstreamRSCI.NewFrequency(Parameters);
+
+    /* tell the IQ file writer that freq has changed in case it needs to start a new file */
+    WriteIQFile.NewFrequency(Parameters);
+}
+
+void
+CDRMReceiver::SetIQRecording(_BOOLEAN bON)
+{
+    if (bON)
+        WriteIQFile.StartRecording(Parameters);
+    else
+        WriteIQFile.StopRecording();
+}
+
+void
+CDRMReceiver::SetRSIRecording(_BOOLEAN bOn, const char cProfile)
+{
+    downstreamRSCI.SetRSIRecording(Parameters, bOn, cProfile);
+}
+
+/* TEST store information about alternative frequency transmitted in SDC */
+void
+CDRMReceiver::saveSDCtoFile()
+{
+    static FILE *pFile = NULL;
+
+    if (pFile == NULL)
+        pFile = fopen("test/altfreq.dat", "w");
+
+    Parameters.Lock();
+    size_t inum = Parameters.AltFreqSign.vecMultiplexes.size();
+    for (size_t z = 0; z < inum; z++)
+    {
+        fprintf(pFile, "sync:%d sr:", Parameters.AltFreqSign.vecMultiplexes[z].bIsSyncMultplx);
+
+        for (int k = 0; k < 4; k++)
+            fprintf(pFile, "%d", Parameters.AltFreqSign.vecMultiplexes[z].  veciServRestrict[k]);
+        fprintf(pFile, " fr:");
+
+        for (size_t kk = 0; kk < Parameters.AltFreqSign.vecMultiplexes[z].veciFrequencies.size(); kk++)
+            fprintf(pFile, "%d ", Parameters.AltFreqSign.vecMultiplexes[z].  veciFrequencies[kk]);
+
+        fprintf(pFile, " rID:%d sID:%d   /   ",
+                Parameters.AltFreqSign.vecMultiplexes[z].iRegionID,
+                Parameters.AltFreqSign.vecMultiplexes[z].iScheduleID);
+    }
+    Parameters.Unlock();
+    fprintf(pFile, "\n");
+    fflush(pFile);
+}
+
+void
+CDRMReceiver::LoadSettings()
+{
+    if (pSettings == NULL) return;
+    CSettings& s = *pSettings;
+
+    /* Serial Number */
+    string sValue = s.Get("Receiver", "serialnumber");
+    if (sValue != "")
+    {
+        // Pad to a minimum of 6 characters
+        while (sValue.length() < 6)
+            sValue += "_";
+        Parameters.sSerialNumber = sValue;
+    }
+
+    Parameters.GenerateReceiverID();
+
+    /* Receiver ------------------------------------------------------------- */
+
+    /* Sound card audio sample rate, some settings below depends on this one */
+    Parameters.SetNewAudSampleRate(s.Get("Receiver", "samplerateaud", int(DEFAULT_SOUNDCRD_SAMPLE_RATE)));
+
+    /* Sound card signal sample rate, some settings below depends on this one */
+    Parameters.SetNewSigSampleRate(s.Get("Receiver", "sampleratesig", int(DEFAULT_SOUNDCRD_SAMPLE_RATE)));
+
+    /* Signal upscale ratio */
+    Parameters.SetNewSigUpscaleRatio(s.Get("Receiver", "sigupratio", int(1)));
+
+    /* Fetch new sample rate if any */
+    Parameters.FetchNewSampleRate();
+
+    /* if 0 then only measure PSD when RSCI in use otherwise always measure it */
+    Parameters.bMeasurePSDAlways = s.Get("Receiver", "measurepsdalways", 0);
+
+    /* Upstream RSCI if any */
+    string str = s.Get("command", "rsiin");
+    if (str != "")
+        SetRsciInput(str);
+
+    /* Input from file if any */
+    str = s.Get("command", string("fileio"));
+    if (str != "")
+        SetInputFile(str);
+
+    /* Channel Estimation: Frequency Interpolation */
+    SetFreqInt((CChannelEstimation::ETypeIntFreq)s.Get("Receiver", "freqint", int(CChannelEstimation::FWIENER)));
+
+    /* Channel Estimation: Time Interpolation */
+    SetTimeInt((CChannelEstimation::ETypeIntTime)s.Get("Receiver", "timeint", int(CChannelEstimation::TWIENER)));
+
+    /* Time Sync Tracking */
+    SetTiSyncTracType((CTimeSyncTrack::ETypeTiSyncTrac)s.Get("Receiver", "timesync", int(CTimeSyncTrack::TSENERGY)));
+
+    /* Flip spectrum flag */
+    ReceiveData.SetFlippedSpectrum(s.Get("Receiver", "flipspectrum", FALSE));
+
+    /* Input channel selection */
+    ReceiveData.SetInChanSel((CReceiveData::EInChanSel)s.Get("Receiver", "inchansel", int(CReceiveData::CS_MIX_CHAN)));
+
+    /* Output channel selection */
+    WriteData.SetOutChanSel((CWriteData::EOutChanSel)s.Get("Receiver", "outchansel", int(CWriteData::CS_BOTH_BOTH)));
+
+    /* AM Parameters */
+
+    /* AGC */
+    AMDemodulation.SetAGCType((CAGC::EType)s.Get("AM Demodulation", "agc", 0));
+
+    /* noise reduction */
+    AMDemodulation.SetNoiRedType((CAMDemodulation::ENoiRedType)s.Get("AM Demodulation", "noisered", 0));
+
+#ifdef HAVE_SPEEX
+    /* noise reduction level */
+    AMDemodulation.SetNoiRedLevel(s.Get("AM Demodulation", "noiseredlvl", -12));
+#endif
+
+    /* pll enabled/disabled */
+    AMDemodulation.EnablePLL(s.Get("AM Demodulation", "enablepll", 0));
+
+    /* auto frequency acquisition */
+    AMDemodulation.EnableAutoFreqAcq(s.Get("AM Demodulation", "autofreqacq", 0));
+
+    /* demodulation type and bandwidth */
+    CAMDemodulation::EDemodType eDemodType
+    = (CAMDemodulation::EDemodType)s.Get("AM Demodulation", "demodulation", CAMDemodulation::DT_AM);
+    iBwAM = s.Get("AM Demodulation", "filterbwam", 10000);
+    iBwUSB = s.Get("AM Demodulation", "filterbwusb", 5000);
+    iBwLSB = s.Get("AM Demodulation", "filterbwlsb", 5000);
+    iBwCW = s.Get("AM Demodulation", "filterbwcw", 150);
+    iBwFM = s.Get("AM Demodulation", "filterbwfm", 6000);
+
+    /* Load user's saved filter bandwidth and demodulation type */
+    SetAMDemodType(eDemodType);
+
+    /* Sound In device */
+    pSoundInInterface->SetDev(s.Get("Receiver", "snddevin", string()));
+
+    /* Sound Out device */
+    pSoundOutInterface->SetDev(s.Get("Receiver", "snddevout", string()));
+
+    str = s.Get("command", "rciout");
+    if (str != "")
+        pUpstreamRSCI->SetDestination(str);
+
+    /* downstream RSCI */
+	string rsiout = s.Get("command", "rsiout", string(""));
+	string rciin = s.Get("command", "rciin", string(""));
+	if(rsiout != "" || rciin != "")
+	{
+		istringstream cc(rciin);
+		vector<string> rci;
+		while(cc >> str)
+		{
+			rci.push_back(str);
+		}
+		istringstream ss(rsiout);
+		size_t n=0;
+		while(ss >> str)
+		{
+			char profile = str[0];
+			string dest = str.substr(2);
+			if(rci.size()>n)
+			{
+				downstreamRSCI.AddSubscriber(dest, profile, rci[n]);
+				n++;
+			}
+			else
+			{
+				downstreamRSCI.AddSubscriber(dest, profile);
+			}
+		}
+		for(;n<rci.size(); n++)
+			downstreamRSCI.AddSubscriber("", ' ', rci[n]);
+    }
+    /* RSCI File Recording */
+    str = s.Get("command", "rsirecordprofile");
+    string s2 = s.Get("command", "rsirecordtype");
+    if (str != "" || s2 != "")
+        downstreamRSCI.SetRSIRecording(Parameters, TRUE, str[0], s2);
+
+    /* IQ File Recording */
+    if (s.Get("command", "recordiq", false))
+        WriteIQFile.StartRecording(Parameters);
+
+    /* Mute audio flag */
+    WriteData.MuteAudio(s.Get("Receiver", "muteaudio", FALSE));
+
+    /* Output to File */
+    str = s.Get("command", "writewav");
+    if (str != "")
+    {
+        WriteData.Init(Parameters); /* Needed for iAudSampleRate initialization */
+        WriteData.StartWriteWaveFile(str);
+    }
+
+    /* Reverberation flag */
+    AudioSourceDecoder.SetReverbEffect(s.Get("Receiver", "reverb", TRUE));
+
+    /* Bandpass filter flag */
+    FreqSyncAcq.SetRecFilter(s.Get("Receiver", "filter", FALSE));
+
+    /* Set parameters for frequency acquisition search window */
+    const _REAL rFreqAcSeWinCenter = s.Get("command", "fracwincent", -1);
+    const _REAL rFreqAcSeWinSize = s.Get("command", "fracwinsize", -1);
+    FreqSyncAcq.SetSearchWindow(rFreqAcSeWinCenter, rFreqAcSeWinSize);
+
+    /* Modified metrics flag */
+    ChannelEstimation.SetIntCons(s.Get("Receiver", "modmetric", FALSE));
+
+    /* Number of iterations for MLC setting */
+    MSCMLCDecoder.SetNumIterations(s.Get("Receiver", "mlciter", 1));
+
+    /* Receiver mode (DRM, AM, FM) */
+    SetReceiverMode(ERecMode(s.Get("Receiver", "mode", int(0))));
+
+    /* Tuned Frequency */
+    Parameters.SetFrequency(s.Get("Receiver", "frequency", 0));
+
+    /* Front-end - combine into Hamlib? */
+    CFrontEndParameters& FrontEndParameters = Parameters.FrontEndParameters;
+
+    FrontEndParameters.eSMeterCorrectionType =
+        CFrontEndParameters::ESMeterCorrectionType(s.Get("FrontEnd", "smetercorrectiontype", 0));
+
+    FrontEndParameters.rSMeterBandwidth = s.Get("FrontEnd", "smeterbandwidth", 0.0);
+
+    FrontEndParameters.rDefaultMeasurementBandwidth = s.Get("FrontEnd", "defaultmeasurementbandwidth", 0);
+
+    FrontEndParameters.bAutoMeasurementBandwidth = s.Get("FrontEnd", "automeasurementbandwidth", TRUE);
+
+    FrontEndParameters.rCalFactorDRM = s.Get("FrontEnd", "calfactordrm", 0.0);
+
+    FrontEndParameters.rCalFactorAM = s.Get("FrontEnd", "calfactoram", 0.0);
+
+    FrontEndParameters.rIFCentreFreq = s.Get("FrontEnd", "ifcentrefrequency", (_REAL(DEFAULT_SOUNDCRD_SAMPLE_RATE) / 4));
+
+    /* Latitude string (used to be just for log file) */
+    double latitude, longitude;
+    latitude = s.Get("GPS", "latitude", s.Get("Logfile", "latitude", 1000.0));
+    /* Longitude string */
+    longitude = s.Get("GPS", "longitude", s.Get("Logfile", "longitude", 1000.0));
+    Parameters.Lock();
+    if(-90.0 <= latitude && latitude <= 90.0 && -180.0 <= longitude  && longitude <= 180.0)
+    {
+        Parameters.gps_data.set = LATLON_SET;
+        Parameters.gps_data.fix.latitude = latitude;
+        Parameters.gps_data.fix.longitude = longitude;
+    }
+    else {
+        Parameters.gps_data.set = 0;
+    }
+    bool use_gpsd = s.Get("GPS", "usegpsd", false);
+    Parameters.use_gpsd=use_gpsd;
+    string host = s.Get("GPS", "host", string("localhost"));
+    Parameters.gps_host = host;
+    Parameters.gps_port = s.Get("GPS", "port", string("2947"));
+    if(use_gpsd)
+        Parameters.restart_gpsd=true;
+
+    bool permissive = s.Get("command", "permissive", false);
+    Parameters.lenient_RSCI = permissive;
+
+    Parameters.Unlock();
+}
+
+void
+CDRMReceiver::SaveSettings()
+{
+    if (pSettings == NULL) return;
+    CSettings& s = *pSettings;
+
+    s.Put("Receiver", "mode", int(eReceiverMode));
+
+    /* Receiver ------------------------------------------------------------- */
+
+    /* Fetch new sample rate if any */
+    Parameters.FetchNewSampleRate();
+
+    /* Sound card audio sample rate */
+    s.Put("Receiver", "samplerateaud", Parameters.GetAudSampleRate());
+
+    /* Sound card signal sample rate */
+    s.Put("Receiver", "sampleratesig", Parameters.GetSoundCardSigSampleRate());
+
+    /* Signal upscale ratio */
+    s.Put("Receiver", "sigupratio", Parameters.GetSigUpscaleRatio());
+
+    /* if 0 then only measure PSD when RSCI in use otherwise always measure it */
+    s.Put("Receiver", "measurepsdalways", Parameters.bMeasurePSDAlways);
+
+    /* Channel Estimation: Frequency Interpolation */
+    s.Put("Receiver", "freqint", GetFreqInt());
+
+    /* Channel Estimation: Time Interpolation */
+    s.Put("Receiver", "timeint", GetTimeInt());
+
+    /* Time Sync Tracking */
+    s.Put("Receiver", "timesync", GetTiSyncTracType());
+
+    /* Flip spectrum flag */
+    s.Put("Receiver", "flipspectrum", ReceiveData.GetFlippedSpectrum());
+
+    /* Input channel selection */
+    s.Put("Receiver", "inchansel", ReceiveData.GetInChanSel());
+
+    /* Output channel selection */
+    s.Put("Receiver", "outchansel",  WriteData.GetOutChanSel());
+
+    /* Mute audio flag */
+    s.Put("Receiver", "muteaudio", WriteData.GetMuteAudio());
+
+    /* Reverberation */
+    s.Put("Receiver", "reverb", AudioSourceDecoder.GetReverbEffect());
+
+    /* Bandpass filter flag */
+    s.Put("Receiver", "filter", FreqSyncAcq.GetRecFilter());
+
+    /* Modified metrics flag */
+    s.Put("Receiver", "modmetric", ChannelEstimation.GetIntCons());
+
+    /* Sound In device */
+    s.Put("Receiver", "snddevin", pSoundInInterface->GetDev());
+
+    /* Sound Out device */
+    s.Put("Receiver", "snddevout", pSoundOutInterface->GetDev());
+
+    /* Number of iterations for MLC setting */
+    s.Put("Receiver", "mlciter", MSCMLCDecoder.GetInitNumIterations());
+
+    /* Tuned Frequency */
+    s.Put("Receiver", "frequency", Parameters.GetFrequency());
+
+    /* AM Parameters */
+
+    /* AGC */
+    s.Put("AM Demodulation", "agc", AMDemodulation.GetAGCType());
+
+    /* noise reduction */
+    s.Put("AM Demodulation", "noisered", AMDemodulation.GetNoiRedType());
+
+#ifdef HAVE_SPEEX
+    /* noise reduction level */
+    s.Put("AM Demodulation", "noiseredlvl", AMDemodulation.GetNoiRedLevel());
+#endif
+
+    /* pll enabled/disabled */
+    s.Put("AM Demodulation", "enablepll", AMDemodulation.PLLEnabled());
+
+    /* auto frequency acquisition */
+    s.Put("AM Demodulation", "autofreqacq", AMDemodulation.AutoFreqAcqEnabled());
+
+    /* demodulation */
+    s.Put("AM Demodulation", "demodulation", AMDemodulation.GetDemodType());
+
+    s.Put("AM Demodulation", "filterbwam", iBwAM);
+    s.Put("AM Demodulation", "filterbwusb", iBwUSB);
+    s.Put("AM Demodulation", "filterbwlsb", iBwLSB);
+    s.Put("AM Demodulation", "filterbwcw", iBwCW);
+    s.Put("AM Demodulation", "filterbwfm", iBwFM);
+
+    /* Front-end - combine into Hamlib? */
+    s.Put("FrontEnd", "smetercorrectiontype", int(Parameters.FrontEndParameters.eSMeterCorrectionType));
+
+    s.Put("FrontEnd", "smeterbandwidth", int(Parameters.FrontEndParameters.rSMeterBandwidth));
+
+    s.Put("FrontEnd", "defaultmeasurementbandwidth", int(Parameters.FrontEndParameters.rDefaultMeasurementBandwidth));
+
+    s.Put("FrontEnd", "automeasurementbandwidth", Parameters.FrontEndParameters.bAutoMeasurementBandwidth);
+
+    s.Put("FrontEnd", "calfactordrm", int(Parameters.FrontEndParameters.rCalFactorDRM));
+
+    s.Put("FrontEnd", "calfactoram", int(Parameters.FrontEndParameters.rCalFactorAM));
+
+    s.Put("FrontEnd", "ifcentrefrequency", int(Parameters.FrontEndParameters.rIFCentreFreq));
+
+    /* Serial Number */
+    s.Put("Receiver", "serialnumber", Parameters.sSerialNumber);
+
+    /* GPS */
+    if(Parameters.gps_data.set & LATLON_SET) {
+	s.Put("GPS", "latitude", Parameters.gps_data.fix.latitude);
+	s.Put("GPS", "longitude", Parameters.gps_data.fix.longitude);
+    }
+    s.Put("GPS", "usegpsd", Parameters.use_gpsd);
+    s.Put("GPS", "host", Parameters.gps_host);
+    s.Put("GPS", "port", Parameters.gps_port);
+}
+
+void CConvertAudio::InitInternal(CParameter& Parameters)
+{
+    iInputBlockSize = Parameters.CellMappingTable.iSymbolBlockSize;
+    iOutputBlockSize = 2*iInputBlockSize;
+    iMaxOutputBlockSize = 2 * int((_REAL) Parameters.GetAudSampleRate() * (_REAL) 0.4 /* 400 ms */);
+}
+
+void CConvertAudio::ProcessDataInternal(CParameter& Parameters)
+{
+    (void)Parameters;
+    for (int i = 0; i < this->iInputBlockSize; i++)
+    {
+        (*this->pvecOutputData)[2*i] = _SAMPLE((*this->pvecInputData)[i]);
+        (*this->pvecOutputData)[2*i+1] = _SAMPLE((*this->pvecInputData)[i]);
+    }
+}
diff --git a/src/DrmReceiver.h b/src/DrmReceiver.h
new file mode 100644
index 0000000..1aa6f54
--- /dev/null
+++ b/src/DrmReceiver.h
@@ -0,0 +1,450 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer, Andrew Murphy, Andrea Russo, Oliver Haffenden
+ *
+ * Description:
+ *	See DrmReceiver.cpp
+ *
+ * 11/21/2005 Andrew Murphy, BBC Research & Development, 2005
+ *	- Additions to include AMSS demodulation
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#if !defined(DRMRECEIVER_H__3B0BA660_CA63_4344_BB2B_23E7A0D31912__INCLUDED_)
+#define DRMRECEIVER_H__3B0BA660_CA63_4344_BB2B_23E7A0D31912__INCLUDED_
+
+#include "GlobalDefinitions.h"
+#include <iostream>
+#include "MDI/MDIRSCI.h" /* OPH: need this near the top so winsock2 is included before winsock */
+#include "MDI/MDIDecode.h"
+#include "Parameter.h"
+#include "util/Buffer.h"
+#include "util/Utilities.h"
+#include "DataIO.h"
+#include "OFDM.h"
+#include "DRMSignalIO.h"
+#include "MSCMultiplexer.h"
+#include "InputResample.h"
+#include "datadecoding/DataDecoder.h"
+#include "sourcedecoders/AudioSourceEncoder.h"
+#include "sourcedecoders/AudioSourceDecoder.h"
+#include "mlc/MLC.h"
+#include "interleaver/SymbolInterleaver.h"
+#include "ofdmcellmapping/OFDMCellMapping.h"
+#include "chanest/ChannelEstimation.h"
+#include "sync/FreqSyncAcq.h"
+#include "sync/TimeSync.h"
+#include "sync/SyncUsingPil.h"
+#include "AMDemodulation.h"
+#include "AMSSDemodulation.h"
+#include "sound/soundinterface.h"
+#include "PlotManager.h"
+#include "DrmTransceiver.h"
+
+/* Definitions ****************************************************************/
+/* Number of FAC frames until the acquisition is activated in case a signal
+   was successfully decoded */
+#define	NUM_FAC_FRA_U_ACQ_WITH			10
+
+/* Number of OFDM symbols until the acquisition is activated in case no signal
+   could be decoded after previous acquisition try */
+#define	NUM_OFDMSYM_U_ACQ_WITHOUT		150
+
+/* Number of FAC blocks for delayed tracking mode switch (caused by time needed
+   for initalizing the channel estimation */
+#define NUM_FAC_DEL_TRACK_SWITCH		2
+
+/* Length of the history for synchronization parameters (used for the plot) */
+#define LEN_HIST_PLOT_SYNC_PARMS		2250
+
+
+typedef void (SFCallback)(void*, int);
+
+
+/* Classes ********************************************************************/
+class CSettings;
+class CRig;
+
+class CSplitFAC : public CSplitModul<_BINARY>
+{
+    void SetInputBlockSize(CParameter& p)
+    {
+        this->iInputBlockSize = p.iNumFACBitsPerBlock;
+    }
+};
+
+class CSplitSDC : public CSplitModul<_BINARY>
+{
+    void SetInputBlockSize(CParameter& p)
+    {
+        this->iInputBlockSize = p.iNumSDCBitsPerSFrame;
+    }
+};
+
+class CSplitMSC : public CSplitModul<_BINARY>
+{
+public:
+    void SetStream(int iID) {
+        iStreamID = iID;
+    }
+
+protected:
+    void SetInputBlockSize(CParameter& p)
+    {
+        this->iInputBlockSize = p.GetStreamLen(iStreamID) * SIZEOF__BYTE;
+    }
+
+    int iStreamID;
+};
+
+class CSplitAudio : public CSplitModul<_SAMPLE>
+{
+protected:
+    void SetInputBlockSize(CParameter& p)
+    {
+        this->iInputBlockSize = (int) ((_REAL) p.GetAudSampleRate() * (_REAL) 0.4 /* 400 ms */) * 2 /* stereo */;
+    }
+};
+
+class CConvertAudio : public CReceiverModul<_REAL,_SAMPLE>
+{
+protected:
+    virtual void InitInternal(CParameter&);
+    virtual void ProcessDataInternal(CParameter&);
+};
+
+class CDRMReceiver : public CDRMTransceiver
+{
+public:
+
+    enum ESFStatus { SF_SNDCARDIN, SF_SNDFILEIN, SF_RSCIMDIIN };
+
+    CDRMReceiver(CSettings* pSettings=NULL);
+    virtual ~CDRMReceiver();
+
+    void					LoadSettings(); // can write to settings to set defaults
+    void					SaveSettings();
+    void					Start();
+    void					SetRsciInput(const string& rsciInput);
+    void					ClearRsciInput();
+    void					SetSoundFile(const string& soundFile);
+    void					ClearSoundFile();
+    void					SetInputFile(const string& inputFile);
+    void					ClearInputFile();
+    ESFStatus				GetInputStatus();
+    string					GetInputFileName();
+    void					RequestNewAcquisition() {
+        bRestartFlag = TRUE;
+    }
+    EAcqStat				GetAcquiState() {
+        return Parameters.GetAcquiState();
+    }
+    ERecMode				GetReceiverMode() {
+        return eReceiverMode;
+    }
+    bool GetDownstreamRSCIOutEnabled()
+    {
+        return downstreamRSCI.GetOutEnabled();
+    }
+
+    void					SetReceiverMode(ERecMode eNewMode);
+    void					SetInitResOff(_REAL rNRO)
+    {
+        rInitResampleOffset = rNRO;
+    }
+    void					SetAMDemodType(CAMDemodulation::EDemodType);
+    void					SetAMFilterBW(int iBw);
+    void					SetAMDemodAcq(_REAL rNewNorCen);
+    void	 				SetSFCallback(SFCallback* psfCallback, void* psfCallbackParam) {
+        sfCallback = psfCallback;
+        sfCallbackParam = psfCallbackParam;
+    }
+    void	 				SetFrequency(int);
+    int		 				GetFrequency() {
+        return Parameters.GetFrequency();
+    }
+    void					SetIQRecording(_BOOLEAN);
+    void					SetRSIRecording(_BOOLEAN, const char);
+
+    /* Channel Estimation */
+    void SetFreqInt(CChannelEstimation::ETypeIntFreq eNewTy)
+    {
+        ChannelEstimation.SetFreqInt(eNewTy);
+    }
+
+    CChannelEstimation::ETypeIntFreq GetFreqInt()
+    {
+        return ChannelEstimation.GetFreqInt();
+    }
+
+    void SetTimeInt(CChannelEstimation::ETypeIntTime eNewTy)
+    {
+        ChannelEstimation.SetTimeInt(eNewTy);
+    }
+
+    CChannelEstimation::ETypeIntTime GetTimeInt() const
+    {
+        return ChannelEstimation.GetTimeInt();
+    }
+
+    void SetIntCons(const _BOOLEAN bNewIntCons)
+    {
+        ChannelEstimation.SetIntCons(bNewIntCons);
+    }
+
+    _BOOLEAN GetIntCons()
+    {
+        return ChannelEstimation.GetIntCons();
+    }
+
+    void SetSNREst(CChannelEstimation::ETypeSNREst eNewTy)
+    {
+        ChannelEstimation.SetSNREst(eNewTy);
+    }
+
+    CChannelEstimation::ETypeSNREst GetSNREst()
+    {
+        return ChannelEstimation.GetSNREst();
+    }
+
+    void SetTiSyncTracType(CTimeSyncTrack::ETypeTiSyncTrac eNewTy)
+    {
+        ChannelEstimation.GetTimeSyncTrack()->SetTiSyncTracType(eNewTy);
+    }
+
+    CTimeSyncTrack::ETypeTiSyncTrac GetTiSyncTracType()
+    {
+        return ChannelEstimation.GetTimeSyncTrack()->GetTiSyncTracType();
+    }
+
+    /* Get pointer to internal modules */
+    CUtilizeFACData*		GetFAC() {
+        return &UtilizeFACData;
+    }
+    CUtilizeSDCData*		GetSDC() {
+        return &UtilizeSDCData;
+    }
+    CTimeSync*				GetTimeSync() {
+        return &TimeSync;
+    }
+    CFACMLCDecoder*			GetFACMLC() {
+        return &FACMLCDecoder;
+    }
+    CSDCMLCDecoder*			GetSDCMLC() {
+        return &SDCMLCDecoder;
+    }
+    CMSCMLCDecoder*			GetMSCMLC() {
+        return &MSCMLCDecoder;
+    }
+    CReceiveData*			GetReceiveData() {
+        return &ReceiveData;
+    }
+    COFDMDemodulation*		GetOFDMDemod() {
+        return &OFDMDemodulation;
+    }
+    CSyncUsingPil*			GetSyncUsPil() {
+        return &SyncUsingPil;
+    }
+    CWriteData*				GetWriteData() {
+        return &WriteData;
+    }
+    CDataDecoder*			GetDataDecoder() {
+        return &DataDecoder;
+    }
+    CAMDemodulation*		GetAMDemod() {
+        return &AMDemodulation;
+    }
+    CAMSSPhaseDemod*		GetAMSSPhaseDemod() {
+        return &AMSSPhaseDemod;
+    }
+    CAMSSDecode*			GetAMSSDecode() {
+        return &AMSSDecode;
+    }
+    CFreqSyncAcq*			GetFreqSyncAcq() {
+        return &FreqSyncAcq;
+    }
+    CAudioSourceDecoder*	GetAudSorceDec() {
+        return &AudioSourceDecoder;
+    }
+    CUpstreamDI*			GetRSIIn() {
+        return pUpstreamRSCI;
+    }
+    CDownstreamDI*			GetRSIOut() {
+        return &downstreamRSCI;
+    }
+    CChannelEstimation*		GetChannelEstimation() {
+        return &ChannelEstimation;
+    }
+
+    CPlotManager*			GetPlotManager() {
+        return &PlotManager;
+    }
+
+    void					InitsForWaveMode();
+    void					InitsForSpectrumOccup();
+    void					InitsForNoDecBitsSDC();
+    void					InitsForAudParam();
+    void					InitsForDataParam();
+    void					InitsForInterlDepth();
+    void					InitsForMSCCodSche();
+    void					InitsForSDCCodSche();
+    void					InitsForMSC();
+    void					InitsForMSCDemux();
+
+protected:
+
+    void					SetInStartMode();
+    void					SetInTrackingMode();
+    void					SetInTrackingModeDelayed();
+    void					InitsForAllModules();
+    void					Run();
+    void					SetInput();
+    void					ResetInput();
+    void					DemodulateDRM(_BOOLEAN&);
+    void					DecodeDRM(_BOOLEAN&, _BOOLEAN&);
+    void					UtilizeDRM(_BOOLEAN&);
+    void					DemodulateAM(_BOOLEAN&);
+    void					DecodeAM(_BOOLEAN&);
+    void					UtilizeAM(_BOOLEAN&);
+    void					DemodulateFM(_BOOLEAN&);
+    void					DecodeFM(_BOOLEAN&);
+    void					UtilizeFM(_BOOLEAN&);
+    void					DetectAcquiFAC();
+    void					DetectAcquiSymbol();
+    void					InitReceiverMode();
+    void					saveSDCtoFile();
+    void                    CloseSoundInterfaces();
+
+    /* Modules */
+    CReceiveData			ReceiveData;
+    CWriteData				WriteData;
+    CInputResample			InputResample;
+    CFreqSyncAcq			FreqSyncAcq;
+    CTimeSync				TimeSync;
+    COFDMDemodulation		OFDMDemodulation;
+    CSyncUsingPil			SyncUsingPil;
+    CChannelEstimation		ChannelEstimation;
+    COFDMCellDemapping		OFDMCellDemapping;
+    CFACMLCDecoder			FACMLCDecoder;
+    CUtilizeFACData			UtilizeFACData;
+    CSDCMLCDecoder			SDCMLCDecoder;
+    CUtilizeSDCData			UtilizeSDCData;
+    CSymbDeinterleaver		SymbDeinterleaver;
+    CMSCMLCDecoder			MSCMLCDecoder;
+    CMSCDemultiplexer		MSCDemultiplexer;
+    CAudioSourceDecoder		AudioSourceDecoder;
+    CDataDecoder			DataDecoder;
+    CSplit					Split;
+    CSplit					SplitForIQRecord;
+    CWriteIQFile			WriteIQFile;
+    CSplitAudio				SplitAudio;
+    CAudioSourceEncoderRx	AudioSourceEncoder; // For encoding the audio for RSI
+    CSplitFAC				SplitFAC;
+    CSplitSDC				SplitSDC;
+    CSplitMSC				SplitMSC[MAX_NUM_STREAMS];
+    CConvertAudio			ConvertAudio;
+    CAMDemodulation			AMDemodulation;
+    CAMSSPhaseDemod			AMSSPhaseDemod;
+    CAMSSExtractBits		AMSSExtractBits;
+    CAMSSDecode				AMSSDecode;
+
+    CUpstreamDI*			pUpstreamRSCI;
+    CDecodeRSIMDI			DecodeRSIMDI;
+    CDownstreamDI			downstreamRSCI;
+
+    /* Buffers */
+    CSingleBuffer<_REAL>			AMDataBuf;
+    CSingleBuffer<_REAL>			AMSSDataBuf;
+    CSingleBuffer<_REAL>			AMSSPhaseBuf;
+    CCyclicBuffer<_REAL>			AMSSResPhaseBuf;
+    CCyclicBuffer<_BINARY>			AMSSBitsBuf;
+
+    CCyclicBuffer<_REAL>			DemodDataBuf;
+    CSingleBuffer<_REAL>			IQRecordDataBuf;
+
+    CCyclicBuffer<_REAL>			RecDataBuf;
+    CCyclicBuffer<_REAL>			InpResBuf;
+    CCyclicBuffer<_COMPLEX>			FreqSyncAcqBuf;
+    CSingleBuffer<_COMPLEX>			TimeSyncBuf;
+    CSingleBuffer<_COMPLEX>			OFDMDemodBuf;
+    CSingleBuffer<_COMPLEX>			SyncUsingPilBuf;
+    CSingleBuffer<CEquSig>			ChanEstBuf;
+    CCyclicBuffer<CEquSig>			MSCCarDemapBuf;
+    CCyclicBuffer<CEquSig>			FACCarDemapBuf;
+    CCyclicBuffer<CEquSig>			SDCCarDemapBuf;
+    CSingleBuffer<CEquSig>			DeintlBuf;
+    CSingleBuffer<_BINARY>			FACDecBuf;
+    CSingleBuffer<_BINARY>			FACUseBuf;
+    CSingleBuffer<_BINARY>			FACSendBuf;
+    CSingleBuffer<_BINARY>			SDCDecBuf;
+    CSingleBuffer<_BINARY>			SDCUseBuf;
+    CSingleBuffer<_BINARY>			SDCSendBuf;
+    CSingleBuffer<_BINARY>			MSCMLCDecBuf;
+    CSingleBuffer<_BINARY>			RSIPacketBuf;
+    vector<CSingleBuffer<_BINARY> >	MSCDecBuf;
+    vector<CSingleBuffer<_BINARY> >	MSCUseBuf;
+    vector<CSingleBuffer<_BINARY> >	MSCSendBuf;
+    CSingleBuffer<_BINARY>			EncAMAudioBuf;
+    CCyclicBuffer<_SAMPLE>			AudSoDecBuf;
+    CCyclicBuffer<_SAMPLE>			AMAudioBuf;
+    CCyclicBuffer<_SAMPLE>			AMSoEncBuf; // For encoding
+
+    int						iAcquRestartCnt;
+    int						iAcquDetecCnt;
+    int						iGoodSignCnt;
+    int						iDelayedTrackModeCnt;
+    ERecState				eReceiverState;
+    ERecMode				eReceiverMode;
+    ERecMode				eNewReceiverMode;
+
+    int						iAudioStreamID;
+    int						iDataStreamID;
+
+
+    _BOOLEAN				bRestartFlag;
+
+    _REAL					rInitResampleOffset;
+
+    CVectorEx<_BINARY>		vecbiMostRecentSDC;
+
+    /* number of frames without FAC data before generating free-running RSCI */
+    static const int		MAX_UNLOCKED_COUNT;
+
+    /* Counter for unlocked frames, to keep generating RSCI even when unlocked */
+    int						iUnlockedCount;
+    int						iBwAM;
+    int						iBwLSB;
+    int						iBwUSB;
+    int						iBwCW;
+    int						iBwFM;
+    time_t					time_keeper;
+    SFCallback*				sfCallback;
+    void*					sfCallbackParam;
+
+    CPlotManager			PlotManager;
+    string					rsiOrigin;
+    string					sSoundFile;
+    int						iPrevSigSampleRate; /* sample rate before sound file */
+};
+
+
+#endif // !defined(DRMRECEIVER_H__3B0BA660_CA63_4344_BB2B_23E7A0D31912__INCLUDED_)
diff --git a/src/DrmSimulation.cpp b/src/DrmSimulation.cpp
new file mode 100644
index 0000000..ecdb587
--- /dev/null
+++ b/src/DrmSimulation.cpp
@@ -0,0 +1,362 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *	DRM-simulation
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "DrmSimulation.h"
+
+
+/* Implementation *************************************************************/
+
+CDRMSimulation::CDRMSimulation() : iSimTime(0), iSimNumErrors(0),
+        rStartSNR(0.0), rEndSNR(0.0), rStepSNR(0.0),
+        Parameters(),
+        DataBuf(), MLCEncBuf(), IntlBuf(), GenFACDataBuf(), FACMapBuf(), GenSDCDataBuf(),
+        SDCMapBuf(), CarMapBuf(), OFDMModBuf(), OFDMDemodBufChan2(), ChanEstInBufSim(),
+        ChanEstOutBufChan(),
+        RecDataBuf(), ChanResInBuf(), InpResBuf(), FreqSyncAcqBuf(), TimeSyncBuf(),
+        OFDMDemodBuf(), SyncUsingPilBuf(), ChanEstBuf(),
+        MSCCarDemapBuf(), FACCarDemapBuf(), SDCCarDemapBuf(), DeintlBuf(),
+        FACDecBuf(), SDCDecBuf(), MSCMLCDecBuf(), GenSimData(),
+        MSCMLCEncoder(), SymbInterleaver(), GenerateFACData(), FACMLCEncoder(),
+        GenerateSDCData(), SDCMLCEncoder(), OFDMCellMapping(), OFDMModulation(),
+        DRMChannel(), InputResample(), FreqSyncAcq(), TimeSync(), OFDMDemodulation(),
+        SyncUsingPil(), ChannelEstimation(), OFDMCellDemapping(), FACMLCDecoder(), UtilizeFACData(),
+        SDCMLCDecoder(), UtilizeSDCData(), SymbDeinterleaver(), MSCMLCDecoder(), EvaSimData(),
+        OFDMDemodSimulation(), IdealChanEst(), DataConvChanResam()
+{
+    /* Set all parameters to meaningful value for startup state. If we want to
+       make a simulation we just have to specify the important values */
+    /* Init streams */
+    Parameters.ResetServicesStreams();
+
+
+    /* Service parameters (only use service 0) ------------------------------- */
+    /* Data service */
+    Parameters.SetNumOfServices(0,1);
+
+    Parameters.SetAudDataFlag(0,  CService::SF_DATA);
+
+    CDataParam DataParam;
+    DataParam.iStreamID = 0;
+    DataParam.ePacketModInd = CDataParam::PM_SYNCHRON_STR_MODE;
+    Parameters.SetDataParam(0, DataParam);
+
+    //Parameters.SetCurSelDataService(1); /* Service ID must be set for activation */
+    Parameters.SetCurSelDataService(0); /* Service ID must be set for activation */
+
+    /* Stream */
+    Parameters.SetStreamLen(0, 0, 0); // EEP, if "= 0"
+
+
+    /* Date, time */
+    Parameters.iDay = 0;
+    Parameters.iMonth = 0;
+    Parameters.iYear = 0;
+    Parameters.iUTCHour = 0;
+    Parameters.iUTCMin = 0;
+
+    /* Frame IDs */
+    Parameters.iFrameIDTransm = 0;
+    Parameters.iFrameIDReceiv = 0;
+
+    /* Initialize synchronization parameters */
+    Parameters.rResampleOffset = (_REAL) 0.0;
+    Parameters.rFreqOffsetAcqui = (_REAL) VIRTUAL_INTERMED_FREQ / Parameters.GetSigSampleRate();
+    Parameters.rFreqOffsetTrack = (_REAL) 0.0;
+    Parameters.iTimingOffsTrack = 0;
+
+    Parameters.InitCellMapTable(RM_ROBUSTNESS_MODE_B, SO_3);
+
+    Parameters.MSCPrLe.iPartA = 1;
+    Parameters.MSCPrLe.iPartB = 1;
+    Parameters.MSCPrLe.iHierarch = 0;
+
+    Parameters.eSymbolInterlMode = SI_SHORT;
+    Parameters.eMSCCodingScheme = CS_3_SM;
+    Parameters.eSDCCodingScheme = CS_2_SM;
+
+    /* DRM channel parameters */
+    Parameters.iDRMChannelNum = 1;
+    Parameters.SetNominalSNRdB(25);
+}
+
+void CDRMSimulation::Run()
+{
+    /*
+     The hand over of data is done via an intermediate-buffer. The calling
+     convention is always "input-buffer, output-buffer". Additional, the
+     DRM-parameters are fed to the function
+    */
+
+    /* Initialization of the modules */
+    Init();
+
+    /* Set run flag */
+    Parameters.eRunState = CParameter::RUNNING;
+
+    while (Parameters.eRunState == CParameter::RUNNING)
+    {
+        /**********************************************************************\
+        * Transmitter														   *
+        \**********************************************************************/
+        /* MSC -------------------------------------------------------------- */
+        /* Read the source signal */
+        GenSimData.ReadData(Parameters, DataBuf);
+
+        /* MLC-encoder */
+        MSCMLCEncoder.ProcessData(Parameters, DataBuf, MLCEncBuf);
+
+        /* Convolutional interleaver */
+        SymbInterleaver.ProcessData(Parameters, MLCEncBuf, IntlBuf);
+
+
+        /* FAC -------------------------------------------------------------- */
+        GenerateFACData.ReadData(Parameters, GenFACDataBuf);
+        FACMLCEncoder.ProcessData(Parameters, GenFACDataBuf, FACMapBuf);
+
+
+        /* SDC -------------------------------------------------------------- */
+        GenerateSDCData.ReadData(Parameters, GenSDCDataBuf);
+        SDCMLCEncoder.ProcessData(Parameters, GenSDCDataBuf, SDCMapBuf);
+
+
+        /* Mapping of the MSC, FAC, SDC and pilots on the carriers */
+        OFDMCellMapping.ProcessData(Parameters, IntlBuf, FACMapBuf,
+                                    SDCMapBuf, CarMapBuf);
+
+        /* OFDM-modulation */
+        OFDMModulation.ProcessData(Parameters, CarMapBuf, OFDMModBuf);
+
+
+
+        /**********************************************************************\
+        * Channel    														   *
+        \**********************************************************************/
+        DRMChannel.TransferData(Parameters, OFDMModBuf, RecDataBuf);
+
+
+
+        /**********************************************************************\
+        * Receiver    														   *
+        \**********************************************************************/
+        switch (Parameters.eSimType)
+        {
+        case CParameter::ST_MSECHANEST:
+        case CParameter::ST_BER_IDEALCHAN:
+        case CParameter::ST_SINR:
+            /* MSE of channel estimation, ideal channel estimation -------------- */
+            /* Special OFDM demodulation for channel estimation tests (with guard-
+               interval removal) */
+            OFDMDemodSimulation.ProcessDataOut(Parameters, RecDataBuf,
+                                               ChanEstInBufSim, OFDMDemodBufChan2);
+
+            /* Channel estimation and equalization */
+            ChannelEstimation.ProcessData(Parameters, ChanEstInBufSim, ChanEstBuf);
+
+            /* Ideal channel estimation (with MSE calculation) */
+            IdealChanEst.ProcessDataIn(Parameters, ChanEstBuf, OFDMDemodBufChan2,
+                                       ChanEstBuf);
+            break;
+
+
+        default: /* Other types like ST_BITERROR or ST_SYNC_PARAM */
+            /* Bit error rate (we can use all synchronization units here!) ------ */
+            /* This module converts the "CChanSimDataMod" data type of "DRMChannel"
+               to the "_REAL" data type, because a regular module can only have ONE
+               type of input buffers */
+            DataConvChanResam.ProcessData(Parameters, RecDataBuf, ChanResInBuf);
+
+            /* Resample input DRM-stream */
+            InputResample.ProcessData(Parameters, ChanResInBuf, InpResBuf);
+
+            /* Frequency synchronization acquisition */
+            FreqSyncAcq.ProcessData(Parameters, InpResBuf, FreqSyncAcqBuf);
+
+            /* Time synchronization */
+            TimeSync.ProcessData(Parameters, FreqSyncAcqBuf, TimeSyncBuf);
+
+            /* OFDM-demodulation */
+            OFDMDemodulation.ProcessData(Parameters, TimeSyncBuf, OFDMDemodBuf);
+
+            /* Synchronization in the frequency domain (using pilots) */
+            SyncUsingPil.ProcessData(Parameters, OFDMDemodBuf, SyncUsingPilBuf);
+
+            /* Channel estimation and equalization */
+            ChannelEstimation.ProcessData(Parameters, SyncUsingPilBuf, ChanEstBuf);
+            break;
+        }
+
+        /* Demapping of the MSC, FAC, SDC and pilots from the carriers */
+        OFDMCellDemapping.ProcessData(Parameters, ChanEstBuf,
+                                      MSCCarDemapBuf, FACCarDemapBuf, SDCCarDemapBuf);
+
+        /* FAC */
+        FACMLCDecoder.ProcessData(Parameters, FACCarDemapBuf, FACDecBuf);
+        UtilizeFACData.WriteData(Parameters, FACDecBuf);
+
+
+        /* SDC */
+        SDCMLCDecoder.ProcessData(Parameters, SDCCarDemapBuf, SDCDecBuf);
+        UtilizeSDCData.WriteData(Parameters, SDCDecBuf);
+
+
+        /* MSC */
+        /* Symbol de-interleaver */
+        SymbDeinterleaver.ProcessData(Parameters, MSCCarDemapBuf, DeintlBuf);
+
+        /* MLC-decoder */
+        MSCMLCDecoder.ProcessData(Parameters, DeintlBuf, MSCMLCDecBuf);
+
+        /* Evaluate simulation data */
+        EvaSimData.WriteData(Parameters, MSCMLCDecBuf);
+    }
+}
+
+void CDRMSimulation::Init()
+{
+    /* Defines number of cells, important! */
+    OFDMCellMapping.Init(Parameters, CarMapBuf);
+
+    /* Defines number of SDC bits per super-frame */
+    SDCMLCEncoder.Init(Parameters, SDCMapBuf);
+
+    MSCMLCEncoder.Init(Parameters, MLCEncBuf);
+    SymbInterleaver.Init(Parameters, IntlBuf);
+    GenerateFACData.Init(Parameters, GenFACDataBuf);
+    FACMLCEncoder.Init(Parameters, FACMapBuf);
+    GenerateSDCData.Init(Parameters, GenSDCDataBuf);
+    OFDMModulation.Init(Parameters, OFDMModBuf);
+    GenSimData.Init(Parameters, DataBuf);
+
+
+    /* Receiver modules */
+    /* The order of modules are important! */
+    InputResample.Init(Parameters, InpResBuf);
+    FreqSyncAcq.Init(Parameters, FreqSyncAcqBuf);
+    TimeSync.Init(Parameters, TimeSyncBuf);
+    SyncUsingPil.Init(Parameters, SyncUsingPilBuf);
+
+    /* Channel estimation init must be called before OFDMDemodSimulation
+       module, because the delay is set here which the other modules use! */
+    ChannelEstimation.Init(Parameters, ChanEstBuf);
+
+    OFDMCellDemapping.Init(Parameters, MSCCarDemapBuf, FACCarDemapBuf,
+                           SDCCarDemapBuf);
+    FACMLCDecoder.Init(Parameters, FACDecBuf);
+    UtilizeFACData.Init(Parameters);
+    SDCMLCDecoder.Init(Parameters, SDCDecBuf);
+    UtilizeSDCData.Init(Parameters);
+    SymbDeinterleaver.Init(Parameters, DeintlBuf);
+    MSCMLCDecoder.Init(Parameters, MSCMLCDecBuf);
+
+
+    /* Special module for simulation */
+    EvaSimData.Init(Parameters);
+
+    /* Init channel. The channel must be initialized before the modules
+       "OFDMDemodSimulation" and "IdealChanEst" because they need iNumTaps and
+       tap delays in global struct */
+    DRMChannel.Init(Parameters, RecDataBuf);
+
+    /* Mode dependent initializations */
+    switch (Parameters.eSimType)
+    {
+    case CParameter::ST_MSECHANEST:
+    case CParameter::ST_BER_IDEALCHAN:
+    case CParameter::ST_SINR:
+        /* Init OFDM demod before IdealChanEst, because the timing offset of
+           useful part extraction is set here */
+        OFDMDemodSimulation.Init(Parameters, ChanEstInBufSim, OFDMDemodBufChan2);
+
+        /* Problem: "ChanEstBuf" is used for input and output buffer. That only
+           works with single buffers. This solution works for this case but is
+           not a very nice solution FIXME */
+        IdealChanEst.Init(Parameters, ChanEstBuf);
+        break;
+
+    default: /* Other types like ST_BITERROR or ST_SYNC_PARAM */
+        DataConvChanResam.Init(Parameters, ChanResInBuf);
+
+        OFDMDemodulation.Init(Parameters, OFDMDemodBuf);
+        break;
+    }
+
+
+    /* Clear all buffers ---------------------------------------------------- */
+    /* The buffers must be cleared in case there is some data left in the
+       buffers from the last simulation (with, e.g., different SNR) */
+    DataBuf.Clear();
+    MLCEncBuf.Clear();
+    IntlBuf.Clear();
+    GenFACDataBuf.Clear();
+    FACMapBuf.Clear();
+    GenSDCDataBuf.Clear();
+    SDCMapBuf.Clear();
+    CarMapBuf.Clear();
+    OFDMModBuf.Clear();
+    OFDMDemodBufChan2.Clear();
+    ChanEstInBufSim.Clear();
+    ChanEstOutBufChan.Clear();
+    RecDataBuf.Clear();
+    ChanResInBuf.Clear();
+    InpResBuf.Clear();
+    FreqSyncAcqBuf.Clear();
+    TimeSyncBuf.Clear();
+    OFDMDemodBuf.Clear();
+    SyncUsingPilBuf.Clear();
+    ChanEstBuf.Clear();
+    MSCCarDemapBuf.Clear();
+    FACCarDemapBuf.Clear();
+    SDCCarDemapBuf.Clear();
+    DeintlBuf.Clear();
+    FACDecBuf.Clear();
+    SDCDecBuf.Clear();
+    MSCMLCDecBuf.Clear();
+
+
+    /* We only want to simulate tracking performance ------------------------ */
+    TimeSync.StopTimingAcqu();
+    TimeSync.StopRMDetAcqu(); /* Robustness mode detection */
+    ChannelEstimation.GetTimeSyncTrack()->StartTracking();
+
+    /* We stop tracking of time wiener interpolation since during acquisition,
+       no automatic update of the statistic estimates is done. We need that
+       because we set the correct parameters once in the init routine */
+    ChannelEstimation.GetTimeWiener()->StopTracking();
+
+    /* Disable FAC evaluation to make sure that no mistakenly correct CRC
+       sets false parameters which can cause run-time errors */
+    UtilizeFACData.SetSyncInput(TRUE);
+
+    /* We have to first start aquisition and then stop it right after it to set
+       internal parameters */
+    SyncUsingPil.StartAcquisition();
+    SyncUsingPil.StopAcquisition();
+
+    SyncUsingPil.StartTrackPil();
+}
+
diff --git a/src/DrmSimulation.h b/src/DrmSimulation.h
new file mode 100644
index 0000000..4a9d7c1
--- /dev/null
+++ b/src/DrmSimulation.h
@@ -0,0 +1,157 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *	See DrmSimulation.cpp
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#if !defined(DRMSIMULATION_H__3B0BA660_CA63_4344_BB2B_23E7A0D31912__INCLUDED_)
+#define DRMSIMULATION_H__3B0BA660_CA63_4344_BB2B_23E7A0D31912__INCLUDED_
+
+#include <iostream>
+#include "GlobalDefinitions.h"
+#include "Parameter.h"
+#include "util/Buffer.h"
+#include "DataIO.h"
+#include "OFDM.h"
+#include "DRMSignalIO.h"
+#include "MSCMultiplexer.h"
+#include "InputResample.h"
+#include "mlc/MLC.h"
+#include "interleaver/SymbolInterleaver.h"
+#include "ofdmcellmapping/OFDMCellMapping.h"
+#include "chanest/ChannelEstimation.h"
+#include "chanest/IdealChannelEstimation.h"
+#include "sync/FreqSyncAcq.h"
+#include "sync/TimeSync.h"
+#include "sync/SyncUsingPil.h"
+#include "drmchannel/ChannelSimulation.h"
+
+
+
+/* Classes ********************************************************************/
+class CDRMSimulation
+{
+public:
+    CDRMSimulation();
+    virtual ~CDRMSimulation() {}
+
+    void SimScript();
+
+    CParameter* GetParameters() {
+        return &Parameters;
+    }
+
+protected:
+    void Run();
+    void Init();
+    string SimFileName(CParameter& Param, string strAddInf, _BOOLEAN bWithSNR);
+
+    int iSimTime;
+    int iSimNumErrors;
+    _REAL rStartSNR, rEndSNR, rStepSNR;
+
+    /* Parameters */
+    CParameter				Parameters;
+
+
+    /* Buffers -------------------------------------------------------------- */
+    /* If you want to add a new buffer, make sure that it is cleared in the
+       "Init()" routine! */
+    /* Transmitter buffers */
+    CSingleBuffer<_BINARY>				DataBuf;
+    CSingleBuffer<_COMPLEX>				MLCEncBuf;
+    CCyclicBuffer<_COMPLEX>				IntlBuf;
+    CSingleBuffer<_BINARY>				GenFACDataBuf;
+    CCyclicBuffer<_COMPLEX>				FACMapBuf;
+    CSingleBuffer<_BINARY>				GenSDCDataBuf;
+    CCyclicBuffer<_COMPLEX>				SDCMapBuf;
+    CSingleBuffer<_COMPLEX>				CarMapBuf;
+    CSingleBuffer<_COMPLEX>				OFDMModBuf;
+
+    /* Simulation */
+    CCyclicBuffer<CChanSimDataDemod>	OFDMDemodBufChan2;
+    CSingleBuffer<_COMPLEX>				ChanEstInBufSim;
+    CSingleBuffer<CChanSimDataDemod>	ChanEstOutBufChan;
+    CSingleBuffer<CChanSimDataMod>		RecDataBuf;
+    CSingleBuffer<_REAL>				ChanResInBuf;
+
+    /* Receiver buffers */
+    CCyclicBuffer<_REAL>				InpResBuf;
+    CSingleBuffer<_COMPLEX>				FreqSyncAcqBuf;
+    CSingleBuffer<_COMPLEX>				TimeSyncBuf;
+    CSingleBuffer<_COMPLEX>				OFDMDemodBuf;
+    CSingleBuffer<_COMPLEX>				SyncUsingPilBuf;
+    CSingleBuffer<CEquSig>				ChanEstBuf;
+    CCyclicBuffer<CEquSig>				MSCCarDemapBuf;
+    CCyclicBuffer<CEquSig>				FACCarDemapBuf;
+    CCyclicBuffer<CEquSig>				SDCCarDemapBuf;
+    CSingleBuffer<CEquSig>				DeintlBuf;
+    CSingleBuffer<_BINARY>				FACDecBuf;
+    CSingleBuffer<_BINARY>				SDCDecBuf;
+    CSingleBuffer<_BINARY>				MSCMLCDecBuf;
+
+
+    /* Modules -------------------------------------------------------------- */
+    /* Transmitter modules */
+    CGenSimData				GenSimData;
+
+    CMSCMLCEncoder			MSCMLCEncoder;
+    CSymbInterleaver		SymbInterleaver;
+    CGenerateFACData		GenerateFACData;
+    CFACMLCEncoder			FACMLCEncoder;
+    CGenerateSDCData		GenerateSDCData;
+    CSDCMLCEncoder			SDCMLCEncoder;
+    COFDMCellMapping		OFDMCellMapping;
+    COFDMModulation			OFDMModulation;
+
+    /* DRM channel */
+    CDRMChannel				DRMChannel;
+
+    /* Receiver modules */
+    CInputResample			InputResample;
+    CFreqSyncAcq			FreqSyncAcq;
+    CTimeSync				TimeSync;
+    COFDMDemodulation		OFDMDemodulation;
+    CSyncUsingPil			SyncUsingPil;
+    CChannelEstimation		ChannelEstimation;
+    COFDMCellDemapping		OFDMCellDemapping;
+    CFACMLCDecoder			FACMLCDecoder;
+    CUtilizeFACData			UtilizeFACData;
+    CSDCMLCDecoder			SDCMLCDecoder;
+    CUtilizeSDCData			UtilizeSDCData;
+    CSymbDeinterleaver		SymbDeinterleaver;
+    CMSCMLCDecoder			MSCMLCDecoder;
+
+    /* Simulation modules */
+    CEvaSimData				EvaSimData;
+    COFDMDemodSimulation	OFDMDemodSimulation;
+    CIdealChanEst			IdealChanEst;
+
+    CDataConvChanResam		DataConvChanResam;
+
+};
+
+
+#endif // !defined(DRMSIMULATION_H__3B0BA660_CA63_4344_BB2B_23E7A0D31912__INCLUDED_)
diff --git a/src/DrmTransceiver.h b/src/DrmTransceiver.h
new file mode 100644
index 0000000..ec47e21
--- /dev/null
+++ b/src/DrmTransceiver.h
@@ -0,0 +1,93 @@
+/******************************************************************************\
+ *
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	David Flamand
+ *
+ * Description:
+ *	DRM receiver-transmitter base class
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#ifndef _DRM_TRANSCEIVER_H_
+#define _DRM_TRANSCEIVER_H_
+
+#include "Parameter.h"
+#include "util/Settings.h"
+#include "sound/soundinterface.h"
+
+class CDRMTransceiver
+{
+public:
+	CDRMTransceiver(CSettings* pSettings, CSoundInInterface* pSoundIn, CSoundOutInterface* pSoundOut, _BOOLEAN bTransmitter = FALSE)
+	: pSettings(pSettings), pSoundInInterface(pSoundIn), pSoundOutInterface(pSoundOut), bTransmitter(bTransmitter) {};
+	virtual ~CDRMTransceiver() {};
+
+    virtual void LoadSettings() = 0;
+    virtual void SaveSettings() = 0;
+    virtual void Start() = 0;
+
+    virtual void Restart()
+    {
+        if (Parameters.eRunState == CParameter::RUNNING)
+            Parameters.eRunState = CParameter::RESTART;
+    }
+    virtual void Stop()
+    {
+        Parameters.eRunState = CParameter::STOP_REQUESTED;
+    }
+    virtual CSettings*				GetSettings() {
+        return pSettings;
+    }
+    virtual void					SetSettings(CSettings* pNewSettings) {
+        pSettings = pNewSettings;
+    }
+    virtual CParameter*				GetParameters() {
+        return &Parameters;
+    }
+    virtual CSoundInInterface*		GetSoundInInterface() {
+        return pSoundInInterface;
+    }
+    virtual CSoundOutInterface*		GetSoundOutInterface() {
+        return pSoundOutInterface;
+    }
+	virtual _BOOLEAN				IsReceiver() const {
+		return !bTransmitter;
+	}
+	virtual _BOOLEAN				IsTransmitter() const {
+		return bTransmitter;
+	}
+
+protected:
+    virtual void CloseSoundInterfaces()
+    {
+        pSoundInInterface->Close();
+        pSoundOutInterface->Close();
+    }
+	CSettings*				pSettings;
+    CParameter				Parameters;
+    CSoundInInterface*		pSoundInInterface;
+    CSoundOutInterface*		pSoundOutInterface;
+
+private:
+	const _BOOLEAN bTransmitter;
+};
+
+#endif
diff --git a/src/DrmTransmitter.cpp b/src/DrmTransmitter.cpp
new file mode 100644
index 0000000..c6294b7
--- /dev/null
+++ b/src/DrmTransmitter.cpp
@@ -0,0 +1,681 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *	DRM-transmitter
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "DrmTransmitter.h"
+#include "sound/sound.h"
+#include <sstream>
+
+/* Implementation *************************************************************/
+void CDRMTransmitter::Start()
+{
+    /* Set restart flag */
+    Parameters.eRunState = CParameter::RESTART;
+    do
+    {
+        /* Initialization of the modules */
+        Init();
+
+        /* Set run flag */
+        Parameters.eRunState = CParameter::RUNNING;
+
+        /* Start the transmitter run routine */
+        Run();
+    }
+    while (Parameters.eRunState == CParameter::RESTART);
+
+    /* Closing the sound interfaces */
+    CloseSoundInterfaces();
+
+    /* Set flag to stopped */
+    Parameters.eRunState = CParameter::STOPPED;
+}
+
+void CDRMTransmitter::Run()
+{
+    /*
+    	The hand over of data is done via an intermediate-buffer. The calling
+    	convention is always "input-buffer, output-buffer". Additional, the
+    	DRM-parameters are fed to the function
+    */
+    for (;;)
+    {
+        /* MSC ****************************************************************/
+        /* Read the source signal */
+        ReadData.ReadData(Parameters, DataBuf);
+
+        /* Audio source encoder */
+        AudioSourceEncoder.ProcessData(Parameters, DataBuf, AudSrcBuf);
+
+        /* MLC-encoder */
+        MSCMLCEncoder.ProcessData(Parameters, AudSrcBuf, MLCEncBuf);
+
+        /* Convolutional interleaver */
+        SymbInterleaver.ProcessData(Parameters, MLCEncBuf, IntlBuf);
+
+
+        /* FAC ****************************************************************/
+        GenerateFACData.ReadData(Parameters, GenFACDataBuf);
+        FACMLCEncoder.ProcessData(Parameters, GenFACDataBuf, FACMapBuf);
+
+
+        /* SDC ****************************************************************/
+        GenerateSDCData.ReadData(Parameters, GenSDCDataBuf);
+        SDCMLCEncoder.ProcessData(Parameters, GenSDCDataBuf, SDCMapBuf);
+
+
+        /* Mapping of the MSC, FAC, SDC and pilots on the carriers ************/
+        OFDMCellMapping.ProcessData(Parameters, IntlBuf, FACMapBuf, SDCMapBuf,
+                                    CarMapBuf);
+
+
+        /* OFDM-modulation ****************************************************/
+        OFDMModulation.ProcessData(Parameters, CarMapBuf, OFDMModBuf);
+
+
+        /* Soft stop **********************************************************/
+        if (CanSoftStopExit())
+            break;
+
+        /* Transmit the signal ************************************************/
+        TransmitData.WriteData(Parameters, OFDMModBuf);
+    }
+}
+
+#if 1
+/* Flavour 1: Stop at the frame boundary (worst case delay one frame) */
+_BOOLEAN CDRMTransmitter::CanSoftStopExit()
+{
+    /* Set new symbol flag */
+    const _BOOLEAN bNewSymbol = OFDMModBuf.GetFillLevel() != 0;
+
+    if (bNewSymbol)
+    {
+        /* Number of symbol by frame */
+        const int iSymbolPerFrame = Parameters.CellMappingTable.iNumSymPerFrame;
+
+        /* Set stop requested flag */
+        const _BOOLEAN bStopRequested = Parameters.eRunState != CParameter::RUNNING;
+
+        /* The soft stop is always started at the beginning of a new frame */
+        if ((bStopRequested && iSoftStopSymbolCount == 0) || iSoftStopSymbolCount < 0)
+        {
+            /* Data in OFDM buffer are set to zero */
+            OFDMModBuf.QueryWriteBuffer()->Reset(_COMPLEX());
+
+            /* The zeroing will continue until the frame end */
+            if (--iSoftStopSymbolCount < -iSymbolPerFrame)
+                return TRUE; /* End of frame reached, signal that loop exit must be done */
+        }
+        else
+        {
+            /* Update the symbol counter to keep track of frame beginning */
+            if (++iSoftStopSymbolCount >= iSymbolPerFrame)
+                iSoftStopSymbolCount = 0;
+        }
+    }
+    return FALSE; /* Signal to continue the normal operation */
+}
+#endif
+#if 0
+/* Flavour 2: Stop at the symbol boundary (worst case delay two frame) */
+_BOOLEAN CDRMTransmitter::CanSoftStopExit()
+{
+    /* Set new symbol flag */
+    const _BOOLEAN bNewSymbol = OFDMModBuf.GetFillLevel() != 0;
+
+    if (bNewSymbol)
+    {
+        /* Set stop requested flag */
+        const _BOOLEAN bStopRequested = Parameters.eRunState != CParameter::RUNNING;
+
+        /* Check if stop is requested */
+        if (bStopRequested || iSoftStopSymbolCount < 0)
+        {
+            /* Reset the counter if positif */
+            if (iSoftStopSymbolCount > 0)
+                iSoftStopSymbolCount = 0;
+
+            /* Data in OFDM buffer are set to zero */
+            OFDMModBuf.QueryWriteBuffer()->Reset(_COMPLEX());
+
+            /* Zeroing only this symbol, the next symbol will be an exiting one */
+            if (--iSoftStopSymbolCount < -1)
+            {
+                TransmitData.FlushData();
+                return TRUE; /* Signal that a loop exit must be done */
+            }
+        }
+        else
+        {
+            /* Number of symbol by frame */
+            const int iSymbolPerFrame = Parameters.CellMappingTable.iNumSymPerFrame;
+
+            /* Update the symbol counter to keep track of frame beginning */
+            if (++iSoftStopSymbolCount >= iSymbolPerFrame)
+                iSoftStopSymbolCount = 0;
+        }
+    }
+    return FALSE; /* Signal to continue the normal operation */
+}
+#endif
+#if 0
+/* Flavour 3: The original behaviour: stop at the symbol boundary,
+   without zeroing any symbol. Cause spreading of the spectrum on the
+   entire bandwidth for the last symbol. */
+_BOOLEAN CDRMTransmitter::CanSoftStopExit()
+{
+    return Parameters.eRunState != CParameter::RUNNING;
+}
+#endif
+
+void CDRMTransmitter::Init()
+{
+    /* Fetch new sample rate if any */
+    Parameters.FetchNewSampleRate();
+
+    /* Init cell mapping table */
+    Parameters.InitCellMapTable(Parameters.GetWaveMode(), Parameters.GetSpectrumOccup());
+
+    /* Defines number of cells, important! */
+    OFDMCellMapping.Init(Parameters, CarMapBuf);
+
+    /* Defines number of SDC bits per super-frame */
+    SDCMLCEncoder.Init(Parameters, SDCMapBuf);
+
+    MSCMLCEncoder.Init(Parameters, MLCEncBuf);
+    SymbInterleaver.Init(Parameters, IntlBuf);
+    GenerateFACData.Init(Parameters, GenFACDataBuf);
+    FACMLCEncoder.Init(Parameters, FACMapBuf);
+    GenerateSDCData.Init(Parameters, GenSDCDataBuf);
+    OFDMModulation.Init(Parameters, OFDMModBuf);
+    AudioSourceEncoder.Init(Parameters, AudSrcBuf);
+    ReadData.Init(Parameters, DataBuf);
+    TransmitData.Init(Parameters);
+
+    /* (Re)Initialization of the buffers */
+    CarMapBuf.Clear();
+    SDCMapBuf.Clear();
+    MLCEncBuf.Clear();
+    IntlBuf.Clear();
+    GenFACDataBuf.Clear();
+    FACMapBuf.Clear();
+    GenSDCDataBuf.Clear();
+    OFDMModBuf.Clear();
+    AudSrcBuf.Clear();
+    DataBuf.Clear();
+
+    /* Initialize the soft stop */
+    InitSoftStop();
+}
+
+CDRMTransmitter::~CDRMTransmitter()
+{
+    delete pSoundInInterface;
+    delete pSoundOutInterface;
+}
+
+CDRMTransmitter::CDRMTransmitter(CSettings* pSettings) : CDRMTransceiver(pSettings, new CSoundIn, new CSoundOut, TRUE),
+        ReadData(pSoundInInterface), TransmitData(pSoundOutInterface),
+        rDefCarOffset((_REAL) VIRTUAL_INTERMED_FREQ),
+        // UEP only works with Dream receiver, FIXME! -> disabled for now
+        bUseUEP(FALSE)
+{
+    /* Init streams */
+    Parameters.ResetServicesStreams();
+
+    /* Init frame ID counter (index) */
+    Parameters.iFrameIDTransm = 0;
+
+    /* Init transmission of current time */
+    Parameters.eTransmitCurrentTime = CParameter::CT_OFF;
+	Parameters.bValidUTCOffsetAndSense = FALSE;
+
+    /**************************************************************************/
+    /* Robustness mode and spectrum occupancy. Available transmission modes:
+       RM_ROBUSTNESS_MODE_A: Gaussian channels, with minor fading,
+       RM_ROBUSTNESS_MODE_B: Time and frequency selective channels, with longer
+       delay spread,
+       RM_ROBUSTNESS_MODE_C: As robustness mode B, but with higher Doppler
+       spread,
+       RM_ROBUSTNESS_MODE_D: As robustness mode B, but with severe delay and
+       Doppler spread.
+       Available bandwidths:
+       SO_0: 4.5 kHz, SO_1: 5 kHz, SO_2: 9 kHz, SO_3: 10 kHz, SO_4: 18 kHz,
+       SO_5: 20 kHz */
+    Parameters.InitCellMapTable(RM_ROBUSTNESS_MODE_B, SO_3);
+
+    /* Protection levels for MSC. Depend on the modulation scheme. Look at
+       TableMLC.h, iCodRateCombMSC16SM, iCodRateCombMSC64SM,
+       iCodRateCombMSC64HMsym, iCodRateCombMSC64HMmix for available numbers */
+    Parameters.MSCPrLe.iPartA = 0;
+    Parameters.MSCPrLe.iPartB = 1;
+    Parameters.MSCPrLe.iHierarch = 0;
+
+    /* Either one audio or one data service can be chosen */
+    _BOOLEAN bIsAudio = TRUE;
+
+    /* In the current version only one service and one stream is supported. The
+       stream IDs must be 0 in both cases */
+    if (bIsAudio == TRUE)
+    {
+        /* Audio */
+        Parameters.SetNumOfServices(1,0);
+        Parameters.SetCurSelAudioService(0);
+
+        CAudioParam AudioParam;
+
+        AudioParam.iStreamID = 0;
+
+        /* Text message */
+        AudioParam.bTextflag = TRUE;
+
+        Parameters.SetAudioParam(0, AudioParam);
+
+        Parameters.SetAudDataFlag(0,  CService::SF_AUDIO);
+
+        /* Programme Type code (see TableFAC.h, "strTableProgTypCod[]") */
+        Parameters.Service[0].iServiceDescr = 15; /* 15 -> other music */
+
+        Parameters.SetCurSelAudioService(0);
+    }
+    else
+    {
+        /* Data */
+        Parameters.SetNumOfServices(0,1);
+        Parameters.SetCurSelDataService(0);
+
+        Parameters.SetAudDataFlag(0,  CService::SF_DATA);
+
+        CDataParam DataParam;
+
+        DataParam.iStreamID = 0;
+
+        /* Init SlideShow application */
+        DataParam.iPacketLen = 45; /* TEST */
+        DataParam.eDataUnitInd = CDataParam::DU_DATA_UNITS;
+        DataParam.eAppDomain = CDataParam::AD_DAB_SPEC_APP;
+        Parameters.SetDataParam(0, DataParam);
+
+        /* The value 0 indicates that the application details are provided
+           solely by SDC data entity type 5 */
+        Parameters.Service[0].iServiceDescr = 0;
+    }
+
+    /* Init service parameters, 24 bit unsigned integer number */
+    Parameters.Service[0].iServiceID = 0;
+
+    /* Service label data. Up to 16 bytes defining the label using UTF-8
+       coding */
+    Parameters.Service[0].strLabel = "Dream Test";
+
+    /* Language (see TableFAC.h, "strTableLanguageCode[]") */
+    Parameters.Service[0].iLanguage = 5; /* 5 -> english */
+
+    /* Interleaver mode of MSC service. Long interleaving (2 s): SI_LONG,
+       short interleaving (400 ms): SI_SHORT */
+    Parameters.eSymbolInterlMode = SI_LONG;
+
+    /* MSC modulation scheme. Available modes:
+       16-QAM standard mapping (SM): CS_2_SM,
+       64-QAM standard mapping (SM): CS_3_SM,
+       64-QAM symmetrical hierarchical mapping (HMsym): CS_3_HMSYM,
+       64-QAM mixture of the previous two mappings (HMmix): CS_3_HMMIX */
+    Parameters.eMSCCodingScheme = CS_3_SM;
+
+    /* SDC modulation scheme. Available modes:
+       4-QAM standard mapping (SM): CS_1_SM,
+       16-QAM standard mapping (SM): CS_2_SM */
+    Parameters.eSDCCodingScheme = CS_2_SM;
+
+    /* Set desired intermedia frequency (IF) in Hertz */
+    SetCarOffset(_REAL(VIRTUAL_INTERMED_FREQ)); /* Default: "VIRTUAL_INTERMED_FREQ" */
+
+    if (bUseUEP == TRUE)
+    {
+        // TEST
+        Parameters.SetStreamLen(0, 80, 0);
+    }
+    else
+    {
+        /* Length of part B is set automatically (equal error protection (EEP),
+           if "= 0"). Sets the number of bytes, should not exceed total number
+           of bytes available in MSC block */
+        Parameters.SetStreamLen(0, 0, 0);
+    }
+}
+
+void CDRMTransmitter::LoadSettings()
+{
+    if (pSettings == NULL) return;
+    CSettings& s = *pSettings;
+
+    const char *Transmitter = "Transmitter";
+    std::ostringstream oss;
+    string value, service;
+
+    /* Sound card audio sample rate */
+    Parameters.SetNewAudSampleRate(s.Get(Transmitter, "samplerateaud", int(DEFAULT_SOUNDCRD_SAMPLE_RATE)));
+
+    /* Sound card signal sample rate */
+    Parameters.SetNewSigSampleRate(s.Get(Transmitter, "sampleratesig", int(DEFAULT_SOUNDCRD_SAMPLE_RATE)));
+
+    /* Fetch new sample rate if any */
+    Parameters.FetchNewSampleRate();
+
+    /* Sound card input device id */
+    pSoundInInterface->SetDev(s.Get(Transmitter, "snddevin", string()));
+
+    /* Sound card output device id */
+    pSoundOutInterface->SetDev(s.Get(Transmitter, "snddevout", string()));
+#if 0 // TODO
+    /* Sound clock drift adjustment */
+    _BOOLEAN bEnabled = s.Get(Transmitter, "sndclkadj", int(0));
+    ((CSoundOutPulse*)pSoundOutInterface)->EnableClockDriftAdj(bEnabled);
+#endif
+    /* Robustness mode and spectrum occupancy */
+    ERobMode eRobustnessMode = RM_ROBUSTNESS_MODE_B;
+    ESpecOcc eSpectOccup = SO_3;
+    /* Robustness mode */
+    value = s.Get(Transmitter, "robustness", string("RM_ROBUSTNESS_MODE_B"));
+    if      (value == "RM_ROBUSTNESS_MODE_A") { eRobustnessMode = RM_ROBUSTNESS_MODE_A; }
+    else if (value == "RM_ROBUSTNESS_MODE_B") { eRobustnessMode = RM_ROBUSTNESS_MODE_B; }
+    else if (value == "RM_ROBUSTNESS_MODE_C") { eRobustnessMode = RM_ROBUSTNESS_MODE_C; }
+    else if (value == "RM_ROBUSTNESS_MODE_D") { eRobustnessMode = RM_ROBUSTNESS_MODE_D; }
+    /* Spectrum occupancy */
+    value = s.Get(Transmitter, "spectocc", string("SO_3"));
+    if      (value == "SO_0") { eSpectOccup = SO_0; }
+    else if (value == "SO_1") { eSpectOccup = SO_1; }
+    else if (value == "SO_2") { eSpectOccup = SO_2; }
+    else if (value == "SO_3") { eSpectOccup = SO_3; }
+    else if (value == "SO_4") { eSpectOccup = SO_4; }
+    else if (value == "SO_5") { eSpectOccup = SO_5; }
+    Parameters.InitCellMapTable(eRobustnessMode, eSpectOccup);
+
+    /* Protection level for MSC */
+    Parameters.MSCPrLe.iPartB = s.Get(Transmitter, "protlevel", int(1));
+
+    /* Interleaver mode of MSC service */
+    value = s.Get(Transmitter, "interleaver", string("SI_LONG"));
+    if      (value == "SI_SHORT") { Parameters.eSymbolInterlMode = SI_SHORT; }
+    else if (value == "SI_LONG")  { Parameters.eSymbolInterlMode = SI_LONG;  }
+
+    /* MSC modulation scheme */
+    value = s.Get(Transmitter, "msc", string("CS_3_SM"));
+    if      (value == "CS_2_SM")    { Parameters.eMSCCodingScheme = CS_2_SM;    }
+    else if (value == "CS_3_SM")    { Parameters.eMSCCodingScheme = CS_3_SM;    }
+    else if (value == "CS_3_HMSYM") { Parameters.eMSCCodingScheme = CS_3_HMSYM; }
+    else if (value == "CS_3_HMMIX") { Parameters.eMSCCodingScheme = CS_3_HMMIX; }
+
+    /* SDC modulation scheme */
+    value = s.Get(Transmitter, "sdc", string("CS_2_SM"));
+    if      (value == "CS_1_SM") { Parameters.eSDCCodingScheme = CS_1_SM; }
+    else if (value == "CS_2_SM") { Parameters.eSDCCodingScheme = CS_2_SM; }
+
+    /* IF frequency */
+    SetCarOffset(s.Get(Transmitter, "iffreq", double(GetCarOffset())));
+
+    /* IF format */
+    value = s.Get(Transmitter, "ifformat", string("OF_REAL_VAL"));
+    if      (value == "OF_REAL_VAL") { GetTransData()->SetIQOutput(CTransmitData::OF_REAL_VAL); }
+    else if (value == "OF_IQ_POS")   { GetTransData()->SetIQOutput(CTransmitData::OF_IQ_POS);   }
+    else if (value == "OF_IQ_NEG")   { GetTransData()->SetIQOutput(CTransmitData::OF_IQ_NEG);   }
+    else if (value == "OF_EP")       { GetTransData()->SetIQOutput(CTransmitData::OF_EP);       }
+
+    /* IF high quality I/Q */
+    GetTransData()->SetHighQualityIQ(s.Get(Transmitter, "hqiq", int(1)));
+
+    /* IF amplified output */
+    GetTransData()->SetAmplifiedOutput(s.Get(Transmitter, "ifamp", int(1)));
+
+    /* Transmission of current time */
+    value = s.Get(Transmitter, "currenttime", string("CT_OFF"));
+    if      (value == "CT_OFF")        { Parameters.eTransmitCurrentTime = CParameter::CT_OFF;        }
+    else if (value == "CT_LOCAL")      { Parameters.eTransmitCurrentTime = CParameter::CT_LOCAL;      }
+    if      (value == "CT_UTC")        { Parameters.eTransmitCurrentTime = CParameter::CT_UTC;        }
+    else if (value == "CT_UTC_OFFSET") { Parameters.eTransmitCurrentTime = CParameter::CT_UTC_OFFSET; }
+
+    /**********************/
+    /* Service parameters */
+    for (int i=0; i<1/*MAX_NUM_SERVICES*/; i++) // TODO
+    {
+        oss << Transmitter << " Service " << i+1;
+        service = oss.str();
+
+        CService& Service = Parameters.Service[i];
+
+        /* Service ID */
+        Service.iServiceID = s.Get(service, "id", int(Service.iServiceID));
+
+        /* Service label data */
+        Service.strLabel = s.Get(service, "label", string(Service.strLabel));
+
+        /* Service description */
+        Service.iServiceDescr = s.Get(service, "description", int(Service.iServiceDescr));
+
+        /* Language */
+        Service.iLanguage = s.Get(service, "language", int(Service.iLanguage));
+
+        /* Audio codec */
+        value = s.Get(service, "codec", string("AAC"));
+        if      (value == "AAC") { Service.AudioParam.eAudioCoding = CAudioParam::AC_AAC;   }
+        else if (value == "Opus") { Service.AudioParam.eAudioCoding = CAudioParam::AC_OPUS; }
+
+        /* Opus Codec Channels */
+        value = s.Get(service, "Opus_Channels", string("OC_STEREO"));
+        if      (value == "OC_MONO")   { Service.AudioParam.eOPUSChan = CAudioParam::OC_MONO;   }
+        else if (value == "OC_STEREO") { Service.AudioParam.eOPUSChan = CAudioParam::OC_STEREO; }
+
+        /* Opus Codec Bandwith */
+        value = s.Get(service, "Opus_Bandwith", string("OB_FB"));
+        if      (value == "OB_NB")  { Service.AudioParam.eOPUSBandwidth = CAudioParam::OB_NB;  }
+        else if (value == "OB_MB")  { Service.AudioParam.eOPUSBandwidth = CAudioParam::OB_MB;  }
+        else if (value == "OB_WB")  { Service.AudioParam.eOPUSBandwidth = CAudioParam::OB_WB;  }
+        else if (value == "OB_SWB") { Service.AudioParam.eOPUSBandwidth = CAudioParam::OB_SWB; }
+        else if (value == "OB_FB")  { Service.AudioParam.eOPUSBandwidth = CAudioParam::OB_FB;  }
+
+        /* Opus Forward Error Correction */
+        value = s.Get(service, "Opus_FEC", string("0"));
+        if      (value == "0") { Service.AudioParam.bOPUSForwardErrorCorrection = FALSE; }
+        else if (value == "1") { Service.AudioParam.bOPUSForwardErrorCorrection = TRUE;  }
+
+        /* Opus encoder signal type */
+        value = s.Get(service, "Opus_Signal", string("OG_MUSIC"));
+        if      (value == "OG_VOICE") { Service.AudioParam.eOPUSSignal = CAudioParam::OG_VOICE; }
+        else if (value == "OG_MUSIC") { Service.AudioParam.eOPUSSignal = CAudioParam::OG_MUSIC; }
+
+        /* Opus encoder intended application */
+        value = s.Get(service, "Opus_Application", string("OA_AUDIO"));
+        if      (value == "OA_VOIP")  { Service.AudioParam.eOPUSApplication = CAudioParam::OA_VOIP;  }
+        else if (value == "OA_AUDIO") { Service.AudioParam.eOPUSApplication = CAudioParam::OA_AUDIO; }
+    }
+}
+
+void CDRMTransmitter::SaveSettings()
+{
+    if (pSettings == NULL) return;
+    CSettings& s = *pSettings;
+
+    const char *Transmitter = "Transmitter";
+    std::ostringstream oss;
+    string value, service;
+
+    /* Fetch new sample rate if any */
+    Parameters.FetchNewSampleRate();
+
+    /* Sound card audio sample rate */
+    s.Put(Transmitter, "samplerateaud", Parameters.GetAudSampleRate());
+
+    /* Sound card signal sample rate */
+    s.Put(Transmitter, "sampleratesig", Parameters.GetSigSampleRate());
+
+    /* Sound card input device id */
+    s.Put(Transmitter, "snddevin", pSoundInInterface->GetDev());
+
+    /* Sound card output device id */
+    s.Put(Transmitter, "snddevout", pSoundOutInterface->GetDev());
+#if 0 // TODO
+    /* Sound clock drift adjustment */
+    s.Put(Transmitter, "sndclkadj", int(((CSoundOutPulse*)pSoundOutInterface)->IsClockDriftAdjEnabled()));
+#endif
+    /* Robustness mode */
+    switch (Parameters.GetWaveMode()) {
+    case RM_ROBUSTNESS_MODE_A: value = "RM_ROBUSTNESS_MODE_A"; break;
+    case RM_ROBUSTNESS_MODE_B: value = "RM_ROBUSTNESS_MODE_B"; break;
+    case RM_ROBUSTNESS_MODE_C: value = "RM_ROBUSTNESS_MODE_C"; break;
+    case RM_ROBUSTNESS_MODE_D: value = "RM_ROBUSTNESS_MODE_D"; break;
+    default: value = ""; }
+    s.Put(Transmitter, "robustness", value);
+	
+    /* Spectrum occupancy */
+    switch (Parameters.GetSpectrumOccup()) {
+    case SO_0: value = "SO_0"; break;
+    case SO_1: value = "SO_1"; break;
+    case SO_2: value = "SO_2"; break;
+    case SO_3: value = "SO_3"; break;
+    case SO_4: value = "SO_4"; break;
+    case SO_5: value = "SO_5"; break;
+    default: value = ""; }
+    s.Put(Transmitter, "spectocc", value);
+
+    /* Protection level for MSC */
+    s.Put(Transmitter, "protlevel", int(Parameters.MSCPrLe.iPartB));
+
+    /* Interleaver mode of MSC service */
+    switch (Parameters.eSymbolInterlMode) {
+    case SI_SHORT: value = "SI_SHORT"; break;
+    case SI_LONG:  value = "SI_LONG";  break;
+    default: value = ""; }
+    s.Put(Transmitter, "interleaver", value);
+
+    /* MSC modulation scheme */
+    switch (Parameters.eMSCCodingScheme) {
+    case CS_2_SM:    value = "CS_2_SM";    break;
+    case CS_3_SM:    value = "CS_3_SM";    break;
+    case CS_3_HMSYM: value = "CS_3_HMSYM"; break;
+    case CS_3_HMMIX: value = "CS_3_HMMIX"; break;
+    default: value = ""; }
+    s.Put(Transmitter, "msc", value);
+
+    /* SDC modulation scheme */
+    switch (Parameters.eSDCCodingScheme) {
+    case CS_1_SM: value = "CS_1_SM"; break;
+    case CS_2_SM: value = "CS_2_SM"; break;
+    default: value = ""; }
+    s.Put(Transmitter, "sdc", value);
+
+    /* IF frequency */
+    s.Put(Transmitter, "iffreq", double(GetCarOffset()));
+
+    /* IF format */
+    switch (GetTransData()->GetIQOutput()) {
+    case CTransmitData::OF_REAL_VAL: value = "OF_REAL_VAL"; break;
+    case CTransmitData::OF_IQ_POS:   value = "OF_IQ_POS";   break;
+    case CTransmitData::OF_IQ_NEG:   value = "OF_IQ_NEG";   break;
+    case CTransmitData::OF_EP:       value = "OF_EP";       break;
+    default: value = ""; }
+    s.Put(Transmitter, "ifformat", value);
+
+    /* IF high quality I/Q */
+    s.Put(Transmitter, "hqiq", int(GetTransData()->GetHighQualityIQ()));
+
+    /* IF amplified output */
+    s.Put(Transmitter, "ifamp", int(GetTransData()->GetAmplifiedOutput()));
+
+    /* Transmission of current time */
+    switch (Parameters.eTransmitCurrentTime) {
+    case CParameter::CT_OFF:        value = "CT_OFF";        break;
+    case CParameter::CT_LOCAL:      value = "CT_LOCAL";      break;
+    case CParameter::CT_UTC:        value = "CT_UTC";        break;
+    case CParameter::CT_UTC_OFFSET: value = "CT_UTC_OFFSET"; break;
+    default: value = ""; }
+    s.Put(Transmitter, "currenttime", value);
+
+    /**********************/
+    /* Service parameters */
+    for (int i=0; i<1/*MAX_NUM_SERVICES*/; i++) // TODO
+    {
+        oss << Transmitter << " Service " << i+1;
+        service = oss.str();
+
+        CService& Service = Parameters.Service[i];
+
+        /* Service ID */
+        s.Put(service, "id", int(Service.iServiceID));
+
+        /* Service label data */
+        s.Put(service, "label", string(Service.strLabel));
+
+        /* Service description */
+        s.Put(service, "description", int(Service.iServiceDescr));
+
+        /* Language */
+        s.Put(service, "language", int(Service.iLanguage));
+
+        /* Audio codec */
+        switch (Service.AudioParam.eAudioCoding) {
+        case CAudioParam::AC_AAC:  value = "AAC";  break;
+        case CAudioParam::AC_OPUS: value = "Opus"; break;
+        default: value = ""; }
+        s.Put(service, "codec", value);
+
+        /* Opus Codec Channels */
+        switch (Service.AudioParam.eOPUSChan) {
+        case CAudioParam::OC_MONO:   value = "OC_MONO";   break;
+        case CAudioParam::OC_STEREO: value = "OC_STEREO"; break;
+        default: value = ""; }
+        s.Put(service, "Opus_Channels", value);
+
+        /* Opus Codec Bandwith */
+        switch (Service.AudioParam.eOPUSBandwidth) {
+        case CAudioParam::OB_NB:  value = "OB_NB";  break;
+        case CAudioParam::OB_MB:  value = "OB_MB";  break;
+        case CAudioParam::OB_WB:  value = "OB_WB";  break;
+        case CAudioParam::OB_SWB: value = "OB_SWB"; break;
+        case CAudioParam::OB_FB:  value = "OB_FB";  break;
+        default: value = ""; }
+        s.Put(service, "Opus_Bandwith", value);
+
+        /* Opus Forward Error Correction */
+        value = Service.AudioParam.bOPUSForwardErrorCorrection ? "1" : "0";
+        s.Put(service, "Opus_FEC", value);
+
+        /* Opus encoder signal type */
+        switch (Service.AudioParam.eOPUSSignal) {
+        case CAudioParam::OG_VOICE: value = "OG_VOICE"; break;
+        case CAudioParam::OG_MUSIC: value = "OG_MUSIC"; break;
+        default: value = ""; }
+        s.Put(service, "Opus_Signal", value);
+
+        /* Opus encoder intended application */
+        switch (Service.AudioParam.eOPUSApplication) {
+        case CAudioParam::OA_VOIP:  value = "OA_VOIP";  break;
+        case CAudioParam::OA_AUDIO: value = "OA_AUDIO"; break;
+        default: value = ""; }
+        s.Put(service, "Opus_Application", value);
+    }
+}
diff --git a/src/DrmTransmitter.h b/src/DrmTransmitter.h
new file mode 100644
index 0000000..b4e91db
--- /dev/null
+++ b/src/DrmTransmitter.h
@@ -0,0 +1,118 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *	See DrmTransmitter.cpp
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#if !defined(DRMTRANSM_H__3B0BA660_CA63_4344_BB2B_23E7A0D31912__INCLUDED_)
+#define DRMTRANSM_H__3B0BA660_CA63_4344_BB2B_23E7A0D31912__INCLUDED_
+
+#include <iostream>
+#include "util/Buffer.h"
+#include "Parameter.h"
+#include "DataIO.h"
+#include "mlc/MLC.h"
+#include "interleaver/SymbolInterleaver.h"
+#include "ofdmcellmapping/OFDMCellMapping.h"
+#include "OFDM.h"
+#include "DRMSignalIO.h"
+#include "sourcedecoders/AudioSourceEncoder.h"
+#include "sound/soundinterface.h"
+#include "DrmTransceiver.h"
+
+/* Classes ********************************************************************/
+class CDRMTransmitter : public CDRMTransceiver
+{
+public:
+    CDRMTransmitter(CSettings* pSettings=NULL);
+    virtual ~CDRMTransmitter();
+
+    void LoadSettings();
+    void SaveSettings();
+    void Init();
+    void Start();
+
+    CAudioSourceEncoder*	GetAudSrcEnc() {
+        return &AudioSourceEncoder;
+    }
+    CTransmitData*			GetTransData() {
+        return &TransmitData;
+    }
+    CReadData*				GetReadData() {
+        return &ReadData;
+    }
+
+    void SetCarOffset(const _REAL rNewCarOffset)
+    {
+        /* Has to be set in OFDM modulation and transmitter filter module */
+        OFDMModulation.SetCarOffset(rNewCarOffset);
+        TransmitData.SetCarOffset(rNewCarOffset);
+        rDefCarOffset = rNewCarOffset;
+    }
+    _REAL GetCarOffset() {
+        return rDefCarOffset;
+    }
+
+protected:
+    void Run();
+    void InitSoftStop() { iSoftStopSymbolCount=0; };
+    _BOOLEAN CanSoftStopExit();
+
+    /* Buffers */
+    CSingleBuffer<_SAMPLE>	DataBuf;
+    CSingleBuffer<_BINARY>	AudSrcBuf;
+
+    CSingleBuffer<_COMPLEX>	MLCEncBuf;
+    CCyclicBuffer<_COMPLEX>	IntlBuf;
+
+    CSingleBuffer<_BINARY>	GenFACDataBuf;
+    CCyclicBuffer<_COMPLEX>	FACMapBuf;
+
+    CSingleBuffer<_BINARY>	GenSDCDataBuf;
+    CCyclicBuffer<_COMPLEX>	SDCMapBuf;
+
+    CSingleBuffer<_COMPLEX>	CarMapBuf;
+    CSingleBuffer<_COMPLEX>	OFDMModBuf;
+
+    /* Modules */
+    CReadData				ReadData;
+    CAudioSourceEncoder		AudioSourceEncoder;
+    CMSCMLCEncoder			MSCMLCEncoder;
+    CSymbInterleaver		SymbInterleaver;
+    CGenerateFACData		GenerateFACData;
+    CFACMLCEncoder			FACMLCEncoder;
+    CGenerateSDCData		GenerateSDCData;
+    CSDCMLCEncoder			SDCMLCEncoder;
+    COFDMCellMapping		OFDMCellMapping;
+    COFDMModulation			OFDMModulation;
+    CTransmitData			TransmitData;
+
+    _REAL					rDefCarOffset;
+    _BOOLEAN				bUseUEP;
+    int						iSoftStopSymbolCount;
+};
+
+
+#endif // !defined(DRMTRANSM_H__3B0BA660_CA63_4344_BB2B_23E7A0D31912__INCLUDED_)
diff --git a/src/FAC/FAC.cpp b/src/FAC/FAC.cpp
new file mode 100644
index 0000000..e4b8ccc
--- /dev/null
+++ b/src/FAC/FAC.cpp
@@ -0,0 +1,645 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *	FAC
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "FAC.h"
+
+
+/* Implementation *************************************************************/
+/******************************************************************************\
+* CFACTransmit																   *
+\******************************************************************************/
+void CFACTransmit::FACParam(CVector<_BINARY>* pbiFACData, CParameter& Parameter)
+{
+    int			iCurShortID;
+
+    /* Reset enqueue function */
+    (*pbiFACData).ResetBitAccess();
+
+    /* Put FAC parameters on stream */
+    /* Channel parameters --------------------------------------------------- */
+    /* Base/Enhancement flag, set it to base which is decodable by all DRM
+       receivers */
+    (*pbiFACData).Enqueue(0 /* 0 */, 1);
+
+    /* Identity */
+    /* Manage index of FAC block in super-frame */
+    switch (Parameter.iFrameIDTransm)
+    {
+    case 0:
+        /* Assuming AFS is valid (AFS not used here), if AFS is not valid, the
+           parameter must be 3 (11) */
+        (*pbiFACData).Enqueue(3 /* 11 */, 2);
+        break;
+
+    case 1:
+        (*pbiFACData).Enqueue(1 /* 01 */, 2);
+        break;
+
+    case 2:
+        (*pbiFACData).Enqueue(2 /* 10 */, 2);
+        break;
+    }
+
+    /* Spectrum occupancy */
+    switch (Parameter.GetSpectrumOccup())
+    {
+    case SO_0:
+        (*pbiFACData).Enqueue(0 /* 0000 */, 4);
+        break;
+
+    case SO_1:
+        (*pbiFACData).Enqueue(1 /* 0001 */, 4);
+        break;
+
+    case SO_2:
+        (*pbiFACData).Enqueue(2 /* 0010 */, 4);
+        break;
+
+    case SO_3:
+        (*pbiFACData).Enqueue(3 /* 0011 */, 4);
+        break;
+
+    case SO_4:
+        (*pbiFACData).Enqueue(4 /* 0100 */, 4);
+        break;
+
+    case SO_5:
+        (*pbiFACData).Enqueue(5 /* 0101 */, 4);
+        break;
+
+    case SO_6:
+        (*pbiFACData).Enqueue(0 /* 0000 */, 4);
+        break;
+    }
+
+    /* Interleaver depth flag */
+    switch (Parameter.eSymbolInterlMode)
+    {
+    case SI_LONG:
+        (*pbiFACData).Enqueue(0 /* 0 */, 1);
+        break;
+
+    case SI_SHORT:
+        (*pbiFACData).Enqueue(1 /* 1 */, 1);
+        break;
+    case SI_MODE_E: // TODO
+	;
+    }
+
+    /* MSC mode */
+    switch (Parameter.eMSCCodingScheme)
+    {
+    case CS_3_SM:
+        (*pbiFACData).Enqueue(0 /* 00 */, 2);
+        break;
+
+    case CS_3_HMMIX:
+        (*pbiFACData).Enqueue(1 /* 01 */, 2);
+        break;
+
+    case CS_3_HMSYM:
+        (*pbiFACData).Enqueue(2 /* 10 */, 2);
+        break;
+
+    case CS_2_SM:
+        (*pbiFACData).Enqueue(3 /* 11 */, 2);
+        break;
+
+    default:
+        break;
+    }
+
+    /* SDC mode */
+    switch (Parameter.eSDCCodingScheme)
+    {
+    case CS_2_SM:
+        (*pbiFACData).Enqueue(0 /* 0 */, 1);
+        break;
+
+    case CS_1_SM:
+        (*pbiFACData).Enqueue(1 /* 1 */, 1);
+        break;
+
+    default:
+        break;
+    }
+
+    /* Number of services */
+    /* Use Table */
+    (*pbiFACData).Enqueue(iTableNumOfServices[Parameter.iNumAudioService]
+                          [Parameter.iNumDataService], 4);
+
+    /* Reconfiguration index (not used) */
+    (*pbiFACData).Enqueue((uint32_t) 0, 3);
+
+    /* rfu */
+    (*pbiFACData).Enqueue((uint32_t) 0, 2);
+
+    /* Service parameters --------------------------------------------------- */
+    /* Transmit service-information of service signalled in the FAC-repetition
+       array */
+    iCurShortID = FACRepetition[FACRepetitionCounter];
+    FACRepetitionCounter++;
+    if (FACRepetitionCounter == FACNumRep)
+        FACRepetitionCounter = 0;
+
+    /* Service identifier */
+    (*pbiFACData).Enqueue(Parameter.Service[iCurShortID].iServiceID, 24);
+
+    /* Short ID */
+    (*pbiFACData).Enqueue((uint32_t) iCurShortID, 2);
+
+    /* CA indication */
+    switch (Parameter.Service[iCurShortID].eCAIndication)
+    {
+    case CService::CA_NOT_USED:
+        (*pbiFACData).Enqueue(0 /* 0 */, 1);
+        break;
+
+    case CService::CA_USED:
+        (*pbiFACData).Enqueue(1 /* 1 */, 1);
+        break;
+    }
+
+    /* Language */
+    (*pbiFACData).Enqueue(
+        (uint32_t) Parameter.Service[iCurShortID].iLanguage, 4);
+
+    /* Audio/Data flag */
+    switch (Parameter.Service[iCurShortID].eAudDataFlag)
+    {
+    case CService::SF_AUDIO:
+        (*pbiFACData).Enqueue(0 /* 0 */, 1);
+        break;
+
+    case CService::SF_DATA:
+        (*pbiFACData).Enqueue(1 /* 1 */, 1);
+    }
+
+    /* Service descriptor */
+    (*pbiFACData).Enqueue(
+        (uint32_t) Parameter.Service[iCurShortID].iServiceDescr, 5);
+
+    /* Rfa */
+    (*pbiFACData).Enqueue(uint32_t(0), 7);
+
+    /* CRC ------------------------------------------------------------------ */
+    /* Calculate the CRC and put at the end of the stream */
+    CRCObject.Reset(8);
+
+    (*pbiFACData).ResetBitAccess();
+
+    for (int i = 0; i < NUM_FAC_BITS_PER_BLOCK_DRM30 / SIZEOF__BYTE - 1; i++)
+        CRCObject.AddByte((_BYTE) (*pbiFACData).Separate(SIZEOF__BYTE));
+
+    /* Now, pointer in "enqueue"-function is back at the same place,
+       add CRC */
+    (*pbiFACData).Enqueue(CRCObject.GetCRC(), 8);
+}
+
+void CFACTransmit::Init(CParameter& Parameter)
+{
+    set<int>	actServ;
+
+    /* Get active services */
+    Parameter.GetActiveServices(actServ);
+    const size_t iTotNumServices = actServ.size();
+
+    /* Check how many audio and data services present */
+    vector<int>	veciAudioServ;
+    vector<int>	veciDataServ;
+    size_t		iNumAudio = 0;
+    size_t		iNumData = 0;
+
+    for (set<int>::iterator i = actServ.begin(); i!=actServ.end(); i++)
+    {
+        if (Parameter.Service[*i].eAudDataFlag == CService::SF_AUDIO)
+        {
+            veciAudioServ.push_back(*i);
+            iNumAudio++;
+        }
+        else
+        {
+            veciDataServ.push_back(*i);
+            iNumData++;
+        }
+    }
+
+    /* Now check special cases which are defined in 6.3.6-------------------- */
+    /* If we have only data or only audio services. When all services are of
+       the same type (e.g. all audio or all data) then the services shall be
+       signalled sequentially */
+    if ((iNumAudio == iTotNumServices) || (iNumData == iTotNumServices))
+    {
+        /* Init repetition vector */
+        FACNumRep = iTotNumServices;
+        FACRepetition.resize(0);
+
+        for (set<int>::iterator i = actServ.begin(); i!=actServ.end(); i++)
+            FACRepetition.push_back(*i);
+    }
+    else
+    {
+        /* Special cases according to Table 60 (Service parameter repetition
+           patterns for mixtures of audio and data services) */
+        if (iNumAudio == 1)
+        {
+            if (iNumData == 1)
+            {
+                /* Init repetion vector */
+                FACNumRep = 5;
+                FACRepetition.resize(FACNumRep);
+
+                /* A1A1A1A1D1 */
+                FACRepetition[0] = veciAudioServ[0];
+                FACRepetition[1] = veciAudioServ[0];
+                FACRepetition[2] = veciAudioServ[0];
+                FACRepetition[3] = veciAudioServ[0];
+                FACRepetition[4] = veciDataServ[0];
+            }
+            else if (iNumData == 2)
+            {
+                /* Init repetion vector */
+                FACNumRep = 10;
+                FACRepetition.resize(FACNumRep);
+
+                /* A1A1A1A1D1A1A1A1A1D2 */
+                FACRepetition[0] = veciAudioServ[0];
+                FACRepetition[1] = veciAudioServ[0];
+                FACRepetition[2] = veciAudioServ[0];
+                FACRepetition[3] = veciAudioServ[0];
+                FACRepetition[4] = veciDataServ[0];
+                FACRepetition[5] = veciAudioServ[0];
+                FACRepetition[6] = veciAudioServ[0];
+                FACRepetition[7] = veciAudioServ[0];
+                FACRepetition[8] = veciAudioServ[0];
+                FACRepetition[9] = veciDataServ[1];
+            }
+            else /* iNumData == 3 */
+            {
+                /* Init repetion vector */
+                FACNumRep = 15;
+                FACRepetition.resize(FACNumRep);
+
+                /* A1A1A1A1D1A1A1A1A1D2A1A1A1A1D3 */
+                FACRepetition[0] = veciAudioServ[0];
+                FACRepetition[1] = veciAudioServ[0];
+                FACRepetition[2] = veciAudioServ[0];
+                FACRepetition[3] = veciAudioServ[0];
+                FACRepetition[4] = veciDataServ[0];
+                FACRepetition[5] = veciAudioServ[0];
+                FACRepetition[6] = veciAudioServ[0];
+                FACRepetition[7] = veciAudioServ[0];
+                FACRepetition[8] = veciAudioServ[0];
+                FACRepetition[9] = veciDataServ[1];
+                FACRepetition[10] = veciAudioServ[0];
+                FACRepetition[11] = veciAudioServ[0];
+                FACRepetition[12] = veciAudioServ[0];
+                FACRepetition[13] = veciAudioServ[0];
+                FACRepetition[14] = veciDataServ[2];
+            }
+        }
+        else if (iNumAudio == 2)
+        {
+            if (iNumData == 1)
+            {
+                /* Init repetion vector */
+                FACNumRep = 5;
+                FACRepetition.resize(FACNumRep);
+
+                /* A1A2A1A2D1 */
+                FACRepetition[0] = veciAudioServ[0];
+                FACRepetition[1] = veciAudioServ[1];
+                FACRepetition[2] = veciAudioServ[0];
+                FACRepetition[3] = veciAudioServ[1];
+                FACRepetition[4] = veciDataServ[0];
+            }
+            else /* iNumData == 2 */
+            {
+                /* Init repetion vector */
+                FACNumRep = 10;
+                FACRepetition.resize(FACNumRep);
+
+                /* A1A2A1A2D1A1A2A1A2D2 */
+                FACRepetition[0] = veciAudioServ[0];
+                FACRepetition[1] = veciAudioServ[1];
+                FACRepetition[2] = veciAudioServ[0];
+                FACRepetition[3] = veciAudioServ[1];
+                FACRepetition[4] = veciDataServ[0];
+                FACRepetition[5] = veciAudioServ[0];
+                FACRepetition[6] = veciAudioServ[1];
+                FACRepetition[7] = veciAudioServ[0];
+                FACRepetition[8] = veciAudioServ[1];
+                FACRepetition[9] = veciDataServ[1];
+            }
+        }
+        else /* iNumAudio == 3 */
+        {
+            /* Init repetion vector */
+            FACNumRep = 7;
+            FACRepetition.resize(FACNumRep);
+
+            /* A1A2A3A1A2A3D1 */
+            FACRepetition[0] = veciAudioServ[0];
+            FACRepetition[1] = veciAudioServ[1];
+            FACRepetition[2] = veciAudioServ[2];
+            FACRepetition[3] = veciAudioServ[0];
+            FACRepetition[4] = veciAudioServ[1];
+            FACRepetition[5] = veciAudioServ[2];
+            FACRepetition[6] = veciDataServ[0];
+        }
+    }
+}
+
+
+/******************************************************************************\
+* CFACReceive																   *
+\******************************************************************************/
+bool CFACReceive::FACParam(CVector<_BINARY>* pbiFACData,
+                               CParameter& Parameter)
+{
+    /*
+    	First get new data from incoming data stream, then check if the new
+    	parameter differs from the old data stored in the receiver. If yes, init
+    	the modules to the new parameter
+    */
+
+    /* CRC ------------------------------------------------------------------ */
+
+    int n = pbiFACData->Size();
+
+    if(n != Parameter.iNumFACBitsPerBlock) {
+        // error
+        ;
+    }
+
+    /* Check the CRC of this data block */
+    CRCObject.Reset(8); // 8 bit CRC
+    (*pbiFACData).ResetBitAccess();
+    /*
+    for (int i = 0; i < n1; i++)
+    {
+        _BYTE b = (_BYTE) (*pbiFACData).Separate(SIZEOF__BYTE);
+        CRCObject.AddByte(b);
+    }
+    */
+    // channel
+    for (int i = 0; i < 20; i++)
+    {
+        _BINARY b = (_BINARY) (*pbiFACData).Separate(1);
+        CRCObject.AddBit(b);
+    }
+    // first set of service parameters
+    for (int i = 0; i < 44; i++)
+    {
+        _BINARY b = (_BINARY) (*pbiFACData).Separate(1);
+        CRCObject.AddBit(b);
+    }
+    if(n!=72)
+    {
+        for (int i = 0; i < 44; i++)
+        {
+            _BINARY b = (_BINARY) (*pbiFACData).Separate(1);
+            CRCObject.AddBit(b);
+        }
+        for (int i = 0; i < 4; i++)
+            CRCObject.AddBit(0);
+    }
+
+    _BYTE crc = (*pbiFACData).Separate(SIZEOF__BYTE);
+    (void)(*pbiFACData).Separate(4);
+    bool crcok = CRCObject.CheckCRC(crc) == TRUE;
+
+    bool permissive = Parameter.lenient_RSCI;
+    if (permissive || crcok)
+    {
+        /* CRC-check successful, extract data from FAC-stream */
+        /* Reset separation function */
+        (*pbiFACData).ResetBitAccess();
+
+        ChannelParam(pbiFACData, Parameter);
+        ServiceParam(pbiFACData, Parameter);
+        if(Parameter.GetSpectrumOccup()==SO_6)
+            ServiceParam(pbiFACData, Parameter);
+
+        /* CRC is ok, or lenient mode selected, return TRUE */
+        return TRUE;
+    }
+    else
+    {
+        /* Data is corrupted, do not use it. Return failure as FALSE */
+        return FALSE;
+    }
+}
+
+void CFACReceive::ChannelParam(CVector<_BINARY>* pbiFACData, CParameter& Parameter)
+{
+    // TODO
+    bool bModeE;
+    int reconfig_index;
+    int toggle_flag;
+
+    Parameter.Lock();
+
+    /* Channel parameters ----------------------------------------------- */
+    /* Base/Enhancement flag (not used) */
+    (*pbiFACData).Separate(1);
+
+    /* Identity */
+    switch ((*pbiFACData).Separate(2))
+    {
+    case 0: /* 00 */
+        Parameter.iFrameIDReceiv = 0;
+        break;
+
+    case 1: /* 01 */
+        Parameter.iFrameIDReceiv = 1;
+        break;
+
+    case 2: /* 10 */
+        Parameter.iFrameIDReceiv = 2;
+        break;
+
+    case 3: /* 11 */
+        Parameter.iFrameIDReceiv = 0;
+        break;
+    }
+
+    /* Robustness Mode */
+    bModeE = (*pbiFACData).Separate(1)==1;
+
+    /* Spectrum occupancy */
+    switch ((*pbiFACData).Separate(3))
+    {
+    case 0: /* 000 */
+        Parameter.SetSpectrumOccup(bModeE?SO_6:SO_0);
+        break;
+
+    case 1: /* 001 */
+        Parameter.SetSpectrumOccup(SO_1);
+        break;
+
+    case 2: /* 010 */
+        Parameter.SetSpectrumOccup(SO_2);
+        break;
+
+    case 3: /* 011 */
+        Parameter.SetSpectrumOccup(SO_3);
+        break;
+
+    case 4: /* 100 */
+        Parameter.SetSpectrumOccup(SO_4);
+        break;
+
+    case 5: /* 101 */
+        Parameter.SetSpectrumOccup(SO_5);
+        break;
+    }
+
+    /* Interleaver depth flag */
+    switch ((*pbiFACData).Separate(1))
+    {
+    case 0: /* 0 */
+        Parameter.SetInterleaverDepth(bModeE?SI_MODE_E:SI_LONG);
+        break;
+
+    case 1: /* 1 */
+        Parameter.SetInterleaverDepth(SI_SHORT);
+        break;
+    }
+
+    /* MSC mode */
+    switch ((*pbiFACData).Separate(2))
+    {
+    case 0: /* 00 */
+        Parameter.SetMSCCodingScheme(bModeE?CS_2_SM:CS_3_SM);
+        break;
+
+    case 1: /* 01 */
+        Parameter.SetMSCCodingScheme(CS_3_HMMIX);
+        break;
+
+    case 2: /* 10 */
+        Parameter.SetMSCCodingScheme(CS_3_HMSYM);
+        break;
+
+    case 3: /* 11 */
+        Parameter.SetMSCCodingScheme(CS_2_SM);
+        break;
+    }
+
+    /* SDC mode */
+    switch ((*pbiFACData).Separate(1))
+    {
+    case 0: /* 0 */
+        Parameter.SetSDCCodingScheme(bModeE?CS_1_SM:CS_2_SM);
+        Parameter.bSDCCodeRateOneQuarter = false;
+        break;
+
+    case 1: /* 1 */
+        Parameter.SetSDCCodingScheme(CS_1_SM);
+        Parameter.bSDCCodeRateOneQuarter = bModeE;
+        break;
+    }
+
+    /* Number of services */
+    /* Search table for entry */
+    int iNumServTabEntry = (*pbiFACData).Separate(4);
+    for (int i = 0; i < 5; i++)
+        for (int j = 0; j < 5; j++)
+            if (iNumServTabEntry == iTableNumOfServices[i][j])
+                Parameter.SetNumOfServices(i, j);
+
+    /* Reconfiguration index (not used, yet) */
+    reconfig_index = (*pbiFACData).Separate(3);
+
+    toggle_flag = (*pbiFACData).Separate(1);
+
+    /* rfu */
+    (*pbiFACData).Separate(1);
+
+    Parameter.Unlock();
+}
+
+/* Service parameters ----------------------------------------------- */
+void CFACReceive::ServiceParam(CVector<_BINARY>* pbiFACData, CParameter& Parameter)
+{
+    uint32_t	iTempServiceID;
+    int			iTempShortID;
+
+    Parameter.Lock();
+
+    /* Service identifier */
+    iTempServiceID = (*pbiFACData).Separate(24);
+
+    /* Short ID (the short ID is the index of the service-array) */
+    iTempShortID = (*pbiFACData).Separate(2);
+
+    /* Set service identifier */
+    Parameter.SetServiceID(iTempShortID, iTempServiceID);
+
+    /* CA indication */
+    switch ((*pbiFACData).Separate(1))
+    {
+    case 0: /* 0 */
+        Parameter.Service[iTempShortID].eCAIndication =
+            CService::CA_NOT_USED;
+        break;
+
+    case 1: /* 1 */
+        Parameter.Service[iTempShortID].eCAIndication =
+            CService::CA_USED;
+        break;
+    }
+
+    /* Language */
+    Parameter.Service[iTempShortID].iLanguage = (*pbiFACData).Separate(4);
+
+    /* Audio/Data flag */
+    switch ((*pbiFACData).Separate(1))
+    {
+    case 0: /* 0 */
+        Parameter.SetAudDataFlag(iTempShortID, CService::SF_AUDIO);
+        break;
+
+    case 1: /* 1 */
+        Parameter.SetAudDataFlag(iTempShortID, CService::SF_DATA);
+        break;
+    }
+
+    /* Service descriptor */
+    Parameter.Service[iTempShortID].iServiceDescr =
+        (*pbiFACData).Separate(5);
+
+
+    /* Rfa */
+    /* Do not use Rfa */
+    (*pbiFACData).Separate(7);
+
+    Parameter.Unlock();
+}
diff --git a/src/FAC/FAC.h b/src/FAC/FAC.h
new file mode 100644
index 0000000..dcb1167
--- /dev/null
+++ b/src/FAC/FAC.h
@@ -0,0 +1,73 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *	See FAC.cpp
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#if !defined(FAC_H__3B0BA660_CA63VEUASDVN89LKVNE877A0D31912__INCLUDED_)
+#define FAC_H__3B0BA660_CA63VEUASDVN89LKVNE877A0D31912__INCLUDED_
+
+#include "../GlobalDefinitions.h"
+#include "../tables/TableFAC.h"
+#include "../Parameter.h"
+#include "../util/CRC.h"
+#include "../util/Vector.h"
+
+
+/* Classes ********************************************************************/
+class CFACTransmit
+{
+public:
+    CFACTransmit():FACRepetitionCounter(0) {}
+    virtual ~CFACTransmit() {}
+
+    /* "pbiFACData" contains 72 bits */
+    void FACParam(CVector<_BINARY>* pbiFACData, CParameter& Parameter);
+    void Init(CParameter& Parameter);
+
+protected:
+    CCRC CRCObject;
+    vector<int>	FACRepetition; /* See 6.3.6 */
+    size_t		FACNumRep;
+    size_t		FACRepetitionCounter;
+};
+
+class CFACReceive
+{
+public:
+    CFACReceive() {}
+    virtual ~CFACReceive() {}
+
+    /* "pbiFACData" contains 72 or 120 bits */
+    bool FACParam(CVector<_BINARY>* pbiFACData, CParameter& Parameter);
+
+protected:
+    void ChannelParam(CVector<_BINARY>* pbiFACData, CParameter& Parameter);
+    void ServiceParam(CVector<_BINARY>* pbiFACData, CParameter& Parameter);
+    CCRC CRCObject;
+};
+
+
+#endif // !defined(FAC_H__3B0BA660_CA63VEUASDVN89LKVNE877A0D31912__INCLUDED_)
diff --git a/src/GUI-QT/AMMainWindow.ui b/src/GUI-QT/AMMainWindow.ui
new file mode 100644
index 0000000..1df315d
--- /dev/null
+++ b/src/GUI-QT/AMMainWindow.ui
@@ -0,0 +1,671 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>AMMainWindow</class>
+ <widget class="QMainWindow" name="AMMainWindow">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>899</width>
+    <height>708</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Analog Demodulation</string>
+  </property>
+  <property name="windowIcon">
+   <iconset resource="res/icons.qrc">
+    <normaloff>:/icons/MainIcon.svg</normaloff>:/icons/MainIcon.svg</iconset>
+  </property>
+  <widget class="QWidget" name="centralwidget">
+   <layout class="QVBoxLayout" name="verticalLayout_3">
+    <item>
+     <widget class="QFrame" name="frame">
+      <property name="sizePolicy">
+       <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
+        <horstretch>0</horstretch>
+        <verstretch>0</verstretch>
+       </sizepolicy>
+      </property>
+      <property name="frameShape">
+       <enum>QFrame::StyledPanel</enum>
+      </property>
+      <property name="frameShadow">
+       <enum>QFrame::Raised</enum>
+      </property>
+      <layout class="QHBoxLayout" name="horizontalLayout">
+       <item>
+        <widget class="QwtPlot" name="plot">
+         <property name="sizePolicy">
+          <sizepolicy hsizetype="MinimumExpanding" vsizetype="Expanding">
+           <horstretch>0</horstretch>
+           <verstretch>0</verstretch>
+          </sizepolicy>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="QFrame" name="frame_2">
+         <property name="sizePolicy">
+          <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
+           <horstretch>0</horstretch>
+           <verstretch>0</verstretch>
+          </sizepolicy>
+         </property>
+         <property name="frameShape">
+          <enum>QFrame::StyledPanel</enum>
+         </property>
+         <property name="frameShadow">
+          <enum>QFrame::Raised</enum>
+         </property>
+         <layout class="QVBoxLayout" name="verticalLayout_4">
+          <item>
+           <widget class="QPushButton" name="ButtonWaterfall">
+            <property name="windowTitle">
+             <string/>
+            </property>
+            <property name="text">
+             <string>&Waterfall</string>
+            </property>
+            <property name="checkable">
+             <bool>true</bool>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <layout class="QVBoxLayout" name="verticalLayout_2">
+            <property name="spacing">
+             <number>0</number>
+            </property>
+            <item>
+             <widget class="QLabel" name="LabelCarrierFrequency">
+              <property name="sizePolicy">
+               <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
+                <horstretch>0</horstretch>
+                <verstretch>0</verstretch>
+               </sizepolicy>
+              </property>
+              <property name="text">
+               <string>Carrier Frequency</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QPushButton" name="ButtonFreqOffset">
+              <property name="sizePolicy">
+               <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
+                <horstretch>0</horstretch>
+                <verstretch>0</verstretch>
+               </sizepolicy>
+              </property>
+              <property name="font">
+               <font>
+                <underline>true</underline>
+               </font>
+              </property>
+              <property name="text">
+               <string>999999.99 Hz</string>
+              </property>
+              <property name="flat">
+               <bool>true</bool>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </item>
+          <item>
+           <widget class="QLabel" name="TextLabelPhaseOffset">
+            <property name="sizePolicy">
+             <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
+              <horstretch>0</horstretch>
+              <verstretch>0</verstretch>
+             </sizepolicy>
+            </property>
+            <property name="text">
+             <string>PLL
+Phase Offset</string>
+            </property>
+            <property name="alignment">
+             <set>Qt::AlignCenter</set>
+            </property>
+            <property name="wordWrap">
+             <bool>false</bool>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QwtDial" name="PhaseDial" native="true">
+            <property name="minimumSize">
+             <size>
+              <width>0</width>
+              <height>70</height>
+             </size>
+            </property>
+            <property name="focusPolicy">
+             <enum>Qt::NoFocus</enum>
+            </property>
+            <property name="lineWidth" stdset="0">
+             <number>4</number>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </widget>
+       </item>
+      </layout>
+     </widget>
+    </item>
+    <item>
+     <widget class="QGroupBox" name="groupBoxBW">
+      <property name="title">
+       <string>Filter Bandwidth</string>
+      </property>
+      <layout class="QHBoxLayout" name="horizontalLayout_5">
+       <item>
+        <widget class="QPushButton" name="ButtonBandWidth">
+         <property name="font">
+          <font>
+           <underline>true</underline>
+          </font>
+         </property>
+         <property name="text">
+          <string>999999 Hz</string>
+         </property>
+         <property name="flat">
+          <bool>true</bool>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="QSlider" name="SliderBandwidth">
+         <property name="sizePolicy">
+          <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
+           <horstretch>0</horstretch>
+           <verstretch>0</verstretch>
+          </sizepolicy>
+         </property>
+         <property name="orientation">
+          <enum>Qt::Horizontal</enum>
+         </property>
+        </widget>
+       </item>
+      </layout>
+     </widget>
+    </item>
+    <item>
+     <layout class="QHBoxLayout" name="_9">
+      <property name="spacing">
+       <number>6</number>
+      </property>
+      <property name="margin">
+       <number>0</number>
+      </property>
+      <item>
+       <widget class="QGroupBox" name="groupBoxDemodulation">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="title">
+         <string>Demodulation</string>
+        </property>
+        <layout class="QHBoxLayout" name="horizontalLayout_2">
+         <item>
+          <widget class="QRadioButton" name="RadioButtonDemAM">
+           <property name="text">
+            <string>AM</string>
+           </property>
+           <attribute name="buttonGroup">
+            <string notr="true">ButtonGroupDemodulation</string>
+           </attribute>
+          </widget>
+         </item>
+         <item>
+          <widget class="QRadioButton" name="RadioButtonDemLSB">
+           <property name="text">
+            <string>LSB</string>
+           </property>
+           <attribute name="buttonGroup">
+            <string notr="true">ButtonGroupDemodulation</string>
+           </attribute>
+          </widget>
+         </item>
+         <item>
+          <widget class="QRadioButton" name="RadioButtonDemUSB">
+           <property name="text">
+            <string>USB</string>
+           </property>
+           <attribute name="buttonGroup">
+            <string notr="true">ButtonGroupDemodulation</string>
+           </attribute>
+          </widget>
+         </item>
+         <item>
+          <widget class="QRadioButton" name="RadioButtonDemCW">
+           <property name="text">
+            <string>CW</string>
+           </property>
+           <attribute name="buttonGroup">
+            <string notr="true">ButtonGroupDemodulation</string>
+           </attribute>
+          </widget>
+         </item>
+         <item>
+          <widget class="QRadioButton" name="RadioButtonDemFM">
+           <property name="text">
+            <string>FM</string>
+           </property>
+           <attribute name="buttonGroup">
+            <string notr="true">ButtonGroupDemodulation</string>
+           </attribute>
+          </widget>
+         </item>
+        </layout>
+       </widget>
+      </item>
+      <item>
+       <widget class="QGroupBox" name="groupBoxAGC">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="title">
+         <string>AGC</string>
+        </property>
+        <layout class="QHBoxLayout" name="horizontalLayout_3">
+         <item>
+          <widget class="QRadioButton" name="RadioButtonAGCOff">
+           <property name="text">
+            <string>Off</string>
+           </property>
+           <attribute name="buttonGroup">
+            <string notr="true">ButtonGroupAGC</string>
+           </attribute>
+          </widget>
+         </item>
+         <item>
+          <widget class="QRadioButton" name="RadioButtonAGCSlow">
+           <property name="text">
+            <string>Slow</string>
+           </property>
+           <attribute name="buttonGroup">
+            <string notr="true">ButtonGroupAGC</string>
+           </attribute>
+          </widget>
+         </item>
+         <item>
+          <widget class="QRadioButton" name="RadioButtonAGCMed">
+           <property name="text">
+            <string>Med</string>
+           </property>
+           <attribute name="buttonGroup">
+            <string notr="true">ButtonGroupAGC</string>
+           </attribute>
+          </widget>
+         </item>
+         <item>
+          <widget class="QRadioButton" name="RadioButtonAGCFast">
+           <property name="text">
+            <string>Fast</string>
+           </property>
+           <attribute name="buttonGroup">
+            <string notr="true">ButtonGroupAGC</string>
+           </attribute>
+          </widget>
+         </item>
+        </layout>
+       </widget>
+      </item>
+      <item>
+       <widget class="QGroupBox" name="groupBoxNoiseReduction">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="title">
+         <string>Noise Reduction</string>
+        </property>
+        <layout class="QGridLayout" name="gridLayout_4">
+         <item row="0" column="0">
+          <widget class="QRadioButton" name="RadioButtonNoiRedOff">
+           <property name="text">
+            <string>Off</string>
+           </property>
+           <attribute name="buttonGroup">
+            <string notr="true">ButtonGroupNoiseReduction</string>
+           </attribute>
+          </widget>
+         </item>
+         <item row="0" column="1">
+          <widget class="QRadioButton" name="RadioButtonNoiRedLow">
+           <property name="text">
+            <string>Low</string>
+           </property>
+           <attribute name="buttonGroup">
+            <string notr="true">ButtonGroupNoiseReduction</string>
+           </attribute>
+          </widget>
+         </item>
+         <item row="0" column="2">
+          <widget class="QRadioButton" name="RadioButtonNoiRedMed">
+           <property name="text">
+            <string>Med</string>
+           </property>
+           <attribute name="buttonGroup">
+            <string notr="true">ButtonGroupNoiseReduction</string>
+           </attribute>
+          </widget>
+         </item>
+         <item row="0" column="3">
+          <widget class="QRadioButton" name="RadioButtonNoiRedHigh">
+           <property name="text">
+            <string>High</string>
+           </property>
+           <attribute name="buttonGroup">
+            <string notr="true">ButtonGroupNoiseReduction</string>
+           </attribute>
+          </widget>
+         </item>
+         <item row="1" column="0">
+          <widget class="QRadioButton" name="RadioButtonNoiRedSpeex">
+           <property name="text">
+            <string>Speex</string>
+           </property>
+           <attribute name="buttonGroup">
+            <string notr="true">ButtonGroupNoiseReduction</string>
+           </attribute>
+          </widget>
+         </item>
+         <item row="1" column="1">
+          <widget class="QSpinBox" name="SpinBoxNoiRedLevel">
+           <property name="suffix">
+            <string> dB</string>
+           </property>
+           <property name="minimum">
+            <number>-96</number>
+           </property>
+           <property name="maximum">
+            <number>-1</number>
+           </property>
+           <property name="value">
+            <number>-1</number>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </widget>
+      </item>
+     </layout>
+    </item>
+    <item>
+     <layout class="QHBoxLayout" name="horizontalLayout_7">
+      <item>
+       <widget class="QGroupBox" name="groupBoxAudio">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="title">
+         <string>Audio</string>
+        </property>
+        <layout class="QHBoxLayout" name="horizontalLayout_8">
+         <item>
+          <widget class="QCheckBox" name="CheckBoxMuteAudio">
+           <property name="text">
+            <string>Mute</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QCheckBox" name="CheckBoxSaveAudioWave">
+           <property name="text">
+            <string>Save</string>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </widget>
+      </item>
+      <item>
+       <widget class="QGroupBox" name="GroupBoxPLL">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="title">
+         <string>PLL</string>
+        </property>
+        <layout class="QGridLayout" name="gridLayout">
+         <item row="0" column="0">
+          <widget class="QCheckBox" name="CheckBoxPLL">
+           <property name="text">
+            <string>Enable</string>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </widget>
+      </item>
+      <item>
+       <widget class="QGroupBox" name="GroupBoxAutoFreqAcq">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="title">
+         <string>Auto Frequency Acquisition</string>
+        </property>
+        <layout class="QGridLayout" name="gridLayout_2">
+         <item row="0" column="0">
+          <widget class="QCheckBox" name="CheckBoxAutoFreqAcq">
+           <property name="text">
+            <string>Enable</string>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </widget>
+      </item>
+      <item>
+       <spacer name="Spacer6">
+        <property name="orientation">
+         <enum>Qt::Horizontal</enum>
+        </property>
+        <property name="sizeType">
+         <enum>QSizePolicy::MinimumExpanding</enum>
+        </property>
+        <property name="sizeHint" stdset="0">
+         <size>
+          <width>20</width>
+          <height>20</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+      <item>
+       <layout class="QVBoxLayout" name="verticalLayout">
+        <property name="spacing">
+         <number>0</number>
+        </property>
+        <item>
+         <widget class="QWidget" name="widget" native="true">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <layout class="QHBoxLayout" name="horizontalLayout_6">
+          <property name="spacing">
+           <number>6</number>
+          </property>
+          <property name="bottomMargin">
+           <number>0</number>
+          </property>
+          <item>
+           <widget class="QPushButton" name="ButtonAMSS">
+            <property name="windowTitle">
+             <string/>
+            </property>
+            <property name="text">
+             <string>&AMSS</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QPushButton" name="ButtonDRM">
+            <property name="windowTitle">
+             <string/>
+            </property>
+            <property name="text">
+             <string>&DRM</string>
+            </property>
+            <property name="default">
+             <bool>true</bool>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </item>
+       </layout>
+      </item>
+     </layout>
+    </item>
+   </layout>
+  </widget>
+  <widget class="QMenuBar" name="menubar">
+   <property name="geometry">
+    <rect>
+     <x>0</x>
+     <y>0</y>
+     <width>899</width>
+     <height>25</height>
+    </rect>
+   </property>
+   <widget class="QMenu" name="menu_View">
+    <property name="title">
+     <string>View</string>
+    </property>
+    <addaction name="action_Stations_Dialog"/>
+    <addaction name="action_Live_Schedule_Dialog"/>
+   </widget>
+   <widget class="QMenu" name="menu_Settings">
+    <property name="title">
+     <string>Settings</string>
+    </property>
+    <addaction name="actionDRM"/>
+    <addaction name="actionFM"/>
+    <addaction name="actionAM"/>
+   </widget>
+   <widget class="QMenu" name="menuHelp">
+    <property name="title">
+     <string>Help</string>
+    </property>
+    <addaction name="actionWhats_This"/>
+    <addaction name="separator"/>
+    <addaction name="actionAbout_Dream"/>
+   </widget>
+   <addaction name="menu_View"/>
+   <addaction name="menu_Settings"/>
+   <addaction name="menuHelp"/>
+  </widget>
+  <action name="action_Stations_Dialog">
+   <property name="text">
+    <string>S&tations Dialog...</string>
+   </property>
+   <property name="shortcut">
+    <string>Alt+T</string>
+   </property>
+  </action>
+  <action name="action_Live_Schedule_Dialog">
+   <property name="text">
+    <string>&Live Schedule Dialog...</string>
+   </property>
+   <property name="shortcut">
+    <string>Alt+L</string>
+   </property>
+  </action>
+  <action name="actionExit">
+   <property name="text">
+    <string>E&xit</string>
+   </property>
+   <property name="shortcut">
+    <string>Alt+X</string>
+   </property>
+  </action>
+  <action name="actionAM">
+   <property name="text">
+    <string>New AM Acquisition</string>
+   </property>
+   <property name="shortcut">
+    <string>Ctrl+A</string>
+   </property>
+  </action>
+  <action name="actionFM">
+   <property name="text">
+    <string>FM (analog)</string>
+   </property>
+   <property name="shortcut">
+    <string>Ctrl+F</string>
+   </property>
+  </action>
+  <action name="actionDRM">
+   <property name="text">
+    <string>DRM (digital)</string>
+   </property>
+   <property name="shortcut">
+    <string>Ctrl+D</string>
+   </property>
+  </action>
+  <action name="actionWhats_This">
+   <property name="text">
+    <string>Whats This...</string>
+   </property>
+   <property name="shortcut">
+    <string>Shift+F1</string>
+   </property>
+  </action>
+  <action name="actionAbout_Dream">
+   <property name="text">
+    <string>About Dream...</string>
+   </property>
+  </action>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>QwtPlot</class>
+   <extends>QFrame</extends>
+   <header>qwt_plot.h</header>
+   <container>1</container>
+  </customwidget>
+  <customwidget>
+   <class>QwtDial</class>
+   <extends>QWidget</extends>
+   <header>qwt_dial.h</header>
+  </customwidget>
+ </customwidgets>
+ <resources>
+  <include location="res/icons.qrc"/>
+ </resources>
+ <connections/>
+ <buttongroups>
+  <buttongroup name="ButtonGroupAGC"/>
+  <buttongroup name="ButtonGroupDemodulation"/>
+  <buttongroup name="ButtonGroupNoiseReduction"/>
+ </buttongroups>
+</ui>
diff --git a/src/GUI-QT/AMSSDlgbase.ui b/src/GUI-QT/AMSSDlgbase.ui
new file mode 100644
index 0000000..b0ea354
--- /dev/null
+++ b/src/GUI-QT/AMSSDlgbase.ui
@@ -0,0 +1,3704 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>CAMSSDlgBase</class>
+ <widget class="QMainWindow" name="CAMSSDlgBase">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>663</width>
+    <height>289</height>
+   </rect>
+  </property>
+  <property name="sizePolicy">
+   <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
+    <horstretch>0</horstretch>
+    <verstretch>0</verstretch>
+   </sizepolicy>
+  </property>
+  <property name="windowTitle">
+   <string>AMSS</string>
+  </property>
+  <property name="windowIcon">
+   <iconset resource="res/icons.qrc">
+    <normaloff>:/icons/MainIcon.svg</normaloff>:/icons/MainIcon.svg</iconset>
+  </property>
+  <widget class="QWidget" name="centralwidget">
+   <layout class="QGridLayout" name="gridLayout">
+    <item row="0" column="0">
+     <widget class="QLabel" name="label">
+      <property name="font">
+       <font>
+        <weight>75</weight>
+        <bold>true</bold>
+       </font>
+      </property>
+      <property name="text">
+       <string>AMSS Decoding</string>
+      </property>
+     </widget>
+    </item>
+    <item row="1" column="0">
+     <widget class="QFrame" name="FrameMainDisplay">
+      <property name="sizePolicy">
+       <sizepolicy hsizetype="Minimum" vsizetype="Expanding">
+        <horstretch>0</horstretch>
+        <verstretch>0</verstretch>
+       </sizepolicy>
+      </property>
+      <property name="minimumSize">
+       <size>
+        <width>380</width>
+        <height>0</height>
+       </size>
+      </property>
+      <property name="maximumSize">
+       <size>
+        <width>32767</width>
+        <height>32767</height>
+       </size>
+      </property>
+      <property name="palette">
+       <palette>
+        <active>
+         <colorrole role="WindowText">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>0</red>
+            <green>0</green>
+            <blue>0</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="Button">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>169</red>
+            <green>134</green>
+            <blue>107</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="Light">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>253</red>
+            <green>200</green>
+            <blue>160</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="Midlight">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>211</red>
+            <green>167</green>
+            <blue>133</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="Dark">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>84</red>
+            <green>66</green>
+            <blue>53</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="Mid">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>112</red>
+            <green>89</green>
+            <blue>71</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="Text">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>0</red>
+            <green>0</green>
+            <blue>0</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="BrightText">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>255</red>
+            <green>255</green>
+            <blue>255</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="ButtonText">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>0</red>
+            <green>0</green>
+            <blue>0</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="Base">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>255</red>
+            <green>255</green>
+            <blue>255</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="Window">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>0</red>
+            <green>0</green>
+            <blue>0</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="Shadow">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>0</red>
+            <green>0</green>
+            <blue>0</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="Highlight">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>0</red>
+            <green>0</green>
+            <blue>128</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="HighlightedText">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>255</red>
+            <green>255</green>
+            <blue>255</blue>
+           </color>
+          </brush>
+         </colorrole>
+        </active>
+        <inactive>
+         <colorrole role="WindowText">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>0</red>
+            <green>0</green>
+            <blue>0</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="Button">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>169</red>
+            <green>134</green>
+            <blue>107</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="Light">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>253</red>
+            <green>200</green>
+            <blue>160</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="Midlight">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>194</red>
+            <green>153</green>
+            <blue>122</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="Dark">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>84</red>
+            <green>66</green>
+            <blue>53</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="Mid">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>112</red>
+            <green>89</green>
+            <blue>71</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="Text">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>0</red>
+            <green>0</green>
+            <blue>0</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="BrightText">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>255</red>
+            <green>255</green>
+            <blue>255</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="ButtonText">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>0</red>
+            <green>0</green>
+            <blue>0</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="Base">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>255</red>
+            <green>255</green>
+            <blue>255</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="Window">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>0</red>
+            <green>0</green>
+            <blue>0</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="Shadow">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>0</red>
+            <green>0</green>
+            <blue>0</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="Highlight">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>0</red>
+            <green>0</green>
+            <blue>128</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="HighlightedText">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>255</red>
+            <green>255</green>
+            <blue>255</blue>
+           </color>
+          </brush>
+         </colorrole>
+        </inactive>
+        <disabled>
+         <colorrole role="WindowText">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>128</red>
+            <green>128</green>
+            <blue>128</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="Button">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>169</red>
+            <green>134</green>
+            <blue>107</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="Light">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>253</red>
+            <green>200</green>
+            <blue>160</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="Midlight">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>194</red>
+            <green>153</green>
+            <blue>122</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="Dark">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>84</red>
+            <green>66</green>
+            <blue>53</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="Mid">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>112</red>
+            <green>89</green>
+            <blue>71</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="Text">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>0</red>
+            <green>0</green>
+            <blue>0</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="BrightText">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>255</red>
+            <green>255</green>
+            <blue>255</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="ButtonText">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>128</red>
+            <green>128</green>
+            <blue>128</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="Base">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>255</red>
+            <green>255</green>
+            <blue>255</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="Window">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>0</red>
+            <green>0</green>
+            <blue>0</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="Shadow">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>0</red>
+            <green>0</green>
+            <blue>0</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="Highlight">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>0</red>
+            <green>0</green>
+            <blue>128</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="HighlightedText">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>255</red>
+            <green>255</green>
+            <blue>255</blue>
+           </color>
+          </brush>
+         </colorrole>
+        </disabled>
+       </palette>
+      </property>
+      <property name="autoFillBackground">
+       <bool>true</bool>
+      </property>
+      <property name="frameShape">
+       <enum>QFrame::StyledPanel</enum>
+      </property>
+      <property name="frameShadow">
+       <enum>QFrame::Raised</enum>
+      </property>
+      <layout class="QGridLayout">
+       <property name="margin">
+        <number>6</number>
+       </property>
+       <property name="spacing">
+        <number>0</number>
+       </property>
+       <item row="3" column="0">
+        <layout class="QHBoxLayout">
+         <property name="spacing">
+          <number>6</number>
+         </property>
+         <property name="margin">
+          <number>0</number>
+         </property>
+         <item>
+          <widget class="QLabel" name="TextAMSSAMCarrierMode">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="palette">
+            <palette>
+             <active>
+              <colorrole role="WindowText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Button">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>169</red>
+                 <green>134</green>
+                 <blue>107</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Light">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>253</red>
+                 <green>200</green>
+                 <blue>160</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Midlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>211</red>
+                 <green>167</green>
+                 <blue>133</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Dark">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>84</red>
+                 <green>66</green>
+                 <blue>53</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Mid">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>112</red>
+                 <green>89</green>
+                 <blue>71</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Text">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="BrightText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ButtonText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Base">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Window">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Shadow">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Highlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>128</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="HighlightedText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+             </active>
+             <inactive>
+              <colorrole role="WindowText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Button">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>169</red>
+                 <green>134</green>
+                 <blue>107</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Light">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>253</red>
+                 <green>200</green>
+                 <blue>160</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Midlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>194</red>
+                 <green>153</green>
+                 <blue>122</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Dark">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>84</red>
+                 <green>66</green>
+                 <blue>53</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Mid">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>112</red>
+                 <green>89</green>
+                 <blue>71</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Text">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="BrightText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ButtonText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Base">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Window">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Shadow">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Highlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>128</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="HighlightedText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+             </inactive>
+             <disabled>
+              <colorrole role="WindowText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>128</red>
+                 <green>128</green>
+                 <blue>128</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Button">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>169</red>
+                 <green>134</green>
+                 <blue>107</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Light">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>253</red>
+                 <green>200</green>
+                 <blue>160</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Midlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>194</red>
+                 <green>153</green>
+                 <blue>122</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Dark">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>84</red>
+                 <green>66</green>
+                 <blue>53</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Mid">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>112</red>
+                 <green>89</green>
+                 <blue>71</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Text">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="BrightText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ButtonText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>128</red>
+                 <green>128</green>
+                 <blue>128</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Base">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Window">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Shadow">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Highlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>128</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="HighlightedText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+             </disabled>
+            </palette>
+           </property>
+           <property name="font">
+            <font>
+             <family>Arial</family>
+             <pointsize>10</pointsize>
+             <weight>75</weight>
+             <bold>true</bold>
+            </font>
+           </property>
+           <property name="text">
+            <string>AMSSAMCarrierMode</string>
+           </property>
+           <property name="scaledContents">
+            <bool>false</bool>
+           </property>
+           <property name="alignment">
+            <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+           </property>
+           <property name="wordWrap">
+            <bool>false</bool>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QLabel" name="TextAMSSInfo">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="palette">
+            <palette>
+             <active>
+              <colorrole role="WindowText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Button">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>169</red>
+                 <green>134</green>
+                 <blue>107</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Light">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>253</red>
+                 <green>200</green>
+                 <blue>160</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Midlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>211</red>
+                 <green>167</green>
+                 <blue>133</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Dark">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>84</red>
+                 <green>66</green>
+                 <blue>53</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Mid">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>112</red>
+                 <green>89</green>
+                 <blue>71</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Text">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="BrightText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ButtonText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Base">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Window">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Shadow">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Highlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>128</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="HighlightedText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+             </active>
+             <inactive>
+              <colorrole role="WindowText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Button">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>169</red>
+                 <green>134</green>
+                 <blue>107</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Light">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>253</red>
+                 <green>200</green>
+                 <blue>160</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Midlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>194</red>
+                 <green>153</green>
+                 <blue>122</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Dark">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>84</red>
+                 <green>66</green>
+                 <blue>53</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Mid">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>112</red>
+                 <green>89</green>
+                 <blue>71</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Text">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="BrightText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ButtonText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Base">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Window">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Shadow">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Highlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>128</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="HighlightedText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+             </inactive>
+             <disabled>
+              <colorrole role="WindowText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>128</red>
+                 <green>128</green>
+                 <blue>128</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Button">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>169</red>
+                 <green>134</green>
+                 <blue>107</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Light">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>253</red>
+                 <green>200</green>
+                 <blue>160</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Midlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>194</red>
+                 <green>153</green>
+                 <blue>122</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Dark">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>84</red>
+                 <green>66</green>
+                 <blue>53</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Mid">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>112</red>
+                 <green>89</green>
+                 <blue>71</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Text">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="BrightText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ButtonText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>128</red>
+                 <green>128</green>
+                 <blue>128</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Base">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Window">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Shadow">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Highlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>128</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="HighlightedText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+             </disabled>
+            </palette>
+           </property>
+           <property name="font">
+            <font>
+             <family>Arial</family>
+             <pointsize>10</pointsize>
+             <weight>75</weight>
+             <bold>true</bold>
+            </font>
+           </property>
+           <property name="text">
+            <string>AMSSInfo</string>
+           </property>
+           <property name="scaledContents">
+            <bool>false</bool>
+           </property>
+           <property name="alignment">
+            <set>Qt::AlignCenter</set>
+           </property>
+           <property name="wordWrap">
+            <bool>false</bool>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QLabel" name="TextAMSSServiceID">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="palette">
+            <palette>
+             <active>
+              <colorrole role="WindowText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Button">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>169</red>
+                 <green>134</green>
+                 <blue>107</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Light">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>253</red>
+                 <green>200</green>
+                 <blue>160</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Midlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>211</red>
+                 <green>167</green>
+                 <blue>133</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Dark">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>84</red>
+                 <green>66</green>
+                 <blue>53</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Mid">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>112</red>
+                 <green>89</green>
+                 <blue>71</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Text">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="BrightText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ButtonText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Base">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Window">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Shadow">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Highlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>128</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="HighlightedText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+             </active>
+             <inactive>
+              <colorrole role="WindowText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Button">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>169</red>
+                 <green>134</green>
+                 <blue>107</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Light">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>253</red>
+                 <green>200</green>
+                 <blue>160</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Midlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>194</red>
+                 <green>153</green>
+                 <blue>122</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Dark">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>84</red>
+                 <green>66</green>
+                 <blue>53</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Mid">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>112</red>
+                 <green>89</green>
+                 <blue>71</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Text">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="BrightText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ButtonText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Base">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Window">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Shadow">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Highlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>128</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="HighlightedText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+             </inactive>
+             <disabled>
+              <colorrole role="WindowText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>128</red>
+                 <green>128</green>
+                 <blue>128</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Button">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>169</red>
+                 <green>134</green>
+                 <blue>107</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Light">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>253</red>
+                 <green>200</green>
+                 <blue>160</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Midlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>194</red>
+                 <green>153</green>
+                 <blue>122</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Dark">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>84</red>
+                 <green>66</green>
+                 <blue>53</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Mid">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>112</red>
+                 <green>89</green>
+                 <blue>71</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Text">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="BrightText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ButtonText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>128</red>
+                 <green>128</green>
+                 <blue>128</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Base">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Window">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Shadow">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Highlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>128</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="HighlightedText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+             </disabled>
+            </palette>
+           </property>
+           <property name="font">
+            <font>
+             <family>Arial</family>
+             <pointsize>10</pointsize>
+             <weight>75</weight>
+             <bold>true</bold>
+            </font>
+           </property>
+           <property name="text">
+            <string>AMSSServiceID</string>
+           </property>
+           <property name="scaledContents">
+            <bool>false</bool>
+           </property>
+           <property name="alignment">
+            <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+           </property>
+           <property name="wordWrap">
+            <bool>false</bool>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </item>
+       <item row="2" column="0">
+        <layout class="QHBoxLayout">
+         <property name="spacing">
+          <number>6</number>
+         </property>
+         <property name="margin">
+          <number>0</number>
+         </property>
+         <item>
+          <widget class="QLabel" name="TextAMSSLanguage">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="palette">
+            <palette>
+             <active>
+              <colorrole role="WindowText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Button">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>169</red>
+                 <green>134</green>
+                 <blue>107</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Light">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>253</red>
+                 <green>200</green>
+                 <blue>160</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Midlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>211</red>
+                 <green>167</green>
+                 <blue>133</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Dark">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>84</red>
+                 <green>66</green>
+                 <blue>53</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Mid">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>112</red>
+                 <green>89</green>
+                 <blue>71</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Text">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="BrightText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ButtonText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Base">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Window">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Shadow">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Highlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>128</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="HighlightedText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+             </active>
+             <inactive>
+              <colorrole role="WindowText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Button">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>169</red>
+                 <green>134</green>
+                 <blue>107</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Light">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>253</red>
+                 <green>200</green>
+                 <blue>160</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Midlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>194</red>
+                 <green>153</green>
+                 <blue>122</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Dark">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>84</red>
+                 <green>66</green>
+                 <blue>53</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Mid">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>112</red>
+                 <green>89</green>
+                 <blue>71</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Text">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="BrightText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ButtonText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Base">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Window">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Shadow">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Highlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>128</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="HighlightedText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+             </inactive>
+             <disabled>
+              <colorrole role="WindowText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>128</red>
+                 <green>128</green>
+                 <blue>128</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Button">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>169</red>
+                 <green>134</green>
+                 <blue>107</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Light">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>253</red>
+                 <green>200</green>
+                 <blue>160</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Midlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>194</red>
+                 <green>153</green>
+                 <blue>122</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Dark">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>84</red>
+                 <green>66</green>
+                 <blue>53</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Mid">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>112</red>
+                 <green>89</green>
+                 <blue>71</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Text">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="BrightText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ButtonText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>128</red>
+                 <green>128</green>
+                 <blue>128</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Base">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Window">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Shadow">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Highlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>128</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="HighlightedText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+             </disabled>
+            </palette>
+           </property>
+           <property name="font">
+            <font>
+             <family>Arial</family>
+             <pointsize>10</pointsize>
+             <weight>75</weight>
+             <bold>true</bold>
+            </font>
+           </property>
+           <property name="text">
+            <string>AMSSLanguage</string>
+           </property>
+           <property name="scaledContents">
+            <bool>false</bool>
+           </property>
+           <property name="alignment">
+            <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+           </property>
+           <property name="wordWrap">
+            <bool>false</bool>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QLabel" name="TextAMSSCountryCode">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="palette">
+            <palette>
+             <active>
+              <colorrole role="WindowText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Button">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>169</red>
+                 <green>134</green>
+                 <blue>107</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Light">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>253</red>
+                 <green>200</green>
+                 <blue>160</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Midlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>211</red>
+                 <green>167</green>
+                 <blue>133</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Dark">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>84</red>
+                 <green>66</green>
+                 <blue>53</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Mid">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>112</red>
+                 <green>89</green>
+                 <blue>71</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Text">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="BrightText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ButtonText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Base">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Window">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Shadow">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Highlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>128</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="HighlightedText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+             </active>
+             <inactive>
+              <colorrole role="WindowText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Button">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>169</red>
+                 <green>134</green>
+                 <blue>107</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Light">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>253</red>
+                 <green>200</green>
+                 <blue>160</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Midlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>194</red>
+                 <green>153</green>
+                 <blue>122</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Dark">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>84</red>
+                 <green>66</green>
+                 <blue>53</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Mid">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>112</red>
+                 <green>89</green>
+                 <blue>71</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Text">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="BrightText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ButtonText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Base">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Window">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Shadow">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Highlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>128</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="HighlightedText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+             </inactive>
+             <disabled>
+              <colorrole role="WindowText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>128</red>
+                 <green>128</green>
+                 <blue>128</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Button">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>169</red>
+                 <green>134</green>
+                 <blue>107</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Light">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>253</red>
+                 <green>200</green>
+                 <blue>160</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Midlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>194</red>
+                 <green>153</green>
+                 <blue>122</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Dark">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>84</red>
+                 <green>66</green>
+                 <blue>53</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Mid">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>112</red>
+                 <green>89</green>
+                 <blue>71</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Text">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="BrightText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ButtonText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>128</red>
+                 <green>128</green>
+                 <blue>128</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Base">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Window">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Shadow">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Highlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>128</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="HighlightedText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+             </disabled>
+            </palette>
+           </property>
+           <property name="font">
+            <font>
+             <family>Arial</family>
+             <pointsize>10</pointsize>
+             <weight>75</weight>
+             <bold>true</bold>
+            </font>
+           </property>
+           <property name="text">
+            <string>AMSSCountryCode</string>
+           </property>
+           <property name="scaledContents">
+            <bool>false</bool>
+           </property>
+           <property name="alignment">
+            <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+           </property>
+           <property name="wordWrap">
+            <bool>false</bool>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </item>
+       <item row="0" column="0">
+        <widget class="QLabel" name="TextAMSSTimeDate">
+         <property name="sizePolicy">
+          <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+           <horstretch>0</horstretch>
+           <verstretch>0</verstretch>
+          </sizepolicy>
+         </property>
+         <property name="palette">
+          <palette>
+           <active>
+            <colorrole role="WindowText">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>170</red>
+               <green>170</green>
+               <blue>127</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Button">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>169</red>
+               <green>134</green>
+               <blue>107</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Light">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>253</red>
+               <green>200</green>
+               <blue>160</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Midlight">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>211</red>
+               <green>167</green>
+               <blue>133</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Dark">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>84</red>
+               <green>66</green>
+               <blue>53</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Mid">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>112</red>
+               <green>89</green>
+               <blue>71</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Text">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>0</red>
+               <green>0</green>
+               <blue>0</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="BrightText">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>255</red>
+               <green>255</green>
+               <blue>255</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="ButtonText">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>0</red>
+               <green>0</green>
+               <blue>0</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Base">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>255</red>
+               <green>255</green>
+               <blue>255</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Window">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>0</red>
+               <green>0</green>
+               <blue>0</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Shadow">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>0</red>
+               <green>0</green>
+               <blue>0</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Highlight">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>0</red>
+               <green>0</green>
+               <blue>128</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="HighlightedText">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>255</red>
+               <green>255</green>
+               <blue>255</blue>
+              </color>
+             </brush>
+            </colorrole>
+           </active>
+           <inactive>
+            <colorrole role="WindowText">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>170</red>
+               <green>170</green>
+               <blue>127</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Button">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>169</red>
+               <green>134</green>
+               <blue>107</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Light">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>253</red>
+               <green>200</green>
+               <blue>160</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Midlight">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>194</red>
+               <green>153</green>
+               <blue>122</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Dark">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>84</red>
+               <green>66</green>
+               <blue>53</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Mid">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>112</red>
+               <green>89</green>
+               <blue>71</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Text">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>0</red>
+               <green>0</green>
+               <blue>0</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="BrightText">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>255</red>
+               <green>255</green>
+               <blue>255</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="ButtonText">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>0</red>
+               <green>0</green>
+               <blue>0</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Base">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>255</red>
+               <green>255</green>
+               <blue>255</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Window">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>0</red>
+               <green>0</green>
+               <blue>0</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Shadow">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>0</red>
+               <green>0</green>
+               <blue>0</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Highlight">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>0</red>
+               <green>0</green>
+               <blue>128</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="HighlightedText">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>255</red>
+               <green>255</green>
+               <blue>255</blue>
+              </color>
+             </brush>
+            </colorrole>
+           </inactive>
+           <disabled>
+            <colorrole role="WindowText">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>128</red>
+               <green>128</green>
+               <blue>128</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Button">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>169</red>
+               <green>134</green>
+               <blue>107</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Light">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>253</red>
+               <green>200</green>
+               <blue>160</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Midlight">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>194</red>
+               <green>153</green>
+               <blue>122</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Dark">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>84</red>
+               <green>66</green>
+               <blue>53</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Mid">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>112</red>
+               <green>89</green>
+               <blue>71</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Text">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>0</red>
+               <green>0</green>
+               <blue>0</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="BrightText">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>255</red>
+               <green>255</green>
+               <blue>255</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="ButtonText">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>128</red>
+               <green>128</green>
+               <blue>128</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Base">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>255</red>
+               <green>255</green>
+               <blue>255</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Window">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>0</red>
+               <green>0</green>
+               <blue>0</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Shadow">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>0</red>
+               <green>0</green>
+               <blue>0</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Highlight">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>0</red>
+               <green>0</green>
+               <blue>128</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="HighlightedText">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>255</red>
+               <green>255</green>
+               <blue>255</blue>
+              </color>
+             </brush>
+            </colorrole>
+           </disabled>
+          </palette>
+         </property>
+         <property name="font">
+          <font>
+           <family>Arial</family>
+           <weight>75</weight>
+           <bold>true</bold>
+          </font>
+         </property>
+         <property name="text">
+          <string>AMSSTimeDate</string>
+         </property>
+         <property name="scaledContents">
+          <bool>false</bool>
+         </property>
+         <property name="alignment">
+          <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+         </property>
+         <property name="wordWrap">
+          <bool>false</bool>
+         </property>
+        </widget>
+       </item>
+       <item row="1" column="0">
+        <widget class="QLabel" name="TextAMSSServiceLabel">
+         <property name="sizePolicy">
+          <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+           <horstretch>0</horstretch>
+           <verstretch>0</verstretch>
+          </sizepolicy>
+         </property>
+         <property name="palette">
+          <palette>
+           <active>
+            <colorrole role="WindowText">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>85</red>
+               <green>255</green>
+               <blue>255</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Button">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>169</red>
+               <green>134</green>
+               <blue>107</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Light">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>253</red>
+               <green>200</green>
+               <blue>160</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Midlight">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>211</red>
+               <green>167</green>
+               <blue>133</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Dark">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>84</red>
+               <green>66</green>
+               <blue>53</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Mid">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>112</red>
+               <green>89</green>
+               <blue>71</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Text">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>0</red>
+               <green>0</green>
+               <blue>0</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="BrightText">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>255</red>
+               <green>255</green>
+               <blue>255</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="ButtonText">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>0</red>
+               <green>0</green>
+               <blue>0</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Base">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>255</red>
+               <green>255</green>
+               <blue>255</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Window">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>0</red>
+               <green>0</green>
+               <blue>0</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Shadow">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>0</red>
+               <green>0</green>
+               <blue>0</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Highlight">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>0</red>
+               <green>0</green>
+               <blue>128</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="HighlightedText">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>255</red>
+               <green>255</green>
+               <blue>255</blue>
+              </color>
+             </brush>
+            </colorrole>
+           </active>
+           <inactive>
+            <colorrole role="WindowText">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>85</red>
+               <green>255</green>
+               <blue>255</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Button">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>169</red>
+               <green>134</green>
+               <blue>107</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Light">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>253</red>
+               <green>200</green>
+               <blue>160</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Midlight">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>194</red>
+               <green>153</green>
+               <blue>122</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Dark">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>84</red>
+               <green>66</green>
+               <blue>53</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Mid">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>112</red>
+               <green>89</green>
+               <blue>71</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Text">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>0</red>
+               <green>0</green>
+               <blue>0</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="BrightText">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>255</red>
+               <green>255</green>
+               <blue>255</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="ButtonText">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>0</red>
+               <green>0</green>
+               <blue>0</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Base">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>255</red>
+               <green>255</green>
+               <blue>255</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Window">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>0</red>
+               <green>0</green>
+               <blue>0</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Shadow">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>0</red>
+               <green>0</green>
+               <blue>0</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Highlight">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>0</red>
+               <green>0</green>
+               <blue>128</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="HighlightedText">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>255</red>
+               <green>255</green>
+               <blue>255</blue>
+              </color>
+             </brush>
+            </colorrole>
+           </inactive>
+           <disabled>
+            <colorrole role="WindowText">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>128</red>
+               <green>128</green>
+               <blue>128</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Button">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>169</red>
+               <green>134</green>
+               <blue>107</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Light">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>253</red>
+               <green>200</green>
+               <blue>160</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Midlight">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>194</red>
+               <green>153</green>
+               <blue>122</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Dark">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>84</red>
+               <green>66</green>
+               <blue>53</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Mid">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>112</red>
+               <green>89</green>
+               <blue>71</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Text">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>0</red>
+               <green>0</green>
+               <blue>0</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="BrightText">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>255</red>
+               <green>255</green>
+               <blue>255</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="ButtonText">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>128</red>
+               <green>128</green>
+               <blue>128</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Base">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>255</red>
+               <green>255</green>
+               <blue>255</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Window">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>0</red>
+               <green>0</green>
+               <blue>0</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Shadow">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>0</red>
+               <green>0</green>
+               <blue>0</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Highlight">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>0</red>
+               <green>0</green>
+               <blue>128</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="HighlightedText">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>255</red>
+               <green>255</green>
+               <blue>255</blue>
+              </color>
+             </brush>
+            </colorrole>
+           </disabled>
+          </palette>
+         </property>
+         <property name="font">
+          <font>
+           <family>Arial</family>
+           <pointsize>14</pointsize>
+           <weight>75</weight>
+           <bold>true</bold>
+          </font>
+         </property>
+         <property name="text">
+          <string>ServiceLabelAMSS</string>
+         </property>
+         <property name="alignment">
+          <set>Qt::AlignCenter</set>
+         </property>
+         <property name="wordWrap">
+          <bool>false</bool>
+         </property>
+        </widget>
+       </item>
+      </layout>
+     </widget>
+    </item>
+    <item row="1" column="1">
+     <layout class="QVBoxLayout">
+      <property name="spacing">
+       <number>6</number>
+      </property>
+      <property name="margin">
+       <number>0</number>
+      </property>
+      <item>
+       <layout class="QHBoxLayout">
+        <property name="spacing">
+         <number>6</number>
+        </property>
+        <property name="margin">
+         <number>0</number>
+        </property>
+        <item>
+         <widget class="QLabel" name="TextLabelStaticSDCPercentage">
+          <property name="enabled">
+           <bool>true</bool>
+          </property>
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="text">
+           <string>SDC:  </string>
+          </property>
+          <property name="alignment">
+           <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+          </property>
+          <property name="wordWrap">
+           <bool>false</bool>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QProgressBar" name="ProgressBarAMSS">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Expanding" vsizetype="Minimum">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="minimumSize">
+           <size>
+            <width>50</width>
+            <height>0</height>
+           </size>
+          </property>
+          <property name="maximumSize">
+           <size>
+            <width>32767</width>
+            <height>32767</height>
+           </size>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QLabel" name="TextDataEntityGroupStatus">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="text">
+           <string>................</string>
+          </property>
+          <property name="alignment">
+           <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+          </property>
+          <property name="wordWrap">
+           <bool>false</bool>
+          </property>
+         </widget>
+        </item>
+       </layout>
+      </item>
+      <item>
+       <layout class="QHBoxLayout">
+        <property name="spacing">
+         <number>6</number>
+        </property>
+        <property name="margin">
+         <number>0</number>
+        </property>
+        <item>
+         <widget class="QLabel" name="TextLabelAMSSAFSList">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Minimum" vsizetype="Expanding">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="text">
+           <string>AFS:  </string>
+          </property>
+          <property name="wordWrap">
+           <bool>false</bool>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QListWidget" name="ListBoxAMSSAFSList"/>
+        </item>
+       </layout>
+      </item>
+     </layout>
+    </item>
+    <item row="1" column="2" rowspan="2">
+     <layout class="QVBoxLayout" name="verticalLayout">
+      <item>
+       <widget class="QLabel" name="TextLabelPhaseOffsetAMSS">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="text">
+         <string>AMSS Offset</string>
+        </property>
+        <property name="alignment">
+         <set>Qt::AlignCenter</set>
+        </property>
+        <property name="wordWrap">
+         <bool>false</bool>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QwtDial" name="PhaseDialAMSS" native="true">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="minimumSize">
+         <size>
+          <width>0</width>
+          <height>70</height>
+         </size>
+        </property>
+        <property name="focusPolicy">
+         <enum>Qt::NoFocus</enum>
+        </property>
+        <property name="lineWidth" stdset="0">
+         <number>4</number>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <spacer name="verticalSpacer_2">
+        <property name="orientation">
+         <enum>Qt::Vertical</enum>
+        </property>
+        <property name="sizeHint" stdset="0">
+         <size>
+          <width>10</width>
+          <height>0</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+      <item>
+       <layout class="QHBoxLayout" name="horizontalLayout">
+        <property name="spacing">
+         <number>0</number>
+        </property>
+        <property name="margin">
+         <number>0</number>
+        </property>
+        <item>
+         <widget class="QWidget" name="widget" native="true">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QPushButton" name="buttonOk">
+          <property name="text">
+           <string>&Close</string>
+          </property>
+          <property name="default">
+           <bool>true</bool>
+          </property>
+         </widget>
+        </item>
+       </layout>
+      </item>
+     </layout>
+    </item>
+    <item row="2" column="0" colspan="2">
+     <layout class="QHBoxLayout" name="horizontalLayout_2">
+      <item>
+       <widget class="QLabel" name="TextLabelCurrentBlock">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Fixed" vsizetype="Minimum">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="minimumSize">
+         <size>
+          <width>0</width>
+          <height>0</height>
+         </size>
+        </property>
+        <property name="text">
+         <string>Block:</string>
+        </property>
+        <property name="alignment">
+         <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+        </property>
+        <property name="wordWrap">
+         <bool>false</bool>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QLabel" name="TextCurrentBlock">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Fixed" vsizetype="Minimum">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="text">
+         <string/>
+        </property>
+        <property name="wordWrap">
+         <bool>false</bool>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QLabel" name="TextLabelBlockBits">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Fixed" vsizetype="Minimum">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="text">
+         <string>Bits:</string>
+        </property>
+        <property name="wordWrap">
+         <bool>false</bool>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QLabel" name="TextBlockBits">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Ignored" vsizetype="Minimum">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="text">
+         <string/>
+        </property>
+        <property name="scaledContents">
+         <bool>false</bool>
+        </property>
+        <property name="wordWrap">
+         <bool>false</bool>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </item>
+   </layout>
+  </widget>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>QwtDial</class>
+   <extends>QWidget</extends>
+   <header>qwt_dial.h</header>
+  </customwidget>
+ </customwidgets>
+ <resources>
+  <include location="res/icons.qrc"/>
+ </resources>
+ <connections/>
+</ui>
diff --git a/src/GUI-QT/AboutDlgbase.ui b/src/GUI-QT/AboutDlgbase.ui
new file mode 100644
index 0000000..5bd286d
--- /dev/null
+++ b/src/GUI-QT/AboutDlgbase.ui
@@ -0,0 +1,192 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>CAboutDlgBase</class>
+ <widget class="QDialog" name="CAboutDlgBase">
+  <property name="windowModality">
+   <enum>Qt::ApplicationModal</enum>
+  </property>
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>588</width>
+    <height>480</height>
+   </rect>
+  </property>
+  <property name="sizePolicy">
+   <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+    <horstretch>0</horstretch>
+    <verstretch>0</verstretch>
+   </sizepolicy>
+  </property>
+  <property name="windowTitle">
+   <string>About Dream</string>
+  </property>
+  <property name="windowIcon">
+   <iconset resource="res/icons.qrc">
+    <normaloff>:/icons/MainIcon.svg</normaloff>:/icons/MainIcon.svg</iconset>
+  </property>
+  <property name="sizeGripEnabled">
+   <bool>true</bool>
+  </property>
+  <layout class="QVBoxLayout">
+   <item>
+    <widget class="QLabel" name="TextLabelVersion">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
+     </property>
+     <property name="text">
+      <string>TextLabelVersion</string>
+     </property>
+     <property name="wordWrap">
+      <bool>true</bool>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <layout class="QHBoxLayout">
+     <property name="spacing">
+      <number>6</number>
+     </property>
+     <property name="margin">
+      <number>0</number>
+     </property>
+     <item>
+      <layout class="QVBoxLayout">
+       <property name="spacing">
+        <number>6</number>
+       </property>
+       <property name="margin">
+        <number>0</number>
+       </property>
+       <item>
+        <widget class="QLabel" name="TextLabelAuthorNames">
+         <property name="sizePolicy">
+          <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+           <horstretch>0</horstretch>
+           <verstretch>0</verstretch>
+          </sizepolicy>
+         </property>
+         <property name="text">
+          <string>TextLabelAuthorNames</string>
+         </property>
+         <property name="wordWrap">
+          <bool>true</bool>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="QLabel" name="TextLabelCopyright">
+         <property name="sizePolicy">
+          <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+           <horstretch>0</horstretch>
+           <verstretch>0</verstretch>
+          </sizepolicy>
+         </property>
+         <property name="text">
+          <string>TextLabelCopyright</string>
+         </property>
+         <property name="wordWrap">
+          <bool>true</bool>
+         </property>
+        </widget>
+       </item>
+      </layout>
+     </item>
+     <item>
+      <widget class="QLabel" name="PixmapLabelDreamLogo">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="pixmap">
+        <pixmap resource="res/icons.qrc">:/icons/LogoSmall.png</pixmap>
+       </property>
+       <property name="scaledContents">
+        <bool>false</bool>
+       </property>
+       <property name="wordWrap">
+        <bool>false</bool>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
+   <item>
+    <widget class="QTextBrowser" name="TextViewCredits">
+     <property name="openExternalLinks">
+      <bool>true</bool>
+     </property>
+     <property name="openLinks">
+      <bool>true</bool>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <layout class="QHBoxLayout">
+     <property name="spacing">
+      <number>6</number>
+     </property>
+     <property name="margin">
+      <number>0</number>
+     </property>
+     <item>
+      <spacer name="Spacer12">
+       <property name="orientation">
+        <enum>Qt::Horizontal</enum>
+       </property>
+       <property name="sizeType">
+        <enum>QSizePolicy::Expanding</enum>
+       </property>
+       <property name="sizeHint" stdset="0">
+        <size>
+         <width>20</width>
+         <height>20</height>
+        </size>
+       </property>
+      </spacer>
+     </item>
+     <item>
+      <widget class="QPushButton" name="buttonOk">
+       <property name="text">
+        <string>&OK</string>
+       </property>
+       <property name="autoDefault">
+        <bool>false</bool>
+       </property>
+       <property name="default">
+        <bool>true</bool>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
+  </layout>
+ </widget>
+ <resources>
+  <include location="res/icons.qrc"/>
+ </resources>
+ <connections>
+  <connection>
+   <sender>buttonOk</sender>
+   <signal>clicked()</signal>
+   <receiver>CAboutDlgBase</receiver>
+   <slot>accept()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>20</x>
+     <y>20</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>20</x>
+     <y>20</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+</ui>
diff --git a/src/GUI-QT/AnalogDemDlg.cpp b/src/GUI-QT/AnalogDemDlg.cpp
new file mode 100644
index 0000000..55a8444
--- /dev/null
+++ b/src/GUI-QT/AnalogDemDlg.cpp
@@ -0,0 +1,1138 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer, Andrew Murphy
+ *
+ * Description:
+ *
+ * 11/21/2005 Andrew Murphy, BBC Research & Development, 2005
+ *	- Additional widgets for displaying AMSS information
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "AnalogDemDlg.h"
+#include "DRMPlot.h"
+#include <QMessageBox>
+#include <QMenuBar>
+#include <QString>
+#include <QLabel>
+#include <QRadioButton>
+#include <QCheckBox>
+#include <QToolTip>
+#include <QButtonGroup>
+#include <QPushButton>
+#include <QCheckBox>
+#include <QFileDialog>
+#include <QSlider>
+#include <QLayout>
+#include <QProgressBar>
+#include <QComboBox>
+#include <QWhatsThis>
+#include <QDateTime>
+#include <QCloseEvent>
+#include <QInputDialog>
+#include <qwt_dial.h>
+#include <qwt_dial_needle.h>
+#include <qwt_plot_layout.h>
+#if QWT_VERSION >= 0x060100
+# include <qwt_round_scale_draw.h>
+#endif
+#include "receivercontroller.h"
+#include "ThemeCustomizer.h"
+
+/* Implementation *************************************************************/
+AnalogDemDlg::AnalogDemDlg(ReceiverController* rc, CSettings& Settings,
+	CFileMenu* pFileMenu, CSoundCardSelMenu* pSoundCardMenu, QWidget* parent) :
+	CWindow(parent, Settings, "AM"),
+    controller(rc),
+    AMSSDlg(*rc->getReceiver(), Settings, this), MainPlot(NULL),
+	pFileMenu(pFileMenu), pSoundCardMenu(pSoundCardMenu)
+{
+	setupUi(this);
+
+	/* Set help text for the controls */
+	AddWhatsThisHelp();
+
+	/* Add file and sound card menu */
+	menuBar()->insertMenu(menu_View->menuAction(), pFileMenu);
+	menu_Settings->addMenu(pSoundCardMenu);
+
+	connect(action_Stations_Dialog, SIGNAL(triggered()), this, SIGNAL(ViewStationsDlg()));
+	connect(action_Live_Schedule_Dialog, SIGNAL(triggered()), this, SIGNAL(ViewLiveScheduleDlg()));
+	connect(actionExit, SIGNAL(triggered()), this, SLOT(close()));
+	connect(actionAM, SIGNAL(triggered()), this, SIGNAL(NewAMAcquisition()));
+	connect(actionFM, SIGNAL(triggered()), this, SLOT(OnSwitchToFM()));
+	connect(actionDRM, SIGNAL(triggered()), this, SLOT(OnSwitchToDRM()));
+	connect(pFileMenu, SIGNAL(soundFileChanged(CDRMReceiver::ESFStatus)), this, SLOT(OnSoundFileChanged(CDRMReceiver::ESFStatus)));
+	connect(pSoundCardMenu, SIGNAL(sampleRateChanged()), this, SLOT(OnSampleRateChanged()));
+	connect(actionAbout_Dream, SIGNAL(triggered()), this, SLOT(OnHelpAbout()));
+	connect(actionWhats_This, SIGNAL(triggered()), this, SLOT(OnWhatsThis()));
+	SliderBandwidth->setTickPosition(QSlider::TicksBothSides);
+    MainPlot = new CDRMPlot(NULL, plot, controller);
+
+	/* Init main plot */
+	bool waterfall = getSetting("waterfall", false);
+	ButtonWaterfall->setChecked(waterfall);
+	MainPlot->SetupChart(waterfall ? CDRMPlot::INP_SPEC_WATERF : CDRMPlot::INPUT_SIG_PSD_ANALOG);
+
+	/* Add tool tip to show the user the possibility of choosing the AM IF */
+	QString ptt = tr("Click on the plot to set the demodulation frequency");
+	MainPlot->plot->setToolTip(ptt);
+
+	/* Init bandwidth slider */
+	UpdateSliderBandwidth();
+	SliderBandwidth->setTickPosition(QSlider::TicksBothSides);
+	SliderBandwidth->setTickInterval(1000); /* Each kHz a tick */
+	SliderBandwidth->setPageStep(1000); /* Hz */
+
+	/* Init PLL phase dial control */
+	PhaseDial->setMode(QwtDial::RotateNeedle);
+	PhaseDial->setWrapping(true);
+	PhaseDial->setReadOnly(true);
+#if QWT_VERSION < 0x060100
+	PhaseDial->setScale(0, 360, 45); /* Degrees */
+#else
+	PhaseDial->setScale(0, 360); /* Degrees */
+	PhaseDial->setScaleStepSize(45);
+#endif
+	PhaseDial->setOrigin(270);
+	PhaseDial->setNeedle(new QwtDialSimpleNeedle(QwtDialSimpleNeedle::Arrow));
+	PhaseDial->setFrameShadow(QwtDial::Plain);
+#if QWT_VERSION < 0x060000
+	PhaseDial->setScaleOptions(QwtDial::ScaleTicks);
+#elif QWT_VERSION < 0x060100
+	PhaseDial->setScaleComponents(QwtAbstractScaleDraw::Ticks);
+#else
+	PhaseDial->setFrameShadow(QwtDial::Sunken);
+	PhaseDial->setScaleMaxMinor(0);
+	PhaseDial->scaleDraw()->enableComponent(QwtAbstractScaleDraw::Labels, false);
+#endif
+
+#ifdef HAVE_SPEEX
+    SpinBoxNoiRedLevel->setValue(controller->getReceiver()->GetAMDemod()->GetNoiRedLevel());
+#else
+	RadioButtonNoiRedSpeex->hide();
+	SpinBoxNoiRedLevel->hide();
+#endif
+
+	/* Update controls */
+	UpdateControls();
+
+	/* Connect controls ----------------------------------------------------- */
+	connect(ButtonDRM, SIGNAL(clicked()),
+		this, SLOT(OnSwitchToDRM()));
+	connect(ButtonAMSS, SIGNAL(clicked()),
+		&AMSSDlg, SLOT(show()));
+	connect(MainPlot, SIGNAL(xAxisValSet(double)),
+		this, SLOT(OnChartxAxisValSet(double)));
+
+	/* Timers */
+	connect(&Timer, SIGNAL(timeout()),
+		this, SLOT(OnTimer()));
+	connect(&TimerPLLPhaseDial, SIGNAL(timeout()),
+		this, SLOT(OnTimerPLLPhaseDial()));
+	connect(&TimerClose, SIGNAL(timeout()),
+		this, SLOT(OnTimerClose()));
+
+	/* Don't activate real-time timers, wait for show event */
+
+    APPLY_CUSTOM_THEME();
+}
+
+void AnalogDemDlg::OnWhatsThis()
+{
+	QWhatsThis::enterWhatsThisMode();
+}
+
+void AnalogDemDlg::OnSwitchToDRM()
+{
+	emit SwitchMode(RM_DRM);
+}
+
+void AnalogDemDlg::OnSwitchToFM()
+{
+	emit SwitchMode(RM_FM);
+}
+
+void AnalogDemDlg::eventUpdate()
+{
+	/* Put (re)initialization code here for the settings that might have
+	   be changed by another top level window. Called on mode switch */
+	pFileMenu->UpdateMenu();
+	UpdateSliderBandwidth();
+}
+
+void AnalogDemDlg::eventShow(QShowEvent*)
+{
+	OnTimer();
+	OnTimerPLLPhaseDial();
+	/* Set correct schedule */
+
+	/* Activate real-time timers */
+	Timer.start(GUI_CONTROL_UPDATE_TIME);
+	TimerPLLPhaseDial.start(PLL_PHASE_DIAL_UPDATE_TIME);
+
+	UpdateControls();
+
+    /* Notify the MainPlot of showEvent */
+    MainPlot->activate();
+}
+
+void AnalogDemDlg::eventHide(QHideEvent*)
+{
+    /* Notify the MainPlot of hideEvent */
+    MainPlot->deactivate();
+
+	/* stop real-time timers */
+	Timer.stop();
+	TimerPLLPhaseDial.stop();
+
+	bool waterfall = ButtonWaterfall->isChecked();
+	putSetting("waterfall", waterfall);
+}
+
+void AnalogDemDlg::eventClose(QCloseEvent* ce)
+{
+	if (!TimerClose.isActive())
+	{
+		/* Stop real-time timers */
+		Timer.stop();
+		TimerPLLPhaseDial.stop();
+
+		/* Tell every other window to close too */
+		emit Closed();
+
+		/* Set the timer for polling the working thread state */
+		TimerClose.start(50);
+	}
+
+	/* Stay open until working thread is done */
+    if (controller->getReceiver()->GetParameters()->eRunState == CParameter::STOPPED)
+	{
+        TimerClose.stop();
+		ce->accept();
+	}
+	else
+		ce->ignore();
+}
+
+void AnalogDemDlg::UpdateControls()
+{
+	/* Set demodulation type */
+    switch (controller->getReceiver()->GetAMDemod()->GetDemodType())
+	{
+	case CAMDemodulation::DT_AM:
+		if (!RadioButtonDemAM->isChecked())
+			RadioButtonDemAM->setChecked(TRUE);
+		break;
+
+	case CAMDemodulation::DT_LSB:
+		if (!RadioButtonDemLSB->isChecked())
+			RadioButtonDemLSB->setChecked(TRUE);
+		break;
+
+	case CAMDemodulation::DT_USB:
+		if (!RadioButtonDemUSB->isChecked())
+			RadioButtonDemUSB->setChecked(TRUE);
+		break;
+
+	case CAMDemodulation::DT_CW:
+		if (!RadioButtonDemCW->isChecked())
+			RadioButtonDemCW->setChecked(TRUE);
+		break;
+
+	case CAMDemodulation::DT_FM:
+		if (!RadioButtonDemFM->isChecked())
+			RadioButtonDemFM->setChecked(TRUE);
+		break;
+	}
+
+	/* Set AGC type */
+    switch (controller->getReceiver()->GetAMDemod()->GetAGCType())
+	{
+	case CAGC::AT_NO_AGC:
+		if (!RadioButtonAGCOff->isChecked())
+			RadioButtonAGCOff->setChecked(TRUE);
+		break;
+
+	case CAGC::AT_SLOW:
+		if (!RadioButtonAGCSlow->isChecked())
+			RadioButtonAGCSlow->setChecked(TRUE);
+		break;
+
+	case CAGC::AT_MEDIUM:
+		if (!RadioButtonAGCMed->isChecked())
+			RadioButtonAGCMed->setChecked(TRUE);
+		break;
+
+	case CAGC::AT_FAST:
+		if (!RadioButtonAGCFast->isChecked())
+			RadioButtonAGCFast->setChecked(TRUE);
+		break;
+	}
+
+	/* Set noise reduction type */
+    switch (controller->getReceiver()->GetAMDemod()->GetNoiRedType())
+	{
+	case CAMDemodulation::NR_OFF:
+		if (!RadioButtonNoiRedOff->isChecked())
+			RadioButtonNoiRedOff->setChecked(TRUE);
+		break;
+
+	case CAMDemodulation::NR_LOW:
+		if (!RadioButtonNoiRedLow->isChecked())
+			RadioButtonNoiRedLow->setChecked(TRUE);
+		break;
+
+	case CAMDemodulation::NR_MEDIUM:
+		if (!RadioButtonNoiRedMed->isChecked())
+			RadioButtonNoiRedMed->setChecked(TRUE);
+		break;
+
+	case CAMDemodulation::NR_HIGH:
+		if (!RadioButtonNoiRedHigh->isChecked())
+			RadioButtonNoiRedHigh->setChecked(TRUE);
+		break;
+
+	case CAMDemodulation::NR_SPEEX:
+		if (!RadioButtonNoiRedSpeex->isChecked())
+			RadioButtonNoiRedSpeex->setChecked(TRUE);
+		break;
+	}
+
+#ifdef HAVE_SPEEX
+	/* Set speex spinbox enable state */
+	SpinBoxNoiRedLevel->setEnabled(RadioButtonNoiRedSpeex->isChecked());
+#endif
+
+	/* Set filter bandwidth */
+    SliderBandwidth->setValue(controller->getReceiver()->GetAMDemod()->GetFilterBW());
+	ButtonBandWidth->setText(QString().setNum(
+        controller->getReceiver()->GetAMDemod()->GetFilterBW()) +	tr(" Hz"));
+
+	/* Update check boxes */
+    CheckBoxMuteAudio->setChecked(controller->getReceiver()->GetWriteData()->GetMuteAudio());
+	CheckBoxSaveAudioWave->
+        setChecked(controller->getReceiver()->GetWriteData()->GetIsWriteWaveFile());
+
+	CheckBoxAutoFreqAcq->
+        setChecked(controller->getReceiver()->GetAMDemod()->AutoFreqAcqEnabled());
+
+    CheckBoxPLL->setChecked(controller->getReceiver()->GetAMDemod()->PLLEnabled());
+}
+
+void AnalogDemDlg::UpdateSliderBandwidth()
+{
+    SliderBandwidth->setRange(0, controller->getReceiver()->GetParameters()->GetSigSampleRate() / 2);
+}
+
+void AnalogDemDlg::UpdatePlotStyle(int iPlotstyle)
+{
+	/* Update main plot window */
+	MainPlot->SetPlotStyle(iPlotstyle);
+}
+
+void AnalogDemDlg::OnSampleRateChanged()
+{
+	UpdateSliderBandwidth();
+}
+
+void AnalogDemDlg::OnSoundFileChanged(CDRMReceiver::ESFStatus)
+{
+	UpdateSliderBandwidth();
+}
+
+void AnalogDemDlg::OnTimer()
+{
+    switch(controller->getReceiver()->GetReceiverMode())
+	{
+	case RM_AM:
+		/* Carrier frequency of AM signal */
+		ButtonFreqOffset->setText(QString().setNum(
+            controller->getReceiver()->GetReceiveData()->ConvertFrequency(
+                controller->getReceiver()->GetAMDemod()->GetCurMixFreqOffs())
+			, 'f', 2) + " Hz");
+		break;
+	case RM_DRM:
+	case RM_FM:
+	case RM_NONE:
+		break;
+	}
+}
+
+void AnalogDemDlg::OnTimerPLLPhaseDial()
+{
+	CReal rCurPLLPhase;
+
+    if (controller->getReceiver()->GetAMDemod()->GetPLLPhase(rCurPLLPhase) == TRUE)
+	{
+		/* Set current PLL phase (convert radiant in degree) */
+		PhaseDial->setValue(rCurPLLPhase * (CReal) 360.0 / (2 * crPi));
+
+		/* Check if control is enabled */
+		if (!PhaseDial->isEnabled())
+			PhaseDial->setEnabled(true);
+	}
+	else
+	{
+		/* Reset dial */
+		PhaseDial->setValue((CReal) 0.0);
+
+		/* Check if control is disabled */
+		if (PhaseDial->isEnabled())
+			PhaseDial->setEnabled(false);
+	}
+}
+
+void AnalogDemDlg::OnTimerClose()
+{
+    if(controller->getReceiver()->GetParameters()->eRunState == CParameter::STOPPED)
+		close();
+}
+
+void AnalogDemDlg::on_ButtonGroupDemodulation_buttonClicked(int iID)
+{
+	iID = -iID - 2; // TODO understand why
+	/* DRMReceiver takes care of setting appropriate filter BW */
+	switch (iID)
+	{
+	case 0:
+        controller->getReceiver()->SetAMDemodType(CAMDemodulation::DT_AM);
+		break;
+
+	case 1:
+        controller->getReceiver()->SetAMDemodType(CAMDemodulation::DT_LSB);
+		break;
+
+	case 2:
+        controller->getReceiver()->SetAMDemodType(CAMDemodulation::DT_USB);
+		break;
+
+	case 3:
+        controller->getReceiver()->SetAMDemodType(CAMDemodulation::DT_CW);
+		break;
+
+	case 4:
+        controller->getReceiver()->SetAMDemodType(CAMDemodulation::DT_FM);
+		break;
+	}
+
+	/* Update controls */
+	UpdateControls();
+}
+
+void AnalogDemDlg::on_ButtonGroupAGC_buttonClicked(int iID)
+{
+	iID = -iID - 2; // TODO understand why
+	switch (iID)
+	{
+	case 0:
+        controller->getReceiver()->GetAMDemod()->SetAGCType(CAGC::AT_NO_AGC);
+		break;
+
+	case 1:
+        controller->getReceiver()->GetAMDemod()->SetAGCType(CAGC::AT_SLOW);
+		break;
+
+	case 2:
+        controller->getReceiver()->GetAMDemod()->SetAGCType(CAGC::AT_MEDIUM);
+		break;
+
+	case 3:
+        controller->getReceiver()->GetAMDemod()->SetAGCType(CAGC::AT_FAST);
+		break;
+	}
+}
+
+void AnalogDemDlg::on_ButtonGroupNoiseReduction_buttonClicked(int iID)
+{
+	iID = -iID - 2; // TODO understand why
+	switch (iID)
+	{
+	case 0:
+        controller->getReceiver()->GetAMDemod()->SetNoiRedType(CAMDemodulation::NR_OFF);
+		break;
+
+	case 1:
+        controller->getReceiver()->GetAMDemod()->SetNoiRedType(CAMDemodulation::NR_LOW);
+		break;
+
+	case 2:
+        controller->getReceiver()->GetAMDemod()->SetNoiRedType(CAMDemodulation::NR_MEDIUM);
+		break;
+
+	case 3:
+        controller->getReceiver()->GetAMDemod()->SetNoiRedType(CAMDemodulation::NR_HIGH);
+		break;
+
+#ifdef HAVE_SPEEX
+	case 4:
+        controller->getReceiver()->GetAMDemod()->SetNoiRedType(CAMDemodulation::NR_SPEEX);
+		break;
+#endif
+	}
+
+#ifdef HAVE_SPEEX
+	/* Set speex spinbox enable state */
+	SpinBoxNoiRedLevel->setEnabled(RadioButtonNoiRedSpeex->isChecked());
+#endif
+}
+
+void AnalogDemDlg::on_SliderBandwidth_valueChanged(int value)
+{
+	/* Set new filter in processing module */
+    controller->getReceiver()->SetAMFilterBW(value);
+	ButtonBandWidth->setText(QString().setNum(value) + tr(" Hz"));
+
+	/* Update chart */
+	MainPlot->UpdateAnalogBWMarker();
+}
+
+void AnalogDemDlg::on_CheckBoxAutoFreqAcq_clicked(bool checked)
+{
+	/* Set parameter in working thread module */
+    controller->getReceiver()->GetAMDemod()->EnableAutoFreqAcq(checked);
+}
+
+void AnalogDemDlg::on_CheckBoxPLL_clicked(bool checked)
+{
+	/* Set parameter in working thread module */
+    controller->getReceiver()->GetAMDemod()->EnablePLL(checked);
+}
+
+void AnalogDemDlg::on_CheckBoxMuteAudio_clicked(bool checked)
+{
+	/* Set parameter in working thread module */
+    controller->getReceiver()->GetWriteData()->MuteAudio(checked);
+}
+
+void AnalogDemDlg::on_CheckBoxSaveAudioWave_clicked(bool checked)
+{
+/*
+	This code is copied in systemevalDlg.cpp. If you do changes here, you should
+	apply the changes in the other file, too
+*/
+	if (checked)
+	{
+		/* Show "save file" dialog */
+		QString strFileName =
+			QFileDialog::getSaveFileName(this, tr("Save Audio"), "DreamOut.wav", tr("Wav (*.wav)"));
+		/* Check if user not hit the cancel button */
+		if (!strFileName.isEmpty())
+		{
+            controller->getReceiver()->GetWriteData()->
+				StartWriteWaveFile(strFileName.toLocal8Bit().constData());
+		}
+		else
+		{
+			/* User hit the cancel button, uncheck the button */
+			CheckBoxSaveAudioWave->setChecked(false);
+		}
+	}
+	else
+        controller->getReceiver()->GetWriteData()->StopWriteWaveFile();
+}
+
+void AnalogDemDlg::OnChartxAxisValSet(double dVal)
+{
+	/* Perform range check */
+	if (dVal < 0.0)
+		dVal = 0.0;
+	else if (dVal > 1.0)
+		dVal = 1.0;
+
+	/* Set new frequency in receiver module */
+    controller->getReceiver()->SetAMDemodAcq(dVal);
+
+	/* Update chart */
+	MainPlot->UpdateAnalogBWMarker();
+}
+
+void AnalogDemDlg::on_ButtonWaterfall_clicked(bool checked)
+{
+	/* Toggle between normal spectrum plot and waterfall spectrum plot */
+	if (checked)
+		MainPlot->SetupChart(CDRMPlot::INP_SPEC_WATERF);
+	else
+		MainPlot->SetupChart(CDRMPlot::INPUT_SIG_PSD_ANALOG);
+}
+
+/* Manual carrier frequency input box */
+void AnalogDemDlg::on_ButtonFreqOffset_clicked(bool)
+{
+	bool ok = false;
+	const double prev_freq =
+		controller->getReceiver()->GetReceiveData()->ConvertFrequency(
+			controller->getReceiver()->GetAMDemod()->GetCurMixFreqOffs());
+	const double new_freq = QInputDialog::getDouble(this, this->windowTitle(),
+		LabelCarrierFrequency->text(), prev_freq, -1e6, 1e6, 2, &ok);
+	if (ok)
+	{
+		const _REAL conv_freq =
+			controller->getReceiver()->GetReceiveData()->ConvertFrequency(new_freq, TRUE);
+		const double dVal = conv_freq /
+			(controller->getReceiver()->GetParameters()->GetSigSampleRate() / 2);
+		OnChartxAxisValSet(dVal);
+	}
+}
+
+/* Manual band width input box */
+void AnalogDemDlg::on_ButtonBandWidth_clicked(bool)
+{
+	bool ok = false;
+	const int sr2 = controller->getReceiver()->GetParameters()->GetSigSampleRate() / 2;
+	const int prev_bw = controller->getReceiver()->GetAMDemod()->GetFilterBW();
+	const int new_bw = QInputDialog::getInt(this, this->windowTitle(),
+		groupBoxBW->title(), prev_bw, 0, sr2, 2, &ok);
+	if (ok)
+	{
+		controller->getReceiver()->GetAMDemod()->SetFilterBW(new_bw);
+		SliderBandwidth->setValue(controller->getReceiver()->GetAMDemod()->GetFilterBW());
+	}
+}
+
+void AnalogDemDlg::on_SpinBoxNoiRedLevel_valueChanged(int value)
+{
+    controller->getReceiver()->GetAMDemod()->SetNoiRedLevel(value);
+}
+
+void AnalogDemDlg::AddWhatsThisHelp()
+{
+	/* Noise Reduction */
+	const QString strNoiseReduction =
+		tr("<b>Noise Reduction:</b> The noise suppression is a frequency "
+		"domain optimal filter design based algorithm. The noise PSD is "
+		"estimated utilizing a minimum statistic. A problem of this type of "
+		"algorithm is that it produces the so called \"musical tones\". The "
+		"noise becomes coloured and sounds a bit strange. At the same time, "
+		"the useful signal (which might be speech or music) is also "
+		"distorted by the algorithm. By selecting the level of noise "
+		"reduction, a compromise between distortion of the useful signal "
+		"and actual noise reduction can be made.");
+
+	/* Automatic Gain Control */
+	const QString strAGC =
+		tr("<b>AGC (Automatic Gain Control):</b> Input signals can have a "
+		"large variation in power due to channel impairments. To compensate "
+		"for that, an automatic gain control can be applied. The AGC has "
+		"four settings: Off, Slow, Medium and Fast.");
+
+	/* Filter Bandwidth */
+	const QString strFilterBW =
+		tr("<b>Filter Bandwidth:</b> A band-pass filter is applied before "
+		"the actual demodulation process. With this filter, adjacent signals "
+		"are attenuated. The bandwidth of this filter can be chosen in steps "
+		"of 1 Hz by using the slider bar. Clicking on the right or left side "
+		"of the slider leveler will increase/decrease the bandwidth by 1 kHz. "
+		"<br>The current filter bandwidth is indicated in the spectrum plot "
+		"by a selection bar.");
+
+	/* Demodulation type */
+	const QString strDemodType =
+		tr("<b>Demodulation Type:</b> The following analog "
+		"demodulation types are available:<ul>"
+		"<li><b>AM:</b> This analog demodulation type is used in most of "
+		"the hardware radios. The envelope of the complex base-band signal "
+		"is used followed by a high-pass filter to remove the DC offset. "
+		"Additionally, a low pass filter with the same bandwidth as the "
+		"pass-band filter is applied to reduce the noise caused by "
+		"non-linear distortions.</li>"
+		"<li><b>LSB / USB:</b> These are single-side-band (SSB) demodulation "
+		"types. Only one side of the spectrum is evaluated, the upper side "
+		"band is used in USB and the lower side band with LSB. It is "
+		"important for SSB demodulation that the DC frequency of the analog "
+		"signal is known to get satisfactory results. The DC frequency is "
+		"automatically estimated by starting a new acquisition or by "
+		"clicking on the plot.</li>"
+		"<li><b>CW:</b> This demodulation type can be used to receive "
+		"CW signals. Only a narrow frequency band in a fixed distance "
+		"to the mixing frequency is used. By clicking on the spectrum "
+		"plot, the center position of the band pass filter can be set.</li>"
+		"<li><b>FM:</b> This is a narrow band frequency demodulation.</li>"
+		"</ul>");
+
+	/* Mute Audio (same as in systemevaldlg.cpp!) */
+	QString strCheckBoxMuteAudio =
+		tr("<b>Mute Audio:</b> The audio can be muted by "
+		"checking this box. The reaction of checking or unchecking this box "
+		"is delayed by approx. 1 second due to the audio buffers.");
+
+	/* Save audio as wave (same as in systemevaldlg.cpp!) */
+	QString strCheckBoxSaveAudioWave =
+		tr("<b>Save Audio as WAV:</b> Save the audio signal "
+		"as stereo, 16-bit, 48 kHz sample rate PCM wave file. Checking this "
+		"box will let the user choose a file name for the recording.");
+
+	/* Carrier Frequency */
+	QString strTextFreqOffset =
+		tr("<b>Carrier Frequency:</b> The (estimated) carrier frequency of the "
+		"analog signal is shown. (The estimation of this parameter can be done "
+		"by the Autom Frequency Acquisition which uses the estimated PSD of "
+		"the input signal and applies a maximum search.)");
+
+	/* Phase lock loop */
+	const QString strPLL =
+		tr("<b>PLL:</b> The Phase-Lock-Loop (PLL) tracks the carrier of the "
+		"modulated received signal. The resulting phase offset between the "
+		"reference oscillator and the received carrier is displayed in "
+		"a dial control. If the pointer is almost steady, the PLL is locked. "
+		"If the pointer of the dial control turns quickly, the PLL is "
+		"out of lock. To get the PLL locked, the frequency offset to "
+		"the true carrier frequency must not exceed a few Hz.");
+
+	/* Auto frequency acquisition */
+	const QString strAutoFreqAcqu =
+		tr("<b>Auto Frequency Acquisition:</b> Clicking on the "
+		"input spectrum plot changes the mixing frequency for demodulation. "
+		"If the Auto Frequency Acquisition is enabled, the largest peak "
+		"near the curser is selected.");
+
+    RadioButtonNoiRedOff->setWhatsThis(strNoiseReduction);
+    RadioButtonNoiRedLow->setWhatsThis(strNoiseReduction);
+    RadioButtonNoiRedMed->setWhatsThis(strNoiseReduction);
+    RadioButtonNoiRedHigh->setWhatsThis(strNoiseReduction);
+    RadioButtonAGCOff->setWhatsThis(strAGC);
+    RadioButtonAGCSlow->setWhatsThis(strAGC);
+    RadioButtonAGCMed->setWhatsThis(strAGC);
+    RadioButtonAGCFast->setWhatsThis(strAGC);
+    ButtonBandWidth->setWhatsThis(strFilterBW);
+    SliderBandwidth->setWhatsThis(strFilterBW);
+    RadioButtonDemAM->setWhatsThis(strDemodType);
+    RadioButtonDemLSB->setWhatsThis(strDemodType);
+    RadioButtonDemUSB->setWhatsThis(strDemodType);
+    RadioButtonDemCW->setWhatsThis(strDemodType);
+    RadioButtonDemFM->setWhatsThis(strDemodType);
+    GroupBoxAutoFreqAcq->setWhatsThis(strAutoFreqAcqu);
+    CheckBoxAutoFreqAcq->setWhatsThis(strAutoFreqAcqu);
+    CheckBoxMuteAudio->setWhatsThis(strCheckBoxMuteAudio);
+    GroupBoxPLL->setWhatsThis(strPLL);
+    CheckBoxPLL->setWhatsThis(strPLL);
+    PhaseDial->setWhatsThis(strPLL);
+    TextLabelPhaseOffset->setWhatsThis(strPLL);
+    ButtonFreqOffset->setWhatsThis(strTextFreqOffset);
+    ButtonFreqOffset->setWhatsThis(strTextFreqOffset);
+    CheckBoxSaveAudioWave->setWhatsThis(strCheckBoxSaveAudioWave);
+    groupBoxNoiseReduction->setWhatsThis(strNoiseReduction);
+    groupBoxAGC->setWhatsThis(strAGC);
+    groupBoxDemodulation->setWhatsThis(strDemodType);
+    groupBoxBW->setWhatsThis(strFilterBW);
+}
+
+
+/******************************************************************************\
+* AMSS controls                                                                *
+\******************************************************************************/
+/*
+	Added by Andrew Murphy, BBC Research & Development, 2005
+
+	Additional widgets have been added to display the AMSS service label,
+	language etc. in in a similar style to that used for DRM reception.
+	A display has also been added to show the status of the AMSS decoding.
+	Everytime an AMSS CRC passes (for block or block 2) the 47 decoded
+	bits are displayed. Note this could also include 'false' passes.
+
+	The percentage of the current data entity group or 'SDC' is displayed
+	along with which parts of the data entity group have been decoded. A
+	'#' indicates that a data entity gruop segment is yet to be received
+	whilst a 'c' or 'C' indicates a CRC pass for the block 2 carrying that
+	particular segment.
+
+	Added phase offset display for AMSS demodulation loop.
+*/
+CAMSSDlg::CAMSSDlg(CDRMReceiver& NDRMR, CSettings& Settings, QWidget* parent) :
+	CWindow(parent, Settings, "AMSS"),
+	DRMReceiver(NDRMR)
+{
+	setupUi(this);
+
+#if QWT_VERSION >= 0x060100
+	/* Workaround for PhaseDialAMSS receiving focus 
+	even if its FocusPolicy is set to Qt::NoFocus,
+	might not be needed in final release of Qwt 6.1.0 */
+	setFocusPolicy(Qt::StrongFocus);
+	setFocus();
+#endif
+
+	/* Set help text for the controls */
+	AddWhatsThisHelp();
+
+	/* Init AMSS PLL phase dial control */
+	PhaseDialAMSS->setMode(QwtDial::RotateNeedle);
+	PhaseDialAMSS->setWrapping(true);
+	PhaseDialAMSS->setReadOnly(true);
+#if QWT_VERSION < 0x060100
+	PhaseDialAMSS->setScale(0, 360, 45); /* Degrees */
+#else
+	PhaseDialAMSS->setScale(0, 360); /* Degrees */
+	PhaseDialAMSS->setScaleStepSize(45);
+#endif
+	PhaseDialAMSS->setOrigin(270);
+	PhaseDialAMSS->setNeedle(new QwtDialSimpleNeedle(QwtDialSimpleNeedle::Arrow));
+	PhaseDialAMSS->setFrameShadow(QwtDial::Plain);
+#if QWT_VERSION < 0x060000
+	PhaseDialAMSS->setScaleOptions(QwtDial::ScaleTicks);
+#elif QWT_VERSION < 0x060100
+	PhaseDialAMSS->setScaleComponents(QwtAbstractScaleDraw::Ticks);
+#else
+	PhaseDialAMSS->setFrameShadow(QwtDial::Sunken);
+	PhaseDialAMSS->setScaleMaxMinor(0);
+	PhaseDialAMSS->scaleDraw()->enableComponent(QwtAbstractScaleDraw::Labels, false);
+#endif
+
+	TextAMSSServiceLabel->setText("");
+	TextAMSSCountryCode->setText("");
+	TextAMSSTimeDate->setText("");
+	TextAMSSLanguage->setText("");
+	TextAMSSServiceID->setText("");
+	TextAMSSAMCarrierMode->setText("");
+	TextAMSSInfo->setText("");
+
+	ListBoxAMSSAFSList->setEnabled(FALSE);
+
+
+	/* Connect controls ----------------------------------------------------- */
+	/* Timers */
+	connect(&Timer, SIGNAL(timeout()),
+		this, SLOT(OnTimer()));
+	connect(&TimerPLLPhaseDial, SIGNAL(timeout()),
+		this, SLOT(OnTimerPLLPhaseDial()));
+	/* Buttons */
+	connect(buttonOk, SIGNAL(clicked()), this, SLOT(close()));
+
+    APPLY_CUSTOM_THEME();
+}
+
+void CAMSSDlg::eventHide(QHideEvent*)
+{
+	/* stop real-time timers */
+	Timer.stop();
+	TimerPLLPhaseDial.stop();
+}
+
+void CAMSSDlg::eventShow(QShowEvent*)
+{
+	OnTimer();
+	OnTimerPLLPhaseDial();
+
+	/* Activate real-time timers */
+	Timer.start(GUI_CONTROL_UPDATE_TIME);
+	TimerPLLPhaseDial.start(PLL_PHASE_DIAL_UPDATE_TIME);
+}
+
+void CAMSSDlg::OnTimer()
+{
+	int j;
+
+    CParameter& Parameters = *DRMReceiver.GetParameters();
+	Parameters.Lock();
+
+	/* Show label if available */
+	if ((Parameters.Service[0].IsActive()) && (Parameters.Service[0].strLabel != ""))
+	{
+		/* Service label (UTF-8 encoded string -> convert) */
+		TextAMSSServiceLabel->setText(QString().fromUtf8(
+			Parameters.Service[0].strLabel.c_str()
+		));
+	}
+	else
+		TextAMSSServiceLabel->setText(tr(""));
+
+	/* Country code */
+	const string strCntryCode = Parameters.Service[0].strCountryCode; /* must be of 2 lowercase chars */
+
+	if ((Parameters.Service[0].IsActive()) && (!strCntryCode.empty()) && (strCntryCode != "--"))
+	{
+		TextAMSSCountryCode->
+			setText(QString(GetISOCountryName(strCntryCode).c_str()));
+	}
+	else
+		TextAMSSCountryCode->setText("");
+
+	/* SDC Language code */
+
+	if (Parameters.Service[0].IsActive())
+	{
+		const string strLangCode = Parameters.Service[0].strLanguageCode; /* must be of 3 lowercase chars */
+
+		if ((!strLangCode.empty()) && (strLangCode != "---"))
+			 TextAMSSLanguage->
+				setText(QString(GetISOLanguageName(strLangCode).c_str()));
+		else
+			TextAMSSLanguage->setText(QString(strTableLanguageCode[Parameters.Service[0].iLanguage].c_str()));
+	}
+	else
+		TextAMSSLanguage->setText("");
+
+	/* Time, date */
+	if ((Parameters.iUTCHour == 0) &&
+		(Parameters.iUTCMin == 0) &&
+		(Parameters.iDay == 0) &&
+		(Parameters.iMonth == 0) &&
+		(Parameters.iYear == 0))
+	{
+		/* No time service available */
+		TextAMSSTimeDate->setText("");
+	}
+	else
+	{
+		QDateTime DateTime;
+		DateTime.setDate(QDate(Parameters.iYear, Parameters.iMonth, Parameters.iDay));
+		DateTime.setTime(QTime(Parameters.iUTCHour, Parameters.iUTCMin));
+
+		TextAMSSTimeDate->setText(DateTime.toString());
+	}
+
+	/* Get number of alternative services */
+	const size_t iNumAltServices = Parameters.AltFreqSign.vecOtherServices.size();
+
+	if (iNumAltServices != 0)
+	{
+		QString val = QString().setNum((long) iNumAltServices);
+		ListBoxAMSSAFSList->insertItem(10, val);
+
+		ListBoxAMSSAFSList->clear();
+		ListBoxAMSSAFSList->setEnabled(TRUE);
+
+		QString freqEntry;
+
+		for (size_t i = 0; i < iNumAltServices; i++)
+		{
+			switch (Parameters.AltFreqSign.vecOtherServices[i].iSystemID)
+			{
+			case 0:
+				freqEntry = "DRM:";
+				break;
+
+			case 1:
+			case 2:
+				freqEntry = "AM:   ";
+				break;
+
+			case 3:
+			case 4:
+			case 5:
+			case 6:
+			case 7:
+			case 8:
+				freqEntry = "FM:   ";
+				break;
+
+			default:
+				freqEntry = "";
+				break;
+			}
+
+			const int iNumAltFreqs = Parameters.AltFreqSign.vecOtherServices[i].veciFrequencies.size();
+
+			const int iSystemID = Parameters.AltFreqSign.vecOtherServices[i].iSystemID;
+
+			switch (iSystemID)
+			{
+			case 0:
+			case 1:
+			case 2:
+				/* AM or DRM, freq in kHz */
+				for (j = 0; j < iNumAltFreqs; j++)
+				{
+					freqEntry +=
+						QString().setNum((long) Parameters.
+						AltFreqSign.vecOtherServices[i].
+						veciFrequencies[j], 10);
+
+					if (j != iNumAltFreqs-1)
+						freqEntry += ",";
+				}
+				freqEntry += " kHz";
+
+
+				if (iSystemID == 0 || iSystemID == 1)
+				{
+					freqEntry += " ID:";
+					freqEntry +=
+						QString().setNum((long) Parameters.
+						AltFreqSign.vecOtherServices[i].
+						iServiceID, 16).toUpper();
+				}
+				break;
+
+			case 3:
+			case 4:
+			case 5:
+				/* 'FM1 frequency' - 87.5 to 107.9 MHz (100 kHz steps) */
+				for (j = 0; j < iNumAltFreqs; j++)
+				{
+					freqEntry +=
+                        QString().setNum((float) (87.5 + 0.1 * DRMReceiver.
+						GetParameters()->AltFreqSign.
+						vecOtherServices[i].veciFrequencies[j]), 'f', 1);
+
+					if (j != iNumAltFreqs-1)
+						freqEntry += ",";
+				}
+				freqEntry += " MHz";
+
+				if (iSystemID == 3)
+				{
+					freqEntry += " ECC+PI:";
+					freqEntry +=
+						QString().setNum((long) Parameters.
+						AltFreqSign.vecOtherServices[i].
+						iServiceID, 16).toUpper();
+				}
+
+				if (iSystemID == 4)
+				{
+					freqEntry += " PI:";
+					freqEntry +=
+						QString().setNum((long) Parameters.
+						AltFreqSign.vecOtherServices[i].
+						iServiceID, 16).toUpper();
+				}
+				break;
+
+			case 6:
+			case 7:
+			case 8:
+				/* 'FM2 frequency'- 76.0 to 90.0 MHz (100 kHz steps) */
+				for (j = 0; j < iNumAltFreqs; j++)
+				{
+					freqEntry +=
+                        QString().setNum((float) (76.0 + 0.1 * DRMReceiver.
+						GetParameters()->AltFreqSign.
+						vecOtherServices[i].veciFrequencies[j]), 'f', 1);
+
+					if (j != iNumAltFreqs-1)
+						freqEntry += ",";
+				}
+				freqEntry += " MHz";
+
+				if (iSystemID == 6)
+				{
+					freqEntry += " ECC+PI:";
+					freqEntry +=
+						QString().setNum((long) Parameters.
+						AltFreqSign.vecOtherServices[i].
+						iServiceID, 16).toUpper();
+				}
+
+				if (iSystemID == 7)
+				{
+					freqEntry += " PI:";
+					freqEntry +=
+						QString().setNum((long) Parameters.
+						AltFreqSign.vecOtherServices[i].
+						iServiceID, 16).toUpper();
+				}
+				break;
+
+			default:
+				freqEntry = "DAB";
+				break;
+			}
+
+			if (Parameters.AltFreqSign.
+				vecOtherServices[i].bSameService)
+			{
+				freqEntry += " (same service)";
+			}
+			else
+			{
+				freqEntry += " (alt service)";
+			}
+			ListBoxAMSSAFSList->insertItem(0, freqEntry);
+		}
+	}
+	else
+	{
+		ListBoxAMSSAFSList->clear();
+		ListBoxAMSSAFSList->setEnabled(FALSE);
+	}
+
+	TextAMSSServiceID->setText("");
+	TextAMSSAMCarrierMode->setText("");
+
+    if (DRMReceiver.GetAMSSDecode()->GetLockStatus() == CAMSSDecode::NO_SYNC
+	|| Parameters.Service[0].iServiceID == SERV_ID_NOT_USED
+	)
+	{
+		TextAMSSInfo->setText(tr("No AMSS detected"));
+	}
+	else
+	{
+		TextAMSSInfo->setText(tr("Awaiting AMSS data..."));
+
+		/* Display 'block 1' info */
+        if (DRMReceiver.GetAMSSDecode()->GetBlock1Status())
+		{
+			TextAMSSInfo->setText("");
+
+            TextAMSSLanguage->setText(QString(strTableLanguageCode[DRMReceiver.
+				GetParameters()->Service[0].iLanguage].c_str()));
+
+			TextAMSSServiceID->setText("ID:" + QString().setNum(
+				(long) Parameters.Service[0].iServiceID, 16).toUpper());
+
+            TextAMSSAMCarrierMode->setText(QString(strTableAMSSCarrierMode[DRMReceiver.
+				GetParameters()->iAMSSCarrierMode].c_str()));
+		}
+	}
+
+    TextDataEntityGroupStatus->setText(DRMReceiver.GetAMSSDecode()->
+		GetDataEntityGroupStatus());
+
+    TextCurrentBlock->setText(QString().setNum(DRMReceiver.GetAMSSDecode()->
+		GetCurrentBlock(), 10));
+
+    TextBlockBits->setText(DRMReceiver.GetAMSSDecode()->GetCurrentBlockBits());
+
+    int val = DRMReceiver.GetAMSSDecode()->GetPercentageDataEntityGroupComplete();
+	Parameters.Unlock();
+	ProgressBarAMSS->setValue(val);
+}
+
+void CAMSSDlg::OnTimerPLLPhaseDial()
+{
+	CReal rCurPLLPhase;
+
+    if (DRMReceiver.GetAMSSPhaseDemod()->GetPLLPhase(rCurPLLPhase) == TRUE)
+	{
+		/* Set current PLL phase (convert radiant in degree) */
+		PhaseDialAMSS->setValue(rCurPLLPhase * (CReal) 360.0 / (2 * crPi));
+
+		/* Check if control is enabled */
+		if (!PhaseDialAMSS->isEnabled())
+			PhaseDialAMSS->setEnabled(true);
+	}
+	else
+	{
+		/* Reset dial */
+		PhaseDialAMSS->setValue((CReal) 0.0);
+
+		/* Check if control is disabled */
+		if (PhaseDialAMSS->isEnabled())
+			PhaseDialAMSS->setEnabled(false);
+	}
+}
+
+void CAMSSDlg::AddWhatsThisHelp()
+{
+	// TODO
+}
diff --git a/src/GUI-QT/AnalogDemDlg.h b/src/GUI-QT/AnalogDemDlg.h
new file mode 100644
index 0000000..4a75853
--- /dev/null
+++ b/src/GUI-QT/AnalogDemDlg.h
@@ -0,0 +1,137 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer, Andrew Murphy
+ *
+ * Description:
+ *	See AnalogDemDlg.cpp
+ *
+ * 11/21/2005 Andrew Murphy, BBC Research & Development, 2005
+ *	- Additional widgets for displaying AMSS information
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+
+#include "ui_AMMainWindow.h"
+#include "ui_AMSSDlgbase.h"
+#include "CWindow.h"
+#include "SoundCardSelMenu.h"
+#include "DRMPlot.h"
+#include "../GlobalDefinitions.h"
+#include "../DrmReceiver.h"
+#include "../tables/TableAMSS.h"
+#include <QTimer>
+#include <QDialog>
+#include <QButtonGroup>
+
+
+/* Definitions ****************************************************************/
+/* Update time of PLL phase dial control */
+#define PLL_PHASE_DIAL_UPDATE_TIME				100
+
+
+/* Classes ********************************************************************/
+
+class ReceiverController;
+
+/* AMSS dialog -------------------------------------------------------------- */
+class CAMSSDlg : public CWindow, public Ui_CAMSSDlgBase
+{
+	Q_OBJECT
+
+public:
+	CAMSSDlg(CDRMReceiver&, CSettings&, QWidget* parent = 0);
+
+protected:
+	CDRMReceiver&	DRMReceiver;
+
+	QTimer			Timer;
+	QTimer			TimerPLLPhaseDial;
+	void			AddWhatsThisHelp();
+	virtual void	eventShow(QShowEvent*);
+	virtual void	eventHide(QHideEvent*);
+
+public slots:
+	void OnTimer();
+	void OnTimerPLLPhaseDial();
+};
+
+
+/* Analog demodulation dialog ----------------------------------------------- */
+class AnalogDemDlg : public CWindow, public Ui_AMMainWindow
+{
+	Q_OBJECT
+
+public:
+    AnalogDemDlg(ReceiverController*, CSettings&, CFileMenu*, CSoundCardSelMenu*,
+	QWidget* parent = 0);
+
+protected:
+    ReceiverController* controller;
+	QTimer				Timer;
+	QTimer				TimerPLLPhaseDial;
+	QTimer				TimerClose;
+	CAMSSDlg			AMSSDlg;
+    CDRMPlot*			MainPlot;
+	CFileMenu*			pFileMenu;
+	CSoundCardSelMenu*	pSoundCardMenu;
+
+	void UpdateControls();
+	void UpdateSliderBandwidth();
+	void AddWhatsThisHelp();
+	virtual void eventClose(QCloseEvent* pEvent);
+	virtual void eventShow(QShowEvent* pEvent);
+	virtual void eventHide(QHideEvent* pEvent);
+	virtual void eventUpdate();
+
+public slots:
+	void UpdatePlotStyle(int);
+	void OnSampleRateChanged();
+	void OnSoundFileChanged(CDRMReceiver::ESFStatus);
+	void OnTimer();
+	void OnTimerPLLPhaseDial();
+	void OnTimerClose();
+	void OnChartxAxisValSet(double dVal);
+	void OnSwitchToDRM();
+	void OnSwitchToFM();
+	void OnHelpAbout() {emit About();}
+	void OnWhatsThis();
+	void on_CheckBoxMuteAudio_clicked(bool);
+	void on_CheckBoxSaveAudioWave_clicked(bool);
+	void on_CheckBoxAutoFreqAcq_clicked(bool);
+	void on_CheckBoxPLL_clicked(bool);
+	void on_ButtonWaterfall_clicked(bool);
+	void on_ButtonFreqOffset_clicked(bool);
+	void on_ButtonBandWidth_clicked(bool);
+	void on_SpinBoxNoiRedLevel_valueChanged(int);
+	void on_SliderBandwidth_valueChanged(int);
+	void on_ButtonGroupDemodulation_buttonClicked(int);
+	void on_ButtonGroupAGC_buttonClicked(int);
+	void on_ButtonGroupNoiseReduction_buttonClicked(int);
+
+signals:
+	void SwitchMode(int);
+	void NewAMAcquisition();
+	void ViewStationsDlg();
+	void ViewLiveScheduleDlg();
+	void Closed();
+	void About();
+};
diff --git a/src/GUI-QT/BWSViewer.cpp b/src/GUI-QT/BWSViewer.cpp
new file mode 100644
index 0000000..2977999
--- /dev/null
+++ b/src/GUI-QT/BWSViewer.cpp
@@ -0,0 +1,472 @@
+/******************************************************************************\
+ * British Broadcasting Corporation
+ * Copyright (c) 2001-2014, 2001-2014
+ *
+ * Author(s):
+ *	 Julian Cable, David Flamand (rewrite)
+ *
+ * Description: MOT Broadcast Website Viewer
+ *
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "BWSViewer.h"
+#include "../DrmReceiver.h"
+#include "../util-QT/Util.h"
+#include "../datadecoding/DataDecoder.h"
+#include <QDir>
+#include <QFile>
+#include <QMessageBox>
+#include <QWebHistory>
+#include "ThemeCustomizer.h"
+
+
+#define CACHE_HOST          "127.0.0.1" /* Not an actual server, MUST be set to "127.0.0.1" */
+
+#define ICON_REFRESH        ":/icons/Refresh.png"
+#define ICON_STOP           ":/icons/Stop.png"
+
+#undef ENABLE_HACK
+#define ENABLE_HACK /* Do we really need these hack unless for vtc trial sample? */
+
+
+BWSViewer::BWSViewer(CDRMReceiver& rec, CSettings& Settings, QWidget* parent):
+    CWindow(parent, Settings, "BWS"),
+    nam(this, cache, waitobjs, bAllowExternalContent, strCacheHost),
+    receiver(rec), decoder(NULL), bHomeSet(false), bPageLoading(false),
+    bSaveFileToDisk(false), bRestrictedProfile(false), bAllowExternalContent(true),
+    bClearCacheOnNewService(true), bDirectoryIndexChanged(false),
+    iLastAwaitingOjects(0), strCacheHost(CACHE_HOST),
+    iLastServiceID(0), iCurrentDataServiceID(0), bLastServiceValid(false), iLastValidServiceID(0)
+{
+    setupUi(this);
+    string sDataFilesDirectory = Settings.Get(
+                "Receiver", "datafilesdirectory", string(DEFAULT_DATA_FILES_DIRECTORY));
+    strDataDir = QString::fromUtf8(sDataFilesDirectory.c_str());
+
+    /* Setup webView */
+    webView->page()->setNetworkAccessManager(&nam);
+    webView->pageAction(QWebPage::OpenLinkInNewWindow)->setVisible(false);
+    webView->pageAction(QWebPage::DownloadLinkToDisk)->setVisible(false);
+    webView->pageAction(QWebPage::OpenImageInNewWindow)->setVisible(false);
+    webView->pageAction(QWebPage::DownloadImageToDisk)->setVisible(false);
+ 
+    /* Update time for color LED */
+    LEDStatus->SetUpdateTime(1000);
+
+    /* Update various buttons and labels */
+    ButtonClearCache->setEnabled(false);
+    actionClear_Cache->setEnabled(false);
+    LabelTitle->setText("");
+    Update();
+
+    /* Connect controls */
+    connect(buttonOk, SIGNAL(clicked()), this, SLOT(close()));
+    connect(actionClear_Cache, SIGNAL(triggered()), SLOT(OnClearCache()));
+    connect(actionClose, SIGNAL(triggered()), SLOT(close()));
+    connect(actionAllow_External_Content, SIGNAL(triggered(bool)), SLOT(OnAllowExternalContent(bool)));
+    connect(actionRestricted_Profile_Only, SIGNAL(triggered(bool)), SLOT(OnSetProfile(bool)));
+    connect(actionSave_File_to_Disk, SIGNAL(triggered(bool)), SLOT(OnSaveFileToDisk(bool)));
+    connect(actionClear_Cache_on_New_Service, SIGNAL(triggered(bool)), SLOT(OnClearCacheOnNewService(bool)));
+    connect(ButtonStepBack, SIGNAL(clicked()), this, SLOT(OnBack()));
+    connect(ButtonStepForward, SIGNAL(clicked()), this, SLOT(OnForward()));
+    connect(ButtonHome, SIGNAL(clicked()), this, SLOT(OnHome()));
+    connect(ButtonStopRefresh, SIGNAL(clicked()), this, SLOT(OnStopRefresh()));
+    connect(ButtonClearCache, SIGNAL(clicked()), this, SLOT(OnClearCache()));
+    connect(webView, SIGNAL(loadStarted()), this, SLOT(OnWebViewLoadStarted()));
+    connect(webView, SIGNAL(loadFinished(bool)), this, SLOT(OnWebViewLoadFinished(bool)));
+    connect(webView, SIGNAL(titleChanged(const QString &)), this, SLOT(OnWebViewTitleChanged(const QString &)));
+    connect(&Timer, SIGNAL(timeout()), this, SLOT(OnTimer()));
+
+    APPLY_CUSTOM_THEME();
+}
+
+BWSViewer::~BWSViewer()
+{
+}
+
+void BWSViewer::UpdateButtons()
+{
+    ButtonStepBack->setEnabled(webView->history()->canGoBack());
+    ButtonStepForward->setEnabled(webView->history()->canGoForward());
+    ButtonHome->setEnabled(bHomeSet);
+    ButtonStopRefresh->setEnabled(bHomeSet);
+    ButtonStopRefresh->setIcon(QIcon(bPageLoading ? ICON_STOP : ICON_REFRESH));
+}
+
+QString BWSViewer::ObjectStr(unsigned int count)
+{
+    return QString(count > 1 ? tr("objects") : tr("object"));
+}
+
+void BWSViewer::UpdateStatus()
+{
+    unsigned int count, size;
+    cache.GetObjectCountAndSize(count, size);
+    if (count == 0)
+        LabelStatus->setText("");
+    else
+    {
+        QString text(tr("%1 %2 cached, %3 kB"));
+        text = text.arg(count).arg(ObjectStr(count)).arg((size+999) / 1000);
+        iLastAwaitingOjects = waitobjs;
+        if (iLastAwaitingOjects)
+            text += tr("  |  %1 %2 pending").arg(iLastAwaitingOjects).arg(ObjectStr(iLastAwaitingOjects));
+        if (bAllowExternalContent && webView->url().isValid() && webView->url().host() != strCacheHost)
+            text += "  |  " + webView->url().toString();
+        LabelStatus->setText(text);
+    }
+}
+
+void BWSViewer::UpdateWindowTitle(const uint32_t iServiceID, const bool bServiceValid, QString strLabel)
+{
+    QString strTitle("MOT Broadcast Website");
+    iLastServiceID = iServiceID;
+    bLastServiceValid = bServiceValid;
+    strLastLabel = strLabel;
+    if (bServiceValid)
+    {
+        if (strLabel != "")
+            strLabel += " - ";
+
+        /* Service ID (plot number in hexadecimal format) */
+        QString strServiceID = "ID:" +
+                       QString().setNum(iServiceID, 16).toUpper();
+
+        /* Add the description on the title of the dialog */
+        if (strLabel != "" || strServiceID != "")
+            strTitle += " [" + strLabel + strServiceID + "]";
+    }
+    setWindowTitle(strTitle);
+}
+
+void BWSViewer::Update()
+{
+    UpdateStatus();
+    UpdateButtons();
+}
+
+void BWSViewer::OnTimer()
+{
+    /* Get current service parameters */
+    uint32_t iServiceID; bool bServiceValid; QString strLabel; ETypeRxStatus eStatus;
+    GetServiceParams(&iServiceID, &bServiceValid, &strLabel, &eStatus);
+
+    /* Set current data service ID */
+    iCurrentDataServiceID = bServiceValid ? iServiceID : 0;
+
+    /* Check for new valid data service */
+    if (bServiceValid && iLastValidServiceID != iServiceID)
+    {
+        iLastValidServiceID = iServiceID;
+        if (bClearCacheOnNewService)
+            OnClearCache();
+    }
+
+    /* Update the window title if something have changed */
+    if (iLastServiceID != iServiceID || bLastServiceValid != bServiceValid || strLastLabel != strLabel)
+        UpdateWindowTitle(iServiceID, bServiceValid, strLabel);
+
+    switch(eStatus)
+    {
+    case NOT_PRESENT:
+        LEDStatus->Reset();
+        break;
+
+    case CRC_ERROR:
+        LEDStatus->SetLight(CMultColorLED::RL_RED);
+        break;
+
+    case DATA_ERROR:
+        LEDStatus->SetLight(CMultColorLED::RL_YELLOW);
+        break;
+
+    case RX_OK:
+        LEDStatus->SetLight(CMultColorLED::RL_GREEN);
+        break;
+    }
+
+    if (decoder == NULL)
+    {
+        decoder = receiver.GetDataDecoder();
+        if (decoder == NULL)
+            qDebug("can't get data decoder from receiver");
+    }
+
+    if (Changed())
+    {
+        if (bDirectoryIndexChanged)
+        {
+            bDirectoryIndexChanged = false;
+            if (!bHomeSet)
+            {
+                bHomeSet = true;
+                OnHome();
+            }
+        }
+        Update();
+        ButtonClearCache->setEnabled(true);
+        actionClear_Cache->setEnabled(true);
+    }
+    else
+    {
+        unsigned int iAwaitingOjects = waitobjs;
+        if (iLastAwaitingOjects != iAwaitingOjects)
+        {
+            iLastAwaitingOjects = iAwaitingOjects;
+            UpdateStatus();
+        }
+    }
+}
+
+void BWSViewer::OnHome()
+{
+    webView->load("http://" + strCacheHost);
+}
+
+void BWSViewer::OnStopRefresh()
+{
+    if (bPageLoading)
+        webView->stop();
+    else
+    {
+        if (webView->url().isEmpty())
+            OnHome();
+        else
+            webView->reload();
+    }
+}
+
+void BWSViewer::OnBack()
+{
+    webView->history()->back();
+}
+
+void BWSViewer::OnForward()
+{
+    webView->history()->forward();
+}
+
+void BWSViewer::OnClearCache()
+{
+    webView->setHtml("");
+    webView->history()->clear();
+    cache.ClearAll();
+    bHomeSet = false;
+    bPageLoading = false;
+    bDirectoryIndexChanged = false;
+    ButtonClearCache->setEnabled(false);
+    actionClear_Cache->setEnabled(false);
+    Update();
+}
+
+void BWSViewer::OnWebViewLoadStarted()
+{
+    bPageLoading = true;
+    QTimer::singleShot(20, this, SLOT(Update()));
+}
+
+void BWSViewer::OnWebViewLoadFinished(bool ok)
+{
+    (void)ok;
+    bPageLoading = false;
+    QTimer::singleShot(20, this, SLOT(Update()));
+}
+
+void BWSViewer::OnWebViewTitleChanged(const QString& title)
+{
+    LabelTitle->setText("<b>" + title + "</b>");
+}
+
+void BWSViewer::OnAllowExternalContent(bool isChecked)
+{
+    bAllowExternalContent = isChecked;
+}
+
+void BWSViewer::OnSetProfile(bool isChecked)
+{
+    bRestrictedProfile = isChecked;
+}
+
+void BWSViewer::OnSaveFileToDisk(bool isChecked)
+{
+    bSaveFileToDisk = isChecked;
+}
+
+void BWSViewer::OnClearCacheOnNewService(bool isChecked)
+{
+    bClearCacheOnNewService = isChecked;
+}
+
+void BWSViewer::eventShow(QShowEvent*)
+{
+    bAllowExternalContent = getSetting("allowexternalcontent", bAllowExternalContent);
+    actionAllow_External_Content->setChecked(bAllowExternalContent);
+
+    bSaveFileToDisk = getSetting("savefiletodisk", bSaveFileToDisk);
+    actionSave_File_to_Disk->setChecked(bSaveFileToDisk);
+
+    bRestrictedProfile = getSetting("restrictedprofile", bRestrictedProfile);
+    actionRestricted_Profile_Only->setChecked(bRestrictedProfile);
+
+    bClearCacheOnNewService = getSetting("clearcacheonnewservice", bClearCacheOnNewService);
+    actionClear_Cache_on_New_Service->setChecked(bClearCacheOnNewService);
+
+    /* Update window title */
+    uint32_t iServiceID; bool bServiceValid; QString strLabel;
+    GetServiceParams(&iServiceID, &bServiceValid, &strLabel);
+    UpdateWindowTitle(iServiceID, bServiceValid, strLabel);
+
+    /* Update window content */
+    OnTimer();
+
+    /* Activate real-time timer when window is shown */
+    Timer.start(GUI_CONTROL_UPDATE_TIME);
+}
+
+void BWSViewer::eventHide(QHideEvent*)
+{
+    /* Deactivate real-time timer so that it does not get new pictures */
+    Timer.stop();
+
+    putSetting("savefiletodisk", bSaveFileToDisk);
+
+    putSetting("restrictedprofile", bRestrictedProfile);
+
+    putSetting("allowexternalcontent", bAllowExternalContent);
+
+    putSetting("clearcacheonnewservice", bClearCacheOnNewService);
+}
+
+bool BWSViewer::Changed()
+{
+    bool bChanged = false;
+    if (decoder != NULL)
+    {
+        CMOTObject obj;
+
+        /* Poll the data decoder module for new object */
+        while (decoder->GetMOTObject(obj, CDataDecoder::AT_BROADCASTWEBSITE) == TRUE)
+        {
+            /* Get the current directory */
+            CMOTDirectory MOTDir;
+            if (decoder->GetMOTDirectory(MOTDir, CDataDecoder::AT_BROADCASTWEBSITE) == TRUE)
+            {
+                /* ETSI TS 101 498-1 Section 5.5.1 */
+
+                /* Checks if the DirectoryIndex has values */
+                if (MOTDir.DirectoryIndex.size() > 0)
+                {
+                    QString strNewDirectoryIndex;
+                    /* TODO proper profile handling */
+                    if(MOTDir.DirectoryIndex.find(UNRESTRICTED_PC_PROFILE) != MOTDir.DirectoryIndex.end())
+                        strNewDirectoryIndex =
+                            MOTDir.DirectoryIndex[UNRESTRICTED_PC_PROFILE].c_str();
+                    else if(MOTDir.DirectoryIndex.find(BASIC_PROFILE) != MOTDir.DirectoryIndex.end())
+                        strNewDirectoryIndex =
+                            MOTDir.DirectoryIndex[BASIC_PROFILE].c_str();
+#ifdef ENABLE_HACK
+                    if (strNewDirectoryIndex == "not_here.html") /* Hack needed for vtc trial sample */
+	                    strNewDirectoryIndex = "index.html";
+#endif
+                    if (!strNewDirectoryIndex.isNull())
+                        bDirectoryIndexChanged |= cache.SetDirectoryIndex(strNewDirectoryIndex);
+                }
+            }
+
+            /* Get object name */
+            QString strObjName(obj.strName.c_str());
+
+            /* Get ContentType */
+            QString strContentType(obj.strMimeType.c_str());
+#ifdef ENABLE_HACK
+            /* Hack needed for vtc trial sample */
+            if (strObjName.endsWith(".stm", Qt::CaseInsensitive) && !strContentType.compare("application/octet-stream", Qt::CaseInsensitive))
+                strContentType = "text/html";
+#endif 
+            /* Add received MOT object to webView */
+            cache.AddObject(strObjName, strContentType, obj.Body.vecData);
+
+            /* Store received MOT object on disk */
+            if (bSaveFileToDisk)
+                SaveMOTObject(strObjName, obj);
+
+            /* Set changed flag */
+        	bChanged = true;
+        }
+    }
+    return bChanged;
+}
+
+void BWSViewer::SaveMOTObject(const QString& strObjName,
+                              const CMOTObject& obj)
+{
+    const CVector<_BYTE>& vecbRawData = obj.Body.vecData;
+
+    QString strCurrentSavePath = savePath();
+
+    /* Generate safe filename */
+    QString strFileName = strCurrentSavePath + VerifyHtmlPath(strObjName);
+
+    /* First, create directory for storing the file (if not exists) */
+    CreateDirectories(strFileName);
+
+    /* Open file */
+    QFile file(strFileName);
+    if (file.open(QIODevice::WriteOnly))// | QIODevice::Truncate))
+    {
+        int i, written, size;
+        size = vecbRawData.Size();
+
+        /* Write data */
+        for (i = 0, written = 0; size > 0 && written >= 0; i+=written, size-=written)
+            written = file.write((const char*)&vecbRawData.at(i), size);
+
+        /* Close the file afterwards */
+        file.close();
+    }
+	else
+	{
+		QMessageBox::information(this, file.errorString(), strFileName);
+	}
+}
+
+QString BWSViewer::savePath()
+{
+    /* Append service ID to MOT save path */
+    return strDataDir+QString("/MOT/%2/").arg(iCurrentDataServiceID, 16).toUpper();
+}
+
+void BWSViewer::GetServiceParams(uint32_t* iServiceID, bool* bServiceValid, QString* strLabel, ETypeRxStatus* eStatus)
+{
+    CParameter& Parameters = *receiver.GetParameters();
+    Parameters.Lock();
+        const int iCurSelDataServ = Parameters.GetCurSelDataService();
+        const CService service = Parameters.Service[iCurSelDataServ];
+        if (eStatus)
+            *eStatus = Parameters.DataComponentStatus[iCurSelDataServ].GetStatus();
+    Parameters.Unlock();
+    if (iServiceID)
+        *iServiceID = service.iServiceID;
+    if (bServiceValid)
+        *bServiceValid = service.IsActive() && service.eAudDataFlag == CService::SF_DATA;
+    /* Do UTF-8 to QString (UNICODE) conversion with the label strings */
+    if (strLabel)
+        *strLabel = QString().fromUtf8(service.strLabel.c_str()).trimmed();
+}
diff --git a/src/GUI-QT/BWSViewer.h b/src/GUI-QT/BWSViewer.h
new file mode 100644
index 0000000..7a75103
--- /dev/null
+++ b/src/GUI-QT/BWSViewer.h
@@ -0,0 +1,103 @@
+/******************************************************************************\
+ * British Broadcasting Corporation
+ * Copyright (c) 2001-2014, 2001-2014
+ *
+ * Author(s):
+ *	 Julian Cable, David Flamand (rewrite)
+ *
+ * Description: MOT Broadcast Website Viewer
+ *
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#ifndef _BWSVIEWER_H
+#define _BWSVIEWER_H
+
+#include "ui_BWSViewer.h"
+#include "DialogUtil.h"
+#include "CWindow.h"
+#include "bwsviewerwidget.h"
+#include <QMutex>
+
+class CMOTObject;
+class CDRMReceiver;
+class CDataDecoder;
+
+class BWSViewer : public CWindow, public Ui_BWSViewer
+{
+    Q_OBJECT
+
+public:
+    BWSViewer(CDRMReceiver&, CSettings&, QWidget* parent = 0);
+    virtual ~BWSViewer();
+
+protected:
+    CNetworkAccessManager nam;
+    QTimer          Timer;
+    CDRMReceiver&   receiver;
+    CDataDecoder*   decoder;
+    CWebsiteCache   cache;
+    bool            bHomeSet;
+    bool            bPageLoading;
+    bool            bSaveFileToDisk;
+    bool            bRestrictedProfile;
+    bool            bAllowExternalContent;
+    bool            bClearCacheOnNewService;
+    bool            bDirectoryIndexChanged;
+    unsigned int    iLastAwaitingOjects;
+    CCounter        waitobjs;
+    const QString   strCacheHost;
+    uint32_t        iLastServiceID;
+    uint32_t        iCurrentDataServiceID;
+    bool            bLastServiceValid;
+    uint32_t        iLastValidServiceID;
+    QString         strLastLabel;
+    QString         strDataDir;
+
+    bool Changed();
+    void SaveMOTObject(const QString& strObjName, const CMOTObject& obj);
+    bool RemoveDir(const QString &dirName, int level = 0);
+    QString savePath();
+    void UpdateButtons();
+    void UpdateStatus();
+    void UpdateWindowTitle(const uint32_t iServiceID, const bool bServiceValid, QString strLabel);
+    QString ObjectStr(unsigned int count);
+    void GetServiceParams(uint32_t* iServiceID=NULL, bool* bServiceValid=NULL, QString* strLabel=NULL, ETypeRxStatus* eStatus=NULL);
+    virtual void eventShow(QShowEvent*);
+    virtual void eventHide(QHideEvent*);
+
+public slots:
+    void OnTimer();
+    void OnClearCache();
+    void OnHome();
+    void OnStopRefresh();
+    void OnBack();
+    void OnForward();
+    void OnSetProfile(bool);
+    void OnSaveFileToDisk(bool);
+    void OnAllowExternalContent(bool);
+    void OnClearCacheOnNewService(bool);
+    void OnWebViewLoadStarted();
+    void OnWebViewLoadFinished(bool ok);
+    void OnWebViewTitleChanged(const QString& title);
+    void Update();
+};
+
+#endif
+
diff --git a/src/GUI-QT/BWSViewer.ui b/src/GUI-QT/BWSViewer.ui
new file mode 100644
index 0000000..943fc3f
--- /dev/null
+++ b/src/GUI-QT/BWSViewer.ui
@@ -0,0 +1,419 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>BWSViewer</class>
+ <widget class="QMainWindow" name="BWSViewer">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>617</width>
+    <height>478</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>MainWindow</string>
+  </property>
+  <property name="windowIcon">
+   <iconset resource="res/icons.qrc">
+    <normaloff>:/icons/MainIcon.svg</normaloff>:/icons/MainIcon.svg</iconset>
+  </property>
+  <widget class="QWidget" name="centralwidget">
+   <layout class="QVBoxLayout" name="verticalLayout">
+    <item>
+     <widget class="QLabel" name="LabelTitle">
+      <property name="sizePolicy">
+       <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+        <horstretch>0</horstretch>
+        <verstretch>0</verstretch>
+       </sizepolicy>
+      </property>
+      <property name="frameShape">
+       <enum>QFrame::NoFrame</enum>
+      </property>
+      <property name="frameShadow">
+       <enum>QFrame::Plain</enum>
+      </property>
+      <property name="lineWidth">
+       <number>0</number>
+      </property>
+      <property name="text">
+       <string><b>Title</b></string>
+      </property>
+      <property name="textFormat">
+       <enum>Qt::RichText</enum>
+      </property>
+      <property name="alignment">
+       <set>Qt::AlignCenter</set>
+      </property>
+      <property name="wordWrap">
+       <bool>true</bool>
+      </property>
+      <property name="textInteractionFlags">
+       <set>Qt::NoTextInteraction</set>
+      </property>
+     </widget>
+    </item>
+    <item>
+     <widget class="QFrame" name="frame">
+      <property name="sizePolicy">
+       <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+        <horstretch>0</horstretch>
+        <verstretch>0</verstretch>
+       </sizepolicy>
+      </property>
+      <property name="frameShape">
+       <enum>QFrame::StyledPanel</enum>
+      </property>
+      <property name="frameShadow">
+       <enum>QFrame::Sunken</enum>
+      </property>
+      <layout class="QVBoxLayout" name="verticalLayout_3">
+       <property name="spacing">
+        <number>0</number>
+       </property>
+       <property name="margin">
+        <number>0</number>
+       </property>
+       <item>
+        <widget class="QWebView" name="webView" native="true">
+         <property name="sizePolicy">
+          <sizepolicy hsizetype="Ignored" vsizetype="Ignored">
+           <horstretch>0</horstretch>
+           <verstretch>0</verstretch>
+          </sizepolicy>
+         </property>
+        </widget>
+       </item>
+      </layout>
+     </widget>
+    </item>
+    <item>
+     <widget class="QLabel" name="LabelStatus">
+      <property name="sizePolicy">
+       <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+        <horstretch>0</horstretch>
+        <verstretch>0</verstretch>
+       </sizepolicy>
+      </property>
+      <property name="frameShape">
+       <enum>QFrame::NoFrame</enum>
+      </property>
+      <property name="frameShadow">
+       <enum>QFrame::Plain</enum>
+      </property>
+      <property name="lineWidth">
+       <number>0</number>
+      </property>
+      <property name="text">
+       <string>Status</string>
+      </property>
+      <property name="textFormat">
+       <enum>Qt::PlainText</enum>
+      </property>
+      <property name="wordWrap">
+       <bool>true</bool>
+      </property>
+      <property name="textInteractionFlags">
+       <set>Qt::NoTextInteraction</set>
+      </property>
+     </widget>
+    </item>
+    <item>
+     <widget class="Line" name="line">
+      <property name="orientation">
+       <enum>Qt::Horizontal</enum>
+      </property>
+     </widget>
+    </item>
+    <item>
+     <layout class="QHBoxLayout" name="_2">
+      <property name="spacing">
+       <number>6</number>
+      </property>
+      <property name="margin">
+       <number>0</number>
+      </property>
+      <item>
+       <widget class="QLabel" name="TextLabel1">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="text">
+         <string>Receiving Status:</string>
+        </property>
+        <property name="wordWrap">
+         <bool>false</bool>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="CMultColorLED" name="LEDStatus" native="true">
+        <property name="minimumSize">
+         <size>
+          <width>13</width>
+          <height>13</height>
+         </size>
+        </property>
+        <property name="maximumSize">
+         <size>
+          <width>13</width>
+          <height>13</height>
+         </size>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <spacer name="Spacer5">
+        <property name="orientation">
+         <enum>Qt::Horizontal</enum>
+        </property>
+        <property name="sizeType">
+         <enum>QSizePolicy::Expanding</enum>
+        </property>
+        <property name="sizeHint" stdset="0">
+         <size>
+          <width>20</width>
+          <height>20</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+      <item>
+       <widget class="QToolButton" name="ButtonStepBack">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="text">
+         <string/>
+        </property>
+        <property name="icon">
+         <iconset resource="res/icons.qrc">
+          <normaloff>:/icons/StepBack.png</normaloff>:/icons/StepBack.png</iconset>
+        </property>
+        <property name="iconSize">
+         <size>
+          <width>16</width>
+          <height>16</height>
+         </size>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QToolButton" name="ButtonStepForward">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="text">
+         <string/>
+        </property>
+        <property name="icon">
+         <iconset resource="res/icons.qrc">
+          <normaloff>:/icons/StepForw.png</normaloff>:/icons/StepForw.png</iconset>
+        </property>
+        <property name="iconSize">
+         <size>
+          <width>16</width>
+          <height>16</height>
+         </size>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QToolButton" name="ButtonHome">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="text">
+         <string/>
+        </property>
+        <property name="icon">
+         <iconset resource="res/icons.qrc">
+          <normaloff>:/icons/Home.png</normaloff>:/icons/Home.png</iconset>
+        </property>
+        <property name="iconSize">
+         <size>
+          <width>16</width>
+          <height>16</height>
+         </size>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QToolButton" name="ButtonStopRefresh">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="text">
+         <string/>
+        </property>
+        <property name="icon">
+         <iconset resource="res/icons.qrc">
+          <normaloff>:/icons/Refresh.png</normaloff>:/icons/Refresh.png</iconset>
+        </property>
+        <property name="iconSize">
+         <size>
+          <width>16</width>
+          <height>16</height>
+         </size>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <spacer name="Spacer5_2">
+        <property name="orientation">
+         <enum>Qt::Horizontal</enum>
+        </property>
+        <property name="sizeType">
+         <enum>QSizePolicy::Expanding</enum>
+        </property>
+        <property name="sizeHint" stdset="0">
+         <size>
+          <width>20</width>
+          <height>20</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+      <item>
+       <widget class="QPushButton" name="ButtonClearCache">
+        <property name="text">
+         <string>Cl&ear Cache</string>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QPushButton" name="buttonOk">
+        <property name="text">
+         <string>&Close</string>
+        </property>
+        <property name="default">
+         <bool>true</bool>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </item>
+   </layout>
+  </widget>
+  <widget class="QMenuBar" name="menubar">
+   <property name="geometry">
+    <rect>
+     <x>0</x>
+     <y>0</y>
+     <width>617</width>
+     <height>25</height>
+    </rect>
+   </property>
+   <widget class="QMenu" name="menuFile">
+    <property name="title">
+     <string>&File</string>
+    </property>
+    <addaction name="actionClear_Cache"/>
+    <addaction name="separator"/>
+    <addaction name="actionClose"/>
+   </widget>
+   <widget class="QMenu" name="menuSettings">
+    <property name="title">
+     <string>&Settings</string>
+    </property>
+    <addaction name="actionAllow_External_Content"/>
+    <addaction name="actionRestricted_Profile_Only"/>
+    <addaction name="actionSave_File_to_Disk"/>
+    <addaction name="actionClear_Cache_on_New_Service"/>
+   </widget>
+   <addaction name="menuFile"/>
+   <addaction name="menuSettings"/>
+  </widget>
+  <action name="actionSet_Font">
+   <property name="text">
+    <string>Set  Font</string>
+   </property>
+  </action>
+  <action name="actionClear_Cache">
+   <property name="text">
+    <string>Cl&ear Cache</string>
+   </property>
+  </action>
+  <action name="actionSave">
+   <property name="text">
+    <string>Save</string>
+   </property>
+  </action>
+  <action name="actionSave_All">
+   <property name="text">
+    <string>Save All</string>
+   </property>
+  </action>
+  <action name="actionClose">
+   <property name="text">
+    <string>&Close</string>
+   </property>
+  </action>
+  <action name="actionRestricted_Profile_Only">
+   <property name="checkable">
+    <bool>true</bool>
+   </property>
+   <property name="text">
+    <string>&Restricted Profile Only</string>
+   </property>
+  </action>
+  <action name="actionSave_File_to_Disk">
+   <property name="checkable">
+    <bool>true</bool>
+   </property>
+   <property name="checked">
+    <bool>false</bool>
+   </property>
+   <property name="text">
+    <string>&Save File to Disk</string>
+   </property>
+  </action>
+  <action name="actionAllow_External_Content">
+   <property name="checkable">
+    <bool>true</bool>
+   </property>
+   <property name="text">
+    <string>&Allow External Content</string>
+   </property>
+  </action>
+  <action name="actionClear_Cache_on_New_Service">
+   <property name="checkable">
+    <bool>true</bool>
+   </property>
+   <property name="text">
+    <string>&Clear Cache on New Service</string>
+   </property>
+  </action>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>QWebView</class>
+   <extends>QWidget</extends>
+   <header>QtWebKit/QWebView</header>
+  </customwidget>
+  <customwidget>
+   <class>CMultColorLED</class>
+   <extends>QWidget</extends>
+   <header>MultColorLED.h</header>
+  </customwidget>
+ </customwidgets>
+ <resources>
+  <include location="res/icons.qrc"/>
+ </resources>
+ <connections/>
+</ui>
diff --git a/src/GUI-QT/CWindow.cpp b/src/GUI-QT/CWindow.cpp
new file mode 100644
index 0000000..1ab33fd
--- /dev/null
+++ b/src/GUI-QT/CWindow.cpp
@@ -0,0 +1,305 @@
+/******************************************************************************\
+ *
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	David Flamand
+ *
+ * Description:
+ *  Base class for gui window derived from QMainWindow.
+ *  The window position is remembered, visibility state by parent is also
+ *  remembered for child window.
+ *  Children are automaticaly deleted when the last parent is deleted.
+ *  A child can have more than one parent.
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "CWindow.h"
+#include <QRect>
+#if QT_VERSION >= 0x050000
+# include <QTimer>
+#endif
+#include <QWhatsThis>
+
+/* Implementation *************************************************************/
+
+
+/* CEventFilter ------------------------------------------------------------- */
+
+CEventFilter::CEventFilter() : eLastEventType(QEvent::Hide)
+{
+}
+
+CEventFilter::~CEventFilter()
+{
+}
+
+bool CEventFilter::isValid(const QEvent* event)
+{
+	bool bValid = FALSE;
+	QEvent::Type eEventType = event->type();
+	switch (eEventType)
+	{
+	case QEvent::Hide:
+		bValid = eLastEventType == QEvent::Show;
+		eLastEventType = eEventType;
+		break;
+	case QEvent::Show:
+		bValid = eLastEventType == QEvent::Hide;
+		eLastEventType = eEventType;
+		break;
+	default:
+		break;
+	}
+	return bValid;
+}
+
+
+/* CWindow ------------------------------------------------------------------ */
+
+CWindow::CWindow(QWidget* parent, CSettings& Settings, const QString& windowName) :
+	QMainWindow(), parents(), windowName(windowName), bHide(false), Settings(Settings)
+{
+	if (parent != NULL)
+		parents[parent] = "";
+	init();
+}
+CWindow::CWindow(QMap<QWidget*,QString>& parents, CSettings& Settings, const QString& windowName) :
+	QMainWindow(), parents(parents), windowName(windowName), bHide(false), Settings(Settings)
+{
+	init();
+}
+void CWindow::init()
+{
+//	printf("################################ CWindow::Init(%s) parents %i\n", getSection().c_str(), parents.count());
+	setAttribute(Qt::WA_QuitOnClose, parents.count() == 0);
+	setAttribute(Qt::WA_DeleteOnClose, false);
+	loadWindowGeometry();
+	foreach(QWidget* parent, parents.keys())
+	{
+		connect(parent, SIGNAL(showWindow(QWidget*, bool)), this, SLOT(OnShowWindow(QWidget*, bool)));
+		connect(parent, SIGNAL(closeWindow(QWidget*)), this, SLOT(OnCloseWindow(QWidget*)));
+		connect(parent, SIGNAL(deleteWindow(QWidget*)), this, SLOT(OnDeleteWindow(QWidget*)));
+	}
+}
+
+CWindow::~CWindow()
+{
+//	printf("################################ CWindow::~CWindow(%s)\n", getSection().c_str());
+	emit deleteWindow(this);
+}
+
+void CWindow::closeEvent(QCloseEvent* pEvent)
+{
+//	printf("################################ CWindow::closeEvent(%s)\n", getSection().c_str());
+	eventClose(pEvent);
+	if (pEvent->isAccepted())
+		emit closeWindow(this);
+}
+void CWindow::showEvent(QShowEvent* pEvent)
+{
+	EVENT_FILTER(pEvent);
+//	printf("################################ CWindow::showEvent(%s)\n", getSection().c_str());
+	loadWindowGeometry();
+	eventShow(pEvent);
+	emit showWindow(this, true);
+}
+void CWindow::hideEvent(QHideEvent* pEvent)
+{
+	EVENT_FILTER(pEvent);
+//	printf("################################ CWindow::hideEvent(%s)\n", getSection().c_str());
+	saveWindowGeometry();
+	eventHide(pEvent);
+	emit showWindow(this, false);
+}
+void CWindow::contextMenuEvent(QContextMenuEvent *event)
+{
+	/* TODO popup a "What's This?" context menu */
+	QWidget *child = childAt(event->pos());
+	while (child)
+	{
+		if (!child->whatsThis().isEmpty())
+		{
+			QWhatsThis::enterWhatsThisMode();
+			break;
+		}
+		child = child->parentWidget();
+	}
+}
+#if QT_VERSION >= 0x050000
+	/* On Qt 5 hideEvent is not generated on window minimize,
+	   so instead we force an hide event, this also have a
+	   side effect: the button is removed from the task bar.
+	   TODO behave like Qt 4 */
+bool CWindow::event(QEvent* pEvent)
+{
+	bool result = QWidget::event(pEvent);
+	if(pEvent->type() == QEvent::WindowStateChange && isMinimized())
+		QTimer::singleShot(0, this, SLOT(hide()));
+	return result;
+}
+#endif
+
+void CWindow::eventClose(QCloseEvent*)
+{
+//	printf("################################ CWindow::eventClose(%s)\n", getSection().c_str());
+}
+void CWindow::eventHide(QHideEvent*)
+{
+//	printf("################################ CWindow::eventHide(%s)\n", getSection().c_str());
+}
+void CWindow::eventShow(QShowEvent*)
+{
+//	printf("################################ CWindow::eventShow(%s)\n", getSection().c_str());
+}
+void CWindow::eventUpdate()
+{
+//	printf("################################ CWindow::eventUpdate(%s)\n", getSection().c_str());
+}
+
+void CWindow::toggleVisibility()
+{
+//	printf("################################ CWindow::toggleVisibility(%s)\n", getSection().c_str());
+	setVisible(!isVisible());
+}
+
+void CWindow::setSettingsTag(const QString& tag, bool hide)
+{
+//	printf("################################ CWindow::setSettingTag(%s)\n", string(tag.toLocal8Bit()).c_str());
+	settingsTag = tag;
+	bHide = hide;
+}
+
+void CWindow::loadWindowGeometry()
+{
+	CWinGeom s;
+	Settings.Get(getTagSection(), s);
+	const QRect WinGeom(s.iXPos, s.iYPos, s.iWSize, s.iHSize);
+	if (WinGeom.isValid() && !WinGeom.isEmpty() && !WinGeom.isNull())
+	{
+		setGeometry(WinGeom);
+//		printf("################################ CWindow::loadWindowGeometry(%s): x=%i y=%i w=%i h=%i\n", getSection().c_str(), s.iXPos, s.iYPos, s.iWSize, s.iHSize);
+	}
+}
+void CWindow::saveWindowGeometry()
+{
+	CWinGeom s;
+	QRect WinGeom(geometry());
+	s.iXPos = WinGeom.x();
+	s.iYPos = WinGeom.y();
+	s.iHSize = WinGeom.height();
+	s.iWSize = WinGeom.width();
+	Settings.Put(getTagSection(), s);
+//	printf("################################ CWindow::saveWindowGeometry(%s): x=%i y=%i w=%i h=%i\n", getSection().c_str(), s.iXPos, s.iYPos, s.iWSize, s.iHSize);
+}
+
+void CWindow::OnShowWindow(QWidget* window, bool bVisible)
+{
+//	printf("################################ CWindow::OnShowWindow(%s) settingsTag='%s' bVisible=%i window=%p\n", getSection().c_str(), string(settingsTag.toLocal8Bit()).c_str(), bVisible, window);
+	if (parents.contains(window))
+	{
+		if (bHide)
+			QMainWindow::setVisible(false);
+		else
+		{
+			const QString key = QString("visible") + settingsTag;
+			if (!bVisible)
+				putSetting(key, isVisible());
+			if (!bVisible || getSetting(key, false))
+			{
+	//			if (bVisible)
+	//				loadWindowGeometry();
+				QMainWindow::setVisible(bVisible);
+			}
+		}
+	}
+}
+
+void CWindow::OnCloseWindow(QWidget* window)
+{
+//	printf("################################ CWindow::OnCloseWindow(%s) %p\n", getSection().c_str(), window);
+	if (parents.contains(window))
+	{
+		QCloseEvent event;
+		eventClose(&event);
+	}
+}
+
+void CWindow::OnDeleteWindow(QWidget* window)
+{
+//	printf("################################ CWindow::OnDeleteWindow(%s) %p\n", getSection().c_str(), window);
+	parents.remove(window);
+//	if (parents.remove(window) >= 1)
+//	{
+//		if (parents.count() == 0)
+//			delete this;
+//	}
+}
+
+void CWindow::setVisible(bool visible)
+{
+	QMainWindow::setVisible(visible);
+	if (visible)
+	{
+		QMainWindow::raise();
+		QMainWindow::activateWindow();
+	}
+}
+
+string CWindow::getTagSection(const bool bCommon) const
+{
+	return getSection(bCommon) + string(settingsTag.toLocal8Bit());
+}
+string CWindow::getSection(const bool bCommon) const
+{
+	return bCommon ? string("GUI") : string(windowName.toLocal8Bit() + " Dialog");
+}
+QString CWindow::getSetting(const QString& key, const QString& defvalue, const bool bCommon)
+{
+	return QString::fromLocal8Bit(Settings.Get(getSection(bCommon), string(key.toLocal8Bit()), string(defvalue.toLocal8Bit())).c_str());
+}
+bool CWindow::getSetting(const QString& key, const bool defvalue, const bool bCommon)
+{
+	return Settings.Get(getSection(bCommon), string(key.toLocal8Bit()), defvalue);
+}
+int CWindow::getSetting(const QString& key, const int defvalue, const bool bCommon)
+{
+	return Settings.Get(getSection(bCommon), string(key.toLocal8Bit()), defvalue);
+}
+_REAL CWindow::getSetting(const QString& key, const _REAL defvalue, const bool bCommon)
+{
+	return Settings.Get(getSection(bCommon), string(key.toLocal8Bit()), defvalue);
+}
+void CWindow::putSetting(const QString& key, const QString& value, const bool bCommon)
+{
+	Settings.Put(getSection(bCommon), string(key.toLocal8Bit()), string(value.toLocal8Bit()));
+}
+void CWindow::putSetting(const QString& key, const bool value, const bool bCommon)
+{
+	Settings.Put(getSection(bCommon), string(key.toLocal8Bit()), value);
+}
+void CWindow::putSetting(const QString& key, const int value, const bool bCommon)
+{
+	Settings.Put(getSection(bCommon), string(key.toLocal8Bit()), value);
+}
+void CWindow::putSetting(const QString& key, const _REAL value, const bool bCommon)
+{
+	Settings.Put(getSection(bCommon), string(key.toLocal8Bit()), value);
+}
+
diff --git a/src/GUI-QT/CWindow.h b/src/GUI-QT/CWindow.h
new file mode 100644
index 0000000..a37b984
--- /dev/null
+++ b/src/GUI-QT/CWindow.h
@@ -0,0 +1,134 @@
+/******************************************************************************\
+ *
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	David Flamand
+ *
+ * Description:
+ *  see CWindow.cpp
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#ifndef _CWINDOW_H
+#define _CWINDOW_H
+
+#include "../util/Settings.h"
+#include <QWidget>
+#include <QMainWindow>
+#if QT_VERSION >= 0x050000
+# include <QEvent>
+#endif
+#include <QHideEvent>
+#include <QShowEvent>
+#include <QCloseEvent>
+#include <QContextMenuEvent>
+#include <QMap>
+#include <QString>
+
+
+/* Definitions ****************************************************************/
+
+#define EVENT_FILTER(e) do { if (!ef.isValid((QEvent*)e)) return; } while(0)
+#define CWINDOW_NOTAG ""
+
+
+/* Classes ********************************************************************/
+
+/* CEventFilter ------------------------------------------------------------- */
+
+/* The purpose of this class is to prevent showEvent and
+   hideEvent from spurious event like unmatched show/hide,
+   which cause some problem for window save and restore.
+   The class may be adapted for other type of filtering
+   as well. The member isValid() return FALSE when the
+   event must be ignored. */
+
+class CEventFilter
+{
+public:
+	CEventFilter();
+	virtual ~CEventFilter();
+	bool isValid(const QEvent* event);
+
+protected:
+	QEvent::Type eLastEventType;
+};
+
+
+/* CWindow ------------------------------------------------------------------ */
+
+class CWindow : public QMainWindow
+{
+	Q_OBJECT
+
+public:
+	CWindow(QWidget* parent, CSettings& Settings, const QString& windowName);
+	CWindow(QMap<QWidget*,QString>& parents, CSettings& Settings, const QString& windowName);
+	virtual ~CWindow();
+	void toggleVisibility();
+	void setSettingsTag(const QString& tag, bool hide);
+	QString getSetting(const QString& key, const QString& defvalue, const bool bCommon=false);
+	bool getSetting(const QString& key, const bool defvalue, const bool bCommon=false);
+	int getSetting(const QString& key, const int defvalue, const bool bCommon=false);
+	_REAL getSetting(const QString& key, const _REAL defvalue, const bool bCommon=false);
+	void putSetting(const QString& key, const QString& value, const bool bCommon=false);
+	void putSetting(const QString& key, const bool value, const bool bCommon=false);
+	void putSetting(const QString& key, const int value, const bool bCommon=false);
+	void putSetting(const QString& key, const _REAL value, const bool bCommon=false);
+	virtual void eventUpdate();
+
+private:
+	void init();
+	virtual void closeEvent(QCloseEvent*);
+	virtual void showEvent(QShowEvent*);
+	virtual void hideEvent(QHideEvent*);
+	virtual void contextMenuEvent(QContextMenuEvent*);
+#if QT_VERSION >= 0x050000
+	virtual bool event(QEvent*);
+#endif
+	void loadWindowGeometry();
+	void saveWindowGeometry();
+	string getTagSection(const bool bCommon=false) const;
+	string getSection(const bool bCommon=false) const;
+	QMap <QWidget*, QString> parents;
+	QString settingsTag;
+	const QString windowName;
+	bool bHide;
+	CEventFilter ef;
+
+protected:
+	virtual void eventClose(QCloseEvent*);
+	virtual void eventHide(QHideEvent*);
+	virtual void eventShow(QShowEvent*);
+	CSettings& Settings;
+
+public slots:
+	virtual void setVisible(bool visible);
+	void OnShowWindow(QWidget* window, bool bVisible);
+	void OnCloseWindow(QWidget* window);
+	void OnDeleteWindow(QWidget* window);
+
+signals:
+	void showWindow(QWidget* window, bool bVisible);
+	void closeWindow(QWidget* window);
+	void deleteWindow(QWidget* window);
+};
+
+#endif
diff --git a/src/GUI-QT/CodecParams.cpp b/src/GUI-QT/CodecParams.cpp
new file mode 100644
index 0000000..9d48996
--- /dev/null
+++ b/src/GUI-QT/CodecParams.cpp
@@ -0,0 +1,305 @@
+/******************************************************************************\
+ *
+ * Copyright (c) 2001-2014-2001-2014
+ *
+ * Author(s):
+ *  David Flamand
+ *
+ * Description:
+ *  Opus Codec Parameters Dialog
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include <QPushButton>
+#include <QString>
+#include <QLabel>
+#include <QRadioButton>
+#include <QButtonGroup>
+#include <QLayout>
+#include "CodecParams.h"
+#include "DialogUtil.h"
+#include "../util-QT/Util.h"
+#include "../DrmTransmitter.h"
+#include "../sourcedecoders/opus_codec.h"
+
+
+CodecParams::CodecParams(CSettings& Settings, CParameter& Parameters,
+	int iShortID, QWidget* parent)
+	:
+	QDialog(parent), Settings(Settings), Parameters(Parameters),
+	iShortID(iShortID), bWasVisible(FALSE), bLastPositionValid(FALSE)
+{
+	setAttribute(Qt::WA_QuitOnClose, false);
+	setupUi(this);
+
+	/* Recover window size and position */
+	CWinGeom s;
+	Settings.Get("Codec Dialog", s);
+	if (s.iXPos && s.iYPos)
+		move(s.iXPos, s.iYPos);
+
+	QString strWebSite(OPUS_WEBSITE_LINK);
+	LabelInfoDescription->setText(tr(OPUS_DESCRIPTION));
+	LabelInfoVersion->setText(opusGetVersion());
+	LabelInfoWebSite->setText(Linkify(strWebSite));
+
+	Parameters.Lock();
+	/* Channels */
+	switch (Parameters.Service[iShortID].AudioParam.eOPUSChan)
+	{
+	case CAudioParam::OC_MONO:
+		RadioButtonChannelsMono->setChecked(TRUE);
+		break;
+	case CAudioParam::OC_STEREO:
+		RadioButtonChannelsStereo->setChecked(TRUE);
+		break;
+	}
+	/* Bandwith */
+	switch (Parameters.Service[iShortID].AudioParam.eOPUSBandwidth)
+	{
+	case CAudioParam::OB_NB:
+		RadioButtonBandwidthNB->setChecked(TRUE);
+		break;
+	case CAudioParam::OB_MB:
+		RadioButtonBandwidthMB->setChecked(TRUE);
+		break;
+	case CAudioParam::OB_WB:
+		RadioButtonBandwidthWB->setChecked(TRUE);
+		break;
+	case CAudioParam::OB_SWB:
+		RadioButtonBandwidthSWB->setChecked(TRUE);
+		break;
+	case CAudioParam::OB_FB:
+		RadioButtonBandwidthFB->setChecked(TRUE);
+		break;
+	}
+	/* FEC */
+	if (Parameters.Service[iShortID].AudioParam.bOPUSForwardErrorCorrection)
+		RadioButtonFECOn->setChecked(TRUE);
+	else
+		RadioButtonFECOff->setChecked(TRUE);
+	/* Signal */
+	switch (Parameters.Service[iShortID].AudioParam.eOPUSSignal)
+	{
+	case CAudioParam::OG_VOICE:
+		RadioButtonSignalVoice->setChecked(TRUE);
+		break;
+	case CAudioParam::OG_MUSIC:
+		RadioButtonSignalMusic->setChecked(TRUE);
+		break;
+	}
+	/* Application */
+	switch (Parameters.Service[iShortID].AudioParam.eOPUSApplication)
+	{
+	case CAudioParam::OA_VOIP:
+		RadioButtonAppVOIP->setChecked(TRUE);
+		break;
+	case CAudioParam::OA_AUDIO:
+		RadioButtonAppAudio->setChecked(TRUE);
+		break;
+	}
+	Parameters.Unlock();
+
+	/* Connections */
+	connect(ButtonGroupChannels, SIGNAL(buttonClicked(int)),
+		this, SLOT(OnButtonGroupChannels(int)));
+	connect(ButtonGroupBandwidth, SIGNAL(buttonClicked(int)),
+		this, SLOT(OnButtonGroupBandwidth(int)));
+	connect(ButtonGroupFEC, SIGNAL(buttonClicked(int)),
+		this, SLOT(OnButtonGroupFEC(int)));
+	connect(ButtonGroupSignal, SIGNAL(buttonClicked(int)),
+		this, SLOT(OnButtonGroupSignal(int)));
+	connect(ButtonGroupApplication, SIGNAL(buttonClicked(int)),
+		this, SLOT(OnButtonGroupApplication(int)));
+}
+
+CodecParams::~CodecParams()
+{
+	/* Save window position */
+	CWinGeom s;
+	if (bLastPositionValid)
+	{
+		s.iXPos = iLastXPosition;
+		s.iYPos = iLastYPosition;
+	}
+	else {
+		QRect WinGeom = geometry();
+		if (WinGeom.isValid() && !WinGeom.isEmpty() && !WinGeom.isNull()) {
+			s.iXPos = WinGeom.x();
+			s.iYPos = WinGeom.y();
+		}
+	}
+	Settings.Put("Codec Dialog", s);
+}
+
+void CodecParams::reject()
+{ 
+	GetDialogPosition();
+	QDialog::reject();
+}
+
+void CodecParams::OnButtonGroupChannels(int iID)
+{
+	iID = -iID - 2; // TODO understand why
+	CAudioParam::EOPUSChan eOPUSChan;
+	switch (iID)
+	{
+	case 0:
+		eOPUSChan = CAudioParam::OC_MONO;
+		break;
+	default:
+	case 1:
+		eOPUSChan = CAudioParam::OC_STEREO;
+		break;
+	}
+	Parameters.Lock();
+	Parameters.Service[iShortID].AudioParam.eOPUSChan = eOPUSChan;
+	Parameters.Service[iShortID].AudioParam.bParamChanged = TRUE;
+	Parameters.Unlock();
+}
+
+void CodecParams::OnButtonGroupBandwidth(int iID)
+{
+	iID = -iID - 2; // TODO understand why
+	CAudioParam::EOPUSBandwidth eOPUSBandwidth;
+	switch (iID)
+	{
+	case 0:
+		eOPUSBandwidth = CAudioParam::OB_NB;
+		break;
+	case 1:
+		eOPUSBandwidth = CAudioParam::OB_MB;
+		break;
+	case 2:
+		eOPUSBandwidth = CAudioParam::OB_WB;
+		break;
+	case 3:
+		eOPUSBandwidth = CAudioParam::OB_SWB;
+		break;
+	default:
+	case 4:
+		eOPUSBandwidth = CAudioParam::OB_FB;
+		break;
+	}
+	Parameters.Lock();
+	Parameters.Service[iShortID].AudioParam.eOPUSBandwidth = eOPUSBandwidth;
+	Parameters.Service[iShortID].AudioParam.bParamChanged = TRUE;
+	Parameters.Unlock();
+}
+
+void CodecParams::OnButtonGroupFEC(int iID)
+{
+	iID = -iID - 2; // TODO understand why
+	_BOOLEAN bOPUSForwardErrorCorrection;
+	switch (iID)
+	{
+	default:
+	case 0:
+		bOPUSForwardErrorCorrection = FALSE;
+		break;
+	case 1:
+		bOPUSForwardErrorCorrection = TRUE;
+		break;
+	}
+	Parameters.Lock();
+	Parameters.Service[iShortID].AudioParam.bOPUSForwardErrorCorrection = bOPUSForwardErrorCorrection;
+	Parameters.Service[iShortID].AudioParam.bParamChanged = TRUE;
+	Parameters.Unlock();
+}
+
+void CodecParams::OnButtonGroupSignal(int iID)
+{
+	iID = -iID - 2; // TODO understand why
+	CAudioParam::EOPUSSignal eOPUSSignal;
+	switch (iID)
+	{
+	case 0:
+		eOPUSSignal = CAudioParam::OG_VOICE;
+		break;
+	default:
+	case 1:
+		eOPUSSignal = CAudioParam::OG_MUSIC;
+		break;
+	}
+	Parameters.Lock();
+	Parameters.Service[iShortID].AudioParam.eOPUSSignal = eOPUSSignal;
+	Parameters.Service[iShortID].AudioParam.bOPUSRequestReset = TRUE;
+	Parameters.Service[iShortID].AudioParam.bParamChanged = TRUE;
+	Parameters.Unlock();
+}
+
+void CodecParams::OnButtonGroupApplication(int iID)
+{
+	iID = -iID - 2; // TODO understand why
+	CAudioParam::EOPUSApplication eOPUSApplication;
+	switch (iID)
+	{
+	case 0:
+		eOPUSApplication = CAudioParam::OA_VOIP;
+		break;
+	default:
+	case 1:
+		eOPUSApplication = CAudioParam::OA_AUDIO;
+		break;
+	}
+	Parameters.Lock();
+	Parameters.Service[iShortID].AudioParam.eOPUSApplication = eOPUSApplication;
+	Parameters.Service[iShortID].AudioParam.bOPUSRequestReset = TRUE;
+	Parameters.Service[iShortID].AudioParam.bParamChanged = TRUE;
+	Parameters.Unlock();
+}
+
+void CodecParams::Toggle(void)
+{
+	bWasVisible = isVisible();
+	if (bWasVisible)
+	{
+		GetDialogPosition();
+		hide();
+	}
+	else
+		show();
+}
+
+void CodecParams::Show(bool bShow)
+{
+	if (bShow)
+	{
+		if (bWasVisible)
+			show();
+	}
+	else {
+		bWasVisible = isVisible();
+		if (bWasVisible)
+			GetDialogPosition();
+		hide();
+	}
+}
+
+void CodecParams::GetDialogPosition(void)
+{
+	QRect WinGeom = geometry();
+	if (WinGeom.isValid() && !WinGeom.isEmpty() && !WinGeom.isNull())
+	{
+		iLastXPosition = WinGeom.x();
+		iLastYPosition = WinGeom.y();
+		bLastPositionValid = TRUE;
+	}
+}
+
diff --git a/src/GUI-QT/CodecParams.h b/src/GUI-QT/CodecParams.h
new file mode 100644
index 0000000..096ca97
--- /dev/null
+++ b/src/GUI-QT/CodecParams.h
@@ -0,0 +1,62 @@
+/******************************************************************************\
+ *
+ * Copyright (c) 2001-2014-2001-2014
+ *
+ * Author(s):
+ *  David Flamand
+ *
+ * Description:
+ *  See CodecParams.cpp
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later 
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT 
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include <QDialog>
+#include "ui_CodecParams.h"
+#include "../Parameter.h"
+#include "../util/Settings.h"
+
+class CodecParams : public QDialog, public Ui_CodecParams
+{
+	Q_OBJECT
+
+public:
+	CodecParams(CSettings&, CParameter&, int iShortID,
+		QWidget* parent = 0);
+	virtual ~CodecParams();
+	void Toggle(void);
+	void Show(bool bShow);
+
+protected:
+	CSettings&		Settings;
+	CParameter&		Parameters;
+	const int		iShortID;
+	bool			bWasVisible;
+	int				iLastXPosition;
+	int				iLastYPosition;
+	bool			bLastPositionValid;
+	void			GetDialogPosition(void);
+	virtual void	reject();
+
+public slots:
+	void OnButtonGroupChannels(int iID);
+	void OnButtonGroupBandwidth(int iID);
+	void OnButtonGroupFEC(int iID);
+	void OnButtonGroupSignal(int iID);
+	void OnButtonGroupApplication(int iID);
+};
diff --git a/src/GUI-QT/CodecParams.ui b/src/GUI-QT/CodecParams.ui
new file mode 100644
index 0000000..0e9dfaf
--- /dev/null
+++ b/src/GUI-QT/CodecParams.ui
@@ -0,0 +1,493 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>CodecParams</class>
+ <widget class="QDialog" name="CodecParams">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>447</width>
+    <height>345</height>
+   </rect>
+  </property>
+  <property name="sizePolicy">
+   <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+    <horstretch>0</horstretch>
+    <verstretch>0</verstretch>
+   </sizepolicy>
+  </property>
+  <property name="windowTitle">
+   <string>Codec Parameters</string>
+  </property>
+  <property name="windowIcon">
+   <iconset resource="res/icons.qrc">
+    <normaloff>:/icons/MainIconTx.svg</normaloff>:/icons/MainIconTx.svg</iconset>
+  </property>
+  <layout class="QGridLayout">
+   <item row="0" column="0" colspan="2">
+    <widget class="QGroupBox" name="GroupBoxInfo">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
+     </property>
+     <property name="title">
+      <string>Codec Information</string>
+     </property>
+     <layout class="QHBoxLayout">
+      <item>
+       <widget class="QLabel" name="Logo">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="pixmap">
+         <pixmap resource="res/icons.qrc">:/icons/LogoOpus.png</pixmap>
+        </property>
+        <property name="scaledContents">
+         <bool>false</bool>
+        </property>
+        <property name="wordWrap">
+         <bool>false</bool>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <spacer name="spacer1">
+        <property name="orientation">
+         <enum>Qt::Horizontal</enum>
+        </property>
+        <property name="sizeType">
+         <enum>QSizePolicy::Fixed</enum>
+        </property>
+        <property name="sizeHint" stdset="0">
+         <size>
+          <width>10</width>
+          <height>20</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+      <item>
+       <layout class="QVBoxLayout">
+        <property name="spacing">
+         <number>0</number>
+        </property>
+        <property name="margin">
+         <number>0</number>
+        </property>
+        <item>
+         <widget class="QLabel" name="LabelInfoDescription">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="text">
+           <string>Description</string>
+          </property>
+          <property name="wordWrap">
+           <bool>false</bool>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <layout class="QHBoxLayout">
+          <property name="spacing">
+           <number>0</number>
+          </property>
+          <property name="margin">
+           <number>0</number>
+          </property>
+          <item>
+           <widget class="QLabel" name="LabelVersion">
+            <property name="sizePolicy">
+             <sizepolicy hsizetype="Minimum" vsizetype="MinimumExpanding">
+              <horstretch>0</horstretch>
+              <verstretch>0</verstretch>
+             </sizepolicy>
+            </property>
+            <property name="text">
+             <string>Version: </string>
+            </property>
+            <property name="alignment">
+             <set>Qt::AlignVCenter</set>
+            </property>
+            <property name="wordWrap">
+             <bool>false</bool>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QLabel" name="LabelInfoVersion">
+            <property name="sizePolicy">
+             <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
+              <horstretch>0</horstretch>
+              <verstretch>0</verstretch>
+             </sizepolicy>
+            </property>
+            <property name="text">
+             <string>_ver_</string>
+            </property>
+            <property name="wordWrap">
+             <bool>false</bool>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </item>
+        <item>
+         <widget class="QLabel" name="LabelInfoWebSite">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="acceptDrops">
+           <bool>false</bool>
+          </property>
+          <property name="text">
+           <string>Website</string>
+          </property>
+          <property name="wordWrap">
+           <bool>false</bool>
+          </property>
+          <property name="openExternalLinks">
+           <bool>true</bool>
+          </property>
+          <property name="textInteractionFlags">
+           <set>Qt::LinksAccessibleByMouse</set>
+          </property>
+         </widget>
+        </item>
+       </layout>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item row="1" column="1">
+    <layout class="QVBoxLayout">
+     <item>
+      <widget class="QGroupBox" name="GroupBoxApplication">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Minimum" vsizetype="MinimumExpanding">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="title">
+        <string>Application</string>
+       </property>
+       <layout class="QHBoxLayout">
+        <item>
+         <widget class="QRadioButton" name="RadioButtonAppVOIP">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Minimum" vsizetype="MinimumExpanding">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="text">
+           <string>VoIP</string>
+          </property>
+          <attribute name="buttonGroup">
+           <string notr="true">ButtonGroupApplication</string>
+          </attribute>
+         </widget>
+        </item>
+        <item>
+         <widget class="QRadioButton" name="RadioButtonAppAudio">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Minimum" vsizetype="MinimumExpanding">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="text">
+           <string>Audio</string>
+          </property>
+          <attribute name="buttonGroup">
+           <string notr="true">ButtonGroupApplication</string>
+          </attribute>
+         </widget>
+        </item>
+       </layout>
+      </widget>
+     </item>
+     <item>
+      <widget class="QGroupBox" name="GroupBoxSignal">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Minimum" vsizetype="MinimumExpanding">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="title">
+        <string>Signal</string>
+       </property>
+       <layout class="QHBoxLayout">
+        <item>
+         <widget class="QRadioButton" name="RadioButtonSignalVoice">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Minimum" vsizetype="MinimumExpanding">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="text">
+           <string>Voice</string>
+          </property>
+          <attribute name="buttonGroup">
+           <string notr="true">ButtonGroupSignal</string>
+          </attribute>
+         </widget>
+        </item>
+        <item>
+         <widget class="QRadioButton" name="RadioButtonSignalMusic">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Minimum" vsizetype="MinimumExpanding">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="text">
+           <string>Music</string>
+          </property>
+          <attribute name="buttonGroup">
+           <string notr="true">ButtonGroupSignal</string>
+          </attribute>
+         </widget>
+        </item>
+       </layout>
+      </widget>
+     </item>
+     <item>
+      <widget class="QGroupBox" name="GroupBoxFEC">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Minimum" vsizetype="MinimumExpanding">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="title">
+        <string>Forward Error Correction</string>
+       </property>
+       <layout class="QHBoxLayout">
+        <item>
+         <widget class="QRadioButton" name="RadioButtonFECOff">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Minimum" vsizetype="MinimumExpanding">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="text">
+           <string>Off</string>
+          </property>
+          <attribute name="buttonGroup">
+           <string notr="true">ButtonGroupFEC</string>
+          </attribute>
+         </widget>
+        </item>
+        <item>
+         <widget class="QRadioButton" name="RadioButtonFECOn">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Minimum" vsizetype="MinimumExpanding">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="text">
+           <string>On</string>
+          </property>
+          <attribute name="buttonGroup">
+           <string notr="true">ButtonGroupFEC</string>
+          </attribute>
+         </widget>
+        </item>
+       </layout>
+      </widget>
+     </item>
+    </layout>
+   </item>
+   <item row="1" column="0">
+    <layout class="QVBoxLayout">
+     <item>
+      <widget class="QGroupBox" name="GroupBoxChannels">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Minimum" vsizetype="MinimumExpanding">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="title">
+        <string>Channels</string>
+       </property>
+       <layout class="QHBoxLayout">
+        <item>
+         <widget class="QRadioButton" name="RadioButtonChannelsMono">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Minimum" vsizetype="MinimumExpanding">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="text">
+           <string>Mono</string>
+          </property>
+          <attribute name="buttonGroup">
+           <string notr="true">ButtonGroupChannels</string>
+          </attribute>
+         </widget>
+        </item>
+        <item>
+         <widget class="QRadioButton" name="RadioButtonChannelsStereo">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Minimum" vsizetype="MinimumExpanding">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="text">
+           <string>Stereo</string>
+          </property>
+          <attribute name="buttonGroup">
+           <string notr="true">ButtonGroupChannels</string>
+          </attribute>
+         </widget>
+        </item>
+       </layout>
+      </widget>
+     </item>
+     <item>
+      <widget class="QGroupBox" name="GroupBoxBandwidth">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Minimum" vsizetype="MinimumExpanding">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="title">
+        <string>Bandwidth</string>
+       </property>
+       <layout class="QVBoxLayout">
+        <item>
+         <widget class="QRadioButton" name="RadioButtonBandwidthNB">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Minimum" vsizetype="MinimumExpanding">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="text">
+           <string>Narrow Band (4 kHz)</string>
+          </property>
+          <attribute name="buttonGroup">
+           <string notr="true">ButtonGroupBandwidth</string>
+          </attribute>
+         </widget>
+        </item>
+        <item>
+         <widget class="QRadioButton" name="RadioButtonBandwidthMB">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Minimum" vsizetype="MinimumExpanding">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="text">
+           <string>Medium Band (6 kHz)</string>
+          </property>
+          <attribute name="buttonGroup">
+           <string notr="true">ButtonGroupBandwidth</string>
+          </attribute>
+         </widget>
+        </item>
+        <item>
+         <widget class="QRadioButton" name="RadioButtonBandwidthWB">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Minimum" vsizetype="MinimumExpanding">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="text">
+           <string>Wide Band (8 kHz)</string>
+          </property>
+          <attribute name="buttonGroup">
+           <string notr="true">ButtonGroupBandwidth</string>
+          </attribute>
+         </widget>
+        </item>
+        <item>
+         <widget class="QRadioButton" name="RadioButtonBandwidthSWB">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Minimum" vsizetype="MinimumExpanding">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="text">
+           <string>Super Wide Band (12 kHz)</string>
+          </property>
+          <attribute name="buttonGroup">
+           <string notr="true">ButtonGroupBandwidth</string>
+          </attribute>
+         </widget>
+        </item>
+        <item>
+         <widget class="QRadioButton" name="RadioButtonBandwidthFB">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="text">
+           <string>Full Band (20 kHz)</string>
+          </property>
+          <attribute name="buttonGroup">
+           <string notr="true">ButtonGroupBandwidth</string>
+          </attribute>
+         </widget>
+        </item>
+       </layout>
+      </widget>
+     </item>
+    </layout>
+   </item>
+  </layout>
+ </widget>
+ <layoutdefault spacing="6" margin="11"/>
+ <tabstops>
+  <tabstop>RadioButtonChannelsMono</tabstop>
+  <tabstop>RadioButtonChannelsStereo</tabstop>
+  <tabstop>RadioButtonBandwidthNB</tabstop>
+  <tabstop>RadioButtonBandwidthMB</tabstop>
+  <tabstop>RadioButtonBandwidthWB</tabstop>
+  <tabstop>RadioButtonBandwidthSWB</tabstop>
+  <tabstop>RadioButtonBandwidthFB</tabstop>
+  <tabstop>RadioButtonAppVOIP</tabstop>
+  <tabstop>RadioButtonAppAudio</tabstop>
+  <tabstop>RadioButtonSignalVoice</tabstop>
+  <tabstop>RadioButtonSignalMusic</tabstop>
+  <tabstop>RadioButtonFECOff</tabstop>
+  <tabstop>RadioButtonFECOn</tabstop>
+ </tabstops>
+ <resources>
+  <include location="res/icons.qrc"/>
+ </resources>
+ <connections/>
+ <buttongroups>
+  <buttongroup name="ButtonGroupChannels"/>
+  <buttongroup name="ButtonGroupSignal"/>
+  <buttongroup name="ButtonGroupFEC"/>
+  <buttongroup name="ButtonGroupBandwidth"/>
+  <buttongroup name="ButtonGroupApplication"/>
+ </buttongroups>
+</ui>
diff --git a/src/GUI-QT/DRMMainWindow.ui b/src/GUI-QT/DRMMainWindow.ui
new file mode 100644
index 0000000..9d3d4c9
--- /dev/null
+++ b/src/GUI-QT/DRMMainWindow.ui
@@ -0,0 +1,9432 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>DRMMainWindow</class>
+ <widget class="QMainWindow" name="DRMMainWindow">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>484</width>
+    <height>212</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Dream</string>
+  </property>
+  <property name="windowIcon">
+   <iconset resource="res/icons.qrc">
+    <normaloff>:/icons/MainIcon.svg</normaloff>:/icons/MainIcon.svg</iconset>
+  </property>
+  <widget class="QWidget" name="centralwidget">
+   <layout class="QVBoxLayout" name="verticalLayout">
+    <item>
+     <widget class="QFrame" name="FrameMainDisplay">
+      <property name="sizePolicy">
+       <sizepolicy hsizetype="Expanding" vsizetype="Minimum">
+        <horstretch>0</horstretch>
+        <verstretch>0</verstretch>
+       </sizepolicy>
+      </property>
+      <property name="palette">
+       <palette>
+        <active>
+         <colorrole role="WindowText">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>255</red>
+            <green>0</green>
+            <blue>0</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="Button">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>255</red>
+            <green>0</green>
+            <blue>0</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="Light">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>255</red>
+            <green>127</green>
+            <blue>127</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="Midlight">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>255</red>
+            <green>63</green>
+            <blue>63</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="Dark">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>127</red>
+            <green>0</green>
+            <blue>0</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="Mid">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>170</red>
+            <green>0</green>
+            <blue>0</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="Text">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>0</red>
+            <green>0</green>
+            <blue>0</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="BrightText">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>255</red>
+            <green>255</green>
+            <blue>255</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="ButtonText">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>0</red>
+            <green>0</green>
+            <blue>0</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="Base">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>255</red>
+            <green>255</green>
+            <blue>255</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="Window">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>0</red>
+            <green>0</green>
+            <blue>0</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="Shadow">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>0</red>
+            <green>0</green>
+            <blue>0</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="Highlight">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>0</red>
+            <green>0</green>
+            <blue>128</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="HighlightedText">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>255</red>
+            <green>255</green>
+            <blue>255</blue>
+           </color>
+          </brush>
+         </colorrole>
+        </active>
+        <inactive>
+         <colorrole role="WindowText">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>255</red>
+            <green>0</green>
+            <blue>0</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="Button">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>255</red>
+            <green>0</green>
+            <blue>0</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="Light">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>255</red>
+            <green>127</green>
+            <blue>127</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="Midlight">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>255</red>
+            <green>38</green>
+            <blue>38</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="Dark">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>127</red>
+            <green>0</green>
+            <blue>0</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="Mid">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>170</red>
+            <green>0</green>
+            <blue>0</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="Text">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>0</red>
+            <green>0</green>
+            <blue>0</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="BrightText">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>255</red>
+            <green>255</green>
+            <blue>255</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="ButtonText">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>0</red>
+            <green>0</green>
+            <blue>0</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="Base">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>255</red>
+            <green>255</green>
+            <blue>255</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="Window">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>0</red>
+            <green>0</green>
+            <blue>0</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="Shadow">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>0</red>
+            <green>0</green>
+            <blue>0</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="Highlight">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>0</red>
+            <green>0</green>
+            <blue>128</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="HighlightedText">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>255</red>
+            <green>255</green>
+            <blue>255</blue>
+           </color>
+          </brush>
+         </colorrole>
+        </inactive>
+        <disabled>
+         <colorrole role="WindowText">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>128</red>
+            <green>128</green>
+            <blue>128</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="Button">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>255</red>
+            <green>0</green>
+            <blue>0</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="Light">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>255</red>
+            <green>127</green>
+            <blue>127</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="Midlight">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>255</red>
+            <green>38</green>
+            <blue>38</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="Dark">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>127</red>
+            <green>0</green>
+            <blue>0</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="Mid">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>170</red>
+            <green>0</green>
+            <blue>0</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="Text">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>0</red>
+            <green>0</green>
+            <blue>0</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="BrightText">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>255</red>
+            <green>255</green>
+            <blue>255</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="ButtonText">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>128</red>
+            <green>128</green>
+            <blue>128</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="Base">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>255</red>
+            <green>255</green>
+            <blue>255</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="Window">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>0</red>
+            <green>0</green>
+            <blue>0</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="Shadow">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>0</red>
+            <green>0</green>
+            <blue>0</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="Highlight">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>0</red>
+            <green>0</green>
+            <blue>128</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="HighlightedText">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>255</red>
+            <green>255</green>
+            <blue>255</blue>
+           </color>
+          </brush>
+         </colorrole>
+        </disabled>
+       </palette>
+      </property>
+      <property name="autoFillBackground">
+       <bool>true</bool>
+      </property>
+      <property name="frameShape">
+       <enum>QFrame::StyledPanel</enum>
+      </property>
+      <property name="frameShadow">
+       <enum>QFrame::Raised</enum>
+      </property>
+      <property name="lineWidth">
+       <number>1</number>
+      </property>
+      <layout class="QGridLayout" name="gridLayout">
+       <item row="0" column="2" rowspan="2">
+        <widget class="QLabel" name="TextTextMessage">
+         <property name="sizePolicy">
+          <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+           <horstretch>0</horstretch>
+           <verstretch>0</verstretch>
+          </sizepolicy>
+         </property>
+         <property name="minimumSize">
+          <size>
+           <width>160</width>
+           <height>80</height>
+          </size>
+         </property>
+         <property name="palette">
+          <palette>
+           <active>
+            <colorrole role="WindowText">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>0</red>
+               <green>0</green>
+               <blue>0</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Button">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>255</red>
+               <green>0</green>
+               <blue>0</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Light">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>255</red>
+               <green>127</green>
+               <blue>127</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Midlight">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>255</red>
+               <green>63</green>
+               <blue>63</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Dark">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>127</red>
+               <green>0</green>
+               <blue>0</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Mid">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>170</red>
+               <green>0</green>
+               <blue>0</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Text">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>255</red>
+               <green>0</green>
+               <blue>255</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="BrightText">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>255</red>
+               <green>255</green>
+               <blue>255</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="ButtonText">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>0</red>
+               <green>0</green>
+               <blue>0</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Base">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>255</red>
+               <green>255</green>
+               <blue>255</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Window">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>255</red>
+               <green>255</green>
+               <blue>255</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Shadow">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>0</red>
+               <green>0</green>
+               <blue>0</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Highlight">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>10</red>
+               <green>36</green>
+               <blue>106</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="HighlightedText">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>255</red>
+               <green>255</green>
+               <blue>255</blue>
+              </color>
+             </brush>
+            </colorrole>
+           </active>
+           <inactive>
+            <colorrole role="WindowText">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>0</red>
+               <green>0</green>
+               <blue>0</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Button">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>255</red>
+               <green>0</green>
+               <blue>0</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Light">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>255</red>
+               <green>127</green>
+               <blue>127</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Midlight">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>255</red>
+               <green>38</green>
+               <blue>38</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Dark">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>127</red>
+               <green>0</green>
+               <blue>0</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Mid">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>170</red>
+               <green>0</green>
+               <blue>0</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Text">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>255</red>
+               <green>0</green>
+               <blue>255</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="BrightText">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>255</red>
+               <green>255</green>
+               <blue>255</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="ButtonText">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>0</red>
+               <green>0</green>
+               <blue>0</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Base">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>255</red>
+               <green>255</green>
+               <blue>255</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Window">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>255</red>
+               <green>255</green>
+               <blue>255</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Shadow">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>0</red>
+               <green>0</green>
+               <blue>0</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Highlight">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>10</red>
+               <green>36</green>
+               <blue>106</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="HighlightedText">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>255</red>
+               <green>255</green>
+               <blue>255</blue>
+              </color>
+             </brush>
+            </colorrole>
+           </inactive>
+           <disabled>
+            <colorrole role="WindowText">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>128</red>
+               <green>128</green>
+               <blue>128</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Button">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>255</red>
+               <green>0</green>
+               <blue>0</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Light">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>255</red>
+               <green>127</green>
+               <blue>127</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Midlight">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>255</red>
+               <green>38</green>
+               <blue>38</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Dark">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>127</red>
+               <green>0</green>
+               <blue>0</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Mid">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>170</red>
+               <green>0</green>
+               <blue>0</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Text">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>255</red>
+               <green>0</green>
+               <blue>255</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="BrightText">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>255</red>
+               <green>255</green>
+               <blue>255</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="ButtonText">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>128</red>
+               <green>128</green>
+               <blue>128</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Base">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>255</red>
+               <green>255</green>
+               <blue>255</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Window">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>255</red>
+               <green>255</green>
+               <blue>255</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Shadow">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>0</red>
+               <green>0</green>
+               <blue>0</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="Highlight">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>10</red>
+               <green>36</green>
+               <blue>106</blue>
+              </color>
+             </brush>
+            </colorrole>
+            <colorrole role="HighlightedText">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>255</red>
+               <green>255</green>
+               <blue>255</blue>
+              </color>
+             </brush>
+            </colorrole>
+           </disabled>
+          </palette>
+         </property>
+         <property name="autoFillBackground">
+          <bool>true</bool>
+         </property>
+         <property name="frameShape">
+          <enum>QFrame::Panel</enum>
+         </property>
+         <property name="frameShadow">
+          <enum>QFrame::Sunken</enum>
+         </property>
+         <property name="lineWidth">
+          <number>2</number>
+         </property>
+         <property name="text">
+          <string>TextTextMessage</string>
+         </property>
+         <property name="textFormat">
+          <enum>Qt::RichText</enum>
+         </property>
+         <property name="alignment">
+          <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+         </property>
+         <property name="wordWrap">
+          <bool>true</bool>
+         </property>
+         <property name="openExternalLinks">
+          <bool>true</bool>
+         </property>
+        </widget>
+       </item>
+       <item row="0" column="1" rowspan="2">
+        <layout class="QVBoxLayout" name="_10">
+         <property name="spacing">
+          <number>1</number>
+         </property>
+         <property name="margin">
+          <number>0</number>
+         </property>
+         <item>
+          <widget class="QFrame" name="FrameAudioDataParams">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="palette">
+            <palette>
+             <active>
+              <colorrole role="WindowText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Button">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Light">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>127</green>
+                 <blue>127</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Midlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>63</green>
+                 <blue>63</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Dark">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>127</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Mid">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>170</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Text">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="BrightText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ButtonText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Base">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Window">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Shadow">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Highlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>128</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="HighlightedText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+             </active>
+             <inactive>
+              <colorrole role="WindowText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Button">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Light">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>127</green>
+                 <blue>127</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Midlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>38</green>
+                 <blue>38</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Dark">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>127</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Mid">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>170</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Text">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="BrightText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ButtonText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Base">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Window">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Shadow">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Highlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>128</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="HighlightedText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+             </inactive>
+             <disabled>
+              <colorrole role="WindowText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>128</red>
+                 <green>128</green>
+                 <blue>128</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Button">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Light">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>127</green>
+                 <blue>127</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Midlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>38</green>
+                 <blue>38</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Dark">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>127</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Mid">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>170</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Text">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="BrightText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ButtonText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>128</red>
+                 <green>128</green>
+                 <blue>128</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Base">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Window">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Shadow">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Highlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>128</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="HighlightedText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+             </disabled>
+            </palette>
+           </property>
+           <property name="frameShape">
+            <enum>QFrame::Box</enum>
+           </property>
+           <property name="frameShadow">
+            <enum>QFrame::Plain</enum>
+           </property>
+           <property name="lineWidth">
+            <number>2</number>
+           </property>
+           <layout class="QHBoxLayout" name="_11">
+            <property name="spacing">
+             <number>6</number>
+            </property>
+            <property name="margin">
+             <number>5</number>
+            </property>
+            <item>
+             <widget class="QLabel" name="LabelBitrate">
+              <property name="palette">
+               <palette>
+                <active>
+                 <colorrole role="WindowText">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>255</red>
+                    <green>0</green>
+                    <blue>0</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Button">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>212</red>
+                    <green>208</green>
+                    <blue>200</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Light">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>255</red>
+                    <green>255</green>
+                    <blue>255</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Midlight">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>233</red>
+                    <green>231</green>
+                    <blue>227</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Dark">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>106</red>
+                    <green>104</green>
+                    <blue>100</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Mid">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>141</red>
+                    <green>138</green>
+                    <blue>133</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Text">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>0</red>
+                    <green>0</green>
+                    <blue>0</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="BrightText">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>255</red>
+                    <green>255</green>
+                    <blue>255</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="ButtonText">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>0</red>
+                    <green>0</green>
+                    <blue>0</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Base">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>255</red>
+                    <green>255</green>
+                    <blue>255</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Window">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>0</red>
+                    <green>0</green>
+                    <blue>0</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Shadow">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>0</red>
+                    <green>0</green>
+                    <blue>0</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Highlight">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>10</red>
+                    <green>36</green>
+                    <blue>106</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="HighlightedText">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>255</red>
+                    <green>255</green>
+                    <blue>255</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                </active>
+                <inactive>
+                 <colorrole role="WindowText">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>255</red>
+                    <green>0</green>
+                    <blue>0</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Button">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>212</red>
+                    <green>208</green>
+                    <blue>200</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Light">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>255</red>
+                    <green>255</green>
+                    <blue>255</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Midlight">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>243</red>
+                    <green>239</green>
+                    <blue>230</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Dark">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>106</red>
+                    <green>104</green>
+                    <blue>100</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Mid">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>141</red>
+                    <green>138</green>
+                    <blue>133</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Text">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>0</red>
+                    <green>0</green>
+                    <blue>0</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="BrightText">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>255</red>
+                    <green>255</green>
+                    <blue>255</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="ButtonText">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>0</red>
+                    <green>0</green>
+                    <blue>0</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Base">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>255</red>
+                    <green>255</green>
+                    <blue>255</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Window">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>0</red>
+                    <green>0</green>
+                    <blue>0</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Shadow">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>0</red>
+                    <green>0</green>
+                    <blue>0</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Highlight">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>10</red>
+                    <green>36</green>
+                    <blue>106</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="HighlightedText">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>255</red>
+                    <green>255</green>
+                    <blue>255</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                </inactive>
+                <disabled>
+                 <colorrole role="WindowText">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>128</red>
+                    <green>128</green>
+                    <blue>128</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Button">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>212</red>
+                    <green>208</green>
+                    <blue>200</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Light">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>255</red>
+                    <green>255</green>
+                    <blue>255</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Midlight">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>243</red>
+                    <green>239</green>
+                    <blue>230</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Dark">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>106</red>
+                    <green>104</green>
+                    <blue>100</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Mid">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>141</red>
+                    <green>138</green>
+                    <blue>133</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Text">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>0</red>
+                    <green>0</green>
+                    <blue>0</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="BrightText">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>255</red>
+                    <green>255</green>
+                    <blue>255</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="ButtonText">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>128</red>
+                    <green>128</green>
+                    <blue>128</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Base">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>255</red>
+                    <green>255</green>
+                    <blue>255</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Window">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>0</red>
+                    <green>0</green>
+                    <blue>0</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Shadow">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>0</red>
+                    <green>0</green>
+                    <blue>0</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Highlight">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>10</red>
+                    <green>36</green>
+                    <blue>106</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="HighlightedText">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>255</red>
+                    <green>255</green>
+                    <blue>255</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                </disabled>
+               </palette>
+              </property>
+              <property name="font">
+               <font>
+                <family>Arial</family>
+                <pointsize>10</pointsize>
+                <weight>75</weight>
+                <bold>true</bold>
+               </font>
+              </property>
+              <property name="text">
+               <string>15 kbps</string>
+              </property>
+              <property name="alignment">
+               <set>Qt::AlignCenter</set>
+              </property>
+              <property name="wordWrap">
+               <bool>false</bool>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QLabel" name="LabelCodec">
+              <property name="palette">
+               <palette>
+                <active>
+                 <colorrole role="WindowText">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>255</red>
+                    <green>0</green>
+                    <blue>0</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Button">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>212</red>
+                    <green>208</green>
+                    <blue>200</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Light">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>255</red>
+                    <green>255</green>
+                    <blue>255</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Midlight">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>233</red>
+                    <green>231</green>
+                    <blue>227</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Dark">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>106</red>
+                    <green>104</green>
+                    <blue>100</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Mid">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>141</red>
+                    <green>138</green>
+                    <blue>133</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Text">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>0</red>
+                    <green>0</green>
+                    <blue>0</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="BrightText">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>255</red>
+                    <green>255</green>
+                    <blue>255</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="ButtonText">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>0</red>
+                    <green>0</green>
+                    <blue>0</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Base">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>255</red>
+                    <green>255</green>
+                    <blue>255</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Window">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>0</red>
+                    <green>0</green>
+                    <blue>0</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Shadow">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>0</red>
+                    <green>0</green>
+                    <blue>0</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Highlight">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>10</red>
+                    <green>36</green>
+                    <blue>106</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="HighlightedText">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>255</red>
+                    <green>255</green>
+                    <blue>255</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                </active>
+                <inactive>
+                 <colorrole role="WindowText">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>255</red>
+                    <green>0</green>
+                    <blue>0</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Button">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>212</red>
+                    <green>208</green>
+                    <blue>200</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Light">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>255</red>
+                    <green>255</green>
+                    <blue>255</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Midlight">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>243</red>
+                    <green>239</green>
+                    <blue>230</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Dark">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>106</red>
+                    <green>104</green>
+                    <blue>100</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Mid">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>141</red>
+                    <green>138</green>
+                    <blue>133</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Text">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>0</red>
+                    <green>0</green>
+                    <blue>0</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="BrightText">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>255</red>
+                    <green>255</green>
+                    <blue>255</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="ButtonText">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>0</red>
+                    <green>0</green>
+                    <blue>0</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Base">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>255</red>
+                    <green>255</green>
+                    <blue>255</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Window">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>0</red>
+                    <green>0</green>
+                    <blue>0</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Shadow">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>0</red>
+                    <green>0</green>
+                    <blue>0</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Highlight">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>10</red>
+                    <green>36</green>
+                    <blue>106</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="HighlightedText">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>255</red>
+                    <green>255</green>
+                    <blue>255</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                </inactive>
+                <disabled>
+                 <colorrole role="WindowText">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>128</red>
+                    <green>128</green>
+                    <blue>128</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Button">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>212</red>
+                    <green>208</green>
+                    <blue>200</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Light">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>255</red>
+                    <green>255</green>
+                    <blue>255</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Midlight">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>243</red>
+                    <green>239</green>
+                    <blue>230</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Dark">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>106</red>
+                    <green>104</green>
+                    <blue>100</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Mid">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>141</red>
+                    <green>138</green>
+                    <blue>133</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Text">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>0</red>
+                    <green>0</green>
+                    <blue>0</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="BrightText">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>255</red>
+                    <green>255</green>
+                    <blue>255</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="ButtonText">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>128</red>
+                    <green>128</green>
+                    <blue>128</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Base">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>255</red>
+                    <green>255</green>
+                    <blue>255</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Window">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>0</red>
+                    <green>0</green>
+                    <blue>0</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Shadow">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>0</red>
+                    <green>0</green>
+                    <blue>0</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Highlight">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>10</red>
+                    <green>36</green>
+                    <blue>106</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="HighlightedText">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>255</red>
+                    <green>255</green>
+                    <blue>255</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                </disabled>
+               </palette>
+              </property>
+              <property name="font">
+               <font>
+                <family>Arial</family>
+                <pointsize>10</pointsize>
+                <weight>75</weight>
+                <bold>true</bold>
+               </font>
+              </property>
+              <property name="text">
+               <string>AAC+</string>
+              </property>
+              <property name="alignment">
+               <set>Qt::AlignCenter</set>
+              </property>
+              <property name="wordWrap">
+               <bool>false</bool>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QLabel" name="LabelStereoMono">
+              <property name="palette">
+               <palette>
+                <active>
+                 <colorrole role="WindowText">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>255</red>
+                    <green>0</green>
+                    <blue>0</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Button">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>212</red>
+                    <green>208</green>
+                    <blue>200</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Light">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>255</red>
+                    <green>255</green>
+                    <blue>255</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Midlight">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>233</red>
+                    <green>231</green>
+                    <blue>227</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Dark">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>106</red>
+                    <green>104</green>
+                    <blue>100</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Mid">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>141</red>
+                    <green>138</green>
+                    <blue>133</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Text">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>0</red>
+                    <green>0</green>
+                    <blue>0</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="BrightText">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>255</red>
+                    <green>255</green>
+                    <blue>255</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="ButtonText">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>0</red>
+                    <green>0</green>
+                    <blue>0</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Base">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>255</red>
+                    <green>255</green>
+                    <blue>255</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Window">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>0</red>
+                    <green>0</green>
+                    <blue>0</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Shadow">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>0</red>
+                    <green>0</green>
+                    <blue>0</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Highlight">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>10</red>
+                    <green>36</green>
+                    <blue>106</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="HighlightedText">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>255</red>
+                    <green>255</green>
+                    <blue>255</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                </active>
+                <inactive>
+                 <colorrole role="WindowText">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>255</red>
+                    <green>0</green>
+                    <blue>0</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Button">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>212</red>
+                    <green>208</green>
+                    <blue>200</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Light">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>255</red>
+                    <green>255</green>
+                    <blue>255</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Midlight">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>243</red>
+                    <green>239</green>
+                    <blue>230</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Dark">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>106</red>
+                    <green>104</green>
+                    <blue>100</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Mid">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>141</red>
+                    <green>138</green>
+                    <blue>133</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Text">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>0</red>
+                    <green>0</green>
+                    <blue>0</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="BrightText">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>255</red>
+                    <green>255</green>
+                    <blue>255</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="ButtonText">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>0</red>
+                    <green>0</green>
+                    <blue>0</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Base">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>255</red>
+                    <green>255</green>
+                    <blue>255</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Window">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>0</red>
+                    <green>0</green>
+                    <blue>0</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Shadow">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>0</red>
+                    <green>0</green>
+                    <blue>0</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Highlight">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>10</red>
+                    <green>36</green>
+                    <blue>106</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="HighlightedText">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>255</red>
+                    <green>255</green>
+                    <blue>255</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                </inactive>
+                <disabled>
+                 <colorrole role="WindowText">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>128</red>
+                    <green>128</green>
+                    <blue>128</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Button">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>212</red>
+                    <green>208</green>
+                    <blue>200</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Light">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>255</red>
+                    <green>255</green>
+                    <blue>255</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Midlight">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>243</red>
+                    <green>239</green>
+                    <blue>230</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Dark">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>106</red>
+                    <green>104</green>
+                    <blue>100</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Mid">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>141</red>
+                    <green>138</green>
+                    <blue>133</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Text">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>0</red>
+                    <green>0</green>
+                    <blue>0</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="BrightText">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>255</red>
+                    <green>255</green>
+                    <blue>255</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="ButtonText">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>128</red>
+                    <green>128</green>
+                    <blue>128</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Base">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>255</red>
+                    <green>255</green>
+                    <blue>255</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Window">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>0</red>
+                    <green>0</green>
+                    <blue>0</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Shadow">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>0</red>
+                    <green>0</green>
+                    <blue>0</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="Highlight">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>10</red>
+                    <green>36</green>
+                    <blue>106</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                 <colorrole role="HighlightedText">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>255</red>
+                    <green>255</green>
+                    <blue>255</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                </disabled>
+               </palette>
+              </property>
+              <property name="font">
+               <font>
+                <family>Arial</family>
+                <pointsize>10</pointsize>
+                <weight>75</weight>
+                <bold>true</bold>
+               </font>
+              </property>
+              <property name="text">
+               <string>Stereo</string>
+              </property>
+              <property name="alignment">
+               <set>Qt::AlignCenter</set>
+              </property>
+              <property name="wordWrap">
+               <bool>false</bool>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </widget>
+         </item>
+         <item>
+          <widget class="QLabel" name="LabelServiceLabel">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Expanding" vsizetype="Minimum">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="palette">
+            <palette>
+             <active>
+              <colorrole role="WindowText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>85</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Button">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>169</red>
+                 <green>134</green>
+                 <blue>107</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Light">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>253</red>
+                 <green>200</green>
+                 <blue>160</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Midlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>211</red>
+                 <green>167</green>
+                 <blue>133</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Dark">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>84</red>
+                 <green>66</green>
+                 <blue>53</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Mid">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>112</red>
+                 <green>89</green>
+                 <blue>71</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Text">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="BrightText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ButtonText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Base">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Window">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Shadow">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Highlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>128</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="HighlightedText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+             </active>
+             <inactive>
+              <colorrole role="WindowText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>85</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Button">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>169</red>
+                 <green>134</green>
+                 <blue>107</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Light">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>253</red>
+                 <green>200</green>
+                 <blue>160</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Midlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>194</red>
+                 <green>153</green>
+                 <blue>122</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Dark">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>84</red>
+                 <green>66</green>
+                 <blue>53</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Mid">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>112</red>
+                 <green>89</green>
+                 <blue>71</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Text">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="BrightText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ButtonText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Base">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Window">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Shadow">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Highlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>128</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="HighlightedText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+             </inactive>
+             <disabled>
+              <colorrole role="WindowText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>128</red>
+                 <green>128</green>
+                 <blue>128</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Button">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>169</red>
+                 <green>134</green>
+                 <blue>107</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Light">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>253</red>
+                 <green>200</green>
+                 <blue>160</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Midlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>194</red>
+                 <green>153</green>
+                 <blue>122</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Dark">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>84</red>
+                 <green>66</green>
+                 <blue>53</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Mid">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>112</red>
+                 <green>89</green>
+                 <blue>71</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Text">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="BrightText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ButtonText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>128</red>
+                 <green>128</green>
+                 <blue>128</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Base">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Window">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Shadow">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Highlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>128</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="HighlightedText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+             </disabled>
+            </palette>
+           </property>
+           <property name="font">
+            <font>
+             <family>Arial</family>
+             <pointsize>14</pointsize>
+             <weight>75</weight>
+             <bold>true</bold>
+            </font>
+           </property>
+           <property name="text">
+            <string>Deutsche Welle</string>
+           </property>
+           <property name="alignment">
+            <set>Qt::AlignBottom|Qt::AlignHCenter</set>
+           </property>
+           <property name="wordWrap">
+            <bool>false</bool>
+           </property>
+           <property name="margin">
+            <number>0</number>
+           </property>
+           <property name="indent">
+            <number>5</number>
+           </property>
+           <property name="textInteractionFlags">
+            <set>Qt::NoTextInteraction</set>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QLineEdit" name="lineEditFrequency">
+           <property name="enabled">
+            <bool>true</bool>
+           </property>
+           <property name="palette">
+            <palette>
+             <active>
+              <colorrole role="WindowText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>170</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Text">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>170</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Base">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+             </active>
+             <inactive>
+              <colorrole role="WindowText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>170</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Text">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>170</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Base">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+             </inactive>
+             <disabled>
+              <colorrole role="WindowText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>128</red>
+                 <green>128</green>
+                 <blue>128</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Text">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Base">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+             </disabled>
+            </palette>
+           </property>
+           <property name="font">
+            <font>
+             <family>Arial</family>
+             <pointsize>14</pointsize>
+             <weight>75</weight>
+             <bold>true</bold>
+            </font>
+           </property>
+           <property name="text">
+            <string>88.1</string>
+           </property>
+           <property name="frame">
+            <bool>false</bool>
+           </property>
+           <property name="alignment">
+            <set>Qt::AlignCenter</set>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <layout class="QHBoxLayout" name="_12">
+           <property name="spacing">
+            <number>2</number>
+           </property>
+           <property name="margin">
+            <number>0</number>
+           </property>
+           <item>
+            <widget class="QLabel" name="LabelLanguage">
+             <property name="sizePolicy">
+              <sizepolicy hsizetype="Expanding" vsizetype="Minimum">
+               <horstretch>0</horstretch>
+               <verstretch>0</verstretch>
+              </sizepolicy>
+             </property>
+             <property name="palette">
+              <palette>
+               <active>
+                <colorrole role="WindowText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Button">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>169</red>
+                   <green>134</green>
+                   <blue>107</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Light">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>253</red>
+                   <green>200</green>
+                   <blue>160</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Midlight">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>211</red>
+                   <green>167</green>
+                   <blue>133</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Dark">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>84</red>
+                   <green>66</green>
+                   <blue>53</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Mid">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>112</red>
+                   <green>89</green>
+                   <blue>71</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Text">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="BrightText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>255</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="ButtonText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Base">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>255</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Window">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Shadow">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Highlight">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>128</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="HighlightedText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>255</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+               </active>
+               <inactive>
+                <colorrole role="WindowText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Button">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>169</red>
+                   <green>134</green>
+                   <blue>107</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Light">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>253</red>
+                   <green>200</green>
+                   <blue>160</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Midlight">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>194</red>
+                   <green>153</green>
+                   <blue>122</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Dark">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>84</red>
+                   <green>66</green>
+                   <blue>53</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Mid">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>112</red>
+                   <green>89</green>
+                   <blue>71</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Text">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="BrightText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>255</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="ButtonText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Base">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>255</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Window">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Shadow">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Highlight">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>128</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="HighlightedText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>255</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+               </inactive>
+               <disabled>
+                <colorrole role="WindowText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>128</red>
+                   <green>128</green>
+                   <blue>128</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Button">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>169</red>
+                   <green>134</green>
+                   <blue>107</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Light">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>253</red>
+                   <green>200</green>
+                   <blue>160</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Midlight">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>194</red>
+                   <green>153</green>
+                   <blue>122</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Dark">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>84</red>
+                   <green>66</green>
+                   <blue>53</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Mid">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>112</red>
+                   <green>89</green>
+                   <blue>71</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Text">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="BrightText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>255</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="ButtonText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>128</red>
+                   <green>128</green>
+                   <blue>128</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Base">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>255</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Window">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Shadow">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Highlight">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>128</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="HighlightedText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>255</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+               </disabled>
+              </palette>
+             </property>
+             <property name="font">
+              <font>
+               <family>Arial</family>
+               <pointsize>10</pointsize>
+               <weight>75</weight>
+               <bold>true</bold>
+              </font>
+             </property>
+             <property name="lineWidth">
+              <number>1</number>
+             </property>
+             <property name="text">
+              <string>German</string>
+             </property>
+             <property name="alignment">
+              <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+             </property>
+             <property name="wordWrap">
+              <bool>false</bool>
+             </property>
+             <property name="margin">
+              <number>0</number>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="QLabel" name="LabelCountryCode">
+             <property name="sizePolicy">
+              <sizepolicy hsizetype="Expanding" vsizetype="Minimum">
+               <horstretch>0</horstretch>
+               <verstretch>0</verstretch>
+              </sizepolicy>
+             </property>
+             <property name="palette">
+              <palette>
+               <active>
+                <colorrole role="WindowText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Button">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>169</red>
+                   <green>134</green>
+                   <blue>107</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Light">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>253</red>
+                   <green>200</green>
+                   <blue>160</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Midlight">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>211</red>
+                   <green>167</green>
+                   <blue>133</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Dark">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>84</red>
+                   <green>66</green>
+                   <blue>53</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Mid">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>112</red>
+                   <green>89</green>
+                   <blue>71</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Text">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="BrightText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>255</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="ButtonText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Base">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>255</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Window">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Shadow">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Highlight">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>128</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="HighlightedText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>255</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+               </active>
+               <inactive>
+                <colorrole role="WindowText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Button">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>169</red>
+                   <green>134</green>
+                   <blue>107</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Light">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>253</red>
+                   <green>200</green>
+                   <blue>160</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Midlight">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>194</red>
+                   <green>153</green>
+                   <blue>122</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Dark">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>84</red>
+                   <green>66</green>
+                   <blue>53</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Mid">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>112</red>
+                   <green>89</green>
+                   <blue>71</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Text">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="BrightText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>255</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="ButtonText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Base">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>255</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Window">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Shadow">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Highlight">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>128</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="HighlightedText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>255</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+               </inactive>
+               <disabled>
+                <colorrole role="WindowText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>128</red>
+                   <green>128</green>
+                   <blue>128</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Button">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>169</red>
+                   <green>134</green>
+                   <blue>107</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Light">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>253</red>
+                   <green>200</green>
+                   <blue>160</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Midlight">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>194</red>
+                   <green>153</green>
+                   <blue>122</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Dark">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>84</red>
+                   <green>66</green>
+                   <blue>53</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Mid">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>112</red>
+                   <green>89</green>
+                   <blue>71</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Text">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="BrightText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>255</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="ButtonText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>128</red>
+                   <green>128</green>
+                   <blue>128</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Base">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>255</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Window">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Shadow">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Highlight">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>128</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="HighlightedText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>255</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+               </disabled>
+              </palette>
+             </property>
+             <property name="font">
+              <font>
+               <family>Arial</family>
+               <pointsize>10</pointsize>
+               <weight>75</weight>
+               <bold>true</bold>
+              </font>
+             </property>
+             <property name="lineWidth">
+              <number>1</number>
+             </property>
+             <property name="text">
+              <string>DE</string>
+             </property>
+             <property name="alignment">
+              <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+             </property>
+             <property name="wordWrap">
+              <bool>false</bool>
+             </property>
+             <property name="margin">
+              <number>0</number>
+             </property>
+            </widget>
+           </item>
+          </layout>
+         </item>
+         <item>
+          <layout class="QHBoxLayout" name="_13">
+           <property name="spacing">
+            <number>2</number>
+           </property>
+           <property name="margin">
+            <number>0</number>
+           </property>
+           <item>
+            <widget class="QLabel" name="LabelProgrType">
+             <property name="sizePolicy">
+              <sizepolicy hsizetype="Expanding" vsizetype="Minimum">
+               <horstretch>0</horstretch>
+               <verstretch>0</verstretch>
+              </sizepolicy>
+             </property>
+             <property name="palette">
+              <palette>
+               <active>
+                <colorrole role="WindowText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Button">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>169</red>
+                   <green>134</green>
+                   <blue>107</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Light">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>253</red>
+                   <green>200</green>
+                   <blue>160</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Midlight">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>211</red>
+                   <green>167</green>
+                   <blue>133</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Dark">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>84</red>
+                   <green>66</green>
+                   <blue>53</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Mid">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>112</red>
+                   <green>89</green>
+                   <blue>71</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Text">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="BrightText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>255</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="ButtonText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Base">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>255</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Window">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Shadow">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Highlight">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>128</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="HighlightedText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>255</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+               </active>
+               <inactive>
+                <colorrole role="WindowText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Button">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>169</red>
+                   <green>134</green>
+                   <blue>107</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Light">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>253</red>
+                   <green>200</green>
+                   <blue>160</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Midlight">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>194</red>
+                   <green>153</green>
+                   <blue>122</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Dark">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>84</red>
+                   <green>66</green>
+                   <blue>53</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Mid">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>112</red>
+                   <green>89</green>
+                   <blue>71</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Text">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="BrightText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>255</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="ButtonText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Base">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>255</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Window">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Shadow">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Highlight">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>128</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="HighlightedText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>255</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+               </inactive>
+               <disabled>
+                <colorrole role="WindowText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>128</red>
+                   <green>128</green>
+                   <blue>128</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Button">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>169</red>
+                   <green>134</green>
+                   <blue>107</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Light">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>253</red>
+                   <green>200</green>
+                   <blue>160</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Midlight">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>194</red>
+                   <green>153</green>
+                   <blue>122</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Dark">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>84</red>
+                   <green>66</green>
+                   <blue>53</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Mid">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>112</red>
+                   <green>89</green>
+                   <blue>71</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Text">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="BrightText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>255</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="ButtonText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>128</red>
+                   <green>128</green>
+                   <blue>128</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Base">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>255</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Window">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Shadow">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Highlight">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>128</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="HighlightedText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>255</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+               </disabled>
+              </palette>
+             </property>
+             <property name="font">
+              <font>
+               <family>Arial</family>
+               <pointsize>10</pointsize>
+               <weight>75</weight>
+               <bold>true</bold>
+              </font>
+             </property>
+             <property name="lineWidth">
+              <number>1</number>
+             </property>
+             <property name="text">
+              <string>Information</string>
+             </property>
+             <property name="alignment">
+              <set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
+             </property>
+             <property name="wordWrap">
+              <bool>false</bool>
+             </property>
+             <property name="margin">
+              <number>0</number>
+             </property>
+             <property name="indent">
+              <number>-1</number>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="QLabel" name="LabelServiceID">
+             <property name="sizePolicy">
+              <sizepolicy hsizetype="Expanding" vsizetype="Minimum">
+               <horstretch>0</horstretch>
+               <verstretch>0</verstretch>
+              </sizepolicy>
+             </property>
+             <property name="palette">
+              <palette>
+               <active>
+                <colorrole role="WindowText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Button">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>169</red>
+                   <green>134</green>
+                   <blue>107</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Light">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>253</red>
+                   <green>200</green>
+                   <blue>160</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Midlight">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>211</red>
+                   <green>167</green>
+                   <blue>133</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Dark">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>84</red>
+                   <green>66</green>
+                   <blue>53</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Mid">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>112</red>
+                   <green>89</green>
+                   <blue>71</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Text">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="BrightText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>255</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="ButtonText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Base">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>255</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Window">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Shadow">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Highlight">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>128</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="HighlightedText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>255</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+               </active>
+               <inactive>
+                <colorrole role="WindowText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Button">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>169</red>
+                   <green>134</green>
+                   <blue>107</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Light">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>253</red>
+                   <green>200</green>
+                   <blue>160</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Midlight">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>194</red>
+                   <green>153</green>
+                   <blue>122</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Dark">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>84</red>
+                   <green>66</green>
+                   <blue>53</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Mid">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>112</red>
+                   <green>89</green>
+                   <blue>71</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Text">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="BrightText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>255</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="ButtonText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Base">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>255</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Window">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Shadow">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Highlight">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>128</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="HighlightedText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>255</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+               </inactive>
+               <disabled>
+                <colorrole role="WindowText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>128</red>
+                   <green>128</green>
+                   <blue>128</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Button">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>169</red>
+                   <green>134</green>
+                   <blue>107</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Light">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>253</red>
+                   <green>200</green>
+                   <blue>160</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Midlight">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>194</red>
+                   <green>153</green>
+                   <blue>122</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Dark">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>84</red>
+                   <green>66</green>
+                   <blue>53</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Mid">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>112</red>
+                   <green>89</green>
+                   <blue>71</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Text">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="BrightText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>255</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="ButtonText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>128</red>
+                   <green>128</green>
+                   <blue>128</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Base">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>255</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Window">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Shadow">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Highlight">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>128</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="HighlightedText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>255</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+               </disabled>
+              </palette>
+             </property>
+             <property name="font">
+              <font>
+               <family>Arial</family>
+               <pointsize>10</pointsize>
+               <weight>75</weight>
+               <bold>true</bold>
+              </font>
+             </property>
+             <property name="lineWidth">
+              <number>1</number>
+             </property>
+             <property name="text">
+              <string>1001</string>
+             </property>
+             <property name="alignment">
+              <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+             </property>
+             <property name="wordWrap">
+              <bool>false</bool>
+             </property>
+             <property name="margin">
+              <number>0</number>
+             </property>
+            </widget>
+           </item>
+          </layout>
+         </item>
+        </layout>
+       </item>
+       <item row="1" column="0">
+        <layout class="QVBoxLayout" name="verticalLayout_2">
+         <property name="spacing">
+          <number>3</number>
+         </property>
+         <property name="topMargin">
+          <number>9</number>
+         </property>
+         <property name="bottomMargin">
+          <number>0</number>
+         </property>
+         <item>
+          <widget class="QLabel" name="TextLabelInputLevel">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="palette">
+            <palette>
+             <active>
+              <colorrole role="WindowText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Button">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>169</red>
+                 <green>134</green>
+                 <blue>107</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Light">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>253</red>
+                 <green>200</green>
+                 <blue>160</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Midlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>211</red>
+                 <green>167</green>
+                 <blue>133</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Dark">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>84</red>
+                 <green>66</green>
+                 <blue>53</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Mid">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>112</red>
+                 <green>89</green>
+                 <blue>71</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Text">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="BrightText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ButtonText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Base">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Window">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Shadow">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Highlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>128</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="HighlightedText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+             </active>
+             <inactive>
+              <colorrole role="WindowText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Button">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>169</red>
+                 <green>134</green>
+                 <blue>107</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Light">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>253</red>
+                 <green>200</green>
+                 <blue>160</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Midlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>194</red>
+                 <green>153</green>
+                 <blue>122</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Dark">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>84</red>
+                 <green>66</green>
+                 <blue>53</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Mid">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>112</red>
+                 <green>89</green>
+                 <blue>71</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Text">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="BrightText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ButtonText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Base">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Window">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Shadow">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Highlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>128</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="HighlightedText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+             </inactive>
+             <disabled>
+              <colorrole role="WindowText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>128</red>
+                 <green>128</green>
+                 <blue>128</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Button">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>169</red>
+                 <green>134</green>
+                 <blue>107</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Light">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>253</red>
+                 <green>200</green>
+                 <blue>160</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Midlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>194</red>
+                 <green>153</green>
+                 <blue>122</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Dark">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>84</red>
+                 <green>66</green>
+                 <blue>53</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Mid">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>112</red>
+                 <green>89</green>
+                 <blue>71</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Text">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="BrightText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ButtonText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>128</red>
+                 <green>128</green>
+                 <blue>128</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Base">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Window">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Shadow">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Highlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>128</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="HighlightedText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+             </disabled>
+            </palette>
+           </property>
+           <property name="font">
+            <font>
+             <family>Arial</family>
+             <pointsize>7</pointsize>
+             <weight>75</weight>
+             <bold>true</bold>
+            </font>
+           </property>
+           <property name="lineWidth">
+            <number>1</number>
+           </property>
+           <property name="text">
+            <string>Level [dB]</string>
+           </property>
+           <property name="alignment">
+            <set>Qt::AlignCenter</set>
+           </property>
+           <property name="wordWrap">
+            <bool>false</bool>
+           </property>
+           <property name="margin">
+            <number>0</number>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QwtThermo" name="ProgrInputLevel" native="true">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="palette">
+            <palette>
+             <active>
+              <colorrole role="WindowText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Button">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Light">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>127</green>
+                 <blue>127</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Midlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>63</green>
+                 <blue>63</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Dark">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>127</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Mid">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>170</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Text">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="BrightText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ButtonText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Base">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Window">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Shadow">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Highlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>128</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="HighlightedText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+             </active>
+             <inactive>
+              <colorrole role="WindowText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Button">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Light">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>127</green>
+                 <blue>127</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Midlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>38</green>
+                 <blue>38</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Dark">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>127</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Mid">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>170</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Text">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="BrightText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ButtonText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Base">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Window">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Shadow">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Highlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>128</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="HighlightedText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+             </inactive>
+             <disabled>
+              <colorrole role="WindowText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>128</red>
+                 <green>128</green>
+                 <blue>128</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Button">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Light">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>127</green>
+                 <blue>127</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Midlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>38</green>
+                 <blue>38</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Dark">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>127</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Mid">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>170</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Text">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="BrightText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ButtonText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>128</red>
+                 <green>128</green>
+                 <blue>128</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Base">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Window">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Shadow">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Highlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>128</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="HighlightedText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+             </disabled>
+            </palette>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </item>
+       <item row="0" column="0">
+        <layout class="QHBoxLayout" name="horizontalLayout">
+         <item>
+          <widget class="QWidget" name="onebar" native="true">
+           <property name="minimumSize">
+            <size>
+             <width>4</width>
+             <height>5</height>
+            </size>
+           </property>
+           <property name="maximumSize">
+            <size>
+             <width>4</width>
+             <height>4</height>
+            </size>
+           </property>
+           <property name="palette">
+            <palette>
+             <active>
+              <colorrole role="WindowText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Button">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>255</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Light">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>127</red>
+                 <green>255</green>
+                 <blue>127</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Midlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>63</red>
+                 <green>255</green>
+                 <blue>63</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Dark">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>127</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Mid">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>170</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Text">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="BrightText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ButtonText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Base">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>255</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Window">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>255</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Shadow">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="AlternateBase">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>127</red>
+                 <green>255</green>
+                 <blue>127</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="NoRole">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>255</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ToolTipBase">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>220</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ToolTipText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+             </active>
+             <inactive>
+              <colorrole role="WindowText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Button">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>255</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Light">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>127</red>
+                 <green>255</green>
+                 <blue>127</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Midlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>63</red>
+                 <green>255</green>
+                 <blue>63</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Dark">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>127</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Mid">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>170</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Text">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="BrightText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ButtonText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Base">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>255</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Window">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>255</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Shadow">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="AlternateBase">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>127</red>
+                 <green>255</green>
+                 <blue>127</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="NoRole">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>255</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ToolTipBase">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>220</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ToolTipText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+             </inactive>
+             <disabled>
+              <colorrole role="WindowText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>127</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Button">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>255</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Light">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>127</red>
+                 <green>255</green>
+                 <blue>127</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Midlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>63</red>
+                 <green>255</green>
+                 <blue>63</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Dark">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>127</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Mid">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>170</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Text">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>127</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="BrightText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ButtonText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>127</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Base">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>255</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Window">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>255</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Shadow">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="AlternateBase">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>255</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="NoRole">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>255</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ToolTipBase">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>220</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ToolTipText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+             </disabled>
+            </palette>
+           </property>
+           <property name="autoFillBackground">
+            <bool>true</bool>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QWidget" name="twobars" native="true">
+           <property name="minimumSize">
+            <size>
+             <width>4</width>
+             <height>5</height>
+            </size>
+           </property>
+           <property name="maximumSize">
+            <size>
+             <width>4</width>
+             <height>8</height>
+            </size>
+           </property>
+           <property name="palette">
+            <palette>
+             <active>
+              <colorrole role="WindowText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Button">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>255</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Light">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>127</red>
+                 <green>255</green>
+                 <blue>127</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Midlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>63</red>
+                 <green>255</green>
+                 <blue>63</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Dark">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>127</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Mid">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>170</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Text">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="BrightText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ButtonText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Base">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>255</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Window">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>255</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Shadow">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="AlternateBase">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>127</red>
+                 <green>255</green>
+                 <blue>127</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="NoRole">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>255</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ToolTipBase">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>220</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ToolTipText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+             </active>
+             <inactive>
+              <colorrole role="WindowText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Button">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>255</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Light">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>127</red>
+                 <green>255</green>
+                 <blue>127</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Midlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>63</red>
+                 <green>255</green>
+                 <blue>63</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Dark">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>127</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Mid">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>170</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Text">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="BrightText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ButtonText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Base">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>255</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Window">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>255</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Shadow">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="AlternateBase">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>127</red>
+                 <green>255</green>
+                 <blue>127</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="NoRole">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>255</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ToolTipBase">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>220</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ToolTipText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+             </inactive>
+             <disabled>
+              <colorrole role="WindowText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>127</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Button">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>255</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Light">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>127</red>
+                 <green>255</green>
+                 <blue>127</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Midlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>63</red>
+                 <green>255</green>
+                 <blue>63</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Dark">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>127</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Mid">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>170</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Text">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>127</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="BrightText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ButtonText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>127</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Base">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>255</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Window">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>255</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Shadow">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="AlternateBase">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>255</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="NoRole">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>255</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ToolTipBase">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>220</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ToolTipText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+             </disabled>
+            </palette>
+           </property>
+           <property name="autoFillBackground">
+            <bool>true</bool>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QWidget" name="threebars" native="true">
+           <property name="minimumSize">
+            <size>
+             <width>4</width>
+             <height>5</height>
+            </size>
+           </property>
+           <property name="maximumSize">
+            <size>
+             <width>4</width>
+             <height>12</height>
+            </size>
+           </property>
+           <property name="palette">
+            <palette>
+             <active>
+              <colorrole role="WindowText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Button">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>255</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Light">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>127</red>
+                 <green>255</green>
+                 <blue>127</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Midlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>63</red>
+                 <green>255</green>
+                 <blue>63</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Dark">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>127</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Mid">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>170</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Text">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="BrightText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ButtonText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Base">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>255</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Window">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>255</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Shadow">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="AlternateBase">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>127</red>
+                 <green>255</green>
+                 <blue>127</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="NoRole">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>255</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ToolTipBase">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>220</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ToolTipText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+             </active>
+             <inactive>
+              <colorrole role="WindowText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Button">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>255</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Light">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>127</red>
+                 <green>255</green>
+                 <blue>127</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Midlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>63</red>
+                 <green>255</green>
+                 <blue>63</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Dark">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>127</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Mid">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>170</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Text">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="BrightText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ButtonText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Base">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>255</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Window">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>255</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Shadow">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="AlternateBase">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>127</red>
+                 <green>255</green>
+                 <blue>127</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="NoRole">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>255</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ToolTipBase">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>220</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ToolTipText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+             </inactive>
+             <disabled>
+              <colorrole role="WindowText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>127</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Button">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>255</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Light">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>127</red>
+                 <green>255</green>
+                 <blue>127</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Midlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>63</red>
+                 <green>255</green>
+                 <blue>63</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Dark">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>127</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Mid">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>170</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Text">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>127</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="BrightText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ButtonText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>127</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Base">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>255</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Window">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>255</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Shadow">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="AlternateBase">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>255</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="NoRole">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>255</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ToolTipBase">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>220</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ToolTipText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+             </disabled>
+            </palette>
+           </property>
+           <property name="autoFillBackground">
+            <bool>true</bool>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QWidget" name="fourbars" native="true">
+           <property name="minimumSize">
+            <size>
+             <width>4</width>
+             <height>5</height>
+            </size>
+           </property>
+           <property name="maximumSize">
+            <size>
+             <width>4</width>
+             <height>16</height>
+            </size>
+           </property>
+           <property name="palette">
+            <palette>
+             <active>
+              <colorrole role="WindowText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Button">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>255</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Light">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>127</red>
+                 <green>255</green>
+                 <blue>127</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Midlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>63</red>
+                 <green>255</green>
+                 <blue>63</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Dark">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>127</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Mid">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>170</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Text">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="BrightText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ButtonText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Base">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>255</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Window">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>255</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Shadow">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="AlternateBase">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>127</red>
+                 <green>255</green>
+                 <blue>127</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="NoRole">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>255</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ToolTipBase">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>220</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ToolTipText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+             </active>
+             <inactive>
+              <colorrole role="WindowText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Button">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>255</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Light">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>127</red>
+                 <green>255</green>
+                 <blue>127</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Midlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>63</red>
+                 <green>255</green>
+                 <blue>63</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Dark">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>127</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Mid">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>170</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Text">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="BrightText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ButtonText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Base">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>255</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Window">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>255</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Shadow">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="AlternateBase">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>127</red>
+                 <green>255</green>
+                 <blue>127</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="NoRole">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>255</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ToolTipBase">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>220</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ToolTipText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+             </inactive>
+             <disabled>
+              <colorrole role="WindowText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>127</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Button">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>255</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Light">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>127</red>
+                 <green>255</green>
+                 <blue>127</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Midlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>63</red>
+                 <green>255</green>
+                 <blue>63</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Dark">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>127</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Mid">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>170</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Text">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>127</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="BrightText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ButtonText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>127</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Base">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>255</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Window">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>255</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Shadow">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="AlternateBase">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>255</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="NoRole">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>255</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ToolTipBase">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>220</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ToolTipText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+             </disabled>
+            </palette>
+           </property>
+           <property name="autoFillBackground">
+            <bool>true</bool>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QWidget" name="fivebars" native="true">
+           <property name="minimumSize">
+            <size>
+             <width>4</width>
+             <height>5</height>
+            </size>
+           </property>
+           <property name="maximumSize">
+            <size>
+             <width>4</width>
+             <height>20</height>
+            </size>
+           </property>
+           <property name="palette">
+            <palette>
+             <active>
+              <colorrole role="WindowText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Button">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>255</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Light">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>127</red>
+                 <green>255</green>
+                 <blue>127</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Midlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>63</red>
+                 <green>255</green>
+                 <blue>63</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Dark">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>127</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Mid">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>170</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Text">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="BrightText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ButtonText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Base">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>255</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Window">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>255</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Shadow">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="AlternateBase">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>127</red>
+                 <green>255</green>
+                 <blue>127</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="NoRole">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>255</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ToolTipBase">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>220</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ToolTipText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+             </active>
+             <inactive>
+              <colorrole role="WindowText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Button">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>255</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Light">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>127</red>
+                 <green>255</green>
+                 <blue>127</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Midlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>63</red>
+                 <green>255</green>
+                 <blue>63</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Dark">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>127</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Mid">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>170</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Text">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="BrightText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ButtonText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Base">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>255</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Window">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>255</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Shadow">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="AlternateBase">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>127</red>
+                 <green>255</green>
+                 <blue>127</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="NoRole">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>255</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ToolTipBase">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>220</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ToolTipText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+             </inactive>
+             <disabled>
+              <colorrole role="WindowText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>127</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Button">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>255</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Light">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>127</red>
+                 <green>255</green>
+                 <blue>127</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Midlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>63</red>
+                 <green>255</green>
+                 <blue>63</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Dark">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>127</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Mid">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>170</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Text">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>127</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="BrightText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ButtonText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>127</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Base">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>255</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Window">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>255</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Shadow">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="AlternateBase">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>255</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="NoRole">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>255</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ToolTipBase">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>220</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ToolTipText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+             </disabled>
+            </palette>
+           </property>
+           <property name="autoFillBackground">
+            <bool>true</bool>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </item>
+       <item row="2" column="0">
+        <layout class="QHBoxLayout" name="horizontalLayout_2">
+         <property name="topMargin">
+          <number>4</number>
+         </property>
+         <property name="bottomMargin">
+          <number>4</number>
+         </property>
+         <item>
+          <widget class="CMultColorLED" name="CLED_FAC" native="true">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="palette">
+            <palette>
+             <active>
+              <colorrole role="WindowText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Button">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Light">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>127</green>
+                 <blue>127</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Midlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>63</green>
+                 <blue>63</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Dark">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>127</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Mid">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>170</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Text">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="BrightText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ButtonText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Base">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Window">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Shadow">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Highlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>128</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="HighlightedText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+             </active>
+             <inactive>
+              <colorrole role="WindowText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Button">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Light">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>127</green>
+                 <blue>127</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Midlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>38</green>
+                 <blue>38</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Dark">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>127</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Mid">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>170</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Text">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="BrightText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ButtonText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Base">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Window">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Shadow">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Highlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>128</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="HighlightedText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+             </inactive>
+             <disabled>
+              <colorrole role="WindowText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>128</red>
+                 <green>128</green>
+                 <blue>128</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Button">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Light">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>127</green>
+                 <blue>127</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Midlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>38</green>
+                 <blue>38</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Dark">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>127</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Mid">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>170</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Text">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="BrightText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ButtonText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>128</red>
+                 <green>128</green>
+                 <blue>128</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Base">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Window">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Shadow">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Highlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>128</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="HighlightedText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+             </disabled>
+            </palette>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="CMultColorLED" name="CLED_SDC" native="true">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="palette">
+            <palette>
+             <active>
+              <colorrole role="WindowText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Button">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Light">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>127</green>
+                 <blue>127</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Midlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>63</green>
+                 <blue>63</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Dark">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>127</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Mid">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>170</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Text">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="BrightText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ButtonText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Base">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Window">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Shadow">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Highlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>128</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="HighlightedText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+             </active>
+             <inactive>
+              <colorrole role="WindowText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Button">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Light">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>127</green>
+                 <blue>127</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Midlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>38</green>
+                 <blue>38</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Dark">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>127</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Mid">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>170</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Text">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="BrightText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ButtonText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Base">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Window">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Shadow">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Highlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>128</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="HighlightedText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+             </inactive>
+             <disabled>
+              <colorrole role="WindowText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>128</red>
+                 <green>128</green>
+                 <blue>128</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Button">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Light">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>127</green>
+                 <blue>127</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Midlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>38</green>
+                 <blue>38</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Dark">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>127</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Mid">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>170</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Text">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="BrightText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ButtonText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>128</red>
+                 <green>128</green>
+                 <blue>128</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Base">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Window">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Shadow">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Highlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>128</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="HighlightedText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+             </disabled>
+            </palette>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="CMultColorLED" name="CLED_MSC" native="true">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="palette">
+            <palette>
+             <active>
+              <colorrole role="WindowText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Button">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Light">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>127</green>
+                 <blue>127</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Midlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>63</green>
+                 <blue>63</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Dark">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>127</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Mid">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>170</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Text">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="BrightText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ButtonText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Base">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Window">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Shadow">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Highlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>128</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="HighlightedText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+             </active>
+             <inactive>
+              <colorrole role="WindowText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Button">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Light">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>127</green>
+                 <blue>127</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Midlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>38</green>
+                 <blue>38</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Dark">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>127</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Mid">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>170</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Text">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="BrightText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ButtonText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Base">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Window">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Shadow">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Highlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>128</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="HighlightedText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+             </inactive>
+             <disabled>
+              <colorrole role="WindowText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>128</red>
+                 <green>128</green>
+                 <blue>128</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Button">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Light">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>127</green>
+                 <blue>127</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Midlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>38</green>
+                 <blue>38</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Dark">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>127</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Mid">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>170</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Text">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="BrightText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="ButtonText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>128</red>
+                 <green>128</green>
+                 <blue>128</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Base">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Window">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Shadow">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="Highlight">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>128</blue>
+                </color>
+               </brush>
+              </colorrole>
+              <colorrole role="HighlightedText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>255</green>
+                 <blue>255</blue>
+                </color>
+               </brush>
+              </colorrole>
+             </disabled>
+            </palette>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </item>
+       <item row="2" column="1">
+        <widget class="QLabel" name="labelAFS">
+         <property name="enabled">
+          <bool>true</bool>
+         </property>
+         <property name="sizePolicy">
+          <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
+           <horstretch>0</horstretch>
+           <verstretch>0</verstretch>
+          </sizepolicy>
+         </property>
+         <property name="palette">
+          <palette>
+           <active>
+            <colorrole role="WindowText">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>255</red>
+               <green>0</green>
+               <blue>0</blue>
+              </color>
+             </brush>
+            </colorrole>
+           </active>
+           <inactive>
+            <colorrole role="WindowText">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>255</red>
+               <green>0</green>
+               <blue>0</blue>
+              </color>
+             </brush>
+            </colorrole>
+           </inactive>
+           <disabled>
+            <colorrole role="WindowText">
+             <brush brushstyle="SolidPattern">
+              <color alpha="255">
+               <red>0</red>
+               <green>0</green>
+               <blue>0</blue>
+              </color>
+             </brush>
+            </colorrole>
+           </disabled>
+          </palette>
+         </property>
+         <property name="font">
+          <font>
+           <family>Arial</family>
+           <pointsize>9</pointsize>
+           <weight>75</weight>
+           <bold>true</bold>
+          </font>
+         </property>
+         <property name="lineWidth">
+          <number>0</number>
+         </property>
+         <property name="text">
+          <string>AFS</string>
+         </property>
+         <property name="textFormat">
+          <enum>Qt::PlainText</enum>
+         </property>
+        </widget>
+       </item>
+      </layout>
+     </widget>
+    </item>
+   </layout>
+  </widget>
+  <widget class="QMenuBar" name="menubar">
+   <property name="geometry">
+    <rect>
+     <x>0</x>
+     <y>0</y>
+     <width>484</width>
+     <height>25</height>
+    </rect>
+   </property>
+   <widget class="QMenu" name="menu_View">
+    <property name="title">
+     <string>&View</string>
+    </property>
+    <addaction name="action_Evaluation_Dialog"/>
+    <addaction name="action_Multimedia_Dialog"/>
+    <addaction name="action_Stations_Dialog"/>
+    <addaction name="action_Live_Schedule_Dialog"/>
+    <addaction name="action_Programme_Guide_Dialog"/>
+   </widget>
+   <widget class="QMenu" name="menu_Settings">
+    <property name="title">
+     <string>&Settings</string>
+    </property>
+    <widget class="QMenu" name="menuAppearance">
+     <property name="title">
+      <string>Appearance</string>
+     </property>
+     <widget class="QMenu" name="menuMessage_Style">
+      <property name="title">
+       <string>Message Style</string>
+      </property>
+      <addaction name="actionBlackOnWhite"/>
+      <addaction name="actionWhiteOnBlack"/>
+     </widget>
+     <widget class="QMenu" name="menuPlot_Style">
+      <property name="title">
+       <string>Plot Style</string>
+      </property>
+      <addaction name="actionBlueWhite"/>
+      <addaction name="actionGreenBlack"/>
+      <addaction name="actionBlackGrey"/>
+     </widget>
+     <addaction name="actionDisplayColor"/>
+     <addaction name="menuMessage_Style"/>
+     <addaction name="menuPlot_Style"/>
+    </widget>
+    <addaction name="actionDRM"/>
+    <addaction name="actionAM"/>
+    <addaction name="actionFM"/>
+    <addaction name="actionReset"/>
+    <addaction name="separator"/>
+    <addaction name="actionSingle_Window_Mode"/>
+    <addaction name="actionEngineering_Mode"/>
+    <addaction name="separator"/>
+    <addaction name="actionMultimediaSettings"/>
+    <addaction name="actionGeneralSettings"/>
+    <addaction name="menuAppearance"/>
+   </widget>
+   <widget class="QMenu" name="menuHelp">
+    <property name="title">
+     <string>&Help</string>
+    </property>
+    <addaction name="actionWhats_This"/>
+    <addaction name="separator"/>
+    <addaction name="actionAbout_Dream"/>
+   </widget>
+   <addaction name="menu_View"/>
+   <addaction name="menu_Settings"/>
+   <addaction name="menuHelp"/>
+  </widget>
+  <action name="action_Evaluation_Dialog">
+   <property name="text">
+    <string>&Evaluation Dialog...</string>
+   </property>
+   <property name="shortcut">
+    <string>Alt+E</string>
+   </property>
+  </action>
+  <action name="action_Multimedia_Dialog">
+   <property name="text">
+    <string>M&ultimedia Dialog...</string>
+   </property>
+   <property name="shortcut">
+    <string>Alt+U</string>
+   </property>
+  </action>
+  <action name="action_Stations_Dialog">
+   <property name="text">
+    <string>S&tations Dialog...</string>
+   </property>
+   <property name="shortcut">
+    <string>Alt+T</string>
+   </property>
+  </action>
+  <action name="action_Live_Schedule_Dialog">
+   <property name="text">
+    <string>&Live Schedule Dialog...</string>
+   </property>
+   <property name="shortcut">
+    <string>Alt+L</string>
+   </property>
+  </action>
+  <action name="action_Programme_Guide_Dialog">
+   <property name="text">
+    <string>&Programme Guide ...</string>
+   </property>
+   <property name="shortcut">
+    <string>Alt+P</string>
+   </property>
+  </action>
+  <action name="actionExit">
+   <property name="text">
+    <string>E&xit</string>
+   </property>
+   <property name="shortcut">
+    <string>Alt+X</string>
+   </property>
+  </action>
+  <action name="actionAM">
+   <property name="text">
+    <string>AM (analog)</string>
+   </property>
+  </action>
+  <action name="actionFM">
+   <property name="text">
+    <string>FM (analog)</string>
+   </property>
+  </action>
+  <action name="actionReset">
+   <property name="text">
+    <string>New Acquisition</string>
+   </property>
+  </action>
+  <action name="actionDisplayColor">
+   <property name="text">
+    <string>Set Display Color</string>
+   </property>
+  </action>
+  <action name="actionBlueWhite">
+   <property name="checkable">
+    <bool>true</bool>
+   </property>
+   <property name="text">
+    <string>Blue / White</string>
+   </property>
+  </action>
+  <action name="actionGreenBlack">
+   <property name="checkable">
+    <bool>true</bool>
+   </property>
+   <property name="text">
+    <string>Green / Black</string>
+   </property>
+  </action>
+  <action name="actionBlackGrey">
+   <property name="checkable">
+    <bool>true</bool>
+   </property>
+   <property name="text">
+    <string>Black / Grey</string>
+   </property>
+  </action>
+  <action name="actionMultimediaSettings">
+   <property name="text">
+    <string>Multimedia Settings...</string>
+   </property>
+  </action>
+  <action name="actionGeneralSettings">
+   <property name="text">
+    <string>General Settings...</string>
+   </property>
+  </action>
+  <action name="actionWhats_This">
+   <property name="text">
+    <string>&Whats This</string>
+   </property>
+   <property name="shortcut">
+    <string>Shift+F1</string>
+   </property>
+  </action>
+  <action name="actionAbout_Dream">
+   <property name="text">
+    <string>&About Dream...</string>
+   </property>
+  </action>
+  <action name="action_Open_Sound_File">
+   <property name="text">
+    <string>&Open Sound File...</string>
+   </property>
+   <property name="shortcut">
+    <string>Alt+O</string>
+   </property>
+  </action>
+  <action name="action_Close_Sound_File">
+   <property name="text">
+    <string>&Close Sound File</string>
+   </property>
+   <property name="shortcut">
+    <string>Alt+C</string>
+   </property>
+  </action>
+  <action name="actionSingle_Window_Mode">
+   <property name="checkable">
+    <bool>true</bool>
+   </property>
+   <property name="text">
+    <string>Single Window Mode</string>
+   </property>
+  </action>
+  <action name="actionEngineering_Mode">
+   <property name="checkable">
+    <bool>true</bool>
+   </property>
+   <property name="text">
+    <string>Engineering Mode</string>
+   </property>
+  </action>
+  <action name="actionDRM">
+   <property name="text">
+    <string>DRM (digital)</string>
+   </property>
+  </action>
+  <action name="actionBlackOnWhite">
+   <property name="checkable">
+    <bool>true</bool>
+   </property>
+   <property name="text">
+    <string>Black on White</string>
+   </property>
+  </action>
+  <action name="actionWhiteOnBlack">
+   <property name="checkable">
+    <bool>true</bool>
+   </property>
+   <property name="text">
+    <string>White on Black</string>
+   </property>
+  </action>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>QwtThermo</class>
+   <extends>QWidget</extends>
+   <header>qwt_thermo.h</header>
+  </customwidget>
+  <customwidget>
+   <class>CMultColorLED</class>
+   <extends>QWidget</extends>
+   <header location="global">MultColorLED.h</header>
+  </customwidget>
+ </customwidgets>
+ <resources>
+  <include location="res/icons.qrc"/>
+ </resources>
+ <connections/>
+</ui>
diff --git a/src/GUI-QT/DRMPlot.cpp b/src/GUI-QT/DRMPlot.cpp
new file mode 100644
index 0000000..199d02f
--- /dev/null
+++ b/src/GUI-QT/DRMPlot.cpp
@@ -0,0 +1,1752 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Original Author(s):
+ *	Volker Fischer
+ *
+ * Qwt 5-6 conversion Author(s):
+ *  David Flamand
+ *
+ * Description:
+ *	Custom settings of the qwt-plot, Support Qwt version 5.0.0 to 6.1.0(+)
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "DRMPlot.h"
+#include "../DrmReceiver.h"
+#include "waterfallwidget.h"
+#include <QTreeWidget>
+#include <QResizeEvent>
+#include <cmath>
+#include <algorithm>
+#include <QHBoxLayout>
+#include <qwt_legend.h>
+#include <qwt_plot_picker.h>
+#include <qwt_picker_machine.h>
+#include <qwt_symbol.h>
+
+/* Define the FAC/SDC/MSC Symbol size */
+#if QWT_VERSION < 0x060000
+# define FAC_SYMBOL_SIZE 5
+# define SDC_SYMBOL_SIZE 5
+# define MSC_SYMBOL_SIZE 2
+# define ALL_FAC_SYMBOL_SIZE 5
+# define ALL_SDC_SYMBOL_SIZE 4
+# define ALL_MSC_SYMBOL_SIZE 2
+#else
+# define FAC_SYMBOL_SIZE 4
+# define SDC_SYMBOL_SIZE 4
+# define MSC_SYMBOL_SIZE 2
+# define ALL_FAC_SYMBOL_SIZE 4
+# define ALL_SDC_SYMBOL_SIZE 4
+# define ALL_MSC_SYMBOL_SIZE 2
+#endif
+
+/* Window margin for chart */
+#define WINDOW_MARGIN 10
+
+/* Sometime between Qwt version some name may change, we fix this */
+#if QWT_VERSION < 0x050200
+# define LOWERBOUND lBound
+# define UPPERBOUND hBound
+#else
+# define LOWERBOUND lowerBound
+# define UPPERBOUND upperBound
+#endif
+#if QWT_VERSION < 0x060000
+# define SETDATA setData
+#else
+# define SETDATA setSamples
+#endif
+#if QWT_VERSION < 0x060100
+# define SETMAJORPEN setMajPen
+# define SETMINORPEN setMinPen
+#else
+# define SETMAJORPEN setMajorPen
+# define SETMINORPEN setMinorPen
+#endif
+
+/* Set workaround flag for Qwt version 5.0.0 and 5.0.1 */
+/* QwtPlotCurve::Xfy seems broken on these versions */
+#if QWT_VERSION < 0x050002
+# define QWT_WORKAROUND_XFY
+#endif
+
+
+/* Define the plot color profiles */
+/* BLUEWHITE */
+#define BLUEWHITE_MAIN_PEN_COLOR_PLOT			Qt::blue
+#define BLUEWHITE_MAIN_PEN_COLOR_CONSTELLATION	Qt::blue
+#define BLUEWHITE_BCKGRD_COLOR_PLOT				Qt::white
+#define BLUEWHITE_MAIN_GRID_COLOR_PLOT			Qt::gray
+#define BLUEWHITE_SPEC_LINE1_COLOR_PLOT			Qt::red
+#define BLUEWHITE_SPEC_LINE2_COLOR_PLOT			Qt::black
+#define BLUEWHITE_PASS_BAND_COLOR_PLOT			QColor(192, 192, 255)
+
+/* GREENBLACK */
+#define GREENBLACK_MAIN_PEN_COLOR_PLOT			Qt::green
+#define GREENBLACK_MAIN_PEN_COLOR_CONSTELLATION	Qt::red
+#define GREENBLACK_BCKGRD_COLOR_PLOT			Qt::black
+#define GREENBLACK_MAIN_GRID_COLOR_PLOT			QColor(128, 0, 0)
+#define GREENBLACK_SPEC_LINE1_COLOR_PLOT		Qt::yellow
+#define GREENBLACK_SPEC_LINE2_COLOR_PLOT		Qt::blue
+#define GREENBLACK_PASS_BAND_COLOR_PLOT			QColor(0, 96, 0)
+
+/* BLACKGREY */
+#define BLACKGREY_MAIN_PEN_COLOR_PLOT			Qt::black
+#define BLACKGREY_MAIN_PEN_COLOR_CONSTELLATION	Qt::green
+#define BLACKGREY_BCKGRD_COLOR_PLOT				Qt::gray
+#define BLACKGREY_MAIN_GRID_COLOR_PLOT			Qt::white
+#define BLACKGREY_SPEC_LINE1_COLOR_PLOT			Qt::blue
+#define BLACKGREY_SPEC_LINE2_COLOR_PLOT			Qt::yellow
+#define BLACKGREY_PASS_BAND_COLOR_PLOT			QColor(128, 128, 128)
+
+
+/* Maximum and minimum values of x-axis of input spectrum plots */
+#define MIN_VAL_INP_SPEC_Y_AXIS_DB				((double) -120.0)
+#define MAX_VAL_INP_SPEC_Y_AXIS_DB				((double) 0.0)
+
+/* Maximum and minimum values of x-axis of input PSD (shifted) */
+#define MIN_VAL_SHIF_PSD_Y_AXIS_DB				((double) -85.0)
+#define MAX_VAL_SHIF_PSD_Y_AXIS_DB				((double) -35.0)
+
+/* Maximum and minimum values of x-axis of SNR spectrum */
+#define MIN_VAL_SNR_SPEC_Y_AXIS_DB				((double) 0.0)
+#define MAX_VAL_SNR_SPEC_Y_AXIS_DB				((double) 35.0)
+
+/* Definitions ****************************************************************/
+#define GUI_CONTROL_UPDATE_WATERFALL			100	/* Milliseconds */
+
+/* Implementation *************************************************************/
+CDRMPlot::CDRMPlot(QWidget* parent, QwtPlot* SuppliedPlot, ReceiverController* rc) :
+    controller(rc),
+	SuppliedPlot(SuppliedPlot), DialogPlot(NULL), bActive(FALSE),
+	CurCharType(NONE_OLD), InitCharType(NONE_OLD),
+	eLastSDCCodingScheme((ECodScheme)-1), eLastMSCCodingScheme((ECodScheme)-1),
+    bLastAudioDecoder(FALSE), pDRMRec(rc->getReceiver()),
+    waterfallWidget(NULL), iAudSampleRate(0), iSigSampleRate(0),
+	iLastXoredSampleRate(0), iLastChanMode(-1)
+{
+	/* Create new plot if none is supplied */
+	if (SuppliedPlot == NULL)
+	{
+		DialogPlot = new QwtPlotDialog(parent);
+		plot = DialogPlot->GetPlot();
+	}
+	else
+		plot = SuppliedPlot;
+
+	/* Setup plot */
+	plot->setAutoDelete(false);
+	plot->setAutoReplot(false);
+    plot->setMinimumHeight(120); // very important for getting sizeHint rational
+
+	/* Base font */
+	QFont basefont;
+	basefont.setPointSize(PLOT_FONT_SIZE);
+	basefont.setStyleHint(QFont::SansSerif, QFont::PreferOutline);
+
+	/* Legend creation */
+	legend = new QwtLegend();
+	QFont legendfont(basefont);
+	legend->setFont(legendfont);
+	plot->insertLegend(legend, QwtPlot::RightLegend);
+
+	/* Curve defaults (other curves are set by PlotDefaults) */
+	curve4.setItemAttribute(QwtPlotItem::Legend, false);
+	curve5.setItemAttribute(QwtPlotItem::Legend, false);
+	vcurvegrid.setItemAttribute(QwtPlotItem::Legend, false);
+	hcurvegrid.setItemAttribute(QwtPlotItem::Legend, false);
+#ifndef QWT_WORKAROUND_XFY
+	vcurvegrid.setStyle(QwtPlotCurve::Sticks);
+	hcurvegrid.setStyle(QwtPlotCurve::Sticks);
+#else
+	vcurvegrid.setStyle(QwtPlotCurve::Steps);
+	hcurvegrid.setStyle(QwtPlotCurve::Steps);
+#endif
+#if QWT_VERSION < 0x060000
+# ifndef QWT_WORKAROUND_XFY
+	vcurvegrid.setCurveType(QwtPlotCurve::Yfx);
+	hcurvegrid.setCurveType(QwtPlotCurve::Xfy);
+# endif
+#else
+	vcurvegrid.setOrientation(Qt::Vertical);
+	hcurvegrid.setOrientation(Qt::Horizontal);
+#endif
+
+	/* Grid */
+	grid.enableXMin(FALSE);
+	grid.enableYMin(FALSE);
+	grid.attach(plot);
+
+	/* Axis and title fonts */
+	QFont axisfont(basefont);
+	QFont titlefont(basefont);
+	titlefont.setWeight(QFont::Bold);
+	plot->setAxisFont(QwtPlot::xBottom, axisfont);
+	plot->setAxisFont(QwtPlot::yLeft, axisfont);
+	plot->setAxisFont(QwtPlot::yRight, axisfont);
+	QwtText title;
+	title.setFont(titlefont);
+	plot->setTitle(title);
+
+	/* Axis titles */
+	bottomTitle.setFont(axisfont);
+	plot->setAxisTitle(QwtPlot::xBottom, bottomTitle);
+	leftTitle.setFont(axisfont);
+	plot->setAxisTitle(QwtPlot::yLeft, leftTitle);
+	rightTitle.setFont(axisfont);
+	plot->setAxisTitle(QwtPlot::yRight, rightTitle);
+
+	/* Global frame */
+	plot->setFrameStyle(QFrame::Plain|QFrame::NoFrame);
+	plot->setLineWidth(0);
+	plot->setContentsMargins(
+		WINDOW_MARGIN, WINDOW_MARGIN,
+		WINDOW_MARGIN, WINDOW_MARGIN);
+
+	/* Canvas */
+#if QWT_VERSION < 0x060100
+	plot->setCanvasLineWidth(0);
+#else
+	((QFrame*)plot->canvas())->setLineWidth(0);
+#endif
+	plot->canvas()->setBackgroundRole(QPalette::Window);
+
+	/* Picker */
+	picker = new QwtPlotPicker(plot->canvas());
+#if QWT_VERSION < 0x060000
+	picker->setSelectionFlags(QwtPicker::PointSelection | QwtPicker::ClickSelection);
+#else
+	picker->initMousePattern(1);
+	QwtPickerClickPointMachine *machine = new QwtPickerClickPointMachine();
+	picker->setStateMachine(machine);
+#endif
+
+	/* Set default style */
+	SetPlotStyle(0);
+
+	/* Connections */
+	connect(&TimerChart, SIGNAL(timeout()), this, SLOT(OnTimerChart()));
+#if QWT_VERSION < 0x060000
+	connect(picker, SIGNAL(selected(const QwtDoublePoint &)),
+		this, SLOT(OnSelected(const QwtDoublePoint &)));
+#else
+	connect(picker, SIGNAL(selected(const QPointF &)),
+		this, SLOT(OnSelected(const QPointF &)));
+#endif
+	if (DialogPlot != NULL)
+	{
+		connect(DialogPlot, SIGNAL(activate()), this, SLOT(activate()));
+		connect(DialogPlot, SIGNAL(deactivate()), this, SLOT(deactivate()));
+	}
+}
+
+CDRMPlot::~CDRMPlot()
+{
+	deactivate();
+	/* Delete DialogPlot if exist */
+	if (DialogPlot != NULL)
+		delete DialogPlot;
+}
+
+void CDRMPlot::UpdateAnalogBWMarker()
+{
+    if(pDRMRec==NULL)
+        return;
+
+    if (CurCharType == INPUT_SIG_PSD_ANALOG)
+	{
+		_REAL rCenterFreq, rBandwidth;
+		/* Get data and parameters from modules */
+		pDRMRec->GetAMDemod()->GetBWParameters(rCenterFreq, rBandwidth);
+		/* Prepare graph and set data */
+		SetDCCarrier(pDRMRec->GetAMDemod()->GetCurMixFreqOffs());
+		SetBWMarker(rCenterFreq, rBandwidth);
+		plot->replot();
+	}
+}
+
+void CDRMPlot::OnTimerChart()
+{
+    if(pDRMRec==NULL)
+        return;
+    CParameter& Parameters = *pDRMRec->GetParameters();
+	/* Update only performed when running */
+	if (Parameters.eRunState != CParameter::RUNNING)
+		return;
+
+	/* CHART ******************************************************************/
+	CVector<_REAL>	vecrData;
+	CVector<_REAL>	vecrData2;
+	CVector<_COMPLEX>	veccData1, veccData2, veccData3;
+	CVector<_REAL>	vecrScale;
+	_REAL		rLowerBound, rHigherBound;
+	_REAL		rStartGuard, rEndGuard;
+	_REAL		rPDSBegin, rPDSEnd;
+	_REAL		rFreqAcquVal;
+	_REAL		rCenterFreq, rBandwidth;
+
+	Parameters.Lock();
+	_REAL rDCFrequency = Parameters.GetDCFrequency();
+	ECodScheme eSDCCodingScheme = Parameters.eSDCCodingScheme;
+	ECodScheme eMSCCodingScheme = Parameters.eMSCCodingScheme;
+#if 1
+    _BOOLEAN bAudioDecoder = !Parameters.audiodecoder.empty();
+#else
+    const int iCurSelAudioServ = Parameters.GetCurSelAudioService();
+    CService audioService = Parameters.Service[iCurSelAudioServ];
+    _BOOLEAN bAudioDecoder = audioService.AudioParam.bCanDecode;
+#endif
+    iAudSampleRate = Parameters.GetAudSampleRate();
+	iSigSampleRate = Parameters.GetSigSampleRate();
+	int iChanMode = (int)pDRMRec->GetReceiveData()->GetInChanSel();
+	Parameters.Unlock();
+
+	/* Needed to detect sample rate change */
+	const int iXoredSampleRate = iAudSampleRate ^ iSigSampleRate;
+
+	CPlotManager& PlotManager = *pDRMRec->GetPlotManager();
+
+	/* First check if plot must be set up */
+	bool change = false;
+	if (InitCharType != CurCharType ||
+		iLastXoredSampleRate != iXoredSampleRate ||
+		iLastChanMode != iChanMode)
+	{
+		InitCharType = CurCharType;
+		iLastXoredSampleRate = iXoredSampleRate;
+		iLastChanMode = iChanMode;
+		change = true;
+		PlotDefaults();
+	}
+	switch (CurCharType)
+	{
+	case AVERAGED_IR:
+		/* Get data from module */
+		PlotManager.GetAvPoDeSp(vecrData, vecrScale, rLowerBound, rHigherBound,
+			rStartGuard, rEndGuard, rPDSBegin, rPDSEnd);
+
+		if (vecrScale.Size() != 0)
+		{
+			if (change) SetupAvIR();
+			SetVerticalBounds(rStartGuard, rEndGuard, rPDSBegin, rPDSEnd);
+			SetHorizontalBounds(vecrScale[0], vecrScale[vecrScale.Size() - 1], rLowerBound, rHigherBound);
+			SetData(vecrData, vecrScale);
+        }
+		else
+		{
+			/* No input data, clear plot (by resetting it) */
+			SetupAvIR();
+		}
+		break;
+
+	case TRANSFERFUNCTION:
+		/* Get data from module */
+		PlotManager.GetTransferFunction(vecrData, vecrData2, vecrScale);
+
+		if (change) SetupTranFct();
+		/* Prepare graph and set data */
+		plot->setAxisScale(QwtPlot::xBottom, (double) 0.0, (double) vecrScale.Size());
+		SetData(vecrData, vecrData2, vecrScale);
+		break;
+
+	case POWER_SPEC_DENSITY:
+		/* Get data from module */
+		pDRMRec->GetOFDMDemod()->GetPowDenSpec(vecrData, vecrScale);
+
+		if (change) SetupPSD();
+		/* Set data */
+		SetData(vecrData, vecrScale);
+		break;
+
+	case SNR_SPECTRUM:
+		/* Get data from module */
+		PlotManager.GetSNRProfile(vecrData, vecrScale);
+
+		if (change) SetupSNRSpectrum();
+		/* Prepare graph and set data */
+		AutoScale3(vecrData, vecrScale);
+		SetData(vecrData, vecrScale);
+		break;
+
+	case INPUTSPECTRUM_NO_AV:
+		/* Get data from module */
+		pDRMRec->GetReceiveData()->GetInputSpec(vecrData, vecrScale);
+
+		if (change) SetupInpSpec();
+		/* Prepare graph and set data */
+		SetDCCarrier(rDCFrequency);
+		SetData(vecrData, vecrScale);
+		break;
+
+	case INP_SPEC_WATERF:
+		/* Get data from module */
+		pDRMRec->GetReceiveData()->GetInputSpec(vecrData, vecrScale);
+
+		if (change) SetupInpSpecWaterf();
+		/* Set data */
+		SetInpSpecWaterf(vecrData, vecrScale);
+		break;
+
+	case INPUT_SIG_PSD:
+		/* Get data from module */
+		PlotManager.GetInputPSD(vecrData, vecrScale);
+
+		if (change) SetupInpPSD();
+		/* Prepare graph and set data */
+		SetDCCarrier(rDCFrequency);
+		SetData(vecrData, vecrScale);
+		break;
+
+	case INPUT_SIG_PSD_ANALOG:
+		/* Get data and parameters from modules */
+		pDRMRec->GetReceiveData()->GetInputPSD(vecrData, vecrScale);
+		pDRMRec->GetAMDemod()->GetBWParameters(rCenterFreq, rBandwidth);
+
+		if (change) SetupInpPSD(TRUE);
+		/* Prepare graph and set data */
+		SetDCCarrier(pDRMRec->GetAMDemod()->GetCurMixFreqOffs());
+		SetBWMarker(rCenterFreq, rBandwidth);
+		SetData(vecrData, vecrScale);
+		break;
+
+	case AUDIO_SPECTRUM:
+		/* Get data from module */
+		pDRMRec->GetWriteData()->GetAudioSpec(vecrData, vecrScale);
+
+		if (change || bLastAudioDecoder != bAudioDecoder)
+		{
+			bLastAudioDecoder = bAudioDecoder;
+			SetupAudioSpec(bAudioDecoder);
+		}
+		/* Set data */
+		if (bAudioDecoder)
+			SetData(vecrData, vecrScale);
+		break;
+
+	case FREQ_SAM_OFFS_HIST:
+		/* Get data from module */
+		PlotManager.GetFreqSamOffsHist(vecrData, vecrData2, vecrScale, rFreqAcquVal);
+
+		if (change) SetupFreqSamOffsHist();
+		/* Prepare graph and set data */
+		plot->setAxisTitle(QwtPlot::yLeft, tr("Freq. Offset [Hz] rel. to ")
+			+ QString().setNum(pDRMRec->GetReceiveData()->
+				ConvertFrequency(rFreqAcquVal))
+			+ " Hz");
+		AutoScale(vecrData, vecrData2, vecrScale);
+		SetData(vecrData, vecrData2, vecrScale);
+		break;
+
+	case DOPPLER_DELAY_HIST:
+		/* Get data from module */
+		PlotManager.GetDopplerDelHist(vecrData, vecrData2, vecrScale);
+
+		if (change) SetupDopplerDelayHist();
+		/* Prepare graph and set data */
+		plot->setAxisScale(QwtPlot::xBottom, (double) vecrScale[0], (double) 0.0);
+		SetData(vecrData, vecrData2, vecrScale);
+		break;
+
+	case SNR_AUDIO_HIST:
+		/* Get data from module */
+		PlotManager.GetSNRHist(vecrData, vecrData2, vecrScale);
+
+		if (change) SetupSNRAudHist();
+		/* Prepare graph and set data */
+		AutoScale2(vecrData, vecrData2, vecrScale);
+		SetData(vecrData, vecrData2, vecrScale);
+		break;
+
+	case FAC_CONSTELLATION:
+		/* Get data vector */
+		pDRMRec->GetFACMLC()->GetVectorSpace(veccData1);
+
+		if (change) SetupFACConst();
+		/* Set data */
+		SetData(veccData1);
+		break;
+
+	case SDC_CONSTELLATION:
+		/* Get data vector */
+		pDRMRec->GetSDCMLC()->GetVectorSpace(veccData1);
+
+		if (change || eLastSDCCodingScheme != eSDCCodingScheme)
+		{
+			eLastSDCCodingScheme = eSDCCodingScheme;
+			SetupSDCConst(eSDCCodingScheme);
+		}
+		/* Set data */
+		SetData(veccData1);
+		break;
+
+	case MSC_CONSTELLATION:
+		/* Get data vector */
+		pDRMRec->GetMSCMLC()->GetVectorSpace(veccData1);
+
+		if (change || eLastMSCCodingScheme != eMSCCodingScheme)
+		{
+			eLastMSCCodingScheme = eMSCCodingScheme;
+			SetupMSCConst(eMSCCodingScheme);
+		}
+		/* Set data */
+		SetData(veccData1);
+		break;
+
+	case ALL_CONSTELLATION:
+		/* Get data vectors */
+		pDRMRec->GetMSCMLC()->GetVectorSpace(veccData1);
+		pDRMRec->GetSDCMLC()->GetVectorSpace(veccData2);
+		pDRMRec->GetFACMLC()->GetVectorSpace(veccData3);
+
+		if (change) SetupAllConst();
+		/* Set data */
+		SetData(veccData1, veccData2, veccData3);
+		break;
+
+	case NONE_OLD:
+		break;
+	}
+
+    plot->replot();
+}
+
+void CDRMPlot::SetupChart(const ECharType eNewType)
+{
+	if (eNewType != NONE_OLD)
+	{
+		/* Set internal variable */
+		CurCharType = eNewType;
+
+		/* Update help text connected with the plot widget */
+		AddWhatsThisHelpChar(eNewType);
+
+		/* Update chart */
+		if (bActive)
+			OnTimerChart();
+
+		/* Set up timer */
+		switch (eNewType)
+		{
+		case INP_SPEC_WATERF:
+			/* Very fast update */
+			TimerChart.setInterval(GUI_CONTROL_UPDATE_WATERFALL);
+			break;
+
+		case AVERAGED_IR:
+		case TRANSFERFUNCTION:
+		case POWER_SPEC_DENSITY:
+		case INPUT_SIG_PSD:
+		case INPUT_SIG_PSD_ANALOG:
+		case SNR_SPECTRUM:
+			/* Fast update */
+			TimerChart.setInterval(GUI_CONTROL_UPDATE_TIME_FAST);
+			break;
+
+		case FAC_CONSTELLATION:
+		case SDC_CONSTELLATION:
+		case MSC_CONSTELLATION:
+		case ALL_CONSTELLATION:
+		case INPUTSPECTRUM_NO_AV:
+		case AUDIO_SPECTRUM:
+		case FREQ_SAM_OFFS_HIST:
+		case DOPPLER_DELAY_HIST:
+		case SNR_AUDIO_HIST:
+			/* Slow update of plot */
+			TimerChart.setInterval(GUI_CONTROL_UPDATE_TIME);
+			break;
+
+		case NONE_OLD:
+			break;
+		}
+	}
+}
+
+void CDRMPlot::activate()
+{
+	/* Set active flag */
+	bActive = TRUE;
+
+	/* Force re-initialization */
+	InitCharType = NONE_OLD;
+	SetupChart(CurCharType);
+
+	/* Activate real-time timers when window is shown */
+	TimerChart.start();
+}
+
+void CDRMPlot::deactivate()
+{
+	/* Deactivate real-time timers when window is hide to save CPU power */
+	TimerChart.stop();
+
+	/* Free some resources */
+	PlotDefaults();
+
+	/* Clear active flag */
+	bActive = FALSE;
+}
+
+void CDRMPlot::SetPlotStyle(const int iNewStyleID)
+{
+	switch (iNewStyleID)
+	{
+	case 1:
+		MainPenColorPlot = GREENBLACK_MAIN_PEN_COLOR_PLOT;
+		MainPenColorConst = GREENBLACK_MAIN_PEN_COLOR_CONSTELLATION;
+		BckgrdColorPlot = GREENBLACK_BCKGRD_COLOR_PLOT;
+		MainGridColorPlot = GREENBLACK_MAIN_GRID_COLOR_PLOT;
+		SpecLine1ColorPlot = GREENBLACK_SPEC_LINE1_COLOR_PLOT;
+		SpecLine2ColorPlot = GREENBLACK_SPEC_LINE2_COLOR_PLOT;
+		PassBandColorPlot = GREENBLACK_PASS_BAND_COLOR_PLOT;
+		break;
+
+	case 2:
+		MainPenColorPlot = BLACKGREY_MAIN_PEN_COLOR_PLOT;
+		MainPenColorConst = BLACKGREY_MAIN_PEN_COLOR_CONSTELLATION;
+		BckgrdColorPlot = BLACKGREY_BCKGRD_COLOR_PLOT;
+		MainGridColorPlot = BLACKGREY_MAIN_GRID_COLOR_PLOT;
+		SpecLine1ColorPlot = BLACKGREY_SPEC_LINE1_COLOR_PLOT;
+		SpecLine2ColorPlot = BLACKGREY_SPEC_LINE2_COLOR_PLOT;
+		PassBandColorPlot = BLACKGREY_PASS_BAND_COLOR_PLOT;
+		break;
+
+	case 0: /* 0 is default */
+	default:
+		MainPenColorPlot = BLUEWHITE_MAIN_PEN_COLOR_PLOT;
+		MainPenColorConst = BLUEWHITE_MAIN_PEN_COLOR_CONSTELLATION;
+		BckgrdColorPlot = BLUEWHITE_BCKGRD_COLOR_PLOT;
+		MainGridColorPlot = BLUEWHITE_MAIN_GRID_COLOR_PLOT;
+		SpecLine1ColorPlot = BLUEWHITE_SPEC_LINE1_COLOR_PLOT;
+		SpecLine2ColorPlot = BLUEWHITE_SPEC_LINE2_COLOR_PLOT;
+		PassBandColorPlot = BLUEWHITE_PASS_BAND_COLOR_PLOT;
+		break;
+	}
+
+	/* Apply colors */
+	grid.SETMAJORPEN(QPen(MainGridColorPlot, 0, Qt::DotLine));
+	grid.SETMINORPEN(QPen(MainGridColorPlot, 0, Qt::DotLine));
+	vcurvegrid.setPen(QPen(MainGridColorPlot, 1, Qt::DotLine));
+	hcurvegrid.setPen(QPen(MainGridColorPlot, 1, Qt::DotLine));
+	plot->setCanvasBackground(QColor(BckgrdColorPlot));
+
+	/* Make sure that plot are being initialized again */
+	InitCharType = NONE_OLD;
+}
+
+void CDRMPlot::SetData(CVector<_REAL>& vecrData, CVector<_REAL>& vecrScale)
+{
+	const int size = vecrData.Size();
+	main1curve.SETDATA(size ? &vecrScale[0] : NULL, size ? &vecrData[0] : NULL, size);
+}
+
+void CDRMPlot::SetData(CVector<_REAL>& vecrData1, CVector<_REAL>& vecrData2,
+                       CVector<_REAL>& vecrScale)
+{
+	const int size1 = vecrData1.Size();
+	main1curve.SETDATA(size1 ? &vecrScale[0] : NULL, size1 ? &vecrData1[0] : NULL, size1);
+	const int size2 = vecrData2.Size();
+	main2curve.SETDATA(size2 ? &vecrScale[0] : NULL, size2 ? &vecrData2[0] : NULL, size2);
+}
+
+void CDRMPlot::SetData(QwtPlotCurve& curve, CVector<_COMPLEX>& veccData)
+{
+	const int size = veccData.Size();
+	if (size)
+	{
+		vector<double> r(size), im(size);
+		for(int i=0; i<size; i++)
+		{
+			r[i] = veccData[i].real();
+			im[i] = veccData[i].imag();
+		}
+		curve.SETDATA(&r[0], &im[0], size);
+	}
+	else
+		curve.SETDATA(NULL, NULL, 0);
+}
+
+void CDRMPlot::SetData(CVector<_COMPLEX>& veccData)
+{
+	SetData(curve1, veccData);
+}
+
+void CDRMPlot::SetData(CVector<_COMPLEX>& veccMSCConst,
+                       CVector<_COMPLEX>& veccSDCConst,
+                       CVector<_COMPLEX>& veccFACConst)
+{
+	SetData(curve1, veccMSCConst);
+	SetData(curve2, veccSDCConst);
+	SetData(curve3, veccFACConst);
+}
+
+void CDRMPlot::PlotDefaults()
+{
+	/* Set default value of plot items */
+	curve1.detach();
+	curve2.detach();
+	curve3.detach();
+	curve4.detach();
+	curve5.detach();
+	hcurvegrid.detach();
+	vcurvegrid.detach();
+	main1curve.detach();
+	main2curve.detach();
+	curve1.SETDATA(NULL, NULL, 0);
+	curve2.SETDATA(NULL, NULL, 0);
+	curve3.SETDATA(NULL, NULL, 0);
+	curve4.SETDATA(NULL, NULL, 0);
+	curve5.SETDATA(NULL, NULL, 0);
+	hcurvegrid.SETDATA(NULL, NULL, 0);
+	vcurvegrid.SETDATA(NULL, NULL, 0);
+	main1curve.SETDATA(NULL, NULL, 0);
+	main2curve.SETDATA(NULL, NULL, 0);
+#if QWT_VERSION < 0x060000
+	curve1.setSymbol(QwtSymbol());
+    curve2.setSymbol(QwtSymbol());
+	curve3.setSymbol(QwtSymbol());
+#else
+	curve1.setSymbol(NULL);
+	curve2.setSymbol(NULL);
+	curve3.setSymbol(NULL);
+	curve1.setLegendAttribute(QwtPlotCurve::LegendShowSymbol, false);
+	curve2.setLegendAttribute(QwtPlotCurve::LegendShowSymbol, false);
+	curve3.setLegendAttribute(QwtPlotCurve::LegendShowSymbol, false);
+#endif
+	grid.enableX(TRUE);
+	grid.enableY(TRUE);
+	grid.SETMAJORPEN(QPen(MainGridColorPlot, 0, Qt::DotLine));
+	grid.SETMINORPEN(QPen(MainGridColorPlot, 0, Qt::DotLine));
+	curve1.setItemAttribute(QwtPlotItem::Legend, false);
+	curve2.setItemAttribute(QwtPlotItem::Legend, false);
+	curve3.setItemAttribute(QwtPlotItem::Legend, false);
+	main1curve.setItemAttribute(QwtPlotItem::Legend, false);
+	main2curve.setItemAttribute(QwtPlotItem::Legend, false);
+	plot->setCanvasBackground(QColor(BckgrdColorPlot));
+    if (waterfallWidget != NULL)
+	{
+        delete waterfallWidget;
+        waterfallWidget = NULL;
+	}
+}
+
+void CDRMPlot::PlotSetLegendFont()
+{
+#if QWT_VERSION < 0x060100
+	foreach(QWidget* item, legend->legendItems())
+		item->setFont(legend->font());
+#endif
+}
+
+void CDRMPlot::SetupAvIR()
+{
+	/* Init chart for averaged impulse response */
+	plot->setTitle(tr("Channel Impulse Response"));
+	plot->enableAxis(QwtPlot::yRight, FALSE);
+	plot->setAxisTitle(QwtPlot::xBottom, tr("Time [ms]"));
+	plot->enableAxis(QwtPlot::yLeft, TRUE);
+	plot->setAxisTitle(QwtPlot::yLeft, tr("IR [dB]"));
+
+	/* Curves color */
+    curve1.setPen(QPen(SpecLine1ColorPlot, 1, Qt::DashLine));
+    curve2.setPen(QPen(SpecLine1ColorPlot, 1, Qt::DashLine));
+    curve3.setPen(QPen(SpecLine2ColorPlot, 1, Qt::DashLine));
+    curve4.setPen(QPen(SpecLine2ColorPlot, 1, Qt::DashLine));
+    curve5.setPen(QPen(SpecLine1ColorPlot, 1, Qt::DashLine));
+	main1curve.setPen(QPen(MainPenColorPlot, 2, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
+
+	/* Curves title */
+	main1curve.setTitle(tr("Channel Impulse Response"));
+
+	/* Insert curves */
+	curve1.attach(plot);
+	curve2.attach(plot);
+	curve3.attach(plot);
+	curve4.attach(plot);
+	curve5.attach(plot);
+	main1curve.attach(plot);
+}
+
+
+void CDRMPlot::SetVerticalBounds(
+	const _REAL rStartGuard, const _REAL rEndGuard,
+	const _REAL rBeginIR, const _REAL rEndIR)
+{
+	/* Fixed scale */
+	const double cdAxMinLeft = (double) -20.0;
+	const double cdAxMaxLeft = (double) 40.0;
+	plot->setAxisScale(QwtPlot::yLeft, cdAxMinLeft, cdAxMaxLeft);
+
+	/* Vertical bounds -------------------------------------------------- */
+	double dX[2], dY[2];
+
+	/* These bounds show the beginning and end of the guard-interval */
+	dY[0] = cdAxMinLeft;
+	dY[1] = cdAxMaxLeft;
+
+	/* Left bound */
+	dX[0] = dX[1] = rStartGuard;
+	curve1.SETDATA(dX, dY, 2);
+
+	/* Right bound */
+	dX[0] = dX[1] = rEndGuard;
+	curve2.SETDATA(dX, dY, 2);
+
+	/* Estimated begin of impulse response */
+	dX[0] = dX[1] = rBeginIR;
+	curve3.SETDATA(dX, dY, 2);
+
+	/* Estimated end of impulse response */
+	dX[0] = dX[1] = rEndIR;
+	curve4.SETDATA(dX, dY, 2);
+}
+
+void CDRMPlot::SetHorizontalBounds( _REAL rScaleMin, _REAL rScaleMax, _REAL rLowerB, _REAL rHigherB)
+{
+	/* Adjust scale for x-axis */
+	plot->setAxisScale(QwtPlot::xBottom, (double) rScaleMin, (double) rScaleMax);
+
+	double dX[2], dY[2];
+	/* These bounds show the peak detection bound from timing tracking */
+	dX[0] = rScaleMin;
+	dX[1] = rScaleMax;
+
+	/* Only include highest bound */
+	dY[0] = dY[1] = Max(rHigherB, rLowerB);
+	curve5.SETDATA(dX, dY, 2);
+}
+
+void CDRMPlot::SetupTranFct()
+{
+	/* Init chart for transfer function */
+	plot->setTitle(tr("Channel Transfer Function / Group Delay"));
+	plot->enableAxis(QwtPlot::yRight);
+	plot->setAxisTitle(QwtPlot::xBottom, tr("Carrier Index"));
+	plot->enableAxis(QwtPlot::yLeft, TRUE);
+	plot->setAxisTitle(QwtPlot::yLeft, tr("TF [dB]"));
+
+	plot->setAxisTitle(QwtPlot::yRight, tr("Group Delay [ms]"));
+	plot->setAxisScale(QwtPlot::yRight, (double) -50.0, (double) 50.0);
+
+	/* Fixed scale */
+	plot->setAxisScale(QwtPlot::yLeft, (double) -85.0, (double) -35.0);
+
+	/* Curve colors */
+	main1curve.setPen(QPen(MainPenColorPlot, 2, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
+	main2curve.setPen(QPen(SpecLine2ColorPlot, 1, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
+
+	/* Set legends */
+	main1curve.setItemAttribute(QwtPlotItem::Legend, true);
+	main2curve.setItemAttribute(QwtPlotItem::Legend, true);
+
+	/* Add main curves */
+	main1curve.setTitle(tr("Transf. Fct."));
+	main1curve.attach(plot);
+	main2curve.setTitle(tr("Group Del."));
+	main2curve.setYAxis(QwtPlot::yRight);
+	main2curve.attach(plot);
+	PlotSetLegendFont();
+}
+
+void CDRMPlot::SetupAudioSpec(_BOOLEAN bAudioDecoder)
+{
+	/* Init chart for audio spectrum */
+	if (bAudioDecoder)
+		plot->setTitle(tr("Audio Spectrum"));
+	else
+	{
+		plot->setTitle(tr("No audio decoding possible"));
+		main1curve.SETDATA(NULL, NULL, 0);
+	}
+	plot->enableAxis(QwtPlot::yRight, FALSE);
+	plot->setAxisTitle(QwtPlot::xBottom, tr("Frequency [kHz]"));
+	plot->enableAxis(QwtPlot::yLeft, TRUE);
+	plot->setAxisTitle(QwtPlot::yLeft, "AS [dB]");
+
+	/* Fixed scale */
+	plot->setAxisScale(QwtPlot::yLeft, (double) -100.0, (double) -20.0);
+	int iMaxAudioFrequency = MAX_SPEC_AUDIO_FREQUENCY;
+	if (iMaxAudioFrequency > iAudSampleRate/2)
+		iMaxAudioFrequency = iAudSampleRate/2;
+	const double dBandwidth = double(iMaxAudioFrequency) / 1000;
+	plot->setAxisScale(QwtPlot::xBottom, (double) 0.0, dBandwidth);
+
+	/* Curve color */
+	main1curve.setPen(QPen(MainPenColorPlot, 2, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
+
+	/* Add main curve */
+	main1curve.setTitle(tr("Audio Spectrum"));
+	main1curve.attach(plot);
+}
+
+void CDRMPlot::SetupFreqSamOffsHist()
+{
+	/* Init chart for transfer function. Enable right axis, too */
+	plot->setTitle(tr("Rel. Frequency Offset / Sample Rate Offset History"));
+	plot->enableAxis(QwtPlot::yRight);
+	plot->setAxisTitle(QwtPlot::xBottom, tr("Time [s]"));
+	plot->enableAxis(QwtPlot::yLeft, TRUE);
+	plot->setAxisTitle(QwtPlot::yRight, tr("Sample Rate Offset [Hz]"));
+
+	/* Curve colors */
+	main1curve.setPen(QPen(MainPenColorPlot, 2, Qt::SolidLine, Qt::RoundCap,
+		Qt::RoundJoin));
+	main2curve.setPen(QPen(SpecLine2ColorPlot, 1, Qt::SolidLine, Qt::RoundCap,
+		Qt::RoundJoin));
+
+	/* Set legends */
+	main1curve.setItemAttribute(QwtPlotItem::Legend, true);
+	main2curve.setItemAttribute(QwtPlotItem::Legend, true);
+
+	/* Add main curves */
+	main1curve.setTitle(tr("Freq."));
+	main1curve.attach(plot);
+	main2curve.setTitle(tr("Samp."));
+	main2curve.setYAxis(QwtPlot::yRight);
+	main2curve.attach(plot);
+	PlotSetLegendFont();
+}
+
+void CDRMPlot::AutoScale(CVector<_REAL>& vecrData,
+                         CVector<_REAL>& vecrData2,
+                         CVector<_REAL>& vecrScale)
+{
+	/* Customized auto-scaling. We adjust the y scale so that it is not larger
+	   than rMinScaleRange"  */
+	const _REAL rMinScaleRange = (_REAL) 1.0; /* Hz */
+
+	/* Get maximum and minimum values */
+	_REAL MaxFreq = -_MAXREAL;
+	_REAL MinFreq = _MAXREAL;
+	_REAL MaxSam = -_MAXREAL;
+	_REAL MinSam = _MAXREAL;
+
+	const int iSize = vecrScale.Size();
+	for (int i = 0; i < iSize; i++)
+	{
+		if (vecrData[i] > MaxFreq)
+			MaxFreq = vecrData[i];
+
+		if (vecrData[i] < MinFreq)
+			MinFreq = vecrData[i];
+
+		if (vecrData2[i] > MaxSam)
+			MaxSam = vecrData2[i];
+
+		if (vecrData2[i] < MinSam)
+			MinSam = vecrData2[i];
+	}
+
+	/* Apply scale to plot */
+	plot->setAxisScale(QwtPlot::yLeft, (double) Floor(MinFreq / rMinScaleRange),
+		(double) Ceil(MaxFreq / rMinScaleRange));
+	plot->setAxisScale(QwtPlot::yRight, (double) Floor(MinSam / rMinScaleRange),
+		(double) Ceil(MaxSam / rMinScaleRange));
+	plot->setAxisScale(QwtPlot::xBottom, (double) vecrScale[0], (double) 0.0);
+}
+
+void CDRMPlot::SetupDopplerDelayHist()
+{
+	/* Init chart for transfer function. Enable right axis, too */
+	plot->setTitle(tr("Delay / Doppler History"));
+	plot->enableAxis(QwtPlot::yRight);
+	plot->setAxisTitle(QwtPlot::xBottom, tr("Time [min]"));
+	plot->enableAxis(QwtPlot::yLeft, TRUE);
+	plot->setAxisTitle(QwtPlot::yLeft, tr("Delay [ms]"));
+	plot->setAxisTitle(QwtPlot::yRight, tr("Doppler [Hz]"));
+
+	/* Fixed scale */
+	plot->setAxisScale(QwtPlot::yLeft, (double) 0.0, (double) 10.0);
+	plot->setAxisScale(QwtPlot::yRight, (double) 0.0, (double) 4.0);
+
+	/* Curve colors */
+	main1curve.setPen(QPen(MainPenColorPlot, 2, Qt::SolidLine, Qt::RoundCap,
+		Qt::RoundJoin));
+	main2curve.setPen(QPen(SpecLine2ColorPlot, 1, Qt::SolidLine, Qt::RoundCap,
+		Qt::RoundJoin));
+
+	/* Set legends */
+	main1curve.setItemAttribute(QwtPlotItem::Legend, true);
+	main2curve.setItemAttribute(QwtPlotItem::Legend, true);
+
+	/* Add main curves */
+	main1curve.setTitle(tr("Delay"));
+	main1curve.attach(plot);
+	main2curve.setTitle(tr("Doppler"));
+	main2curve.setYAxis(QwtPlot::yRight);
+	main2curve.attach(plot);
+	PlotSetLegendFont();
+}
+
+void CDRMPlot::SetupSNRAudHist()
+{
+	/* Init chart for transfer function. Enable right axis, too */
+	plot->setTitle(tr("SNR / Correctly Decoded Audio History"));
+	plot->enableAxis(QwtPlot::yRight);
+	plot->setAxisTitle(QwtPlot::xBottom, tr("Time [min]"));
+	plot->enableAxis(QwtPlot::yLeft, TRUE);
+	plot->setAxisTitle(QwtPlot::yLeft, tr("SNR [dB]"));
+	plot->setAxisTitle(QwtPlot::yRight, tr("Corr. Dec. Audio / DRM-Frame"));
+
+	/* Curve colors */
+	main1curve.setPen(QPen(MainPenColorPlot, 2, Qt::SolidLine, Qt::RoundCap,
+		Qt::RoundJoin));
+	main2curve.setPen(QPen(SpecLine2ColorPlot, 1, Qt::SolidLine, Qt::RoundCap,
+		Qt::RoundJoin));
+
+	/* Set legends */
+	main1curve.setItemAttribute(QwtPlotItem::Legend, true);
+	main2curve.setItemAttribute(QwtPlotItem::Legend, true);
+
+	/* Add main curves */
+	main1curve.setTitle(tr("SNR"));
+	main1curve.attach(plot);
+	main2curve.setTitle(tr("Audio"));
+	main2curve.setYAxis(QwtPlot::yRight);
+	main2curve.attach(plot);
+	PlotSetLegendFont();
+}
+
+void CDRMPlot::AutoScale2(CVector<_REAL>& vecrData,
+                          CVector<_REAL>& vecrData2,
+                          CVector<_REAL>& vecrScale)
+{
+	(void)vecrData2;
+
+	/* Customized auto-scaling. We adjust the y scale maximum so that it
+	   is not more than "rMaxDisToMax" to the curve */
+	const int iMaxDisToMax = 5; /* dB */
+	const int iMinValueSNRYScale = 15; /* dB */
+
+	/* Get maximum value */
+	_REAL MaxSNR = -_MAXREAL;
+
+	const int iSize = vecrScale.Size();
+	for (int i = 0; i < iSize; i++)
+	{
+		if (vecrData[i] > MaxSNR)
+			MaxSNR = vecrData[i];
+	}
+
+	/* Quantize scale to a multiple of "iMaxDisToMax" */
+	double dMaxYScaleSNR =
+		(double) (Ceil(MaxSNR / iMaxDisToMax) * iMaxDisToMax);
+
+	/* Bound at the minimum allowed value */
+	if (dMaxYScaleSNR < (double) iMinValueSNRYScale)
+		dMaxYScaleSNR = (double) iMinValueSNRYScale;
+
+	/* Ratio between the maximum values for audio and SNR. The ratio should be
+	   chosen so that the audio curve is not in the same range as the SNR curve
+	   under "normal" conditions to increase readability of curves.
+	   Since at very low SNRs, no audio can received anyway so we do not have to
+	   check whether the audio y-scale is in range of the curve */
+	const _REAL rRatioAudSNR = (double) 1.5;
+	const double dMaxYScaleAudio = dMaxYScaleSNR * (double) rRatioAudSNR;
+
+	/* Apply scale to plot */
+	plot->setAxisScale(QwtPlot::yLeft, (double) 0.0, dMaxYScaleSNR);
+	plot->setAxisScale(QwtPlot::yRight, (double) 0.0, dMaxYScaleAudio);
+	plot->setAxisScale(QwtPlot::xBottom, (double) vecrScale[0], (double) 0.0);
+}
+
+void CDRMPlot::AutoScale3(CVector<_REAL>& vecrData, CVector<_REAL>& vecrScale)
+{
+	const int iSize = vecrScale.Size();
+
+	/* Fixed scale for x-axis */
+	plot->setAxisScale(QwtPlot::xBottom, (double) 0.0, (double) iSize);
+
+	/* Fixed / variable scale (if SNR is in range, use fixed scale otherwise enlarge scale) */
+	/* Get maximum value */
+	_REAL rMaxSNR = -_MAXREAL;
+	for (int i = 0; i < iSize; i++)
+	{
+		if (vecrData[i] > rMaxSNR)
+			rMaxSNR = vecrData[i];
+	}
+
+	double dMaxScaleYAxis = MAX_VAL_SNR_SPEC_Y_AXIS_DB;
+
+	if (rMaxSNR > dMaxScaleYAxis)
+	{
+		const double rEnlareStep = (double) 10.0; /* dB */
+		dMaxScaleYAxis = ceil(rMaxSNR / rEnlareStep) * rEnlareStep;
+	}
+
+	/* Set scale */
+	plot->setAxisScale(QwtPlot::yLeft, MIN_VAL_SNR_SPEC_Y_AXIS_DB, dMaxScaleYAxis);
+}
+
+void CDRMPlot::SetupPSD()
+{
+	/* Init chart for power spectram density estimation */
+	plot->setTitle(tr("Shifted Power Spectral Density of Input Signal"));
+	plot->enableAxis(QwtPlot::yRight, FALSE);
+	plot->setAxisTitle(QwtPlot::xBottom, tr("Frequency [kHz]"));
+	plot->enableAxis(QwtPlot::yLeft, TRUE);
+	plot->setAxisTitle(QwtPlot::yLeft, tr("PSD [dB]"));
+
+	/* Fixed scale */
+	plot->setAxisScale(QwtPlot::xBottom,
+		(double) 0.0, (double) iSigSampleRate / 2000);
+
+	plot->setAxisScale(QwtPlot::yLeft, MIN_VAL_SHIF_PSD_Y_AXIS_DB,
+		MAX_VAL_SHIF_PSD_Y_AXIS_DB);
+
+	double dX[2], dY[2];
+	dX[0] = dX[1] = (_REAL) VIRTUAL_INTERMED_FREQ / 1000;
+
+	/* Take the min-max values from scale to get vertical line */
+	dY[0] = MIN_VAL_SHIF_PSD_Y_AXIS_DB;
+	dY[1] = MAX_VAL_SHIF_PSD_Y_AXIS_DB;
+
+	curve1.SETDATA(dX, dY, 2);
+
+	/* Insert line for DC carrier */
+    curve1.setPen(QPen(SpecLine1ColorPlot, 1, Qt::DashLine));
+	curve1.attach(plot);
+
+	/* Curve color */
+	main1curve.setPen(QPen(MainPenColorPlot, 1, Qt::SolidLine, Qt::RoundCap,
+		Qt::RoundJoin));
+
+	/* Add main curve */
+	main1curve.setTitle(tr("Shifted PSD"));
+	main1curve.attach(plot);
+}
+
+void CDRMPlot::SetupSNRSpectrum()
+{
+	/* Init chart for power spectram density estimation */
+	plot->setTitle(tr("SNR Spectrum (Weighted MER on MSC Cells)"));
+	plot->enableAxis(QwtPlot::yRight, FALSE);
+	plot->setAxisTitle(QwtPlot::xBottom, tr("Carrier Index"));
+	plot->enableAxis(QwtPlot::yLeft, TRUE);
+	plot->setAxisTitle(QwtPlot::yLeft, tr("WMER [dB]"));
+
+	/* Curve color */
+	main1curve.setPen(QPen(MainPenColorPlot, 2, Qt::SolidLine, Qt::RoundCap,
+		Qt::RoundJoin));
+
+	/* Add main curve */
+	main1curve.setTitle(tr("SNR Spectrum"));
+	main1curve.attach(plot);
+}
+
+void CDRMPlot::SetupInpSpec()
+{
+	/* Init chart for power spectram density estimation */
+	plot->setTitle(tr("Input Spectrum"));
+	plot->enableAxis(QwtPlot::yRight, FALSE);
+	plot->setAxisTitle(QwtPlot::xBottom, tr("Frequency [kHz]"));
+	plot->enableAxis(QwtPlot::yLeft, TRUE);
+	plot->setAxisTitle(QwtPlot::yLeft, tr("Input Spectrum [dB]"));
+
+	/* Fixed scale */
+	const double dXScaleMin = pDRMRec->GetReceiveData()->
+		ConvertFrequency((_REAL) 0.0) / 1000;
+	const double dXScaleMax = pDRMRec->GetReceiveData()->
+		ConvertFrequency((_REAL) iSigSampleRate / 2) / 1000;
+	plot->setAxisScale(QwtPlot::xBottom, dXScaleMin, dXScaleMax);
+
+	plot->setAxisScale(QwtPlot::yLeft, MIN_VAL_INP_SPEC_Y_AXIS_DB,
+		MAX_VAL_INP_SPEC_Y_AXIS_DB);
+
+	/* Insert line for DC carrier */
+    curve1.setPen(QPen(SpecLine1ColorPlot, 1, Qt::DashLine));
+	curve1.attach(plot);
+
+	/* Curve color */
+	main1curve.setPen(QPen(MainPenColorPlot, 1, Qt::SolidLine, Qt::RoundCap,
+		Qt::RoundJoin));
+
+	/* Add main curve */
+	main1curve.setTitle(tr("Input spectrum"));
+	main1curve.attach(plot);
+}
+
+void CDRMPlot::SetDCCarrier(const _REAL rDCFreq)
+{
+	/* Insert line for DC carrier */
+	double dX[2], dY[2];
+	dX[0] = dX[1] =
+		pDRMRec->GetReceiveData()->ConvertFrequency(rDCFreq) / 1000;
+
+	/* Take the min-max values from scale to get vertical line */
+	dY[0] = MIN_VAL_INP_SPEC_Y_AXIS_DB;
+	dY[1] = MAX_VAL_INP_SPEC_Y_AXIS_DB;
+
+	curve1.SETDATA(dX, dY, 2);
+}
+
+void CDRMPlot::SetupInpPSD(_BOOLEAN bAnalog)
+{
+	/* Init chart for power spectram density estimation */
+	plot->setTitle(tr("Input PSD"));
+	plot->enableAxis(QwtPlot::yRight, FALSE);
+	plot->setAxisTitle(QwtPlot::xBottom, tr("Frequency [kHz]"));
+	plot->enableAxis(QwtPlot::yLeft, TRUE);
+	plot->setAxisTitle(QwtPlot::yLeft, tr("Input PSD [dB]"));
+
+	/* Fixed scale */
+	const double dXScaleMin = pDRMRec->GetReceiveData()->
+		ConvertFrequency((_REAL) 0.0) / 1000;
+	const double dXScaleMax = pDRMRec->GetReceiveData()->
+		ConvertFrequency((_REAL) iSigSampleRate / 2) / 1000;
+	plot->setAxisScale(QwtPlot::xBottom, dXScaleMin, dXScaleMax);
+
+	plot->setAxisScale(QwtPlot::yLeft, MIN_VAL_INP_SPEC_Y_AXIS_DB,
+		MAX_VAL_INP_SPEC_Y_AXIS_DB);
+
+	/* Insert line for bandwidth marker */
+	if (bAnalog)
+	{
+		QColor color = PassBandColorPlot;
+		color.setAlpha(125);
+		QBrush brush(color);
+		brush.setStyle(Qt::SolidPattern);
+		curve2.setBrush(QBrush(color));
+		curve2.setBaseline(MIN_VAL_INP_SPEC_Y_AXIS_DB);
+		curve2.setPen(QPen(Qt::NoPen));
+		curve2.attach(plot);
+	}
+
+	/* Insert line for DC carrier */
+    curve1.setPen(QPen(SpecLine1ColorPlot, 1, Qt::DashLine));
+	curve1.attach(plot);
+
+	/* Curve color */
+	main1curve.setPen(QPen(MainPenColorPlot, 2, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
+
+	/* Add main curve */
+	main1curve.setTitle(tr("Input PSD"));
+	main1curve.attach(plot);
+}
+
+void CDRMPlot::SetBWMarker(const _REAL rBWCenter, const _REAL rBWWidth)
+{
+	double	dX[2], dY[2];
+	/* Insert marker for filter bandwidth if required */
+	if (rBWWidth != (_REAL) 0.0)
+	{
+		dX[0] = pDRMRec->GetReceiveData()->ConvertFrequency(
+			(rBWCenter - rBWWidth / 2) * (double)iSigSampleRate) / 1000.0;
+		dX[1] = pDRMRec->GetReceiveData()->ConvertFrequency(
+			(rBWCenter + rBWWidth / 2) * (double)iSigSampleRate) / 1000.0;
+
+		/* Take the min-max values from scale to get vertical line */
+		dY[0] = MAX_VAL_INP_SPEC_Y_AXIS_DB;//MIN_VAL_INP_SPEC_Y_AXIS_DB;
+		dY[1] = MAX_VAL_INP_SPEC_Y_AXIS_DB;//MIN_VAL_INP_SPEC_Y_AXIS_DB;
+
+		curve2.SETDATA(dX, dY, 2);
+	}
+	else
+		curve2.SETDATA(NULL, NULL, 0);
+}
+
+void CDRMPlot::SetupInpSpecWaterf()
+{
+	/* Init chart for waterfall input spectrum */
+	plot->setTitle(tr("Waterfall Input Spectrum"));
+	plot->enableAxis(QwtPlot::yRight, FALSE);
+	plot->setAxisTitle(QwtPlot::xBottom, tr("Frequency [kHz]"));
+	plot->enableAxis(QwtPlot::yLeft, FALSE);
+	grid.enableX(FALSE);
+	grid.enableY(FALSE);
+
+	/* Create a new waterfall widget if not exists */
+    if (waterfallWidget == NULL) {
+        waterfallWidget = new WaterfallWidget(plot->canvas());
+        waterfallWidget->show();
+    }
+    QLayout *layout = plot->canvas()->layout();
+    if(layout != NULL)
+    {
+        delete layout;
+    }
+    layout = new QHBoxLayout;
+    layout->addWidget(waterfallWidget);
+    // remove top and bottom margins, set left/right to axis
+    layout->setContentsMargins(4, 0, 5, 0); // assume axis size is fixed
+    plot->canvas()->setLayout(layout);
+    // fill the margins to match the surrounding background
+    QColor c = plot->palette().color(QPalette::Window);
+    plot->setCanvasBackground(c);
+
+    /* Fixed scale DC to 50% sample rate in kHz */
+    const CReceiveData* rd = pDRMRec->GetReceiveData();
+    const double dXScaleMin = rd->ConvertFrequency(0.0) / 1000;
+    const double dXScaleMax = rd->ConvertFrequency(_REAL(iSigSampleRate) / 2.0) / 1000;
+	plot->setAxisScale(QwtPlot::xBottom, dXScaleMin, dXScaleMax);
+}
+
+void CDRMPlot::SetInpSpecWaterf(CVector<_REAL>& vecrData, CVector<_REAL>&)
+{
+    /* No waterfallWidget so return */
+    if (waterfallWidget == NULL)
+        return;
+    waterfallWidget->updatePlot(vecrData, MIN_VAL_INP_SPEC_Y_AXIS_DB, MAX_VAL_INP_SPEC_Y_AXIS_DB);
+}
+
+void CDRMPlot::SetupFACConst()
+{
+	/* Init chart for FAC constellation */
+	plot->setTitle(tr("FAC Constellation"));
+	plot->enableAxis(QwtPlot::yRight, FALSE);
+	plot->setAxisTitle(QwtPlot::xBottom, tr("Real"));
+	plot->enableAxis(QwtPlot::yLeft, TRUE);
+	plot->setAxisTitle(QwtPlot::yLeft, tr("Imaginary"));
+
+	/* Set fixed scale */
+	SetQAMGrid(CS_1_SM);
+
+#if QWT_VERSION < 0x060000
+	QwtSymbol *MarkerSym1_ptr = &MarkerSym1;
+#else
+	QwtSymbol *MarkerSym1, *MarkerSym1_ptr;
+	MarkerSym1 = MarkerSym1_ptr = new QwtSymbol();
+#endif
+
+	/* Set marker symbol */
+	MarkerSym1_ptr->setStyle(QwtSymbol::Ellipse);
+	MarkerSym1_ptr->setSize(FAC_SYMBOL_SIZE);
+	MarkerSym1_ptr->setPen(QPen(MainPenColorConst));
+	MarkerSym1_ptr->setBrush(QBrush(MainPenColorConst));
+
+	curve1.setPen(QPen(Qt::NoPen));
+	curve1.setSymbol(MarkerSym1);
+	curve1.attach(plot);
+}
+
+void CDRMPlot::SetupSDCConst(const ECodScheme eNewCoSc)
+{
+	/* Init chart for SDC constellation */
+	plot->setTitle(tr("SDC Constellation"));
+	plot->enableAxis(QwtPlot::yRight, FALSE);
+	plot->setAxisTitle(QwtPlot::xBottom, tr("Real"));
+	plot->enableAxis(QwtPlot::yLeft, TRUE);
+	plot->setAxisTitle(QwtPlot::yLeft, tr("Imaginary"));
+
+	/* Set fixed scale */
+	SetQAMGrid(eNewCoSc);
+
+#if QWT_VERSION < 0x060000
+	QwtSymbol *MarkerSym1_ptr = &MarkerSym1;
+#else
+	QwtSymbol *MarkerSym1, *MarkerSym1_ptr;
+	MarkerSym1 = MarkerSym1_ptr = new QwtSymbol();
+#endif
+
+	/* Set marker symbol */
+	MarkerSym1_ptr->setStyle(QwtSymbol::Ellipse);
+	MarkerSym1_ptr->setSize(SDC_SYMBOL_SIZE);
+	MarkerSym1_ptr->setPen(QPen(MainPenColorConst));
+	MarkerSym1_ptr->setBrush(QBrush(MainPenColorConst));
+
+	curve1.setPen(QPen(Qt::NoPen));
+	curve1.setSymbol(MarkerSym1);
+	curve1.attach(plot);
+}
+
+void CDRMPlot::SetupMSCConst(const ECodScheme eNewCoSc)
+{
+	/* Init chart for MSC constellation */
+	plot->setTitle(tr("MSC Constellation"));
+	plot->enableAxis(QwtPlot::yRight, FALSE);
+	plot->setAxisTitle(QwtPlot::xBottom, tr("Real"));
+	plot->enableAxis(QwtPlot::yLeft, TRUE);
+	plot->setAxisTitle(QwtPlot::yLeft, tr("Imaginary"));
+
+	/* Set fixed scale */
+	SetQAMGrid(eNewCoSc);
+
+#if QWT_VERSION < 0x060000
+	QwtSymbol *MarkerSym1_ptr = &MarkerSym1;
+#else
+	QwtSymbol *MarkerSym1, *MarkerSym1_ptr;
+	MarkerSym1 = MarkerSym1_ptr = new QwtSymbol();
+#endif
+
+	/* Set marker symbol */
+	MarkerSym1_ptr->setStyle(QwtSymbol::Ellipse);
+	MarkerSym1_ptr->setSize(MSC_SYMBOL_SIZE);
+	MarkerSym1_ptr->setPen(QPen(MainPenColorConst));
+	MarkerSym1_ptr->setBrush(QBrush(MainPenColorConst));
+
+	curve1.setPen(QPen(Qt::NoPen));
+	curve1.setSymbol(MarkerSym1);
+	curve1.attach(plot);
+}
+
+void CDRMPlot::SetupAllConst()
+{
+	/* Init chart for constellation */
+	plot->setTitle(tr("MSC / SDC / FAC Constellation"));
+	plot->enableAxis(QwtPlot::yRight, FALSE);
+	plot->setAxisTitle(QwtPlot::xBottom, tr("Real"));
+	plot->enableAxis(QwtPlot::yLeft, TRUE);
+	plot->setAxisTitle(QwtPlot::yLeft, tr("Imaginary"));
+
+	/* Set fixed scale */
+	SetGrid(1.5, 3, 5);
+
+#if QWT_VERSION < 0x060000
+	QwtSymbol *MarkerSym1_ptr;
+	QwtSymbol *MarkerSym2_ptr;
+	QwtSymbol *MarkerSym3_ptr;
+	MarkerSym1_ptr = &MarkerSym1;
+	MarkerSym2_ptr = &MarkerSym2;
+	MarkerSym3_ptr = &MarkerSym3;
+#else
+	QwtSymbol *MarkerSym1, *MarkerSym1_ptr;
+	QwtSymbol *MarkerSym2, *MarkerSym2_ptr;
+	QwtSymbol *MarkerSym3, *MarkerSym3_ptr;
+	MarkerSym1 = MarkerSym1_ptr = new QwtSymbol();
+	MarkerSym2 = MarkerSym2_ptr = new QwtSymbol();
+	MarkerSym3 = MarkerSym3_ptr = new QwtSymbol();
+	curve1.setLegendAttribute(QwtPlotCurve::LegendShowSymbol, true);
+	curve2.setLegendAttribute(QwtPlotCurve::LegendShowSymbol, true);
+	curve3.setLegendAttribute(QwtPlotCurve::LegendShowSymbol, true);
+#endif
+
+	/* Set marker symbols */
+	/* MSC */
+	MarkerSym1_ptr->setStyle(QwtSymbol::Rect);
+	MarkerSym1_ptr->setSize(ALL_MSC_SYMBOL_SIZE);
+	MarkerSym1_ptr->setPen(QPen(MainPenColorConst));
+	MarkerSym1_ptr->setBrush(QBrush(MainPenColorConst));
+	/* SDC */
+	MarkerSym2_ptr->setStyle(QwtSymbol::XCross);
+	MarkerSym2_ptr->setSize(ALL_SDC_SYMBOL_SIZE);
+	MarkerSym2_ptr->setPen(QPen(SpecLine1ColorPlot));
+	MarkerSym2_ptr->setBrush(QBrush(SpecLine1ColorPlot));
+	/* FAC */
+	MarkerSym3_ptr->setStyle(QwtSymbol::Ellipse);
+	MarkerSym3_ptr->setSize(ALL_FAC_SYMBOL_SIZE);
+	MarkerSym3_ptr->setPen(QPen(SpecLine2ColorPlot));
+	MarkerSym3_ptr->setBrush(QBrush(SpecLine2ColorPlot));
+
+	/* Insert "dummy" curves for legend */
+	curve1.setTitle(QString("MSC"));
+	curve1.setSymbol(MarkerSym1);
+	curve1.setPen(QPen(Qt::NoPen));
+	curve1.setItemAttribute(QwtPlotItem::Legend, true);
+	curve2.setTitle(QString("SDC"));
+	curve2.setSymbol(MarkerSym2);
+	curve2.setPen(QPen(Qt::NoPen));
+	curve2.setItemAttribute(QwtPlotItem::Legend, true);
+	curve3.setTitle(QString("FAC"));
+	curve3.setSymbol(MarkerSym3);
+	curve3.setPen(QPen(Qt::NoPen));
+	curve3.setItemAttribute(QwtPlotItem::Legend, true);
+
+	curve1.attach(plot);
+	curve2.attach(plot);
+	curve3.attach(plot);
+	PlotSetLegendFont();
+}
+
+void CDRMPlot::SetGrid(double div, int step, int substep)
+{
+	int i;
+	_REAL pos;
+#if QWT_VERSION < 0x060000
+	QwtValueList ticks[3];
+#else
+	QList <double> ticks[3];
+#endif
+
+	for (i=0; i<=step*2; i++)
+	{
+		pos = -div + div / step * i;
+		/* Keep 2 digit after the point */
+		pos = Round(pos * 100.0) / 100.0;
+		ticks[2].push_back((double)pos);
+	}
+
+	substep *= step;
+	for (i=0; i<=substep*2; i++)
+	{
+		pos = -div + div / substep * i;
+		/* Keep 2 digit after the point */
+		pos = Round(pos * 100.0) / 100.0;
+		ticks[1].push_back((double)pos);
+	}
+
+	/* Keep 2 digit after the point */
+	div = (double)Round(div * 100.0) / 100.0;
+
+	/* Set the scale */
+	QwtScaleDiv scaleDiv(-div, div, ticks);
+	plot->setAxisScaleDiv(QwtPlot::xBottom, scaleDiv);
+	plot->setAxisScaleDiv(QwtPlot::yLeft, scaleDiv);
+}
+
+void CDRMPlot::SetQAMGrid(const ECodScheme eCoSc)
+{
+	switch (eCoSc)
+	{
+	case CS_1_SM:
+		SetGrid(2.0 / sqrt(2.0), 1, 4); /* QAM4 */
+		break;
+
+	case CS_2_SM:
+		SetGrid(4.0 / sqrt(10.0), 2, 4); /* QAM16 */
+		break;
+
+	default:
+		SetGrid(8.0 / sqrt(42.0), 4, 4); /* QAM64 */
+		break;
+	}
+}
+
+#if QWT_VERSION < 0x060000
+void CDRMPlot::OnSelected(const QwtDoublePoint &pos)
+#else
+void CDRMPlot::OnSelected(const QPointF &pos)
+#endif
+{
+	/* Send normalized frequency to receiver */
+#if QWT_VERSION < 0x060100
+	const double dMaxxBottom = plot->axisScaleDiv(QwtPlot::xBottom)->UPPERBOUND();
+#else
+	const double dMaxxBottom = plot->axisScaleDiv(QwtPlot::xBottom).UPPERBOUND();
+#endif
+
+	/* Check if dMaxxBottom is valid */
+	if (dMaxxBottom > 0.0)
+	{
+		/* Get frequency from current cursor position */
+		double dFreq = pos.x();
+
+		/* Emit signal containing normalized selected frequency */
+		emit xAxisValSet(
+			pDRMRec->GetReceiveData()->ConvertFrequency(dFreq * 1000, TRUE) /
+			pDRMRec->GetReceiveData()->ConvertFrequency(dMaxxBottom * 1000, TRUE));
+	}
+}
+
+void CDRMPlot::setupTreeWidget(QTreeWidget* tw)
+{
+    /* Set the Char Type of each selectable item */
+    QTreeWidgetItemIterator it(tw, QTreeWidgetItemIterator::NoChildren);
+    for (; *it; it++)
+    {
+        if ((*it)->text(0) == tr("SNR Spectrum"))
+            (*it)->setData(0,  Qt::UserRole, CDRMPlot::SNR_SPECTRUM);
+        if ((*it)->text(0) == tr("Audio Spectrum"))
+            (*it)->setData(0,  Qt::UserRole, CDRMPlot::AUDIO_SPECTRUM);
+        if ((*it)->text(0) == tr("Shifted PSD"))
+            (*it)->setData(0,  Qt::UserRole, CDRMPlot::POWER_SPEC_DENSITY);
+        if ((*it)->text(0) == tr("Waterfall Input Spectrum"))
+            (*it)->setData(0,  Qt::UserRole, CDRMPlot::INP_SPEC_WATERF);
+        if ((*it)->text(0) == tr("Input Spectrum"))
+            (*it)->setData(0,  Qt::UserRole, CDRMPlot::INPUTSPECTRUM_NO_AV);
+        if ((*it)->text(0) == tr("Input PSD"))
+            (*it)->setData(0,  Qt::UserRole, CDRMPlot::INPUT_SIG_PSD);
+        if ((*it)->text(0) == tr("MSC"))
+            (*it)->setData(0,  Qt::UserRole, CDRMPlot::MSC_CONSTELLATION);
+        if ((*it)->text(0) == tr("SDC"))
+            (*it)->setData(0,  Qt::UserRole, CDRMPlot::SDC_CONSTELLATION);
+        if ((*it)->text(0) == tr("FAC"))
+            (*it)->setData(0,  Qt::UserRole, CDRMPlot::FAC_CONSTELLATION);
+        if ((*it)->text(0) == tr("FAC / SDC / MSC"))
+            (*it)->setData(0,  Qt::UserRole, CDRMPlot::ALL_CONSTELLATION);
+        if ((*it)->text(0) == tr("Frequency / Sample Rate"))
+            (*it)->setData(0,  Qt::UserRole, CDRMPlot::FREQ_SAM_OFFS_HIST);
+        if ((*it)->text(0) == tr("Delay / Doppler"))
+            (*it)->setData(0,  Qt::UserRole, CDRMPlot::DOPPLER_DELAY_HIST);
+        if ((*it)->text(0) == tr("SNR / Audio"))
+            (*it)->setData(0,  Qt::UserRole, CDRMPlot::SNR_AUDIO_HIST);
+        if ((*it)->text(0) == tr("Transfer Function"))
+            (*it)->setData(0,  Qt::UserRole, CDRMPlot::TRANSFERFUNCTION);
+        if ((*it)->text(0) == tr("Impulse Response"))
+            (*it)->setData(0,  Qt::UserRole, CDRMPlot::AVERAGED_IR);
+    }
+
+    /* Expand all items */
+    tw->expandAll();
+}
+
+void CDRMPlot::AddWhatsThisHelpChar(const ECharType NCharType)
+{
+	QString strCurPlotHelp;
+
+	switch (NCharType)
+	{
+	case AVERAGED_IR:
+		/* Impulse Response */
+		strCurPlotHelp =
+			tr("<b>Impulse Response:</b> This plot shows "
+			   "the estimated Impulse Response (IR) of the channel based on the "
+			   "channel estimation. It is the averaged, Hamming Window weighted "
+			   "Fourier back transformation of the transfer function. The length "
+			   "of PDS estimation and time synchronization tracking is based on "
+			   "this function. The two red dashed vertical lines show the "
+			   "beginning and the end of the guard-interval. The two black dashed "
+			   "vertical lines show the estimated beginning and end of the PDS of "
+			   "the channel (derived from the averaged impulse response "
+			   "estimation). If the \"First Peak\" timing tracking method is "
+			   "chosen, a bound for peak estimation (horizontal dashed red line) "
+			   "is shown. Only peaks above this bound are used for timing "
+			   "estimation.");
+		break;
+
+	case TRANSFERFUNCTION:
+		/* Transfer Function */
+		strCurPlotHelp =
+			tr("<b>Transfer Function / Group Delay:</b> "
+			   "This plot shows the squared magnitude and the group delay of "
+			   "the estimated channel at each sub-carrier.");
+		break;
+
+	case FAC_CONSTELLATION:
+	case SDC_CONSTELLATION:
+	case MSC_CONSTELLATION:
+	case ALL_CONSTELLATION:
+		/* Constellations */
+		strCurPlotHelp =
+			tr("<b>FAC, SDC, MSC:</b> The plots show the "
+			   "constellations of the FAC, SDC and MSC logical channel of the DRM "
+			   "stream. Depending on the current transmitter settings, the SDC "
+			   "and MSC can have 4-QAM, 16-QAM or 64-QAM modulation.");
+		break;
+
+	case POWER_SPEC_DENSITY:
+		/* Shifted PSD */
+		strCurPlotHelp =
+			tr("<b>Shifted PSD:</b> This plot shows the "
+			   "estimated Power Spectrum Density (PSD) of the input signal. The "
+			   "DC frequency (red dashed vertical line) is fixed at 6 kHz. If "
+			   "the frequency offset acquisition was successful, the rectangular "
+			   "DRM spectrum should show up with a center frequency of 6 kHz. "
+			   "This plot represents the frequency synchronized OFDM spectrum. "
+			   "If the frequency synchronization was successful, the useful "
+			   "signal really shows up only inside the actual DRM bandwidth "
+			   "since the side loops have in this case only energy between the "
+			   "samples in the frequency domain. On the sample positions outside "
+			   "the actual DRM spectrum, the DRM signal has zero crossings "
+			   "because of the orthogonality. Therefore this spectrum represents "
+			   "NOT the actual spectrum but the \"idealized\" OFDM spectrum.");
+			break;
+
+	case SNR_SPECTRUM:
+		/* SNR Spectrum (Weighted MER on MSC Cells) */
+		strCurPlotHelp =
+			tr("<b>SNR Spectrum (Weighted MER on MSC Cells):</b> "
+			   "This plot shows the Weighted MER on MSC cells for each carrier "
+			   "separately.");
+			break;
+
+	case INPUTSPECTRUM_NO_AV:
+		/* Input Spectrum */
+		strCurPlotHelp =
+		tr("<b>Input Spectrum:</b> This plot shows the "
+		   "Fast Fourier Transformation (FFT) of the input signal. This plot "
+		   "is active in both modes, analog and digital. There is no "
+		   "averaging applied. The screen shot of the Evaluation Dialog shows "
+		   "the significant shape of a DRM signal (almost rectangular). The "
+		   "dashed vertical line shows the estimated DC frequency. This line "
+		   "is very important for the analog AM demodulation. Each time a "
+		   "new carrier frequency is acquired, the red line shows the "
+		   "selected AM spectrum. If more than one AM spectrums are within "
+		   "the sound card frequency range, the strongest signal is chosen.");
+		break;
+
+    case INPUT_SIG_PSD:
+    case INPUT_SIG_PSD_ANALOG:
+		/* Input PSD */
+		strCurPlotHelp =
+			tr("<b>Input PSD:</b> This plot shows the "
+			   "estimated power spectral density (PSD) of the input signal. The "
+			   "PSD is estimated by averaging some Hamming Window weighted "
+			   "Fourier transformed blocks of the input signal samples. The "
+			   "dashed vertical line shows the estimated DC frequency.");
+		break;
+
+	case AUDIO_SPECTRUM:
+		/* Audio Spectrum */
+		strCurPlotHelp =
+			tr("<b>Audio Spectrum:</b> This plot shows the "
+			   "averaged audio spectrum of the currently played audio. With this "
+			   "plot the actual audio bandwidth can easily determined. Since a "
+			   "linear scale is used for the frequency axis, most of the energy "
+			   "of the signal is usually concentrated on the far left side of the "
+			   "spectrum.");
+		break;
+
+	case FREQ_SAM_OFFS_HIST:
+		/* Frequency Offset / Sample Rate Offset History */
+		strCurPlotHelp =
+			tr("<b>Frequency Offset / Sample Rate Offset History:"
+			   "</b> The history "
+			   "of the values for frequency offset and sample rate offset "
+			   "estimation is shown. If the frequency offset drift is very small, "
+			   "this is an indication that the analog front end is of high "
+			   "quality.");
+		break;
+
+	case DOPPLER_DELAY_HIST:
+		/* Doppler / Delay History */
+		strCurPlotHelp =
+			tr("<b>Doppler / Delay History:</b> "
+			   "The history of the values for the "
+			   "Doppler and Impulse response length is shown. Large Doppler "
+			   "values might be responsable for audio drop-outs.");
+		break;
+
+	case SNR_AUDIO_HIST:
+		/* SNR History */
+		strCurPlotHelp =
+			tr("<b>SNR History:</b> "
+			   "The history of the values for the "
+			   "SNR and correctly decoded audio blocks is shown. The maximum "
+			   "achievable number of correctly decoded audio blocks per DRM "
+			   "frame is 10 or 5 depending on the audio sample rate (24 kHz "
+			   "or 12 kHz AAC core bandwidth).");
+		break;
+
+	case INP_SPEC_WATERF:
+		/* Waterfall Display of Input Spectrum */
+		strCurPlotHelp =
+			tr("<b>Waterfall Display of Input Spectrum:</b> "
+			   "The input spectrum is displayed as a waterfall type. The "
+			   "different colors represent different levels.");
+		break;
+
+	case NONE_OLD:
+		break;
+	}
+
+	/* Main plot */
+	plot->setWhatsThis(strCurPlotHelp);
+}
+
+void QwtPlotDialog::resizeEvent(QResizeEvent *e)
+{
+    QRect rf(0, 0, e->size().width(), e->size().height());
+    Frame->setGeometry(rf);
+    QRect rp(rf.x()+WINDOW_BORDER, rf.y()+WINDOW_BORDER,
+        rf.width()-WINDOW_BORDER*2,
+        rf.height()-WINDOW_BORDER*2);
+    Plot->setGeometry(rp);
+}
diff --git a/src/GUI-QT/DRMPlot.h b/src/GUI-QT/DRMPlot.h
new file mode 100644
index 0000000..8bd6e9c
--- /dev/null
+++ b/src/GUI-QT/DRMPlot.h
@@ -0,0 +1,249 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Original Author(s):
+ *	Volker Fischer
+ *
+ * Qwt 5-6 conversion Author(s):
+ *  David Flamand
+ *
+ * Description:
+ *	Custom settings of the qwt-plot, Support Qwt version 5.0.0 to 6.1.0(+)
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#ifndef __DRMPLOT_QWT5_H
+#define __DRMPLOT_QWT5_H
+
+#include <QTimer>
+#include <QDialog>
+#include <qwt_plot.h>
+#include <qwt_plot_curve.h>
+#include <qwt_plot_grid.h>
+#if QWT_VERSION < 0x060000
+#include <qwt_symbol.h>
+#endif
+#include <../Parameter.h>
+#include <../util/Vector.h>
+#include "receivercontroller.h"
+
+/* Window size for standalone chart */
+#define WINDOW_CHART_WIDTH 256
+#define WINDOW_CHART_HEIGHT 256
+
+/* Window border for standalone chart */
+#define WINDOW_BORDER 1
+
+/* Define the plot font size */
+#define PLOT_FONT_SIZE 8
+
+/* Classes ********************************************************************/
+
+class WaterfallWidget;
+class CDRMReceiver;
+class QTreeWidget;
+class QResizeEvent;
+class QwtPlotPicker;
+class QwtLegend;
+
+/* This class is needed to handle events for standalone window chart */
+class QwtPlotDialog : public QDialog
+{
+	Q_OBJECT
+
+public:
+    QwtPlotDialog(QWidget* parent) : QDialog(parent)
+	{
+		setWindowFlags(Qt::Window);
+		resize(WINDOW_CHART_WIDTH, WINDOW_CHART_HEIGHT);
+		Frame = new QFrame(this);
+		Frame->setFrameStyle(QFrame::Panel|QFrame::Sunken);
+		Frame->setLineWidth(WINDOW_BORDER);
+		Plot = new QwtPlot(Frame);
+	}
+    ~QwtPlotDialog() { }
+	QwtPlot *GetPlot() { return Plot; }
+	void show() { QDialog::show(); emit activate(); }
+	void hide() { emit deactivate(); QDialog::hide(); }
+
+protected:
+	QFrame *Frame;
+	QwtPlot *Plot;
+	void reject() { emit deactivate(); QDialog::reject(); }
+    void resizeEvent(QResizeEvent *e);
+
+signals:
+	void activate();
+	void deactivate();
+};
+
+class CDRMPlot : public QObject
+{
+	Q_OBJECT
+
+public:
+	enum ECharType
+	{
+		INPUT_SIG_PSD = 0, /* default */
+		TRANSFERFUNCTION = 1,
+		FAC_CONSTELLATION = 2,
+		SDC_CONSTELLATION = 3,
+		MSC_CONSTELLATION = 4,
+		POWER_SPEC_DENSITY = 5,
+		INPUTSPECTRUM_NO_AV = 6,
+		AUDIO_SPECTRUM = 7,
+		FREQ_SAM_OFFS_HIST = 8,
+		DOPPLER_DELAY_HIST = 9,
+		ALL_CONSTELLATION = 10,
+		SNR_AUDIO_HIST = 11,
+		AVERAGED_IR = 12,
+		SNR_SPECTRUM = 13,
+		INPUT_SIG_PSD_ANALOG = 14,
+		INP_SPEC_WATERF = 15,
+		NONE_OLD = 16 /* None must always be the last element! (see settings) */
+	};
+
+    CDRMPlot(QWidget*, QwtPlot*, ReceiverController*);
+	~CDRMPlot();
+
+	QwtPlot         *plot;
+
+	void SetupChart(const ECharType eNewType);
+	ECharType GetChartType() const { return CurCharType; }
+	void UpdateAnalogBWMarker();
+	void SetPlotStyle(const int iNewStyleID);
+
+    void setupTreeWidget(QTreeWidget* tw);
+    void setCaption(const QString& s) { if (DialogPlot) DialogPlot->setWindowTitle(s); }
+	void setIcon(const QIcon& s) { if (DialogPlot) DialogPlot->setWindowIcon(s); }
+	void setGeometry(const QRect& g) { if (DialogPlot) DialogPlot->setGeometry(g); }
+	bool isVisible() { if (DialogPlot) return DialogPlot->isVisible(); else return FALSE; }
+	const QRect geometry() { if (DialogPlot) return DialogPlot->geometry(); else return QRect(); }
+	void close() { if (DialogPlot) delete this; }
+	void hide() { if (DialogPlot) DialogPlot->hide(); }
+	void show() { if (DialogPlot) DialogPlot->show(); }
+
+
+protected:
+	void SetVerticalBounds(
+		const _REAL rStartGuard, const _REAL rEndGuard,
+		const _REAL rBeginIR, const _REAL rEndIR);
+	void SetHorizontalBounds( _REAL rScaleMin, _REAL rScaleMax, _REAL rLowerB, _REAL rHigherB);
+	void SetInpSpecWaterf(CVector<_REAL>& vecrData, CVector<_REAL>& vecrScale);
+	void SetDCCarrier(const _REAL rDCFreq);
+	void SetBWMarker(const _REAL rBWCenter, const _REAL rBWWidth);
+	void AutoScale(CVector<_REAL>& vecrData, CVector<_REAL>& vecrData2,
+		CVector<_REAL>& vecrScale);
+	void AutoScale2(CVector<_REAL>& vecrData,
+		CVector<_REAL>& vecrData2,
+		CVector<_REAL>& vecrScale);
+	void AutoScale3(CVector<_REAL>& vecrData, CVector<_REAL>& vecrScale);
+	void SetData(CVector<_REAL>& vecrData, CVector<_REAL>& vecrScale);
+	void SetData(CVector<_REAL>& vecrData1, CVector<_REAL>& vecrData2,
+		CVector<_REAL>& vecrScale);
+	void SetData(QwtPlotCurve& curve, CVector<_COMPLEX>& veccData);
+	void SetData(CVector<_COMPLEX>& veccData);
+	void SetData(CVector<_COMPLEX>& veccMSCConst,
+		CVector<_COMPLEX>& veccSDCConst,
+		CVector<_COMPLEX>& veccFACConst);
+	void SetGrid(double div, int step, int substep);
+	void SetQAMGrid(const ECodScheme eCoSc);
+
+	void PlotDefaults();
+	void PlotForceUpdate();
+	void PlotSetLegendFont();
+
+	void SetupAvIR();
+	void SetupTranFct();
+	void SetupAudioSpec(_BOOLEAN bAudioDecoder);
+	void SetupFreqSamOffsHist();
+	void SetupDopplerDelayHist();
+	void SetupSNRAudHist();
+	void SetupPSD();
+	void SetupSNRSpectrum();
+	void SetupInpSpec();
+	void SetupFACConst();
+	void SetupSDCConst(const ECodScheme eNewCoSc);
+	void SetupMSCConst(const ECodScheme eNewCoSc);
+	void SetupAllConst();
+	void SetupInpPSD(_BOOLEAN bAnalog = FALSE);
+	void SetupInpSpecWaterf();
+
+	void AddWhatsThisHelpChar(const ECharType NCharType);
+
+    ReceiverController* controller;
+	QwtPlot         *SuppliedPlot;
+	QwtPlotDialog   *DialogPlot;
+
+	bool            bActive;
+
+    /* Colors */
+	QColor			MainPenColorPlot;
+	QColor			MainPenColorConst;
+	QColor			MainGridColorPlot;
+	QColor			SpecLine1ColorPlot;
+	QColor			SpecLine2ColorPlot;
+	QColor			PassBandColorPlot;
+	QColor			BckgrdColorPlot;
+
+	ECharType		CurCharType;
+	ECharType		InitCharType;
+	ECodScheme		eLastSDCCodingScheme;
+	ECodScheme		eLastMSCCodingScheme;
+	_BOOLEAN		bLastAudioDecoder;
+
+	QwtText			leftTitle, rightTitle, bottomTitle;
+
+	QwtPlotCurve	main1curve, main2curve;
+	QwtPlotCurve	curve1, curve2, curve3, curve4, curve5;
+	QwtPlotCurve	hcurvegrid, vcurvegrid;
+	QwtPlotGrid		grid;
+#if QWT_VERSION < 0x060000
+	QwtSymbol		MarkerSym1, MarkerSym2, MarkerSym3;
+#endif
+	QwtPlotPicker	*picker;
+	QwtLegend		*legend;
+
+	QTimer			TimerChart;
+	CDRMReceiver	*pDRMRec;
+
+	/* Waterfall spectrum stuff */
+    WaterfallWidget* waterfallWidget;
+	int				iAudSampleRate;
+	int				iSigSampleRate;
+	int				iLastXoredSampleRate;
+	int				iLastChanMode;
+
+public slots:
+#if QWT_VERSION < 0x060000
+	void OnSelected(const QwtDoublePoint &pos);
+#else
+	void OnSelected(const QPointF &pos);
+#endif
+	void OnTimerChart();
+	void activate();
+	void deactivate();
+
+signals:
+	void xAxisValSet(double);
+};
+
+
+#endif
diff --git a/src/GUI-QT/DialogUtil.cpp b/src/GUI-QT/DialogUtil.cpp
new file mode 100644
index 0000000..de8d9de
--- /dev/null
+++ b/src/GUI-QT/DialogUtil.cpp
@@ -0,0 +1,459 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * British Broadcasting Corporation
+ * Copyright (c) 2001-2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer, Julian Cable
+ *
+ * Description:
+ *
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include <QMenuBar>
+#include <QLabel>
+#include <QAction>
+#include <QMessageBox>
+#include <QDir>
+#include <QFile>
+#include <QCoreApplication>
+#include <QWhatsThis>
+#ifdef _WIN32
+# include <winsock2.h>
+#endif
+#include "../Version.h"
+#include "../util-QT/Util.h"
+#include "DialogUtil.h"
+#ifdef HAVE_LIBHAMLIB
+# include "../util-QT/Rig.h"
+#endif
+
+/* to extract the library version */
+#ifdef USE_ALSA
+# include <alsa/version.h>
+#endif
+#ifdef USE_OSS
+# include <sys/soundcard.h>
+#endif
+#ifdef USE_PORTAUDIO
+# include <portaudio.h>
+#endif
+#ifdef USE_PULSEAUDIO
+# include <pulse/version.h>
+#endif
+#ifdef HAVE_LIBSNDFILE
+# include <sndfile.h>
+#endif
+#ifdef HAVE_LIBPCAP
+# include <pcap.h>
+#endif
+#ifdef HAVE_LIBFREEIMAGE
+# include <FreeImage.h>
+#endif
+#ifdef QT_GUI_LIB
+# include <qwt_global.h>
+#endif
+#ifdef USE_OPUS_LIBRARY
+# include "../sourcedecoders/opus_codec.h"
+#endif
+#ifdef USE_FAAD2_LIBRARY
+# include <neaacdec.h>
+#else
+# include "../sourcedecoders/neaacdec_dll.h"
+#endif
+/* fftw 3.3.2 doesn't export the symbol fftw_version
+ * for windows in libfftw3-3.def
+ * You can add it regenerate the lib file and it's supposed to work,
+ * but for now the version string is disabled for windows. */
+#ifndef _WIN32
+# include <fftw3.h>
+#endif
+#include "ThemeCustomizer.h"
+
+QString VersionString(QWidget* parent)
+{
+    QString strVersionText;
+    strVersionText =
+        "<center><b>" + parent->tr("Dream, Version ");
+    if (dream_version_patch == 0)
+        strVersionText += QString("%1.%2%3")
+            .arg(dream_version_major)
+            .arg(dream_version_minor)
+            .arg(dream_version_build);
+    else
+        strVersionText += QString("%1.%2.%3%4")
+            .arg(dream_version_major)
+            .arg(dream_version_minor)
+            .arg(dream_version_patch)
+            .arg(dream_version_build);
+    strVersionText +=
+        "</b><br> " + parent->tr("Open-Source Software Implementation of "
+                                 "a DRM-Receiver") +
+        "<br>";
+    strVersionText += parent->tr("Under the GNU General Public License (GPL)") +
+        "</center>";
+    return strVersionText;
+#ifdef _MSC_VER /* MSVC 2008 */
+    parent; // warning C4100: 'parent' : unreferenced formal parameter
+#endif
+}
+
+/* Implementation *************************************************************/
+/* About dialog ------------------------------------------------------------- */
+CAboutDlg::CAboutDlg(QWidget* parent):
+    QDialog(parent)
+{
+    setupUi(this);
+#ifdef HAVE_LIBSNDFILE
+    char  sfversion [128] ;
+    sf_command (NULL, SFC_GET_LIB_VERSION, sfversion, sizeof (sfversion)) ;
+#endif
+    QString strCredits = 
+        "<p>" /* General description of Dream software */
+        "<big><b>Dream</b> " + tr("is a software implementation of a Digital "
+                                  "Radio Mondiale (DRM) receiver. With Dream, DRM broadcasts can be received "
+                                  "with a modified analog receiver (SW, MW, LW) and a PC with a sound card.")
+        + "</big></p><br>"
+        "<p><font face=\"" FONT_COURIER "\">" /* GPL header text */
+        "This program is free software; you can redistribute it and/or modify "
+        "it under the terms of the GNU General Public License as published by "
+        "the Free Software Foundation; either version 2 of the License, or "
+        "(at your option) any later version.<br>This program is distributed in "
+        "the hope that it will be useful, but WITHOUT ANY WARRANTY; without "
+        "even the implied warranty of MERCHANTABILITY or FITNESS FOR A "
+        "PARTICULAR PURPOSE. See the GNU General Public License for more "
+        "details.<br>You should have received a copy of the GNU General Public "
+        "License along with his program; if not, write to the Free Software "
+        "Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 "
+        "USA"
+        "</font></p><br>" /* Our warning text */
+        "<p><font color=\"#ff0000\" face=\"" FONT_COURIER "\">" +
+        tr("Although this software is going to be "
+           "distributed as free software under the terms of the GPL this does not "
+           "mean that its use is free of rights of others. The use may infringe "
+           "third party IP and thus may not be legal in some countries.") +
+        "</font></p><br>"
+        "<p>" /* Libraries used by this compilation of Dream */
+        "<b>" + tr("This compilation of Dream uses the following libraries:") +
+        "</b></p>"
+        "<ul>"
+#ifndef _WIN32
+        "<li><b>FFTW</b> (" + QString(fftw_version) + ") <i>http://www.fftw.org</i></li>"
+#else
+        "<li><b>FFTW</b> <i>http://www.fftw.org</i></li>"
+#endif
+#if USE_FAAD2_LIBRARY
+        "<li><b>FAAD2</b> (" + QString(FAAD2_VERSION) + ") <i>AAC/HE-AAC/HE-AACv2/DRM decoder "
+        "(c) Ahead Software, www.nero.com (http://faac.sf.net)</i></li>"
+#endif
+#ifdef USE_FAAC_LIBRARY
+        "<li><b>FAAC</b> <i>http://faac.sourceforge.net</i></li>"
+#endif
+#ifdef QT_CORE_LIB
+        "<li><b>Qt</b> (" + QString(QT_VERSION_STR) + ") <i>http://qt-project.org</i></li>"
+#endif
+#ifdef QT_GUI_LIB
+        "<li><b>QWT</b> (" + QString(QWT_VERSION_STR) + ") <i>Dream is based in part on the work of the Qwt "
+        "project (http://qwt.sf.net).</i></li>"
+#endif
+#ifdef HAVE_LIBHAMLIB
+        "<li><b>Hamlib</b> (" + QString(hamlib_version) + ") <i>http://hamlib.sourceforge.net</i></li>"
+#endif
+        "<li><b>FhG IIS Journaline Decoder</b> <i>Features NewsService "
+        "Journaline(R) decoder technology by Fraunhofer IIS, Erlangen, "
+        "Germany. For more information visit http://www.iis.fraunhofer.de/en/bf/db/pro.html</i></li>"
+#ifdef HAVE_LIBFREEIMAGE
+        "<li><b>FreeImage</b> (" + QString(FreeImage_GetVersion()) + ") <i>This software uses the FreeImage open source "
+        "image library. See http://freeimage.sourceforge.net for details. "
+        "FreeImage is used under the GNU GPL.</i></li>"
+#endif
+#ifdef HAVE_LIBPCAP
+        "<li><b>LIBPCAP</b> (" + QString(pcap_lib_version()) + ") <i>http://www.tcpdump.org/ "
+        "This product includes software developed by the Computer Systems "
+        "Engineering Group at Lawrence Berkeley Laboratory.</i></li>"
+#endif
+#ifdef HAVE_LIBSNDFILE
+        "<li><b>LIBSNDFILE</b> (" + QString(sfversion) + ") <i>http://www.mega-nerd.com/libsndfile</i></li>"
+#endif
+#ifdef HAVE_SPEEX
+        "<li><b>LIBSPEEX</b> <i>http://www.speex.org</i></li>"
+#endif
+#ifdef USE_OSS
+        "<li><b>OSS</b> (" + QString("Open Sound System version %1").arg(SOUND_VERSION, 0, 16) + ")</li>"
+#endif
+#ifdef USE_ALSA
+        "<li><b>ALSA</b> (" + QString(SND_LIB_VERSION_STR) + ") <i>http://www.alsa-project.org</i></li>"
+#endif
+#ifdef USE_PORTAUDIO
+        "<li><b>PortAudio</b> (" + QString(Pa_GetVersionText()) + ") <i>http://www.portaudio.com</i></li>"
+#endif
+#ifdef USE_PULSEAUDIO
+        "<li><b>PulseAudio</b> (" + QString(pa_get_headers_version()) + ") <i>http://www.pulseaudio.org</i></li>"
+#endif
+#ifdef USE_JACK
+        "<li><b>libjack</b> (The Jack Audio Connection Kit) <i>http://www.jackaudio.org</i></li>"
+#endif
+#ifdef USE_OPUS_LIBRARY
+		"<li><b>" + QString(OPUS_DESCRIPTION) + "</b> (" + QString(opusGetVersion()) + ") <i>" + QString(OPUS_WEBSITE_LINK) + "</i></li>"
+#endif
+        "</ul><br><br><hr/><br><br>"
+        "<center><b>HISTORY</b></center><br>"
+        "The Dream software development was started at <i>Darmstadt University "
+        "of Technology</i> at the Institute of Communication Technology by <i>Volker "
+        "Fischer</i> and <i>Alexander Kurpiers</i> in 2001-2014. "
+        "The core digital signal processing and most of the GUI were the "
+        "result of this development.<br>In 2005, <i>Andrew Murphy</i> of the <i>British "
+        "Broadcasting Corporation</i> added code for an "
+        "AMSS demodulator. <i>Oliver Haffenden</i> and <i>Julian Cable</i> (also <i>BBC</i>) rewrote "
+        "the MDI interface and added RSCI support."
+        " Many other GUI improvements were implemented by <i>Andrea Russo and David Flamand</i>."
+        "<br>Right now the code is mainly maintained by <i>David Flamand and Julian Cable</i>."
+        " Quality Assurance and user testing is provided by <i>Simone Stöppler.</i>"
+        "<br><br><br>"
+        "<center><b>"+tr("CREDITS")+"</b></center><br>"
+        +tr("We want to thank all the contributors to the Dream software (in "
+            "alphabetical order):")+"<br><br>"
+        "<b>"+tr("Developers")+"</b>"
+        "<center>"
+        "<p>Bakker, Menno</p>"
+        "<p>Cable, Julian</p>"
+        "<p>Cesco</p>"
+        "<p>Diniz, Rafael</p>"
+        "<p>Fillod, Stephane</p>"
+        "<p>Fischer, Volker</p>"
+        "<p>Fine, Mark J.</p>"
+        "<p>Flamand, David</p>"
+        "<p>Haffenden, Oliver</p>"
+        "<p>Kurpiers, Alexander</p>"
+        "<p>Manninen, Tomi</p>"
+        "<p>Moore, Josh</p>"
+        "<p>Murphy, Andrew</p>"
+        "<p>Pascutto, Gian C.</p>"
+        "<p>Peca, Marek</p>"
+        "<p>Richard, Doyle</p>"
+        "<p>Russo, Andrea</p>"
+        "<p>Turnbull, Robert</p>"
+        "</center>"
+        "<p>"+tr("If your name should be in the above list and its missing, please let us know.")+"</p>"
+        "<br><b>"+tr("Parts of Dream are based on code by")+"</b>"
+        "<center>"
+        "<p>Karn, Phil (www.ka9q.net)</p>"
+        "<p>Ptolemy Project (http://ptolemy.eecs.berkeley.edu)</p>"
+        "<p>Tavernini, Lucio (http://tavernini.com/home.html)</p>"
+        "<p>The Math Forum (http://mathforum.org)</p>"
+        "<p>The Synthesis ToolKit in C++ (STK) "
+        "(http://ccrma.stanford.edu/software/stk)</p>"
+        "</center>"
+        "<br><b>"+tr("Supporters")+"</b>"
+        "<center>"
+        "<p>Amorim, Roberto José de</p>"
+        "<p>Kainka, Burkhard</p>"
+        "<p>Keil, Jens</p>"
+        "<p>Kilian, Gerd</p>"
+        "<p>Knütter, Carsten</p>"
+        "<p>Ramisch, Roland</p>"
+        "<p>Schall, Norbert</p>"
+        "<p>Schill, Dietmar</p>"
+        "<p>Schneider, Klaus</p>"
+        "<p>Stöppler, Simone</p>"
+        "<p>Varlamov, Oleg</p>"
+        "<p>Wade, Graham</p>"
+        "</center><br>";
+
+    /* Add link to text */
+    Linkify(strCredits);
+
+    /* Set the text for the about dialog html text control */
+    TextViewCredits->setText(strCredits);
+
+    /* Set version number in about dialog */
+    TextLabelVersion->setText(VersionString(this));
+
+    /* Set author names in about dialog */
+    TextLabelAuthorNames->setText("Volker Fischer, Alexander Kurpiers, Andrea Russo\nJulian Cable, Andrew Murphy, Oliver Haffenden, David Flamand");
+
+    /* Set copyright year in about dialog */
+    TextLabelCopyright->setText("Copyright (C) 2001 - 2001-2014");
+
+    APPLY_CUSTOM_THEME();
+}
+
+/* Help Usage --------------------------------------------------------------- */
+CHelpUsage::CHelpUsage(const char* usage, const char* argv0, QWidget* parent)
+    : CAboutDlg(parent)
+{
+    setWindowTitle(tr("Dream Command Line Help"));
+    TextLabelVersion->setText(VersionString(this));
+    TextLabelAuthorNames->setText("");
+    TextLabelCopyright->setText(tr("Command line usage:"));
+    QString text(tr(usage));
+    text.replace(QRegExp("\\$EXECNAME"), QString::fromUtf8(argv0));
+    TextViewCredits->setFontFamily(FONT_COURIER);
+    TextViewCredits->setPlainText(text);
+    show();
+}
+
+/* System Tray -------------------------------------------------------------- */
+
+CSysTray::CSysTray(QWidget* parent, const char* callbackIcon, const char* callbackTimer, const char* icon)
+    : parent(parent), pTimer(NULL), pContextMenu(NULL)
+{
+    pSystemTrayIcon = new QSystemTrayIcon(QIcon(icon), parent);
+    if (callbackIcon != NULL)
+        parent->connect(pSystemTrayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), parent, callbackIcon);
+    if (callbackTimer != NULL)
+    {
+        pTimer = new QTimer(pSystemTrayIcon);
+        parent->connect(pTimer, SIGNAL(timeout()), parent, callbackTimer);
+    }
+    pSystemTrayIcon->show();
+}
+
+CSysTray::~CSysTray()
+{
+    if (pSystemTrayIcon != NULL)
+        delete pSystemTrayIcon;
+}
+
+void CSysTray::CreateContextMenu()
+{
+    if (pContextMenu == NULL)
+    {
+        pContextMenu = new QMenu(parent);
+        pSystemTrayIcon->setContextMenu(pContextMenu);
+    }
+}
+
+CSysTray* CSysTray::Create(QWidget* parent, const char* callbackIcon, const char* callbackTimer, const char* icon)
+{
+    CSysTray* pSysTray = NULL;
+    if (QSystemTrayIcon::isSystemTrayAvailable())
+        pSysTray = new CSysTray(parent, callbackIcon, callbackTimer, icon);
+    return pSysTray;
+}
+
+void CSysTray::Destroy(CSysTray** pSysTray)
+{
+    if (*pSysTray != NULL)
+    {
+        delete *pSysTray;
+        *pSysTray = NULL;
+    }
+}
+
+void CSysTray::Start(CSysTray* pSysTray)
+{
+    if (pSysTray == NULL) return;
+    if (pSysTray->pTimer != NULL)
+        pSysTray->pTimer->start(GUI_CONTROL_UPDATE_TIME);
+}
+
+void CSysTray::Stop(CSysTray* pSysTray, const QString& Message)
+{
+    if (pSysTray == NULL) return;
+    if (pSysTray->pTimer != NULL)
+        pSysTray->pTimer->stop();
+    SetToolTip(pSysTray, QString(), Message);
+}
+
+QAction* CSysTray::AddAction(CSysTray* pSysTray, const QString& text, const QObject* receiver, const char* member)
+{
+    if (pSysTray == NULL) return NULL;
+    pSysTray->CreateContextMenu();
+    return pSysTray->pContextMenu->addAction(text, receiver, member);
+}
+
+QAction* CSysTray::AddSeparator(CSysTray* pSysTray)
+{
+    if (pSysTray == NULL) return NULL;
+    pSysTray->CreateContextMenu();
+    return pSysTray->pContextMenu->addSeparator();
+}
+
+void CSysTray::SetToolTip(CSysTray* pSysTray, const QString& Title, const QString& Message)
+{
+    if (pSysTray != NULL &&
+        (pSysTray->Title != Title || pSysTray->Message != Message))
+    {
+        pSysTray->Title = Title;
+        pSysTray->Message = Message;
+        QString ToolTip;
+#ifdef _WIN32
+        ToolTip = Title;
+        if (!Message.isEmpty())
+        {
+            if (!Title.isEmpty())
+                ToolTip += " |  ";
+            ToolTip += Message;
+        }
+        ToolTip.replace(QRegExp("(\r|\n|\v|\t|\b)"), " ");
+#else
+        if (!Title.isEmpty())
+        {
+            QString NewTitle(Title);
+            NewTitle.replace('&', "&");
+            NewTitle.replace(' ', " ");
+            NewTitle.replace('<', "<");
+            NewTitle.replace('>', ">");
+            ToolTip = "<b>" + NewTitle + "</b>";
+        }
+        if (!Message.isEmpty())
+        {
+            QString NewMessage(Message);
+            if (!Title.isEmpty())
+                ToolTip += "<br>";
+            NewMessage.replace('&', "&");
+            NewMessage.replace('<', "<");
+            NewMessage.replace('>', ">");
+            ToolTip += NewMessage;
+        }
+        ToolTip.replace(QRegExp("(\r|\n|\v)"), "<br>");
+#endif
+        pSysTray->pSystemTrayIcon->setToolTip(ToolTip);
+    }
+}
+
+/* -------------------------------------------------------------------------- */
+
+void InitSMeter(QWidget* parent, QwtThermo* sMeter)
+{
+#if QWT_VERSION < 0x060100
+    sMeter->setRange(S_METER_THERMO_MIN, S_METER_THERMO_MAX);
+    sMeter->setScale(S_METER_THERMO_MIN, S_METER_THERMO_MAX, 10.0);
+#else
+    sMeter->setScale(S_METER_THERMO_MIN, S_METER_THERMO_MAX);
+    sMeter->setScaleStepSize(10.0);
+#endif
+    sMeter->setAlarmLevel(S_METER_THERMO_ALARM);
+    sMeter->setAlarmLevel(-12.5);
+    sMeter->setAlarmEnabled(TRUE);
+    sMeter->setValue(S_METER_THERMO_MIN);
+#if QWT_VERSION < 0x060000
+    (void)parent;
+    sMeter->setAlarmColor(QColor(255, 0, 0));
+    sMeter->setFillColor(QColor(0, 190, 0));
+#else
+    QPalette newPalette = parent->palette();
+    newPalette.setColor(QPalette::Base, newPalette.color(QPalette::Window));
+    newPalette.setColor(QPalette::ButtonText, QColor(0, 190, 0));
+    newPalette.setColor(QPalette::Highlight,  QColor(255, 0, 0));
+    sMeter->setPalette(newPalette);
+#endif
+}
diff --git a/src/GUI-QT/DialogUtil.h b/src/GUI-QT/DialogUtil.h
new file mode 100644
index 0000000..33d1eb4
--- /dev/null
+++ b/src/GUI-QT/DialogUtil.h
@@ -0,0 +1,139 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer, Andrea Russo
+ *
+ * Description:
+ *
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#if !defined(DIALOGUTIL_H__FD6B23452398345OIJ9453_804E1606C2AC__INCLUDED_)
+#define DIALOGUTIL_H__FD6B23452398345OIJ9453_804E1606C2AC__INCLUDED_
+
+#include "../Parameter.h"
+#include "../DrmTransceiver.h"
+#include "../sound/selectioninterface.h"
+
+#include <map>
+
+#include "ui_AboutDlgbase.h"
+#include <QThread>
+#include <QMenu>
+#include <QDialog>
+#include <QAction>
+#include <QEvent>
+#include <QSystemTrayIcon>
+#include <QTimer>
+#include <QAction>
+
+#include <qwt_thermo.h> /* S-Meter */
+
+class CRig;
+typedef int rig_model_t;
+
+/* Definitions ****************************************************************/
+
+/* Definition for Courier font */
+#ifdef _WIN32
+# define FONT_COURIER    "Courier New"
+#elif defined(__linux__)
+# define FONT_COURIER    "Monospace"
+#else
+# define FONT_COURIER    "Courier"
+#endif
+/* Classes ********************************************************************/
+
+/* About dialog ------------------------------------------------------------- */
+class CAboutDlg : public QDialog, public Ui_CAboutDlgBase
+{
+	Q_OBJECT
+
+public:
+	CAboutDlg(QWidget* parent = 0);
+	virtual ~CAboutDlg() {}
+};
+
+/* Help Usage --------------------------------------------------------------- */
+class CHelpUsage : public CAboutDlg
+{
+	Q_OBJECT
+
+public:
+	CHelpUsage(const char* usage, const char* argv0, QWidget* parent = 0);
+	virtual ~CHelpUsage() {}
+};
+
+/* System Tray -------------------------------------------------------------- */
+class CSysTray
+{
+public:
+	static CSysTray* Create(QWidget* parent, const char* callbackIcon, const char* callbackTimer, const char* icon);
+	static void Destroy(CSysTray** pSysTray);
+	static void SetToolTip(CSysTray* pSysTray, const QString& Title, const QString& Message);
+	static void Start(CSysTray* pSysTray);
+	static void Stop(CSysTray* pSysTray, const QString& Message);
+	static QAction* AddAction(CSysTray* pSysTray, const QString& text, const QObject* receiver, const char* member);
+	static QAction* AddSeparator(CSysTray* pSysTray);
+
+protected:
+	virtual ~CSysTray();
+	CSysTray(QWidget* parent, const char* callbackIcon, const char* callbackTimer, const char* icon);
+	void CreateContextMenu();
+	QWidget* parent;
+	QString Title;
+	QString Message;
+	QSystemTrayIcon* pSystemTrayIcon;
+	QTimer* pTimer;
+	QMenu* pContextMenu;
+};
+
+/* GUI help functions ------------------------------------------------------- */
+/* Converts from RGB to integer and back */
+class CRGBConversion
+{
+public:
+	static int RGB2int(const QColor newColor)
+	{
+		/* R, G and B are encoded as 8-bit numbers */
+		int iReturn = newColor.red();
+		iReturn <<= 8;
+		iReturn |= newColor.green();
+		iReturn <<= 8;
+		iReturn |= newColor.blue();
+		return iReturn;
+	}
+
+	static QColor int2RGB(const int iValue)
+	{
+		return QColor((iValue >> 16) & 255, (iValue >> 8) & 255, iValue & 255);
+	}
+};
+
+
+/* s-meter thermo parameters */
+#define S_METER_THERMO_MIN				((_REAL) -60.0) /* dB */
+#define S_METER_THERMO_MAX				((_REAL) 60.0) /* dB */
+#define S_METER_THERMO_ALARM			((_REAL) 0.0) /* dB */
+
+void InitSMeter(QWidget* parent, QwtThermo* sMeter);
+
+#endif // DIALOGUTIL_H__FD6B23452398345OIJ9453_804E1606C2AC__INCLUDED_
diff --git a/src/GUI-QT/EPGDlg.cpp b/src/GUI-QT/EPGDlg.cpp
new file mode 100644
index 0000000..3c6012e
--- /dev/null
+++ b/src/GUI-QT/EPGDlg.cpp
@@ -0,0 +1,347 @@
+/******************************************************************************\
+ * British Broadcasting Corporation
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Julian Cable
+ *
+ * Description:
+ *	ETSI DAB/DRM Electronic Programme Guide Viewer
+ *
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "EPGDlg.h"
+#include "../util-QT/EPG.h"
+#include "../datadecoding/epgutil.h"
+#include <QFile>
+#include <set>
+#include "ThemeCustomizer.h"
+
+EPGDlg::EPGDlg(CSettings& Settings, QWidget* parent):
+    CWindow(parent, Settings, "EPG"),
+    do_updates(false),
+    pEpg(NULL),
+    greenCube(":/icons/greenCube.png"),
+    next(NULL)
+{
+    setupUi(this);
+
+    /* auto resize of the programme name column */
+    dateEdit->setDate(QDate::currentDate());
+    connect(channel, SIGNAL(activated(const QString&)), this , SLOT(on_channel_activated(const QString&)));
+    connect(dateEdit, SIGNAL(dateChanged(const QDate&)), this , SLOT(on_dateEdit_dateChanged(const QDate&)));
+    connect(&Timer, SIGNAL(timeout()), this, SLOT(OnTimer()));
+
+    TextEPGDisabled->hide();
+
+    APPLY_CUSTOM_THEME();
+}
+
+EPGDlg::~EPGDlg()
+{
+}
+
+void EPGDlg::setServiceInformation(const map<uint32_t,CServiceInformation>& si, uint32_t current_sid)
+{
+    // update the channels combobox from the epg
+    channel->clear();
+    for (map < uint32_t, CServiceInformation >::const_iterator i = si.begin(); i != si.end(); i++) {
+        QString channel_label = QString().fromUtf8(i->second.label.begin()->c_str());
+        channel->addItem(channel_label, i->second.id);
+    }
+    channel->setCurrentIndex(channel->findData(current_sid));
+}
+
+void EPGDlg::setDecoder(EPG* p)
+{
+    pEpg = p;
+}
+
+void EPGDlg::setActive(QTreeWidgetItem* item)
+{
+    if(isActive(item))
+    {
+        item->setIcon(COL_START, greenCube);
+        Data->scrollToItem(item);
+        emit NowNext(item->text(COL_NAME));
+        next = Data->itemBelow(item);
+    }
+    else
+    {
+        item->setIcon(COL_START, QPixmap()); /* no pixmap */
+    }
+}
+
+void EPGDlg::OnTimer()
+{
+    /* Get current UTC time */
+    time_t ltime;
+    time(&ltime);
+    tm gmtCur = *gmtime(&ltime);
+    if(gmtCur.tm_sec==0) // minute boundary
+    {
+        /* today in UTC */
+        QDate todayUTC = QDate(gmtCur.tm_year + 1900, gmtCur.tm_mon + 1, gmtCur.tm_mday);
+
+        if ((basic->toPlainText() == tr("no basic profile data"))
+                || (advanced->toPlainText() == tr("no advanced profile data")))
+        {
+            /* not all information is loaded */
+            select();
+        }
+        /* Check the items now on line. */
+        if (dateEdit->date() == todayUTC) /* if today */
+        {
+            for(int i=0; i<Data->topLevelItemCount(); i++)
+                setActive(Data->topLevelItem(i));
+        }
+    }
+}
+
+void EPGDlg::eventShow()
+{
+    // use the current date
+    dateEdit->setDate(QDate::currentDate());
+    // update the current selection
+    do_updates = true;
+    if(pEpg)
+        pEpg->progs.clear();
+    select();
+
+    /* Activate real-time timer when window is shown */
+    Timer.start(GUI_TIMER_EPG_UPDATE);
+}
+
+void EPGDlg::eventHide()
+{
+    /* Deactivate real-time timer */
+    Timer.stop();
+}
+
+void EPGDlg::on_dateEdit_dateChanged(const QDate&)
+{
+    select();
+}
+
+void EPGDlg::on_channel_activated(const QString&)
+{
+    if(pEpg)
+        pEpg->progs.clear();
+    select();
+}
+
+void EPGDlg::select()
+{
+    QTreeWidgetItem* CurrActiveItem = NULL;
+    QDate date = dateEdit->date();
+
+    if (!do_updates)
+        return;
+    Data->clear();
+    basic->setText(tr("no basic profile data"));
+    advanced->setText(tr("no advanced profile data"));
+    uint32_t chan = channel->itemData(channel->currentIndex()).toUInt();
+    // get schedule for date +/- 1 - will allow user timezones sometime
+    QDomDocument *doc;
+    QDate o = date.addDays(-1);
+    doc = getFile (o, chan, false);
+    if(pEpg == NULL)
+    {
+        return;
+    }
+    if(doc)
+        pEpg->parseDoc(*doc);
+    doc = getFile (o, chan, true);
+    if(doc)
+        pEpg->parseDoc(*doc);
+    o = date.addDays(1);
+    doc = getFile (o, chan, false);
+    if(doc)
+        pEpg->parseDoc(*doc);
+    doc = getFile (o, chan, true);
+    if(doc)
+        pEpg->parseDoc(*doc);
+
+    QString xml;
+    doc = getFile (date, chan, false);
+    if(doc)
+    {
+        pEpg->parseDoc(*doc);
+        xml = doc->toString();
+        if (xml.length() > 0)
+            basic->setText(xml);
+    }
+
+    doc = getFile (date, chan, true);
+    if(doc)
+    {
+        pEpg->parseDoc(*doc);
+        xml = doc->toString();
+        if (xml.length() > 0)
+            advanced->setText(xml);
+    }
+
+    if (pEpg->progs.count()==0) {
+        (void) new QTreeWidgetItem(Data, QStringList() << tr("no data"));
+        return;
+    }
+    Data->sortItems(COL_START, Qt::AscendingOrder);
+
+    for (QMap < time_t, EPG::CProg >::Iterator i = pEpg->progs.begin();
+            i != pEpg->progs.end(); i++)
+    {
+        const EPG::CProg & p = i.value();
+        // TODO - let user choose time or actualTime if available, or show as tooltip
+        time_t start;
+        int duration;
+        if (p.actualTime!=0)
+        {
+            start = p.actualTime;
+            duration = p.actualDuration;
+        }
+        else
+        {
+            start = p.time;
+            duration = p.duration;
+        }
+        QString s_start, s_duration;
+        tm bdt = *gmtime(&start);
+
+        // skip entries not on the wanted day
+        if((bdt.tm_year+1900) != date.year())
+        {
+            continue;
+        }
+        if((bdt.tm_mon+1) != date.month())
+        {
+            continue;
+        }
+        if(bdt.tm_mday != date.day())
+        {
+            continue;
+        }
+
+        char s[40];
+        sprintf(s, "%02d:%02d", bdt.tm_hour, bdt.tm_min);
+        s_start = s;
+        int min = duration / 60;
+        sprintf(s, "%02d:%02d", int(min/60), min%60);
+        s_duration = s;
+        QString name, description, genre;
+        if (p.name=="" && p.mainGenre.size()>0)
+            name = "unknown " + p.mainGenre[0] + " programme";
+        else
+            name = p.name;
+        description = p.description;
+        // collapse white space in description
+        description.replace(QRegExp("[\t\r\n ]+"), " ");
+        if (p.mainGenre.size()==0)
+            genre = "";
+        else
+        {
+            // remove duplicate genres
+            set<QString> genres;
+            for (size_t i=0; i<p.mainGenre.size(); i++) {
+                if (p.mainGenre[i] != "Audio only") {
+                    genres.insert(p.mainGenre[i]);
+                }
+            }
+            QString sep="";
+            for(set<QString>::const_iterator g = genres.begin(); g!=genres.end(); g++)
+            {
+                genre = genre+sep+(*g);
+                sep = ", ";
+            }
+        }
+        QStringList l;
+        l << s_start << name << genre << description << s_duration;
+        QTreeWidgetItem* CurrItem = new QTreeWidgetItem(Data, l);
+        QDateTime dt;
+        dt.setTime_t(start);
+        CurrItem->setData(COL_START, Qt::UserRole, dt);
+        CurrItem->setData(COL_DURATION, Qt::UserRole, duration);
+        if (isActive(CurrItem))
+            CurrActiveItem = CurrItem;
+    }
+    if (CurrActiveItem) /* programme is now on line */
+        setActive(CurrActiveItem);
+}
+
+QString EPGDlg::getFileName(const QDate& date, uint32_t sid, bool bAdvanced)
+{
+    CDateAndTime d;
+    d.year = date.year();
+    d.month = date.month();
+    d.day = date.day();
+    return pEpg->dir + PATH_SEPARATOR + epgFilename(d, sid, 1, bAdvanced).c_str();
+}
+
+QString EPGDlg::getFileName_etsi(const QDate& date, uint32_t sid, bool bAdvanced)
+{
+    CDateAndTime d;
+    d.year = date.year();
+    d.month = date.month();
+    d.day = date.day();
+    return pEpg->dir + PATH_SEPARATOR + epgFilename_etsi(d, sid, 1, bAdvanced).c_str();
+}
+
+QDomDocument*
+EPGDlg::getFile(const QString& path)
+{
+    QFile file (path);
+    if (!file.open (QIODevice::ReadOnly))
+    {
+        return NULL;
+    }
+    vector<_BYTE> vecData;
+    vecData.resize (file.size ());
+    file.read((char *) &vecData.front (), file.size ());
+    file.close ();
+    CEPGDecoder *epg = new CEPGDecoder();
+    epg->decode (vecData);
+    epg->doc.documentElement().insertBefore(
+        epg->doc.createComment(path),
+        epg->doc.documentElement().firstChild()
+    );
+    return &(epg->doc);
+}
+
+QDomDocument*
+EPGDlg::getFile (const QDate& date, uint32_t sid, bool bAdvanced)
+{
+    QString path = getFileName(date, sid, bAdvanced);
+    QDomDocument* doc = getFile(path);
+    if(doc != NULL)
+        return doc;
+    return getFile(getFileName_etsi(date, sid, bAdvanced));
+}
+
+bool EPGDlg::isActive(QTreeWidgetItem* item)
+{
+    QDateTime start = item->data(COL_START, Qt::UserRole).toDateTime();
+    int duration = item->data(COL_DURATION, Qt::UserRole).toInt();
+    QDateTime end = start.addSecs(duration);
+    QDateTime now = QDateTime::currentDateTime();
+    if(now<start)
+        return false;
+    if(now>=end)
+        return false;
+    return true;
+}
diff --git a/src/GUI-QT/EPGDlg.h b/src/GUI-QT/EPGDlg.h
new file mode 100644
index 0000000..2e95919
--- /dev/null
+++ b/src/GUI-QT/EPGDlg.h
@@ -0,0 +1,96 @@
+/******************************************************************************\
+ * British Broadcasting Corporation
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Julian Cable
+ *
+ * Description:
+ *	ETSI DAB/DRM Electronic Programme Guide Viewer
+ *
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#ifndef _EPGDLG_H
+#define _EPGDLG_H
+
+#include "ui_EPGDlgbase.h"
+#include "CWindow.h"
+#include <../Parameter.h>
+#include <QTimer>
+#include <map>
+
+
+/* Definitions ****************************************************************/
+#define COL_NAME	1
+
+/* Define the timer interval of updating */
+#define GUI_TIMER_EPG_UPDATE		1000 /* ms (1 second) */
+
+/* list view columns */
+#define COL_START		0
+#define COL_NAME		1
+#define	COL_GENRE		2
+#define	COL_DESCRIPTION	3
+#define COL_DURATION	4
+
+
+/* Classes ********************************************************************/
+
+class EPG;
+class QDomDocument;
+
+class EPGDlg : public CWindow, public Ui_CEPGDlgbase
+{
+    Q_OBJECT
+
+public:
+    EPGDlg(CSettings&, QWidget* parent = 0);
+    virtual ~EPGDlg();
+    void setServiceInformation(const map<uint32_t,CServiceInformation>&, uint32_t);
+    void setDecoder(EPG*);
+
+protected:
+    virtual void eventShow();
+    virtual void eventHide();
+    void setActive(QTreeWidgetItem*);
+    bool isActive(QTreeWidgetItem*);
+
+    QString getFileName(const QDate& date, uint32_t sid, bool bAdvanced);
+    QString getFileName_etsi(const QDate& date, uint32_t sid, bool bAdvanced);
+    QDomDocument* getFile (const QString&);
+    QDomDocument* getFile (const QDate& date, uint32_t sid, bool bAdvanced);
+    void select();
+
+    bool                  do_updates;
+    EPG*                  pEpg;
+    QTimer		          Timer;
+    QIcon		          greenCube;
+    QTreeWidgetItem*	  next;
+
+signals:
+    void NowNext(QString);
+
+private slots:
+    void on_channel_activated(const QString&);
+    void on_dateEdit_dateChanged(const QDate&);
+    void OnTimer();
+};
+
+#endif
diff --git a/src/GUI-QT/EPGDlgbase.ui b/src/GUI-QT/EPGDlgbase.ui
new file mode 100644
index 0000000..11b82f4
--- /dev/null
+++ b/src/GUI-QT/EPGDlgbase.ui
@@ -0,0 +1,264 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>CEPGDlgbase</class>
+ <widget class="QMainWindow" name="CEPGDlgbase">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>501</width>
+    <height>422</height>
+   </rect>
+  </property>
+  <property name="sizePolicy">
+   <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+    <horstretch>0</horstretch>
+    <verstretch>0</verstretch>
+   </sizepolicy>
+  </property>
+  <property name="cursor">
+   <cursorShape>ArrowCursor</cursorShape>
+  </property>
+  <property name="windowTitle">
+   <string>Programme Guide</string>
+  </property>
+  <property name="windowIcon">
+   <iconset resource="res/icons.qrc">
+    <normaloff>:/icons/MainIcon.svg</normaloff>:/icons/MainIcon.svg</iconset>
+  </property>
+  <widget class="QWidget" name="centralwidget">
+   <layout class="QGridLayout">
+    <item row="0" column="0">
+     <widget class="QFrame" name="frame">
+      <property name="frameShape">
+       <enum>QFrame::StyledPanel</enum>
+      </property>
+      <property name="frameShadow">
+       <enum>QFrame::Sunken</enum>
+      </property>
+      <layout class="QHBoxLayout" name="horizontalLayout_2">
+       <item>
+        <widget class="QComboBox" name="channel">
+         <property name="sizePolicy">
+          <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
+           <horstretch>0</horstretch>
+           <verstretch>0</verstretch>
+          </sizepolicy>
+         </property>
+         <property name="maximumSize">
+          <size>
+           <width>300</width>
+           <height>32767</height>
+          </size>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <spacer name="Spacer4">
+         <property name="orientation">
+          <enum>Qt::Horizontal</enum>
+         </property>
+         <property name="sizeType">
+          <enum>QSizePolicy::Minimum</enum>
+         </property>
+         <property name="sizeHint" stdset="0">
+          <size>
+           <width>20</width>
+           <height>20</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
+       <item>
+        <widget class="QDateEdit" name="dateEdit">
+         <property name="calendarPopup">
+          <bool>true</bool>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <spacer name="Spacer4_2">
+         <property name="orientation">
+          <enum>Qt::Horizontal</enum>
+         </property>
+         <property name="sizeType">
+          <enum>QSizePolicy::Minimum</enum>
+         </property>
+         <property name="sizeHint" stdset="0">
+          <size>
+           <width>20</width>
+           <height>20</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
+       <item>
+        <widget class="QLabel" name="TextEPGDisabled">
+         <property name="text">
+          <string>EPG decoding is disabled</string>
+         </property>
+         <property name="wordWrap">
+          <bool>false</bool>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <spacer name="Spacer3">
+         <property name="orientation">
+          <enum>Qt::Horizontal</enum>
+         </property>
+         <property name="sizeType">
+          <enum>QSizePolicy::Expanding</enum>
+         </property>
+         <property name="sizeHint" stdset="0">
+          <size>
+           <width>20</width>
+           <height>20</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
+      </layout>
+     </widget>
+    </item>
+    <item row="1" column="0">
+     <widget class="QTabWidget" name="pages">
+      <property name="currentIndex">
+       <number>0</number>
+      </property>
+      <widget class="QWidget" name="GuideTab">
+       <attribute name="title">
+        <string>Guide</string>
+       </attribute>
+       <layout class="QGridLayout">
+        <property name="margin">
+         <number>6</number>
+        </property>
+        <property name="spacing">
+         <number>6</number>
+        </property>
+        <item row="0" column="0">
+         <widget class="QTreeWidget" name="Data">
+          <column>
+           <property name="text">
+            <string>Time [UTC]</string>
+           </property>
+          </column>
+          <column>
+           <property name="text">
+            <string>Name</string>
+           </property>
+          </column>
+          <column>
+           <property name="text">
+            <string>Genre</string>
+           </property>
+          </column>
+          <column>
+           <property name="text">
+            <string>Description</string>
+           </property>
+          </column>
+         </widget>
+        </item>
+       </layout>
+      </widget>
+      <widget class="QWidget" name="BasicTab">
+       <attribute name="title">
+        <string>Basic Profile Data</string>
+       </attribute>
+       <layout class="QGridLayout">
+        <property name="margin">
+         <number>6</number>
+        </property>
+        <property name="spacing">
+         <number>6</number>
+        </property>
+        <item row="0" column="0">
+         <widget class="QTextBrowser" name="basic"/>
+        </item>
+       </layout>
+      </widget>
+      <widget class="QWidget" name="AdvancedTab">
+       <attribute name="title">
+        <string>Advanced Profile Data</string>
+       </attribute>
+       <layout class="QGridLayout">
+        <property name="margin">
+         <number>6</number>
+        </property>
+        <property name="spacing">
+         <number>6</number>
+        </property>
+        <item row="0" column="0">
+         <widget class="QTextBrowser" name="advanced"/>
+        </item>
+       </layout>
+      </widget>
+     </widget>
+    </item>
+    <item row="2" column="0">
+     <layout class="QHBoxLayout">
+      <property name="spacing">
+       <number>6</number>
+      </property>
+      <property name="margin">
+       <number>0</number>
+      </property>
+      <item>
+       <spacer name="Spacer2">
+        <property name="orientation">
+         <enum>Qt::Horizontal</enum>
+        </property>
+        <property name="sizeType">
+         <enum>QSizePolicy::Expanding</enum>
+        </property>
+        <property name="sizeHint" stdset="0">
+         <size>
+          <width>20</width>
+          <height>20</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+      <item>
+       <widget class="QPushButton" name="buttonOk">
+        <property name="text">
+         <string>&Close</string>
+        </property>
+        <property name="default">
+         <bool>true</bool>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </item>
+   </layout>
+  </widget>
+ </widget>
+ <tabstops>
+  <tabstop>pages</tabstop>
+  <tabstop>buttonOk</tabstop>
+ </tabstops>
+ <resources>
+  <include location="res/icons.qrc"/>
+ </resources>
+ <connections>
+  <connection>
+   <sender>buttonOk</sender>
+   <signal>clicked()</signal>
+   <receiver>CEPGDlgbase</receiver>
+   <slot>close()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>20</x>
+     <y>20</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>20</x>
+     <y>20</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+</ui>
diff --git a/src/GUI-QT/EvaluationDlg.cpp b/src/GUI-QT/EvaluationDlg.cpp
new file mode 100644
index 0000000..a8917ef
--- /dev/null
+++ b/src/GUI-QT/EvaluationDlg.cpp
@@ -0,0 +1,1381 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "EvaluationDlg.h"
+#include "DialogUtil.h"
+#include "receivercontroller.h"
+#include "../util-QT/Util.h"
+#ifdef HAVE_LIBHAMLIB
+# include "../util-QT/Rig.h"
+#endif
+#include <QMessageBox>
+#include <QLayout>
+#include <QDateTime>
+#include <QFileDialog>
+#include <QHideEvent>
+#include <QShowEvent>
+#include "ThemeCustomizer.h"
+
+/* Implementation *************************************************************/
+systemevalDlg::systemevalDlg(ReceiverController* rc, CSettings& Settings,
+                             QWidget* parent) :
+    CWindow(parent, Settings, "System Evaluation"),
+    controller(rc),Parameters(*rc->getReceiver()->GetParameters()),
+    eNewCharType(CDRMPlot::NONE_OLD), iPlotStyle(0)
+{
+    setupUi(this);
+
+    /* Set help text for the controls */
+    AddWhatsThisHelp();
+
+    /* Init controls -------------------------------------------------------- */
+
+    /* Init main plot */
+    MainPlot = new CDRMPlot(NULL, plot, controller);
+
+    /* Update times for colour LEDs */
+    LEDFAC->SetUpdateTime(1500);
+    LEDSDC->SetUpdateTime(1500);
+    LEDMSC->SetUpdateTime(600);
+    LEDFrameSync->SetUpdateTime(600);
+    LEDTimeSync->SetUpdateTime(600);
+    LEDIOInterface->SetUpdateTime(2000); /* extra long -> red light stays long */
+
+    /* Initialise controls */
+    setControls(Settings);
+
+    /* Set the Char Type of each selectable item */
+    QTreeWidgetItemIterator it(chartSelector, QTreeWidgetItemIterator::NoChildren);
+    for (; *it; it++)
+    {
+        if ((*it)->text(0) == tr("SNR Spectrum"))
+            (*it)->setData(0,  Qt::UserRole, CDRMPlot::SNR_SPECTRUM);
+        if ((*it)->text(0) == tr("Audio Spectrum"))
+            (*it)->setData(0,  Qt::UserRole, CDRMPlot::AUDIO_SPECTRUM);
+        if ((*it)->text(0) == tr("Shifted PSD"))
+            (*it)->setData(0,  Qt::UserRole, CDRMPlot::POWER_SPEC_DENSITY);
+        if ((*it)->text(0) == tr("Waterfall Input Spectrum"))
+            (*it)->setData(0,  Qt::UserRole, CDRMPlot::INP_SPEC_WATERF);
+        if ((*it)->text(0) == tr("Input Spectrum"))
+            (*it)->setData(0,  Qt::UserRole, CDRMPlot::INPUTSPECTRUM_NO_AV);
+        if ((*it)->text(0) == tr("Input PSD"))
+            (*it)->setData(0,  Qt::UserRole, CDRMPlot::INPUT_SIG_PSD);
+        if ((*it)->text(0) == tr("MSC"))
+            (*it)->setData(0,  Qt::UserRole, CDRMPlot::MSC_CONSTELLATION);
+        if ((*it)->text(0) == tr("SDC"))
+            (*it)->setData(0,  Qt::UserRole, CDRMPlot::SDC_CONSTELLATION);
+        if ((*it)->text(0) == tr("FAC"))
+            (*it)->setData(0,  Qt::UserRole, CDRMPlot::FAC_CONSTELLATION);
+        if ((*it)->text(0) == tr("FAC / SDC / MSC"))
+            (*it)->setData(0,  Qt::UserRole, CDRMPlot::ALL_CONSTELLATION);
+        if ((*it)->text(0) == tr("Frequency / Sample Rate"))
+            (*it)->setData(0,  Qt::UserRole, CDRMPlot::FREQ_SAM_OFFS_HIST);
+        if ((*it)->text(0) == tr("Delay / Doppler"))
+            (*it)->setData(0,  Qt::UserRole, CDRMPlot::DOPPLER_DELAY_HIST);
+        if ((*it)->text(0) == tr("SNR / Audio"))
+            (*it)->setData(0,  Qt::UserRole, CDRMPlot::SNR_AUDIO_HIST);
+        if ((*it)->text(0) == tr("Transfer Function"))
+            (*it)->setData(0,  Qt::UserRole, CDRMPlot::TRANSFERFUNCTION);
+        if ((*it)->text(0) == tr("Impulse Response"))
+            (*it)->setData(0,  Qt::UserRole, CDRMPlot::AVERAGED_IR);
+    }
+
+    /* Expand all items */
+    chartSelector->expandAll();
+
+    /* Load saved main plot type */
+    eCurCharType = PlotNameToECharType(string(getSetting("plottype", QString()).toLocal8Bit()));
+
+    /* If MDI in is enabled, disable some of the controls and use different
+       initialization for the chart and chart selector */
+    if (controller->getReceiver()->GetRSIIn()->GetInEnabled() == TRUE)
+    {
+        SliderNoOfIterations->setEnabled(FALSE);
+
+        ButtonGroupChanEstFreqInt->setEnabled(FALSE);
+        ButtonGroupChanEstTimeInt->setEnabled(FALSE);
+        ButtonGroupTimeSyncTrack->setEnabled(FALSE);
+        CheckBoxFlipSpec->setEnabled(FALSE);
+        GroupBoxInterfRej->setEnabled(FALSE);
+
+        /* Only audio spectrum makes sence for MDI in */
+        eCurCharType = CDRMPlot::AUDIO_SPECTRUM;
+    }
+
+    /* Init context menu for tree widget */
+    pTreeWidgetContextMenu = new QMenu(tr("Chart Selector context menu"), this);
+    pTreeWidgetContextMenu->addAction(tr("&Open in separate window"),
+            this, SLOT(OnTreeWidgetContMenu(bool)));
+
+    /* Connect controls ----------------------------------------------------- */
+    connect(SliderNoOfIterations, SIGNAL(valueChanged(int)),
+            this, SLOT(OnSliderIterChange(int)));
+
+    /* Radio buttons */
+    connect(RadioButtonTiLinear, SIGNAL(clicked()),
+            this, SLOT(OnRadioTimeLinear()));
+    connect(RadioButtonTiWiener, SIGNAL(clicked()),
+            this, SLOT(OnRadioTimeWiener()));
+    connect(RadioButtonFreqLinear, SIGNAL(clicked()),
+            this, SLOT(OnRadioFrequencyLinear()));
+    connect(RadioButtonFreqDFT, SIGNAL(clicked()),
+            this, SLOT(OnRadioFrequencyDft()));
+    connect(RadioButtonFreqWiener, SIGNAL(clicked()),
+            this, SLOT(OnRadioFrequencyWiener()));
+    connect(RadioButtonTiSyncEnergy, SIGNAL(clicked()),
+            this, SLOT(OnRadioTiSyncEnergy()));
+    connect(RadioButtonTiSyncFirstPeak, SIGNAL(clicked()),
+            this, SLOT(OnRadioTiSyncFirstPeak()));
+
+    /* Char selector list view */
+    connect(chartSelector, SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)),
+            this, SLOT(OnListSelChanged( QTreeWidgetItem *, QTreeWidgetItem *)));
+	chartSelector->setContextMenuPolicy(Qt::CustomContextMenu);
+	connect(chartSelector, SIGNAL(customContextMenuRequested ( const QPoint&  )),
+		this, SLOT(OnCustomContextMenuRequested(const QPoint&)));
+
+    /* Buttons */
+    connect(buttonOk, SIGNAL(clicked()), this, SLOT(close()));
+
+    /* Check boxes */
+    connect(CheckBoxFlipSpec, SIGNAL(clicked()),
+            this, SLOT(OnCheckFlipSpectrum()));
+    connect(CheckBoxMuteAudio, SIGNAL(clicked()),
+            this, SLOT(OnCheckBoxMuteAudio()));
+    connect(CheckBoxWriteLog, SIGNAL(stateChanged(int)),
+            this, SLOT(OnCheckWriteLog(int)));
+    connect(CheckBoxSaveAudioWave, SIGNAL(clicked()),
+            this, SLOT(OnCheckSaveAudioWAV()));
+    connect(CheckBoxRecFilter, SIGNAL(clicked()),
+            this, SLOT(OnCheckRecFilter()));
+    connect(CheckBoxModiMetric, SIGNAL(clicked()),
+            this, SLOT(OnCheckModiMetric()));
+    connect(CheckBoxReverb, SIGNAL(clicked()),
+            this, SLOT(OnCheckBoxReverb()));
+
+    /* Timer */
+    connect(&Timer, SIGNAL(timeout()),
+            this, SLOT(OnTimer()));
+
+    /* Select chart type */
+    chartSelector->setCurrentItem(FindItemByECharType(eCurCharType), 0);
+
+    /* Force update */
+    OnTimer();
+
+    APPLY_CUSTOM_THEME();
+}
+
+void systemevalDlg::connectController(ReceiverController* controller)
+{
+    connect(this, SIGNAL(saveAudio(const string&)), controller, SLOT(setSaveAudio(const string&)));
+    connect(this, SIGNAL(muteAudio(bool)), controller, SLOT(muteAudio(bool)));
+    connect(this, SIGNAL(setReverbEffect(bool)), controller, SLOT(setReverbEffect(bool)));
+    connect(this, SIGNAL(setRecFilter(bool)), controller, SLOT(setRecFilter(bool)));
+    connect(this, SIGNAL(setFlippedSpectrum(bool)), controller, SLOT(setFlippedSpectrum(bool)));
+    connect(this, SIGNAL(setIntCons(bool)), controller, SLOT(setIntCons(bool)));
+    connect(this, SIGNAL(setNumMSCMLCIterations(int)), controller, SLOT(setNumMSCMLCIterations(int)));
+    connect(this, SIGNAL(setTimeInt(int)), controller, SLOT(setTimeInt(int)));
+    connect(this, SIGNAL(setFreqInt(int)), controller, SLOT(setFreqInt(int)));
+    connect(this, SIGNAL(setTiSyncTracType(int)), controller, SLOT(setTiSyncTracType(int)));
+}
+
+systemevalDlg::~systemevalDlg()
+{
+    // close wav file
+    if(CheckBoxSaveAudioWave->isChecked())
+        emit saveAudio("");
+    delete MainPlot;
+}
+
+void systemevalDlg::setControls(CSettings& s)
+{
+    /* Slider for MLC number of iterations */
+    const int iNumIt = s.Get("Receiver", "mlciter", 1);
+    if (SliderNoOfIterations->value() != iNumIt)
+    {
+        /* Update slider and label */
+        SliderNoOfIterations->setValue(iNumIt);
+        TextNumOfIterations->setText(tr("MLC: Number of Iterations: ") +
+                                     QString().setNum(iNumIt));
+    }
+
+    /* Update for channel estimation and time sync switches */
+    switch (s.Get("Receiver", "timeint", 1))
+    {
+    case CChannelEstimation::TLINEAR:
+        if (!RadioButtonTiLinear->isChecked())
+            RadioButtonTiLinear->setChecked(TRUE);
+        break;
+
+    case CChannelEstimation::TWIENER:
+        if (!RadioButtonTiWiener->isChecked())
+            RadioButtonTiWiener->setChecked(TRUE);
+        break;
+    }
+
+    switch (s.Get("Receiver", "freqint", 1))
+    {
+    case CChannelEstimation::FLINEAR:
+        if (!RadioButtonFreqLinear->isChecked())
+            RadioButtonFreqLinear->setChecked(TRUE);
+        break;
+
+    case CChannelEstimation::FDFTFILTER:
+        if (!RadioButtonFreqDFT->isChecked())
+            RadioButtonFreqDFT->setChecked(TRUE);
+        break;
+
+    case CChannelEstimation::FWIENER:
+        if (!RadioButtonFreqWiener->isChecked())
+            RadioButtonFreqWiener->setChecked(TRUE);
+        break;
+    }
+
+    switch (s.Get("Receiver", "timesync", 1))
+    {
+    case CTimeSyncTrack::TSFIRSTPEAK:
+        if (!RadioButtonTiSyncFirstPeak->isChecked())
+            RadioButtonTiSyncFirstPeak->setChecked(TRUE);
+        break;
+
+    case CTimeSyncTrack::TSENERGY:
+        if (!RadioButtonTiSyncEnergy->isChecked())
+            RadioButtonTiSyncEnergy->setChecked(TRUE);
+        break;
+    }
+
+    /* Update settings checkbuttons */
+    CheckBoxReverb->setChecked(s.Get("Receiver", "reverb", FALSE));
+    CheckBoxRecFilter->setChecked(s.Get("Receiver", "filter", FALSE));
+    CheckBoxModiMetric->setChecked(s.Get("Receiver", "modemetric", FALSE));
+    CheckBoxMuteAudio->setChecked(s.Get("Receiver", "muteaudio", FALSE));
+    CheckBoxFlipSpec->setChecked(s.Get("Receiver", "flipspectrum", FALSE));
+
+    CheckBoxSaveAudioWave->setChecked(s.Get("command", "writewav")!="");
+}
+
+void systemevalDlg::eventShow(QShowEvent*)
+{
+    /* Restore chart windows */
+    const int iNumChartWin = getSetting("numchartwin", 0);
+    for (int i = 0; i < iNumChartWin; i++)
+    {
+        stringstream s;
+
+        /* create the section key for this window */
+        s << "Chart Window " << i;
+
+        /* get the chart type */
+        const CDRMPlot::ECharType eNewType = PlotNameToECharType(Settings.Get(s.str(), "plottype", string()));
+
+        /* get window geometry data */
+        CWinGeom c;
+        Settings.Get(s.str(), c);
+        const QRect WinGeom(c.iXPos, c.iYPos, c.iWSize, c.iHSize);
+
+        /* Open the new chart window */
+        CDRMPlot* pNewChartWin = OpenChartWin(eNewType);
+
+        /* and restore its geometry */
+        if (WinGeom.isValid() && !WinGeom.isEmpty() && !WinGeom.isNull())
+            pNewChartWin->setGeometry(WinGeom);
+
+        /* Add window pointer in vector (needed for closing the windows) */
+        vecpDRMPlots.push_back(pNewChartWin);
+
+		/* Show new window */
+		pNewChartWin->show();
+    }
+
+    /* Activate real-time timer */
+    Timer.start(GUI_CONTROL_UPDATE_TIME);
+
+    /* Notify the MainPlot of showEvent */
+    MainPlot->activate();
+}
+
+void systemevalDlg::eventHide(QHideEvent*)
+{
+    /* Notify the MainPlot of hideEvent */
+    MainPlot->deactivate();
+
+    /* Stop the real-time timer */
+    Timer.stop();
+
+    /* Store size and position of all additional chart windows */
+    int iNumOpenCharts = 0;
+
+    for (size_t i = 0; i < vecpDRMPlots.size(); i++)
+    {
+        /* Check, if window wasn't closed by the user */
+        if (vecpDRMPlots[i]->isVisible())
+        {
+            stringstream s;
+            CWinGeom c;
+            const QRect CWGeom = vecpDRMPlots[i]->geometry();
+
+            /* Set parameters */
+            c.iXPos = CWGeom.x();
+            c.iYPos = CWGeom.y();
+            c.iHSize = CWGeom.height();
+            c.iWSize = CWGeom.width();
+
+            s << "Chart Window " << iNumOpenCharts;
+            Settings.Put(s.str(), c);
+            Settings.Put(s.str(), "plottype", ECharTypeToPlotName(vecpDRMPlots[i]->GetChartType()));
+
+            iNumOpenCharts++;
+        }
+        /* Close window afterwards */
+        vecpDRMPlots[i]->close();
+    }
+    putSetting("numchartwin", iNumOpenCharts);
+
+    /* We do not need the pointers anymore, reset vector */
+    vecpDRMPlots.clear();
+
+    /* Store current plot type */
+    putSetting("plottype", QString::fromLocal8Bit(ECharTypeToPlotName(eCurCharType).c_str()));
+}
+
+void systemevalDlg::UpdatePlotStyle(int iPlotStyle)
+{
+    this->iPlotStyle = iPlotStyle;
+
+    /* Update chart windows */
+    for (size_t i = 0; i < vecpDRMPlots.size(); i++)
+        vecpDRMPlots[i]->SetPlotStyle(iPlotStyle);
+
+    /* Update main plot window */
+    MainPlot->SetPlotStyle(iPlotStyle);
+}
+
+void systemevalDlg::OnTreeWidgetContMenu(bool)
+{
+    if (eNewCharType != CDRMPlot::NONE_OLD)
+    {
+        /* Open the new chart */
+		CDRMPlot* pNewChartWin = OpenChartWin(eNewCharType);
+        vecpDRMPlots.push_back(pNewChartWin);
+
+		/* Show new window */
+		pNewChartWin->show();
+
+        eNewCharType = CDRMPlot::NONE_OLD;
+    }
+}
+
+void systemevalDlg::OnCustomContextMenuRequested(const QPoint& p)
+{
+	QModelIndex index = chartSelector->indexAt(p);
+    /* Make sure we have a non root item */
+    if (index.parent() != QModelIndex())
+    {
+        /* Popup the context menu */
+        eNewCharType = CDRMPlot::ECharType(index.data(Qt::UserRole).toInt());
+        pTreeWidgetContextMenu->exec(QCursor::pos());
+    }
+}
+
+CDRMPlot* systemevalDlg::OpenChartWin(CDRMPlot::ECharType eNewType)
+{
+    /* Create new chart window */
+    CDRMPlot* pNewChartWin = new CDRMPlot(this, NULL, controller);
+    pNewChartWin->setCaption(tr("Chart Window"));
+
+    /* Set correct icon (use the same as this dialog) */
+    const QIcon& icon = windowIcon();
+    pNewChartWin->setIcon(icon);
+
+    /* Set receiver object and correct chart type */
+    pNewChartWin->SetupChart(eNewType);
+
+    /* Set plot style*/
+    pNewChartWin->SetPlotStyle(iPlotStyle);
+
+    return pNewChartWin;
+}
+
+QTreeWidgetItem* systemevalDlg::FindItemByECharType(CDRMPlot::ECharType eCharType)
+{
+    for (int i = 0;; i++)
+    {
+        QTreeWidgetItem* item = chartSelector->topLevelItem(i);
+        if (item == NULL)
+            return NULL;
+        for (int j = 0; j < item->childCount(); j++)
+        {
+            QTreeWidgetItem* subitem = item->child(j);
+            CDRMPlot::ECharType eCurCharType = CDRMPlot::ECharType(subitem->data(0, Qt::UserRole).toInt());
+            if (eCurCharType == eCharType)
+                return subitem;
+        }
+    }
+}
+
+CDRMPlot::ECharType systemevalDlg::PlotNameToECharType(const string& PlotName)
+{
+    QString plotName(PlotName.c_str());
+    for (int i = 0;; i++)
+    {
+        QTreeWidgetItem* item = chartSelector->topLevelItem(i);
+        if (item == NULL)
+            return CDRMPlot::AUDIO_SPECTRUM; /* safe value */
+        for (int j = 0; j < item->childCount(); j++)
+        {
+            QTreeWidgetItem* subitem = item->child(j);
+            if (plotName == subitem->text(0))
+                return CDRMPlot::ECharType(subitem->data(0, Qt::UserRole).toInt());
+        }
+    }
+}
+
+string systemevalDlg::ECharTypeToPlotName(CDRMPlot::ECharType eCharType)
+{
+    QTreeWidgetItem* item = FindItemByECharType(eCharType);
+    if (item != NULL)
+        return item->text(0).toStdString();
+    return string();
+}
+
+void systemevalDlg::OnTimer()
+{
+    Parameters.Lock();
+
+        SetStatus(LEDFAC, Parameters.ReceiveStatus.FAC.GetStatus());
+        SetStatus(LEDSDC, Parameters.ReceiveStatus.SDC.GetStatus());
+		// TODO Data Broadcasts
+		int iShortID = Parameters.GetCurSelAudioService();
+        SetStatus(LEDMSC, Parameters.AudioComponentStatus[iShortID].GetStatus());
+        SetStatus(LEDFrameSync, Parameters.ReceiveStatus.FSync.GetStatus());
+        SetStatus(LEDTimeSync, Parameters.ReceiveStatus.TSync.GetStatus());
+        ETypeRxStatus soundCardStatusI = Parameters.ReceiveStatus.InterfaceI.GetStatus(); /* Input */
+        ETypeRxStatus soundCardStatusO = Parameters.ReceiveStatus.InterfaceO.GetStatus(); /* Output */
+        SetStatus(LEDIOInterface, soundCardStatusO == NOT_PRESENT || (soundCardStatusI != NOT_PRESENT && soundCardStatusI != RX_OK) ? soundCardStatusI : soundCardStatusO);
+
+        /* Show SNR if receiver is in tracking mode */
+        if (Parameters.GetAcquiState() == AS_WITH_SIGNAL)
+        {
+            /* Get a consistant snapshot */
+
+            /* We only get SNR from a local DREAM Front-End */
+            _REAL rSNR = Parameters.GetSNR();
+            if (rSNR >= 0.0)
+            {
+                /* SNR */
+                ValueSNR->setText("<b>" +
+                                  QString().setNum(rSNR, 'f', 1) + " dB</b>");
+            }
+            else
+            {
+                ValueSNR->setText("<b>---</b>");
+            }
+            /* We get MER from a local DREAM Front-End or an RSCI input but not an MDI input */
+            _REAL rMER = Parameters.rMER;
+            if (rMER >= 0.0 )
+            {
+                ValueMERWMER->setText(QString().
+                                      setNum(Parameters.rWMERMSC, 'f', 1) + " dB / "
+                                      + QString().setNum(rMER, 'f', 1) + " dB");
+            }
+            else
+            {
+                ValueMERWMER->setText("---");
+            }
+
+            /* Doppler estimation (assuming Gaussian doppler spectrum) */
+            if (Parameters.rSigmaEstimate >= 0.0)
+            {
+                /* Plot delay and Doppler values */
+                ValueWiener->setText(
+                    QString().setNum(Parameters.rSigmaEstimate, 'f', 2) + " Hz / "
+                    + QString().setNum(Parameters.rMinDelay, 'f', 2) + " ms");
+            }
+            else
+            {
+                /* Plot only delay, Doppler not available */
+                ValueWiener->setText("--- / "
+                                     + QString().setNum(Parameters.rMinDelay, 'f', 2) + " ms");
+            }
+
+            /* Sample frequency offset estimation */
+            const _REAL rCurSamROffs = Parameters.rResampleOffset;
+
+            /* Display value in [Hz] and [ppm] (parts per million) */
+            ValueSampFreqOffset->setText(
+                QString().setNum(rCurSamROffs, 'f', 2) + " Hz (" +
+                QString().setNum((int) (rCurSamROffs / Parameters.GetSigSampleRate() * 1e6))
+                + " ppm)");
+
+        }
+        else
+        {
+            ValueSNR->setText("<b>---</b>");
+            ValueMERWMER->setText("---");
+            ValueWiener->setText("--- / ---");
+            ValueSampFreqOffset->setText("---");
+        }
+
+#ifdef _DEBUG_
+        TextFreqOffset->setText("DC: " +
+                                QString().setNum(DRMReceiver.GetReceiveData()->
+                                        ConvertFrequency(Parameters.GetDCFrequency()), 'f', 3) + " Hz ");
+
+        /* Metric values */
+        ValueFreqOffset->setText(tr("Metrics [dB]: MSC: ") +
+                                 QString().setNum(
+                                     DRMReceiver.GetMSCMLC()->GetAccMetric(), 'f', 2) +	"\nSDC: " +
+                                 QString().setNum(
+                                     DRMReceiver.GetSDCMLC()->GetAccMetric(), 'f', 2) +	" / FAC: " +
+                                 QString().setNum(
+                                     DRMReceiver.GetFACMLC()->GetAccMetric(), 'f', 2));
+#else
+        /* DC frequency */
+        ValueFreqOffset->setText(QString().setNum(controller->getReceiver()->GetReceiveData()->
+                                     ConvertFrequency(Parameters.GetDCFrequency()), 'f', 2) + " Hz");
+#endif
+
+        /* If MDI in is enabled, do not show any synchronization parameter */
+        if (controller->getReceiver()->GetRSIIn()->GetInEnabled() == TRUE)
+        {
+            ValueSNR->setText("<b>---</b>");
+            if (Parameters.vecrRdelThresholds.GetSize() > 0)
+                ValueWiener->setText(QString().setNum(Parameters.rRdop, 'f', 2) + " Hz / "
+                                     + QString().setNum(Parameters.vecrRdelIntervals[0], 'f', 2) + " ms ("
+                                     + QString().setNum(Parameters.vecrRdelThresholds[0]) + "%)");
+            else
+                ValueWiener->setText(QString().setNum(Parameters.rRdop, 'f', 2) + " Hz / ---");
+
+            ValueSampFreqOffset->setText("---");
+            ValueFreqOffset->setText("---");
+        }
+
+        /* FAC info static ------------------------------------------------------ */
+        QString strFACInfo;
+
+        /* Robustness mode #################### */
+        strFACInfo = GetRobModeStr(Parameters.GetWaveMode())
+                + " / " + GetSpecOccStr(Parameters.GetSpectrumOccup());
+
+        //FACDRMModeBWL->setText(tr("DRM Mode / Bandwidth:")); /* Label */
+        FACDRMModeBWV->setText(strFACInfo); /* Value */
+
+
+        /* Interleaver Depth #################### */
+        switch (Parameters.eSymbolInterlMode)
+        {
+        case SI_LONG:
+            strFACInfo = tr("2 s (Long Interleaving)");
+            break;
+
+        case SI_SHORT:
+            strFACInfo = tr("400 ms (Short Interleaving)");
+            break;
+
+        default:
+            strFACInfo = "?";
+        }
+
+        //FACInterleaverDepthL->setText(tr("Interleaver Depth:")); /* Label */
+        FACInterleaverDepthV->setText(strFACInfo); /* Value */
+
+
+        /* SDC, MSC mode #################### */
+        /* SDC */
+        switch (Parameters.eSDCCodingScheme)
+        {
+        case CS_1_SM:
+            strFACInfo = "4-QAM / ";
+            break;
+
+        case CS_2_SM:
+            strFACInfo = "16-QAM / ";
+            break;
+
+        default:
+            strFACInfo = "? / ";
+        }
+
+        /* MSC */
+        switch (Parameters.eMSCCodingScheme)
+        {
+        case CS_2_SM:
+            strFACInfo += "SM 16-QAM";
+            break;
+
+        case CS_3_SM:
+            strFACInfo += "SM 64-QAM";
+            break;
+
+        case CS_3_HMSYM:
+            strFACInfo += "HMsym 64-QAM";
+            break;
+
+        case CS_3_HMMIX:
+            strFACInfo += "HMmix 64-QAM";
+            break;
+
+        default:
+            strFACInfo += "?";
+        }
+
+        //FACSDCMSCModeL->setText(tr("SDC / MSC Mode:")); /* Label */
+        FACSDCMSCModeV->setText(strFACInfo); /* Value */
+
+
+        /* Code rates #################### */
+        strFACInfo = QString().setNum(Parameters.MSCPrLe.iPartB);
+        strFACInfo += " / ";
+        strFACInfo += QString().setNum(Parameters.MSCPrLe.iPartA);
+
+        //FACCodeRateL->setText(tr("Prot. Level (B / A):")); /* Label */
+        FACCodeRateV->setText(strFACInfo); /* Value */
+
+
+        /* Number of services #################### */
+        strFACInfo = tr("Audio: ");
+        strFACInfo += QString().setNum(Parameters.iNumAudioService);
+        strFACInfo += tr(" / Data: ");
+        strFACInfo += QString().setNum(Parameters.iNumDataService);
+
+        //FACNumServicesL->setText(tr("Number of Services:")); /* Label */
+        FACNumServicesV->setText(strFACInfo); /* Value */
+
+
+        /* Time, date #################### */
+        if ((Parameters.iUTCHour == 0) &&
+                (Parameters.iUTCMin == 0) &&
+                (Parameters.iDay == 0) &&
+                (Parameters.iMonth == 0) &&
+                (Parameters.iYear == 0))
+        {
+            /* No time service available */
+            strFACInfo = tr("Service not available");
+        }
+        else
+        {
+#ifdef GUI_QT_DATE_TIME_TYPE
+            /* QT type of displaying date and time */
+            QDateTime DateTime;
+            DateTime.setDate(QDate(Parameters.iYear,
+                                   Parameters.iMonth,
+                                   Parameters.iDay));
+            DateTime.setTime(QTime(Parameters.iUTCHour,
+                                   Parameters.iUTCMin));
+
+            strFACInfo = DateTime.toString();
+#else
+            /* Set time and date */
+            QString strMin;
+            const int iMin = Parameters.iUTCMin;
+
+            /* Add leading zero to number smaller than 10 */
+            if (iMin < 10)
+                strMin = "0";
+            else
+                strMin = "";
+
+            strMin += QString().setNum(iMin);
+
+            strFACInfo =
+                /* Time */
+                QString().setNum(Parameters.iUTCHour) + ":" +
+                strMin + "  -  " +
+                /* Date */
+                QString().setNum(Parameters.iMonth) + "/" +
+                QString().setNum(Parameters.iDay) + "/" +
+                QString().setNum(Parameters.iYear);
+#endif
+            /* Add UTC offset if available */
+            if (Parameters.bValidUTCOffsetAndSense)
+                strFACInfo += QString(" %1%2%3%4")
+                    .arg(tr("UTC"))
+                    .arg(Parameters.iUTCSense ? "-" : "+")
+                    .arg(Parameters.iUTCOff / 2, 0, 10)
+                    .arg(Parameters.iUTCOff & 1 ? ".5" : "");
+        }
+
+        //FACTimeDateL->setText(tr("Received time - date:")); /* Label */
+        FACTimeDateV->setText(strFACInfo); /* Value */
+
+        UpdateGPS(Parameters);
+
+    Parameters.Unlock();
+}
+
+void systemevalDlg::UpdateGPS(CParameter& Parameters)
+{
+    gps_data_t& gps = Parameters.gps_data;
+
+    if((gps.set&STATUS_SET)==0) {
+        LEDGPS->SetLight(CMultColorLED::RL_RED);
+    } else {
+
+        if(gps.status==0)
+            LEDGPS->SetLight(CMultColorLED::RL_YELLOW);
+        else
+            LEDGPS->SetLight(CMultColorLED::RL_GREEN);
+    }
+
+    QString qStrPosition;
+    if (gps.set&LATLON_SET)
+//      Wrong char on Qt 5
+//      qStrPosition = QString(tr("Lat: %1\260  Long: %2\260")).arg(gps.fix.latitude, 0, 'f', 4).arg(gps.fix.longitude,0, 'f',4);
+        qStrPosition = QString(trUtf8("Lat: %1°  Long: %2°")).arg(gps.fix.latitude, 0, 'f', 4).arg(gps.fix.longitude,0, 'f',4);
+    else
+        qStrPosition = tr("Lat: ?  Long: ?");
+
+    QString qStrAltitude;
+    if (gps.set&ALTITUDE_SET)
+        qStrAltitude = QString(tr("  Alt: %1 m")).arg(gps.fix.altitude, 0, 'f', 0);
+    else
+        qStrAltitude = tr("  Alt: ?");
+    QString qStrSpeed;
+    if (gps.set&SPEED_SET)
+        qStrSpeed = QString(tr("Speed: %1 m/s")).arg(gps.fix.speed, 0, 'f', 1);
+    else
+        qStrSpeed = tr("Speed: ?");
+    QString qStrTrack;
+    if (gps.set&TRACK_SET)
+        qStrTrack =  QString(tr("  Track: %1\260")).arg(gps.fix.track);
+    else
+        qStrTrack =  tr("  Track: ?");
+    QString qStrTime;
+    if (gps.set&TIME_SET)
+    {
+        struct tm * p_ts;
+        time_t tt = time_t(gps.fix.time);
+        p_ts = gmtime(&tt);
+        QChar fill('0');
+        qStrTime = QString("UTC: %1/%2/%3 %4:%5:%6  ")
+                .arg(1900 + p_ts->tm_year)
+                .arg(1 + p_ts->tm_mon, 2, 10, fill)
+                .arg(p_ts->tm_mday, 2, 10, fill)
+                .arg(p_ts->tm_hour, 2, 10, fill)
+                .arg(p_ts->tm_min, 2, 10, fill)
+                .arg(p_ts->tm_sec,2, 10, fill);
+    }
+    else
+	qStrTime = "UTC: ?";
+    QString qStrSat;
+    if (gps.set&SATELLITE_SET)
+        qStrSat = tr("  Satellites: ") + QString().setNum(gps.satellites_used);
+    else
+        qStrSat = tr("  Satellites: ?");
+
+    TextLabelGPSPosition->setText(qStrPosition+qStrAltitude);
+    TextLabelGPSSpeedHeading->setText(qStrSpeed+qStrTrack);
+    TextLabelGPSTime->setText(qStrTime+qStrSat);
+}
+
+
+void systemevalDlg::OnRadioTimeLinear()
+{
+    emit setTimeInt(CChannelEstimation::TLINEAR);
+}
+
+void systemevalDlg::OnRadioTimeWiener()
+{
+    emit setTimeInt(CChannelEstimation::TWIENER);
+}
+
+void systemevalDlg::OnRadioFrequencyLinear()
+{
+    emit setFreqInt(CChannelEstimation::FLINEAR);
+}
+
+void systemevalDlg::OnRadioFrequencyDft()
+{
+    emit setFreqInt(CChannelEstimation::FDFTFILTER);
+}
+
+void systemevalDlg::OnRadioFrequencyWiener()
+{
+    emit setFreqInt(CChannelEstimation::FWIENER);
+}
+
+void systemevalDlg::OnRadioTiSyncFirstPeak()
+{
+    emit setTiSyncTracType(CTimeSyncTrack::TSFIRSTPEAK);
+}
+
+void systemevalDlg::OnRadioTiSyncEnergy()
+{
+    emit setTiSyncTracType(CTimeSyncTrack::TSENERGY);
+}
+
+void systemevalDlg::OnSliderIterChange(int value)
+{
+    emit setNumMSCMLCIterations(value);
+    /* Show the new value in the label control */
+    TextNumOfIterations->setText(tr("MLC: Number of Iterations: ") +
+                                 QString().setNum(value));
+}
+
+void systemevalDlg::OnListSelChanged(QTreeWidgetItem *curr, QTreeWidgetItem *)
+{
+    /* Make sure we have a non root item */
+    if (curr && curr->parent())
+    {
+        /* Get chart type from selected item */
+        eCurCharType = CDRMPlot::ECharType(curr->data(0, Qt::UserRole).toInt());
+        /* Setup chart */
+        MainPlot->SetupChart(eCurCharType);
+    }
+}
+
+void systemevalDlg::OnCheckFlipSpectrum()
+{
+    emit setFlippedSpectrum(CheckBoxFlipSpec->isChecked());
+}
+
+void systemevalDlg::OnCheckRecFilter()
+{
+    emit setRecFilter(CheckBoxRecFilter->isChecked());
+}
+
+void systemevalDlg::OnCheckModiMetric()
+{
+    emit setIntCons(CheckBoxModiMetric->isChecked());
+}
+
+void systemevalDlg::OnCheckBoxMuteAudio()
+{
+    emit muteAudio(CheckBoxMuteAudio->isChecked());
+}
+
+void systemevalDlg::OnCheckBoxReverb()
+{
+    emit setReverbEffect(CheckBoxReverb->isChecked());
+}
+
+void systemevalDlg::OnCheckSaveAudioWAV()
+{
+    /*
+    	This code is copied in AnalogDemDlg.cpp. If you do changes here, you should
+    	apply the changes in the other file, too
+    */
+    if (CheckBoxSaveAudioWave->isChecked() == TRUE)
+    {
+        /* Show "save file" dialog */
+        QString strFileName =
+            QFileDialog::getSaveFileName(this, "*.wav", tr("DreamOut.wav"));
+
+        /* Check if user not hit the cancel button */
+        if (!strFileName.isEmpty())
+        {
+			string s = strFileName.toUtf8().constData();
+            emit saveAudio(s);
+        }
+        else
+        {
+            /* User hit the cancel button, uncheck the button */
+            CheckBoxSaveAudioWave->setChecked(FALSE);
+        }
+    }
+    else
+        emit saveAudio("");
+}
+
+
+void systemevalDlg::OnCheckWriteLog(int state)
+{
+    if (state == Qt::Checked)
+    {
+		emit startLogging();
+    }
+    else
+    {
+		emit stopLogging();
+    }
+}
+
+QString	systemevalDlg::GetRobModeStr(ERobMode v)
+{
+    switch (v)
+    {
+    case RM_ROBUSTNESS_MODE_A:
+        return "A";
+        break;
+
+    case RM_ROBUSTNESS_MODE_B:
+        return "B";
+        break;
+
+    case RM_ROBUSTNESS_MODE_C:
+        return "C";
+        break;
+
+    case RM_ROBUSTNESS_MODE_D:
+        return "D";
+        break;
+
+    default:
+        return "?";
+    }
+}
+
+QString	systemevalDlg::GetSpecOccStr(ESpecOcc v)
+{
+    switch (v)
+    {
+    case SO_0:
+        return "4.5 kHz";
+        break;
+
+    case SO_1:
+        return "5 kHz";
+        break;
+
+    case SO_2:
+        return "9 kHz";
+        break;
+
+    case SO_3:
+        return "10 kHz";
+        break;
+
+    case SO_4:
+        return "18 kHz";
+        break;
+
+    case SO_5:
+        return "20 kHz";
+        break;
+
+    default:
+        return "?";
+    }
+}
+
+void systemevalDlg::AddWhatsThisHelp()
+{
+    /*
+    	This text was taken from the only documentation of Dream software
+    */
+    /* DC Frequency Offset */
+    const QString strDCFreqOffs =
+        tr("<b>DC Frequency Offset:</b> This is the "
+           "estimation of the DC frequency offset. This offset corresponds "
+           "to the resulting sound card intermedia frequency of the front-end. "
+           "This frequency is not restricted to a certain value. The only "
+           "restriction is that the DRM spectrum must be completely inside the "
+           "bandwidth of the sound card.");
+
+    TextFreqOffset->setWhatsThis(strDCFreqOffs);
+    ValueFreqOffset->setWhatsThis(strDCFreqOffs);
+
+    /* Sample Frequency Offset */
+    const QString strFreqOffset =
+        tr("<b>Sample Frequency Offset:</b> This is the "
+           "estimation of the sample rate offset between the sound card sample "
+           "rate of the local computer and the sample rate of the D / A (digital "
+           "to analog) converter in the transmitter. Usually the sample rate "
+           "offset is very constant for a given sound card. Therefore it is "
+           "useful to inform the Dream software about this value at application "
+           "startup to increase the acquisition speed and reliability.");
+
+    TextSampFreqOffset->setWhatsThis(strFreqOffset);
+    ValueSampFreqOffset->setWhatsThis(strFreqOffset);
+
+    /* Doppler / Delay */
+    const QString strDopplerDelay =
+        tr("<b>Doppler / Delay:</b> The Doppler frequency "
+           "of the channel is estimated for the Wiener filter design of channel "
+           "estimation in time direction. If linear interpolation is set for "
+           "channel estimation in time direction, this estimation is not updated. "
+           "The Doppler frequency is an indication of how fast the channel varies "
+           "with time. The higher the frequency, the faster the channel changes "
+           "are.<br>The total delay of the Power Delay Spectrum "
+           "(PDS) is estimated from the impulse response estimation derived from "
+           "the channel estimation. This delay corresponds to the range between "
+           "the two vertical dashed black lines in the Impulse Response (IR) "
+           "plot.");
+
+	TextWiener->setWhatsThis(strDopplerDelay);
+    ValueWiener->setWhatsThis(strDopplerDelay);
+
+    /* I / O Interface LED */
+    const QString strLEDIOInterface =
+        tr("<b>I / O Interface LED:</b> This LED shows the "
+           "current status of the sound card interface. The yellow light shows "
+           "that the audio output was corrected. Since the sample rate of the "
+           "transmitter and local computer are different, from time to time the "
+           "audio buffers will overflow or under run and a correction is "
+           "necessary. When a correction occurs, a \"click\" sound can be heard. "
+           "The red light shows that a buffer was lost in the sound card input "
+           "stream. This can happen if a thread with a higher priority is at "
+           "100% and the Dream software cannot read the provided blocks fast "
+           "enough. In this case, the Dream software will instantly loose the "
+           "synchronization and has to re-synchronize. Another reason for red "
+           "light is that the processor is too slow for running the Dream "
+           "software.");
+
+    TextLabelLEDIOInterface->setWhatsThis(strLEDIOInterface);
+    LEDIOInterface->setWhatsThis(strLEDIOInterface);
+
+    /* Time Sync Acq LED */
+    const QString strLEDTimeSyncAcq =
+        tr("<b>Time Sync Acq LED:</b> This LED shows the "
+           "state of the timing acquisition (search for the beginning of an OFDM "
+           "symbol). If the acquisition is done, this LED will stay green.");
+
+    TextLabelLEDTimeSyncAcq->setWhatsThis(strLEDTimeSyncAcq);
+    LEDTimeSync->setWhatsThis(strLEDTimeSyncAcq);
+
+    /* Frame Sync LED */
+    const QString strLEDFrameSync =
+        tr("<b>Frame Sync LED:</b> The DRM frame "
+           "synchronization status is shown with this LED. This LED is also only "
+           "active during acquisition state of the Dream receiver. In tracking "
+           "mode, this LED is always green.");
+
+    TextLabelLEDFrameSync->setWhatsThis(strLEDFrameSync);
+    LEDFrameSync->setWhatsThis(strLEDFrameSync);
+
+    /* FAC CRC LED */
+    const QString strLEDFACCRC =
+        tr("<b>FAC CRC LED:</b> This LED shows the Cyclic "
+           "Redundancy Check (CRC) of the Fast Access Channel (FAC) of DRM. FAC "
+           "is one of the three logical channels and is always modulated with a "
+           "4-QAM. If the FAC CRC check was successful, the receiver changes to "
+           "tracking mode. The FAC LED is the indication whether the receiver "
+           "is synchronized to a DRM transmission or not.<br>"
+           "The bandwidth of the DRM signal, the constellation scheme of MSC and "
+           "SDC channels and the interleaver depth are some of the parameters "
+           "which are provided by the FAC.");
+
+    TextLabelLEDFACCRC->setWhatsThis(strLEDFACCRC);
+    LEDFAC->setWhatsThis(strLEDFACCRC);
+
+    /* SDC CRC LED */
+    const QString strLEDSDCCRC =
+        tr("<b>SDC CRC LED:</b> This LED shows the CRC "
+           "check result of the Service Description Channel (SDC) which is one "
+           "logical channel of the DRM stream. This data is transmitted in "
+           "approx. 1 second intervals and contains information about station "
+           "label, audio and data format, etc. The error protection is normally "
+           "lower than the protection of the FAC. Therefore this LED will turn "
+           "to red earlier than the FAC LED in general.<br>If the CRC check "
+           "is ok but errors in the content were detected, the LED turns "
+           "yellow.");
+
+    TextLabelLEDSDCCRC->setWhatsThis(strLEDSDCCRC);
+    LEDSDC->setWhatsThis(strLEDSDCCRC);
+
+    /* MSC CRC LED */
+    const QString strLEDMSCCRC =
+        tr("<b>MSC CRC LED:</b> This LED shows the status "
+           "of the Main Service Channel (MSC). This channel contains the actual "
+           "audio and data bits. The LED shows the CRC check of the AAC core "
+           "decoder. The SBR has a separate CRC, but this status is not shown "
+           "with this LED. If SBR CRC is wrong but the AAC CRC is ok one can "
+           "still hear something (of course, the high frequencies are not there "
+           "in this case). If this LED turns red, interruptions of the audio are "
+           "heard. The yellow light shows that only one 40 ms audio frame CRC "
+           "was wrong. This causes usually no hearable artifacts.");
+
+    TextLabelLEDMSCCRC->setWhatsThis(strLEDMSCCRC);
+    LEDMSC->setWhatsThis(strLEDMSCCRC);
+
+    /* MLC, Number of Iterations */
+    const QString strNumOfIterations =
+        tr("<b>MLC, Number of Iterations:</b> In DRM, a "
+           "multilevel channel coder is used. With this code it is possible to "
+           "iterate the decoding process in the decoder to improve the decoding "
+           "result. The more iterations are used the better the result will be. "
+           "But switching to more iterations will increase the CPU load. "
+           "Simulations showed that the first iteration (number of "
+           "iterations = 1) gives the most improvement (approx. 1.5 dB at a "
+           "BER of 10-4 on a Gaussian channel, Mode A, 10 kHz bandwidth). The "
+           "improvement of the second iteration will be as small as 0.3 dB."
+           "<br>The recommended number of iterations given in the DRM "
+           "standard is one iteration (number of iterations = 1).");
+
+    TextNumOfIterations->setWhatsThis(strNumOfIterations);
+    SliderNoOfIterations->setWhatsThis(strNumOfIterations);
+
+    /* Flip Input Spectrum */
+    CheckBoxFlipSpec->setWhatsThis(
+                     tr("<b>Flip Input Spectrum:</b> Checking this box "
+                        "will flip or invert the input spectrum. This is necessary if the "
+                        "mixer in the front-end uses the lower side band."));
+
+    /* Mute Audio */
+    CheckBoxMuteAudio->setWhatsThis(
+                     tr("<b>Mute Audio:</b> The audio can be muted by "
+                        "checking this box. The reaction of checking or unchecking this box "
+                        "is delayed by approx. 1 second due to the audio buffers."));
+
+    /* Reverberation Effect */
+    CheckBoxReverb->setWhatsThis(
+                     tr("<b>Reverberation Effect:</b> If this check box is checked, a "
+                        "reverberation effect is applied each time an audio drop-out occurs. "
+                        "With this effect it is possible to mask short drop-outs."));
+
+    /* Log File */
+    CheckBoxWriteLog->setWhatsThis(
+                     tr("<b>Log File:</b> Checking this box brings the "
+                        "Dream software to write a log file about the current reception. "
+                        "Every minute the average SNR, number of correct decoded FAC and "
+                        "number of correct decoded MSC blocks are logged including some "
+                        "additional information, e.g. the station label and bit-rate. The "
+                        "log mechanism works only for audio services using AAC source coding. "
+#ifdef _WIN32
+                        "During the logging no Dream windows "
+                        "should be moved or re-sized. This can lead to incorrect log files "
+                        "(problem with QT timer implementation under Windows). This problem "
+                        "does not exist in the Linux version of Dream."
+#endif
+                        "<br>The log file will be "
+                        "written in the directory were the Dream application was started and "
+                        "the name of this file is always DreamLog.txt"));
+
+    /* Wiener */
+    const QString strWienerChanEst =
+        tr("<b>Channel Estimation Settings:</b> With these "
+           "settings, the channel estimation method in time and frequency "
+           "direction can be selected. The default values use the most powerful "
+           "algorithms. For more detailed information about the estimation "
+           "algorithms there are a lot of papers and books available.<br>"
+           "<b>Wiener:</b> Wiener interpolation method "
+           "uses estimation of the statistics of the channel to design an optimal "
+           "filter for noise reduction.");
+
+    RadioButtonFreqWiener->setWhatsThis(strWienerChanEst);
+    RadioButtonTiWiener->setWhatsThis(strWienerChanEst);
+
+    /* Linear */
+    const QString strLinearChanEst =
+        tr("<b>Channel Estimation Settings:</b> With these "
+           "settings, the channel estimation method in time and frequency "
+           "direction can be selected. The default values use the most powerful "
+           "algorithms. For more detailed information about the estimation "
+           "algorithms there are a lot of papers and books available.<br>"
+           "<b>Linear:</b> Simple linear interpolation "
+           "method to get the channel estimate. The real and imaginary parts "
+           "of the estimated channel at the pilot positions are linearly "
+           "interpolated. This algorithm causes the lowest CPU load but "
+           "performs much worse than the Wiener interpolation at low SNRs.");
+
+    RadioButtonFreqLinear->setWhatsThis(strLinearChanEst);
+    RadioButtonTiLinear->setWhatsThis(strLinearChanEst);
+
+    /* DFT Zero Pad */
+    RadioButtonFreqDFT->setWhatsThis(
+                     tr("<b>Channel Estimation Settings:</b> With these "
+                        "settings, the channel estimation method in time and frequency "
+                        "direction can be selected. The default values use the most powerful "
+                        "algorithms. For more detailed information about the estimation "
+                        "algorithms there are a lot of papers and books available.<br>"
+                        "<b>DFT Zero Pad:</b> Channel estimation method "
+                        "for the frequency direction using Discrete Fourier Transformation "
+                        "(DFT) to transform the channel estimation at the pilot positions to "
+                        "the time domain. There, a zero padding is applied to get a higher "
+                        "resolution in the frequency domain -> estimates at the data cells. "
+                        "This algorithm is very speed efficient but has problems at the edges "
+                        "of the OFDM spectrum due to the leakage effect."));
+
+    /* Guard Energy */
+    RadioButtonTiSyncEnergy->setWhatsThis(
+                     tr("<b>Guard Energy:</b> Time synchronization "
+                        "tracking algorithm utilizes the estimation of the impulse response. "
+                        "This method tries to maximize the energy in the guard-interval to set "
+                        "the correct timing."));
+
+    /* First Peak */
+    RadioButtonTiSyncFirstPeak->setWhatsThis(
+                     tr("<b>First Peak:</b> This algorithms searches for "
+                        "the first peak in the estimated impulse response and moves this peak "
+                        "to the beginning of the guard-interval (timing tracking algorithm)."));
+
+    /* SNR */
+    const QString strSNREst =
+        tr("<b>SNR:</b> Signal to Noise Ratio (SNR) "
+           "estimation based on FAC cells. Since the FAC cells are only "
+           "located approximately in the region 0-5 kHz relative to the DRM DC "
+           "frequency, it may happen that the SNR value is very high "
+           "although the DRM spectrum on the left side of the DRM DC frequency "
+           "is heavily distorted or disturbed by an interferer so that the true "
+           "overall SNR is lower as indicated by the SNR value. Similarly, "
+           "the SNR value might show a very low value but audio can still be "
+           "decoded if only the right side of the DRM spectrum is degraded "
+           "by an interferer.");
+
+    ValueSNR->setWhatsThis(strSNREst);
+    TextSNRText->setWhatsThis(strSNREst);
+
+    /* MSC WMER / MSC MER */
+    const QString strMERWMEREst =
+        tr("<b>MSC WMER / MSC MER:</b> Modulation Error Ratio (MER) and "
+           "weighted MER (WMER) calculated on the MSC cells is shown. The MER is "
+           "calculated as follows: For each equalized MSC cell (only MSC cells, "
+           "no FAC cells, no SDC cells, no pilot cells), the error vector from "
+           "the nearest ideal point of the constellation diagram is measured. The "
+           "squared magnitude of this error is found, and a mean of the squared "
+           "errors is calculated (over one frame). The MER is the ratio in [dB] "
+           "of the mean of the squared magnitudes of the ideal points of the "
+           "constellation diagram to the mean squared error. This gives an "
+           "estimate of the ratio of the total signal power to total noise "
+           "power at the input to the equalizer for channels with flat frequency "
+           "response.<br> In case of the WMER, the calculations of the means are "
+           "multiplied by the squared magnitude of the estimated channel "
+           "response.<br>For more information see ETSI TS 102 349.");
+
+    ValueMERWMER->setWhatsThis(strMERWMEREst);
+    TextMERWMER->setWhatsThis(strMERWMEREst);
+
+    /* DRM Mode / Bandwidth */
+    const QString strRobustnessMode =
+        tr("<b>DRM Mode / Bandwidth:</b> In a DRM system, "
+           "four possible robustness modes are defined to adapt the system to "
+           "different channel conditions. According to the DRM standard:<ul>"
+           "<li><i>Mode A:</i> Gaussian channels, with "
+           "minor fading</li><li><i>Mode B:</i> Time "
+           "and frequency selective channels, with longer delay spread</li>"
+           "<li><i>Mode C:</i> As robustness mode B, but "
+           "with higher Doppler spread</li>"
+           "<li><i>Mode D:</i> As robustness mode B, but "
+           "with severe delay and Doppler spread</li></ul>The "
+           "bandwith is the gross bandwidth of the current DRM signal");
+
+    FACDRMModeBWL->setWhatsThis(strRobustnessMode);
+    FACDRMModeBWV->setWhatsThis(strRobustnessMode);
+
+    /* Interleaver Depth */
+    const QString strInterleaver =
+        tr("<b>Interleaver Depth:</b> The symbol "
+           "interleaver depth can be either short (approx. 400 ms) or long "
+           "(approx. 2 s). The longer the interleaver the better the channel "
+           "decoder can correct errors from slow fading signals. But the "
+           "longer the interleaver length the longer the delay until (after a "
+           "re-synchronization) audio can be heard.");
+
+    FACInterleaverDepthL->setWhatsThis(strInterleaver);
+    FACInterleaverDepthV->setWhatsThis(strInterleaver);
+
+    /* SDC / MSC Mode */
+    const QString strSDCMSCMode =
+        tr("<b>SDC / MSC Mode:</b> Shows the modulation "
+           "type of the SDC and MSC channel. For the MSC channel, some "
+           "hierarchical modes are defined which can provide a very strong "
+           "protected service channel.");
+
+    FACSDCMSCModeL->setWhatsThis(strSDCMSCMode);
+    FACSDCMSCModeV->setWhatsThis(strSDCMSCMode);
+
+    /* Prot. Level (B/A) */
+    const QString strProtLevel =
+        tr("<b>Prot. Level (B/A):</b> The error protection "
+           "level of the channel coder. For 64-QAM, there are four protection "
+           "levels defined in the DRM standard. Protection level 0 has the "
+           "highest protection whereas level 3 has the lowest protection. The "
+           "letters A and B are the names of the higher and lower protected parts "
+           "of a DRM block when Unequal Error Protection (UEP) is used. If Equal "
+           "Error Protection (EEP) is used, only the protection level of part B "
+           "is valid.");
+
+    FACCodeRateL->setWhatsThis(strProtLevel);
+    FACCodeRateV->setWhatsThis(strProtLevel);
+
+    /* Number of Services */
+    const QString strNumServices =
+        tr("<b>Number of Services:</b> This shows the "
+           "number of audio and data services transmitted in the DRM stream. "
+           "The maximum number of streams is four.");
+
+    FACNumServicesL->setWhatsThis(strNumServices);
+    FACNumServicesV->setWhatsThis(strNumServices);
+
+    /* Received time - date */
+    const QString strTimeDate =
+        tr("<b>Received time - date:</b> This label shows "
+           "the received time and date in UTC. This information is carried in "
+           "the SDC channel.");
+
+    FACTimeDateL->setWhatsThis(strTimeDate);
+    FACTimeDateV->setWhatsThis(strTimeDate);
+
+    /* Save audio as wave */
+    CheckBoxSaveAudioWave->setWhatsThis(
+                     tr("<b>Save Audio as WAV:</b> Save the audio signal "
+                        "as stereo, 16-bit, 48 kHz sample rate PCM wave file. Checking this "
+                        "box will let the user choose a file name for the recording."));
+
+    /* Interferer Rejection */
+    const QString strInterfRej =
+        tr("<b>Interferer Rejection:</b> There are two "
+           "algorithms available to reject interferers:<ul>"
+           "<li><b>Bandpass Filter (BP-Filter):</b>"
+           " The bandpass filter is designed to have the same bandwidth as "
+           "the DRM signal. If, e.g., a strong signal is close to the border "
+           "of the actual DRM signal, under some conditions this signal will "
+           "produce interference in the useful bandwidth of the DRM signal "
+           "although it is not on the same frequency as the DRM signal. "
+           "The reason for that behaviour lies in the way the OFDM "
+           "demodulation is done. Since OFDM demodulation is a block-wise "
+           "operation, a windowing has to be applied (which is rectangular "
+           "in case of OFDM). As a result, the spectrum of a signal is "
+           "convoluted with a Sinc function in the frequency domain. If a "
+           "sinusoidal signal close to the border of the DRM signal is "
+           "considered, its spectrum will not be a distinct peak but a "
+           "shifted Sinc function. So its spectrum is broadened caused by "
+           "the windowing. Thus, it will spread in the DRM spectrum and "
+           "act as an in-band interferer.<br>"
+           "There is a special case if the sinusoidal signal is in a "
+           "distance of a multiple of the carrier spacing of the DRM signal. "
+           "Since the Sinc function has zeros at certain positions it happens "
+           "that in this case the zeros are exactly at the sub-carrier "
+           "frequencies of the DRM signal. In this case, no interference takes "
+           "place. If the sinusoidal signal is in a distance of a multiple of "
+           "the carrier spacing plus half of the carrier spacing away from the "
+           "DRM signal, the interference reaches its maximum.<br>"
+           "As a result, if only one DRM signal is present in the 20 kHz "
+           "bandwidth, bandpass filtering has no effect. Also,  if the "
+           "interferer is far away from the DRM signal, filtering will not "
+           "give much improvement since the squared magnitude of the spectrum "
+           "of the Sinc function is approx -15 dB down at 1 1/2 carrier "
+           "spacing (approx 70 Hz with DRM mode B) and goes down to approx "
+           "-30 dB at 10 times the carrier spacing plus 1 / 2 of the carrier "
+           "spacing (approx 525 Hz with DRM mode B). The bandpass filter must "
+           "have very sharp edges otherwise the gain in performance will be "
+           "very small.</li>"
+           "<li><b>Modified Metrics:</b> Based on the "
+           "information from the SNR versus sub-carrier estimation, the metrics "
+           "for the Viterbi decoder can be modified so that sub-carriers with "
+           "high noise are attenuated and do not contribute too much to the "
+           "decoding result. That can improve reception under bad conditions but "
+           "may worsen the reception in situations where a lot of fading happens "
+           "and no interferer are present since the SNR estimation may be "
+           "not correct.</li></ul>");
+
+    GroupBoxInterfRej->setWhatsThis(strInterfRej);
+    CheckBoxRecFilter->setWhatsThis(strInterfRej);
+    CheckBoxModiMetric->setWhatsThis(strInterfRej);
+}
diff --git a/src/GUI-QT/EvaluationDlg.h b/src/GUI-QT/EvaluationDlg.h
new file mode 100644
index 0000000..aa8480b
--- /dev/null
+++ b/src/GUI-QT/EvaluationDlg.h
@@ -0,0 +1,119 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#ifndef __EVALUATIONDLG_H
+#define __EVALUATIONDLG_H
+
+#include "ui_systemevalDlgbase.h"
+#include "CWindow.h"
+#include "DRMPlot.h"
+#include "DialogUtil.h"
+#include "MultColorLED.h"
+#include "../GlobalDefinitions.h"
+#include "../util/Vector.h"
+#include "../DrmReceiver.h"
+
+/* Definitions ****************************************************************/
+/* Define this macro if you prefer the QT-type of displaying date and time */
+#define GUI_QT_DATE_TIME_TYPE
+
+
+/* Classes ********************************************************************/
+class ReceiverController;
+
+class systemevalDlg : public CWindow, public Ui_SystemEvaluationWindow
+{
+	Q_OBJECT
+
+public:
+    systemevalDlg(ReceiverController*, CSettings&, QWidget* parent = 0);
+	virtual ~systemevalDlg();
+    void            connectController(ReceiverController*);
+
+protected:
+    ReceiverController* controller;
+    CParameter&     Parameters;
+
+	QTimer			Timer;
+	CDRMPlot*		MainPlot;
+
+	virtual void	eventShow(QShowEvent* pEvent);
+	virtual void	eventHide(QHideEvent* pEvent);
+	void			UpdateGPS(CParameter&);
+    void			setControls(CSettings& s);
+    void			AddWhatsThisHelp();
+	CDRMPlot*		OpenChartWin(CDRMPlot::ECharType eNewType);
+	QTreeWidgetItem* FindItemByECharType(CDRMPlot::ECharType eCharType);
+	string			ECharTypeToPlotName(CDRMPlot::ECharType eCharType);
+	CDRMPlot::ECharType PlotNameToECharType(const string& PlotName);
+
+    QString			GetRobModeStr(ERobMode);
+    QString			GetSpecOccStr(ESpecOcc v);
+
+	QMenu*			pTreeWidgetContextMenu;
+	CDRMPlot::ECharType eCurCharType, eNewCharType;
+	int				iPlotStyle;
+	vector<CDRMPlot*>	vecpDRMPlots;
+
+public slots:
+	void OnTimer();
+	void OnRadioTimeLinear();
+	void OnRadioTimeWiener();
+	void OnRadioFrequencyLinear();
+	void OnRadioFrequencyDft();
+	void OnRadioFrequencyWiener();
+	void OnRadioTiSyncFirstPeak();
+	void OnRadioTiSyncEnergy();
+	void OnSliderIterChange(int value);
+	void OnCheckFlipSpectrum();
+	void OnCheckBoxMuteAudio();
+	void OnCheckBoxReverb();
+	void OnCheckWriteLog(int);
+	void OnCheckSaveAudioWAV();
+	void OnCheckRecFilter();
+	void OnCheckModiMetric();
+	void OnListSelChanged(QTreeWidgetItem*, QTreeWidgetItem*);
+	void OnTreeWidgetContMenu(bool);
+	void OnCustomContextMenuRequested(const QPoint&);
+	void UpdatePlotStyle(int);
+signals:
+	void startLogging();
+	void stopLogging();
+    void saveAudio(const string&);
+    void setTimeInt(int);
+    void setFreqInt(int);
+    void setTiSyncTracType(int);
+    void setNumMSCMLCIterations(int);
+    void setFlippedSpectrum(bool);
+    void setReverbEffect(bool);
+    void setRecFilter(bool);
+    void setIntCons(bool);
+    void muteAudio(bool);
+};
+
+#endif
diff --git a/src/GUI-QT/GeneralSettingsDlg.cpp b/src/GUI-QT/GeneralSettingsDlg.cpp
new file mode 100644
index 0000000..8237758
--- /dev/null
+++ b/src/GUI-QT/GeneralSettingsDlg.cpp
@@ -0,0 +1,330 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Andrea Russo
+ *
+ * Description:
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "DialogUtil.h"
+#include "GeneralSettingsDlg.h"
+#include <QLineEdit>
+#include <QPushButton>
+#include <QValidator>
+#include <QMessageBox>
+#include <QCheckBox>
+#include <QShowEvent>
+#include <QHideEvent>
+#include "ThemeCustomizer.h"
+
+/* Implementation *************************************************************/
+
+GeneralSettingsDlg::GeneralSettingsDlg(CSettings& NSettings, QWidget* parent) :
+    QDialog(parent),Settings(NSettings)
+{
+    setAttribute(Qt::WA_QuitOnClose, false);
+    setupUi(this);
+
+    /* Set the validators fro the receiver coordinate */
+    EdtLatitudeDegrees->setValidator(new QIntValidator(0, 90, EdtLatitudeDegrees));
+    EdtLongitudeDegrees->setValidator(new QIntValidator(0, 180, EdtLongitudeDegrees));
+
+    EdtLatitudeMinutes->setValidator(new QIntValidator(0, 59, EdtLatitudeMinutes));
+    EdtLongitudeMinutes->setValidator(new QIntValidator(0, 59, EdtLongitudeMinutes));
+
+    /* Set help text for the controls */
+    AddWhatsThisHelp();
+
+    APPLY_CUSTOM_THEME();
+}
+
+GeneralSettingsDlg::~GeneralSettingsDlg()
+{
+}
+
+void GeneralSettingsDlg::showEvent(QShowEvent*)
+{
+}
+
+void GeneralSettingsDlg::hideEvent(QHideEvent*)
+{
+}
+
+void GeneralSettingsDlg::onGPSd(const QString& s, bool checked)
+{
+    if(s!="")
+    {
+        QStringList l = s.split(":");
+        LineEditGPSHost->setText(l[0]);
+        LineEditGPSPort->setText(l[1]);
+        CheckBoxUseGPS->setChecked(checked);
+    }
+    else
+    {
+        LineEditGPSHost->setText("");
+        LineEditGPSPort->setText("");
+        CheckBoxUseGPS->setChecked(false);
+    }
+}
+
+void GeneralSettingsDlg::onPosition(double latitude, double longitude)
+{
+    QString sVal;
+
+    /* Extract latitude values */
+
+    if(latitude<0.0)
+    {
+        latitude = -latitude;
+        EdtLatitudeNS->setText("S");
+    }
+    else
+    {
+        EdtLatitudeNS->setText("N");
+    }
+
+    int degrees = int(latitude);
+    int minutes = int(((floor((latitude - degrees) * 1000000) / 1000000) + 0.00005) * 60.0);
+
+    /* Extract degrees */
+
+    /* Latitude degrees max 2 digits */
+    sVal = QString("%1").arg(degrees);
+
+    EdtLatitudeDegrees->setText(sVal);
+
+
+    sVal = QString("%1").arg(minutes);
+
+    EdtLatitudeMinutes->setText(sVal);
+
+    /* Extract longitude values */
+
+    if(longitude<0.0)
+    {
+        longitude = -longitude;
+        EdtLongitudeEW->setText("W");
+    }
+    else if(longitude>180.0)
+    {
+        longitude = 360.0-longitude;
+        EdtLongitudeEW->setText("E");
+    }
+    else
+    {
+        EdtLongitudeEW->setText("E");
+    }
+
+    /* Extract degrees */
+
+    degrees = int(longitude);
+    minutes = int(((floor((longitude - degrees) * 1000000) / 1000000) + 0.00005) * 60.0);
+
+    /* Longitude degrees max 3 digits */
+    sVal = QString("%1").arg(degrees);
+
+    EdtLongitudeDegrees->setText(sVal);
+
+    /* Extract minutes */
+    sVal = QString("%1").arg(minutes);
+
+    EdtLongitudeMinutes->setText(sVal);
+}
+
+void GeneralSettingsDlg::on_CheckBoxUseGPS_stateChanged(int s)
+{
+    if(s==0)
+        emit useGPSd("");
+}
+
+void GeneralSettingsDlg::on_buttonOk_clicked()
+{
+    _BOOLEAN bOK = TRUE;
+    _BOOLEAN bAllEmpty = TRUE;
+    _BOOLEAN bAllCompiled = FALSE;
+
+    /* Check the values and close the dialog */
+
+    if (ValidInput(EdtLatitudeDegrees) == FALSE)
+    {
+        bOK = FALSE;
+        QMessageBox::information(this, "Dream",
+                                 tr("Latitude value must be in the range 0 to 90")
+                                 ,QMessageBox::Ok);
+    }
+    else if (ValidInput(EdtLongitudeDegrees) == FALSE)
+    {
+        bOK = FALSE;
+
+        QMessageBox::information(this, "Dream",
+                                 tr("Longitude value must be in the range 0 to 180")
+                                 ,QMessageBox::Ok);
+    }
+    else if (ValidInput(EdtLongitudeMinutes) == FALSE
+             || ValidInput(EdtLatitudeMinutes) == FALSE)
+    {
+        bOK = FALSE;
+
+        QMessageBox::information(this, "Dream",
+                                 tr("Minutes value must be in the range 0 to 59")
+                                 ,QMessageBox::Ok);
+    }
+
+    if (bOK == TRUE)
+    {
+        /* Check if all coordinates are empty */
+
+        bAllEmpty = (EdtLongitudeDegrees->text()
+                     + EdtLongitudeMinutes->text()
+                     + EdtLongitudeEW->text()
+                     + EdtLatitudeDegrees->text()
+                     + EdtLatitudeMinutes->text()
+                     + EdtLatitudeNS->text()
+                    ) == "";
+
+        /* Check if all coordinates are compiled */
+
+        bAllCompiled = (EdtLongitudeDegrees->text() != "")
+                       && (EdtLongitudeMinutes->text() != "")
+                       && (EdtLongitudeEW->text() != "")
+                       && (EdtLatitudeDegrees->text() != "")
+                       && (EdtLatitudeMinutes->text() != "")
+                       && (EdtLatitudeNS->text() != "");
+
+        if (!bAllEmpty && !bAllCompiled)
+        {
+            bOK = FALSE;
+
+            QMessageBox::information(this, "Dream",
+                                     tr("Compile all fields on receiver coordinates")
+                                     ,QMessageBox::Ok);
+        }
+    }
+
+    if (bOK == TRUE)
+    {
+        /* save current settings */
+
+        if (!bAllEmpty)
+        {
+            double latitude, longitude;
+
+            latitude = EdtLatitudeDegrees->text().toDouble() + EdtLatitudeMinutes->text().toDouble()/60.0;
+            if(EdtLatitudeNS->text()[0]=='S' || EdtLatitudeNS->text()[0]=='s')
+                latitude = - latitude;
+
+            longitude = EdtLongitudeDegrees->text().toDouble() + EdtLongitudeMinutes->text().toDouble()/60.0;
+            if(EdtLongitudeEW->text()[0]=='W' || EdtLongitudeEW->text()[0]=='w')
+                longitude = - longitude;
+
+            emit position(latitude, longitude);
+        }
+
+        if(CheckBoxUseGPS->isChecked())
+        {
+            emit useGPSd(LineEditGPSHost->text()+":"+LineEditGPSPort->text());
+        }
+        else
+            emit useGPSd("");
+
+        accept(); /* If the values are valid close the dialog */
+    }
+}
+
+void GeneralSettingsDlg::on_EdtLatitudeNS_textChanged(const QString& NewText)
+{
+    /* Only S or N char are accepted */
+
+    const QString sVal = NewText.toUpper();
+
+    if (sVal != "S" && sVal != "N" && sVal != "")
+        EdtLatitudeNS->setText("");
+    else
+        EdtLatitudeNS->setText(sVal);
+}
+
+void GeneralSettingsDlg::on_EdtLongitudeEW_textChanged(const QString& NewText)
+{
+    /* Only E or W char are accepted */
+
+    const QString sVal = NewText.toUpper();
+
+    if (sVal != "E" && sVal != "W" && sVal != "")
+        EdtLongitudeEW->setText("");
+    else
+        EdtLongitudeEW->setText(sVal);
+}
+
+_BOOLEAN GeneralSettingsDlg::ValidInput(const QLineEdit* le)
+{
+    QString sText;
+
+    /* Use the validator for check if the value is valid */
+
+    sText = le->text();
+
+    if (sText == "")
+        return TRUE;
+    else
+    {
+        int iPosCursor = 0;
+        return le->validator()->validate(sText,iPosCursor) == QValidator::Acceptable;
+    }
+}
+
+QString GeneralSettingsDlg::ExtractDigits(const QString strStr, const int iStart
+        , const int iDigits)
+{
+    QString sVal;
+    QChar ch;
+    _BOOLEAN bStop;
+
+    /* Extract the first iDigits from position iStart */
+
+    sVal = "";
+    bStop = FALSE;
+
+    for (int i = iStart - 1 ; i <= iStart + iDigits - 1; i++)
+    {
+        if (bStop == FALSE)
+        {
+            ch = strStr.at(i);
+            if (ch.isDigit() == TRUE)
+                sVal = sVal + ch;
+            else
+                bStop = TRUE;
+        }
+    }
+    return sVal;
+}
+
+void GeneralSettingsDlg::AddWhatsThisHelp()
+{
+    QString str =
+        tr("<b>Receiver coordinates:</b> Are used on "
+           "Live Schedule Dialog to show a little green cube on the left"
+           " of the target column if the receiver coordinates (latitude and longitude)"
+           " are inside the target area of this transmission.<br>"
+           "Receiver coordinates are also saved into the Log file.");
+    setWhatsThis(str);
+}
+
diff --git a/src/GUI-QT/GeneralSettingsDlg.h b/src/GUI-QT/GeneralSettingsDlg.h
new file mode 100644
index 0000000..ddb306e
--- /dev/null
+++ b/src/GUI-QT/GeneralSettingsDlg.h
@@ -0,0 +1,73 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Andrea Russo
+ *
+ * Description:
+ *	
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later 
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT 
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#ifndef __GENERAL_SETTINGS_DLG_H
+#define __GENERAL_SETTINGS_DLG_H
+
+#include "../Parameter.h"
+#include "../util/Settings.h"
+
+#include <qglobal.h>
+#include <QDialog>
+#include "ui_GeneralSettingsDlgbase.h"
+
+/* Definitions ****************************************************************/
+
+/* Classes ********************************************************************/
+class GeneralSettingsDlg : public QDialog, public Ui_CGeneralSettingsDlgBase
+{
+	Q_OBJECT
+
+public:
+    GeneralSettingsDlg(CSettings& NSettings, QWidget* parent = 0);
+	virtual ~GeneralSettingsDlg();
+public slots:
+    void onPosition(double latitude, double longitude);
+    void onGPSd(const QString&, bool);
+
+protected:
+    void	showEvent(QShowEvent* pEvent);
+    void	hideEvent(QHideEvent* pEvent);
+
+	_BOOLEAN 	ValidInput(const QLineEdit* le);
+	QString 	ExtractDigits(const QString strS, const int iStart, const int iDigits);
+
+	void			AddWhatsThisHelp();
+	CSettings&		Settings;
+
+private slots:
+    void on_EdtLatitudeNS_textChanged(const QString&);
+    void on_EdtLongitudeEW_textChanged(const QString&);
+    void on_buttonOk_clicked();
+    void on_CheckBoxUseGPS_stateChanged(int);
+signals:
+    void useGPSd(const QString&);
+    void position(double, double);
+
+};
+
+#endif
diff --git a/src/GUI-QT/GeneralSettingsDlgbase.ui b/src/GUI-QT/GeneralSettingsDlgbase.ui
new file mode 100644
index 0000000..98c7fa2
--- /dev/null
+++ b/src/GUI-QT/GeneralSettingsDlgbase.ui
@@ -0,0 +1,523 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>CGeneralSettingsDlgBase</class>
+ <widget class="QDialog" name="CGeneralSettingsDlgBase">
+  <property name="windowModality">
+   <enum>Qt::ApplicationModal</enum>
+  </property>
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>269</width>
+    <height>259</height>
+   </rect>
+  </property>
+  <property name="sizePolicy">
+   <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+    <horstretch>0</horstretch>
+    <verstretch>0</verstretch>
+   </sizepolicy>
+  </property>
+  <property name="cursor">
+   <cursorShape>ArrowCursor</cursorShape>
+  </property>
+  <property name="windowTitle">
+   <string>General settings</string>
+  </property>
+  <property name="windowIcon">
+   <iconset resource="res/icons.qrc">
+    <normaloff>:/icons/MainIcon.svg</normaloff>:/icons/MainIcon.svg</iconset>
+  </property>
+  <property name="sizeGripEnabled">
+   <bool>true</bool>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout_3">
+   <item>
+    <widget class="QGroupBox" name="GroupReceiverCoord">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
+     </property>
+     <property name="minimumSize">
+      <size>
+       <width>0</width>
+       <height>0</height>
+      </size>
+     </property>
+     <property name="title">
+      <string>Default Receiver coordinates</string>
+     </property>
+     <layout class="QVBoxLayout" name="verticalLayout">
+      <item>
+       <layout class="QGridLayout" name="gridLayout">
+        <item row="0" column="0">
+         <widget class="QLabel" name="TextLatitude">
+          <property name="minimumSize">
+           <size>
+            <width>64</width>
+            <height>0</height>
+           </size>
+          </property>
+          <property name="text">
+           <string>Latitude</string>
+          </property>
+          <property name="wordWrap">
+           <bool>false</bool>
+          </property>
+         </widget>
+        </item>
+        <item row="0" column="1">
+         <widget class="QLineEdit" name="EdtLatitudeDegrees">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="maximumSize">
+           <size>
+            <width>32</width>
+            <height>32767</height>
+           </size>
+          </property>
+          <property name="text">
+           <string/>
+          </property>
+          <property name="maxLength">
+           <number>2</number>
+          </property>
+         </widget>
+        </item>
+        <item row="0" column="2">
+         <widget class="QLabel" name="TextDegLat">
+          <property name="font">
+           <font>
+            <pointsize>12</pointsize>
+           </font>
+          </property>
+          <property name="text">
+           <string>°</string>
+          </property>
+          <property name="wordWrap">
+           <bool>false</bool>
+          </property>
+         </widget>
+        </item>
+        <item row="0" column="3">
+         <widget class="QLineEdit" name="EdtLatitudeMinutes">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="maximumSize">
+           <size>
+            <width>32</width>
+            <height>32767</height>
+           </size>
+          </property>
+          <property name="text">
+           <string/>
+          </property>
+          <property name="maxLength">
+           <number>2</number>
+          </property>
+         </widget>
+        </item>
+        <item row="0" column="4">
+         <widget class="QLabel" name="TextMinutesLat">
+          <property name="font">
+           <font>
+            <pointsize>12</pointsize>
+           </font>
+          </property>
+          <property name="text">
+           <string>'</string>
+          </property>
+          <property name="wordWrap">
+           <bool>false</bool>
+          </property>
+         </widget>
+        </item>
+        <item row="0" column="5">
+         <widget class="QLineEdit" name="EdtLatitudeNS">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="maximumSize">
+           <size>
+            <width>24</width>
+            <height>32767</height>
+           </size>
+          </property>
+          <property name="text">
+           <string/>
+          </property>
+          <property name="maxLength">
+           <number>1</number>
+          </property>
+         </widget>
+        </item>
+        <item row="0" column="6">
+         <widget class="QLabel" name="TextNS">
+          <property name="minimumSize">
+           <size>
+            <width>0</width>
+            <height>0</height>
+           </size>
+          </property>
+          <property name="text">
+           <string>N/S</string>
+          </property>
+          <property name="wordWrap">
+           <bool>false</bool>
+          </property>
+         </widget>
+        </item>
+        <item row="0" column="7">
+         <spacer name="Spacer10_2">
+          <property name="orientation">
+           <enum>Qt::Horizontal</enum>
+          </property>
+          <property name="sizeType">
+           <enum>QSizePolicy::Expanding</enum>
+          </property>
+          <property name="sizeHint" stdset="0">
+           <size>
+            <width>13</width>
+            <height>22</height>
+           </size>
+          </property>
+         </spacer>
+        </item>
+        <item row="1" column="0">
+         <widget class="QLabel" name="TextLongitude">
+          <property name="minimumSize">
+           <size>
+            <width>64</width>
+            <height>0</height>
+           </size>
+          </property>
+          <property name="text">
+           <string>Longitude</string>
+          </property>
+          <property name="wordWrap">
+           <bool>false</bool>
+          </property>
+         </widget>
+        </item>
+        <item row="1" column="1">
+         <widget class="QLineEdit" name="EdtLongitudeDegrees">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="maximumSize">
+           <size>
+            <width>32</width>
+            <height>32767</height>
+           </size>
+          </property>
+          <property name="text">
+           <string/>
+          </property>
+          <property name="maxLength">
+           <number>3</number>
+          </property>
+         </widget>
+        </item>
+        <item row="1" column="2">
+         <widget class="QLabel" name="TextDegLong">
+          <property name="font">
+           <font>
+            <pointsize>12</pointsize>
+           </font>
+          </property>
+          <property name="text">
+           <string>°</string>
+          </property>
+          <property name="wordWrap">
+           <bool>false</bool>
+          </property>
+         </widget>
+        </item>
+        <item row="1" column="3">
+         <widget class="QLineEdit" name="EdtLongitudeMinutes">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="maximumSize">
+           <size>
+            <width>32</width>
+            <height>32767</height>
+           </size>
+          </property>
+          <property name="text">
+           <string/>
+          </property>
+          <property name="maxLength">
+           <number>2</number>
+          </property>
+         </widget>
+        </item>
+        <item row="1" column="4">
+         <widget class="QLabel" name="TextMinutesLong">
+          <property name="font">
+           <font>
+            <pointsize>12</pointsize>
+           </font>
+          </property>
+          <property name="text">
+           <string>'</string>
+          </property>
+          <property name="wordWrap">
+           <bool>false</bool>
+          </property>
+         </widget>
+        </item>
+        <item row="1" column="5">
+         <widget class="QLineEdit" name="EdtLongitudeEW">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="maximumSize">
+           <size>
+            <width>24</width>
+            <height>32767</height>
+           </size>
+          </property>
+          <property name="text">
+           <string/>
+          </property>
+          <property name="maxLength">
+           <number>1</number>
+          </property>
+         </widget>
+        </item>
+        <item row="1" column="6">
+         <widget class="QLabel" name="TextEW">
+          <property name="minimumSize">
+           <size>
+            <width>0</width>
+            <height>0</height>
+           </size>
+          </property>
+          <property name="text">
+           <string>E/W</string>
+          </property>
+          <property name="wordWrap">
+           <bool>false</bool>
+          </property>
+         </widget>
+        </item>
+        <item row="1" column="7">
+         <spacer name="Spacer10">
+          <property name="orientation">
+           <enum>Qt::Horizontal</enum>
+          </property>
+          <property name="sizeType">
+           <enum>QSizePolicy::Expanding</enum>
+          </property>
+          <property name="sizeHint" stdset="0">
+           <size>
+            <width>20</width>
+            <height>20</height>
+           </size>
+          </property>
+         </spacer>
+        </item>
+       </layout>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item>
+    <spacer name="verticalSpacer">
+     <property name="orientation">
+      <enum>Qt::Vertical</enum>
+     </property>
+     <property name="sizeHint" stdset="0">
+      <size>
+       <width>20</width>
+       <height>1</height>
+      </size>
+     </property>
+    </spacer>
+   </item>
+   <item>
+    <widget class="QGroupBox" name="GroupGPS">
+     <property name="title">
+      <string>GPS</string>
+     </property>
+     <layout class="QVBoxLayout" name="verticalLayout_2">
+      <item>
+       <layout class="QGridLayout">
+        <property name="margin">
+         <number>0</number>
+        </property>
+        <property name="spacing">
+         <number>6</number>
+        </property>
+        <item row="0" column="0">
+         <widget class="QCheckBox" name="CheckBoxUseGPS">
+          <property name="text">
+           <string>Use GPS</string>
+          </property>
+         </widget>
+        </item>
+        <item row="1" column="2">
+         <widget class="QLineEdit" name="LineEditGPSPort"/>
+        </item>
+        <item row="0" column="2">
+         <widget class="QLineEdit" name="LineEditGPSHost"/>
+        </item>
+        <item row="1" column="3">
+         <spacer name="Spacer6">
+          <property name="orientation">
+           <enum>Qt::Horizontal</enum>
+          </property>
+          <property name="sizeType">
+           <enum>QSizePolicy::Expanding</enum>
+          </property>
+          <property name="sizeHint" stdset="0">
+           <size>
+            <width>20</width>
+            <height>20</height>
+           </size>
+          </property>
+         </spacer>
+        </item>
+        <item row="1" column="0">
+         <spacer name="Spacer4">
+          <property name="orientation">
+           <enum>Qt::Horizontal</enum>
+          </property>
+          <property name="sizeType">
+           <enum>QSizePolicy::Expanding</enum>
+          </property>
+          <property name="sizeHint" stdset="0">
+           <size>
+            <width>20</width>
+            <height>20</height>
+           </size>
+          </property>
+         </spacer>
+        </item>
+        <item row="0" column="3">
+         <spacer name="Spacer5_2">
+          <property name="orientation">
+           <enum>Qt::Horizontal</enum>
+          </property>
+          <property name="sizeType">
+           <enum>QSizePolicy::Expanding</enum>
+          </property>
+          <property name="sizeHint" stdset="0">
+           <size>
+            <width>20</width>
+            <height>20</height>
+           </size>
+          </property>
+         </spacer>
+        </item>
+        <item row="0" column="1">
+         <widget class="QLabel" name="GPSHost">
+          <property name="text">
+           <string>Host</string>
+          </property>
+          <property name="wordWrap">
+           <bool>false</bool>
+          </property>
+         </widget>
+        </item>
+        <item row="1" column="1">
+         <widget class="QLabel" name="GPSPort">
+          <property name="text">
+           <string>Port</string>
+          </property>
+          <property name="wordWrap">
+           <bool>false</bool>
+          </property>
+         </widget>
+        </item>
+       </layout>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item>
+    <spacer name="verticalSpacer_2">
+     <property name="orientation">
+      <enum>Qt::Vertical</enum>
+     </property>
+     <property name="sizeHint" stdset="0">
+      <size>
+       <width>20</width>
+       <height>2</height>
+      </size>
+     </property>
+    </spacer>
+   </item>
+   <item>
+    <layout class="QHBoxLayout" name="horizontalLayout">
+     <item>
+      <spacer name="Spacer5">
+       <property name="orientation">
+        <enum>Qt::Horizontal</enum>
+       </property>
+       <property name="sizeType">
+        <enum>QSizePolicy::Expanding</enum>
+       </property>
+       <property name="sizeHint" stdset="0">
+        <size>
+         <width>20</width>
+         <height>20</height>
+        </size>
+       </property>
+      </spacer>
+     </item>
+     <item>
+      <widget class="QPushButton" name="buttonOk">
+       <property name="text">
+        <string>&OK</string>
+       </property>
+       <property name="autoDefault">
+        <bool>false</bool>
+       </property>
+       <property name="default">
+        <bool>true</bool>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
+  </layout>
+ </widget>
+ <tabstops>
+  <tabstop>EdtLatitudeDegrees</tabstop>
+  <tabstop>EdtLatitudeMinutes</tabstop>
+  <tabstop>EdtLatitudeNS</tabstop>
+  <tabstop>EdtLongitudeDegrees</tabstop>
+  <tabstop>EdtLongitudeMinutes</tabstop>
+  <tabstop>EdtLongitudeEW</tabstop>
+  <tabstop>buttonOk</tabstop>
+ </tabstops>
+ <resources>
+  <include location="res/icons.qrc"/>
+ </resources>
+ <connections/>
+</ui>
diff --git a/src/GUI-QT/JLViewer.cpp b/src/GUI-QT/JLViewer.cpp
new file mode 100644
index 0000000..aa1d6fb
--- /dev/null
+++ b/src/GUI-QT/JLViewer.cpp
@@ -0,0 +1,176 @@
+/******************************************************************************\
+ * British Broadcasting Corporation
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	 Julian Cable
+ *
+ * Description: Journaline Viewer
+ *
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "JLViewer.h"
+#include "jlbrowser.h"
+#include <../datadecoding/DataDecoder.h>
+#include <../util-QT/Util.h>
+#include <QFontDialog>
+#include "ThemeCustomizer.h"
+
+JLViewer::JLViewer(CSettings& Settings, QWidget* parent):
+    CWindow(parent, Settings, "Journaline")
+{
+    setupUi(this);
+
+    string p = Settings.Get(
+                "Receiver", "datafilesdirectory", string(DEFAULT_DATA_FILES_DIRECTORY));
+
+    strCurrentSavePath = QString::fromUtf8((p+PATH_SEPARATOR+"Journaline").c_str());
+
+    connect(buttonOk, SIGNAL(clicked()), this, SLOT(close()));
+    connect(actionClose, SIGNAL(triggered()), SLOT(close()));
+    connect(ButtonStepBack, SIGNAL(clicked()), textBrowser, SLOT(backward()));
+    connect(textBrowser, SIGNAL(backwardAvailable(bool)), ButtonStepBack, SLOT(setEnabled(bool)));
+
+    textBrowser->setDocument(&document);
+
+    /* Update time for color LED */
+    LEDStatus->SetUpdateTime(1000);
+
+    on_actionClear_All_triggered();
+
+    APPLY_CUSTOM_THEME();
+}
+
+JLViewer::~JLViewer()
+{
+}
+
+void JLViewer::setDecoder(CDataDecoder* dec)
+{
+    textBrowser->setDecoder(dec);
+}
+
+void JLViewer::setServiceInformation(const CService& service, uint32_t iAudioServiceID)
+{
+    /* Add the service description into the dialog caption */
+    QString strTitle = tr("Journaline");
+
+    if (service.IsActive())
+    {
+        /* Do UTF-8 to QString (UNICODE) conversion with the label strings */
+        QString strLabel = QString().fromUtf8(service.strLabel.c_str()).trimmed();
+
+        /* Service ID (plot number in hexadecimal format) */
+        QString strServiceID = "";
+
+        /* show the ID only if differ from the audio service */
+        if ((service.iServiceID != 0) && (service.iServiceID != iAudioServiceID))
+        {
+            if (strLabel != "")
+                strLabel += " ";
+
+            strServiceID = "- ID:" +
+                           QString().setNum(long(service.iServiceID), 16).toUpper();
+        }
+
+        /* add the description on the title of the dialog */
+        if (strLabel != "" || strServiceID != "")
+            strTitle += " [" + strLabel + strServiceID + "]";
+    }
+    setWindowTitle(strTitle);
+}
+
+void JLViewer::setStatus(int, ETypeRxStatus status)
+{
+    SetStatus(LEDStatus, status);
+
+    if(textBrowser->changed())
+    {
+        textBrowser->reload();
+    }
+}
+
+void JLViewer::eventShow(QShowEvent*)
+{
+    /* Store the default font */
+    QFont fontDefault = textBrowser->font();
+
+    /* Retrieve the font setting saved into the .ini file */
+    const QString strFontFamily = getSetting("fontfamily", QString());
+    if (strFontFamily != "")
+    {
+        QFont fontTextBrowser = QFont(strFontFamily,
+                                      getSetting("fontpointsize", 0),
+                                      getSetting("fontweight", 0),
+                                      getSetting("fontitalic", false));
+        textBrowser->setFont(fontTextBrowser);
+    }
+
+    textBrowser->setSource(QUrl("0"));
+}
+
+void JLViewer::eventHide(QHideEvent*)
+{
+    /* Store current textBrowser font */
+    QFont fontTextBrowser = textBrowser->currentFont();
+    putSetting("fontfamily", fontTextBrowser.family());
+    putSetting("fontpointsize", fontTextBrowser.pointSize());
+    putSetting("fontweight", fontTextBrowser.weight());
+    putSetting("fontitalic", fontTextBrowser.italic());
+}
+
+void JLViewer::on_actionSave_triggered()
+{
+}
+
+void JLViewer::on_actionSave_All_triggered()
+{
+}
+
+void JLViewer::on_actionClear_All_triggered()
+{
+    actionClear_All->setEnabled(false);
+    actionSave->setEnabled(false);
+    actionSave_All->setEnabled(false);
+    ButtonStepBack->setEnabled(false);
+    textBrowser->clear();
+    textBrowser->clearHistory();
+    // TODO - clear JL object cache ?
+}
+
+void JLViewer::on_actionSet_Font_triggered()
+{
+    bool bok;
+
+    /* Open the font dialog */
+    QFont newFont = QFontDialog::getFont(&bok, textBrowser->currentFont(), this);
+
+    if (bok == true)
+    {
+        /* Store the current text and then reset it */
+        QString strOldText = textBrowser->toHtml();
+        textBrowser->setText("<br>");
+
+        textBrowser->setFont(newFont);
+
+        /* Restore the text to refresh it with the new font */
+        textBrowser->setText(strOldText);
+    }
+}
diff --git a/src/GUI-QT/JLViewer.h b/src/GUI-QT/JLViewer.h
new file mode 100644
index 0000000..ed38d47
--- /dev/null
+++ b/src/GUI-QT/JLViewer.h
@@ -0,0 +1,63 @@
+/******************************************************************************\
+ * British Broadcasting Corporation
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	 Julian Cable
+ *
+ * Description: Journaline Viewer
+ *
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#ifndef _JLVIEWER_H
+#define _JLVIEWER_H
+
+#include "ui_JLViewer.h"
+#include "CWindow.h"
+#include "../Parameter.h"
+#include <QTextDocument>
+#include <string>
+
+class JLViewer : public CWindow, public Ui_JLViewer
+{
+    Q_OBJECT
+
+public:
+    JLViewer(CSettings&, QWidget* parent = 0);
+    ~JLViewer();
+public slots:
+    void setStatus(int, ETypeRxStatus);
+    void setDecoder(CDataDecoder* dec);
+    void setServiceInformation(const CService&, uint32_t);
+
+protected:
+    virtual void eventShow(QShowEvent*);
+    virtual void eventHide(QHideEvent*);
+    QTextDocument document;
+    QString       strCurrentSavePath;
+
+private slots:
+    void on_actionSave_triggered();
+    void on_actionSave_All_triggered();
+    void on_actionClear_All_triggered();
+    void on_actionSet_Font_triggered();
+};
+
+#endif
diff --git a/src/GUI-QT/JLViewer.ui b/src/GUI-QT/JLViewer.ui
new file mode 100644
index 0000000..76898a7
--- /dev/null
+++ b/src/GUI-QT/JLViewer.ui
@@ -0,0 +1,194 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>JLViewer</class>
+ <widget class="QMainWindow" name="JLViewer">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>531</width>
+    <height>485</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>MainWindow</string>
+  </property>
+  <property name="windowIcon">
+   <iconset resource="res/icons.qrc">
+    <normaloff>:/icons/MainIcon.svg</normaloff>:/icons/MainIcon.svg</iconset>
+  </property>
+  <widget class="QWidget" name="centralwidget">
+   <layout class="QVBoxLayout" name="verticalLayout">
+    <item>
+     <widget class="JLBrowser" name="textBrowser"/>
+    </item>
+    <item>
+     <layout class="QHBoxLayout" name="_2">
+      <property name="spacing">
+       <number>6</number>
+      </property>
+      <property name="margin">
+       <number>0</number>
+      </property>
+      <item>
+       <widget class="QLabel" name="TextLabel1">
+        <property name="text">
+         <string>Receiving Status:</string>
+        </property>
+        <property name="wordWrap">
+         <bool>false</bool>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="CMultColorLED" name="LEDStatus" native="true">
+        <property name="minimumSize">
+         <size>
+          <width>13</width>
+          <height>13</height>
+         </size>
+        </property>
+        <property name="maximumSize">
+         <size>
+          <width>13</width>
+          <height>13</height>
+         </size>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <spacer name="horizontalSpacer">
+        <property name="orientation">
+         <enum>Qt::Horizontal</enum>
+        </property>
+        <property name="sizeHint" stdset="0">
+         <size>
+          <width>40</width>
+          <height>20</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+      <item>
+       <widget class="QToolButton" name="ButtonStepBack">
+        <property name="text">
+         <string/>
+        </property>
+        <property name="icon">
+         <iconset resource="res/icons.qrc">
+          <normaloff>:/icons/StepBack.png</normaloff>:/icons/StepBack.png</iconset>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <spacer name="Spacer5_2">
+        <property name="orientation">
+         <enum>Qt::Horizontal</enum>
+        </property>
+        <property name="sizeType">
+         <enum>QSizePolicy::Expanding</enum>
+        </property>
+        <property name="sizeHint" stdset="0">
+         <size>
+          <width>20</width>
+          <height>20</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+      <item>
+       <widget class="QPushButton" name="pushButtonClearCache">
+        <property name="text">
+         <string>Cl&ear Cache</string>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QPushButton" name="buttonOk">
+        <property name="text">
+         <string>&Close</string>
+        </property>
+        <property name="autoDefault">
+         <bool>true</bool>
+        </property>
+        <property name="default">
+         <bool>true</bool>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </item>
+   </layout>
+  </widget>
+  <widget class="QMenuBar" name="menubar">
+   <property name="geometry">
+    <rect>
+     <x>0</x>
+     <y>0</y>
+     <width>531</width>
+     <height>25</height>
+    </rect>
+   </property>
+   <widget class="QMenu" name="menuFile">
+    <property name="title">
+     <string>&File</string>
+    </property>
+    <addaction name="actionClear_All"/>
+    <addaction name="separator"/>
+    <addaction name="actionSave"/>
+    <addaction name="actionSave_All"/>
+    <addaction name="separator"/>
+    <addaction name="actionClose"/>
+   </widget>
+   <widget class="QMenu" name="menuSettings">
+    <property name="title">
+     <string>&Settings</string>
+    </property>
+    <addaction name="actionSet_Font"/>
+   </widget>
+   <addaction name="menuFile"/>
+   <addaction name="menuSettings"/>
+  </widget>
+  <action name="actionSet_Font">
+   <property name="text">
+    <string>Set  &Font...</string>
+   </property>
+  </action>
+  <action name="actionClear_All">
+   <property name="text">
+    <string>Cl&ear Cache</string>
+   </property>
+  </action>
+  <action name="actionSave">
+   <property name="text">
+    <string>Save...</string>
+   </property>
+  </action>
+  <action name="actionSave_All">
+   <property name="text">
+    <string>Save All...</string>
+   </property>
+  </action>
+  <action name="actionClose">
+   <property name="text">
+    <string>&Close</string>
+   </property>
+  </action>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>CMultColorLED</class>
+   <extends>QWidget</extends>
+   <header>MultColorLED.h</header>
+  </customwidget>
+  <customwidget>
+   <class>JLBrowser</class>
+   <extends>QTextBrowser</extends>
+   <header>jlbrowser.h</header>
+  </customwidget>
+ </customwidgets>
+ <resources>
+  <include location="res/icons.qrc"/>
+ </resources>
+ <connections/>
+</ui>
diff --git a/src/GUI-QT/LiveScheduleDlg.cpp b/src/GUI-QT/LiveScheduleDlg.cpp
new file mode 100644
index 0000000..1353d7d
--- /dev/null
+++ b/src/GUI-QT/LiveScheduleDlg.cpp
@@ -0,0 +1,1001 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2005
+ *
+ * Author(s):
+ *	Andrea Russo
+ *
+ * Description:
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "LiveScheduleDlg.h"
+#include <QFile>
+#include <QDir>
+#include <QFileDialog>
+#include <QTextStream>
+#include <QDateTime>
+#include <QHideEvent>
+#include <QShowEvent>
+#include "../util-QT/Util.h"
+#include "ThemeCustomizer.h"
+
+#define UTF8_DEGREE_SIGN "\xc2\xb0"
+
+/* Implementation *************************************************************/
+
+QString
+LiveScheduleDlg::ExtractTime(const CAltFreqSched& schedule)
+{
+    int iTimeStart = schedule.iStartTime;
+    int iDuration = schedule.iDuration;
+    QString sDays = "";
+    QString sResult = "";
+
+    if ((iTimeStart == 0) && (iDuration == 0))
+        return sResult;
+
+    /* Start time */
+    int iStartMinutes = iTimeStart % 60;
+    int iStartHours = iTimeStart / 60;
+
+    /* Stop time */
+    _BOOLEAN bAllWeek24Hours = FALSE;
+    const int iTimeStop = iTimeStart + iDuration;
+
+    int iStopMinutes = iTimeStop % 60;
+    int iStopHours = iTimeStop / 60;
+
+    if (iStopHours > 24)
+    {
+        int iDays = iStopHours / 24;
+
+        if (iDays == 7)
+            /* All the week */
+            bAllWeek24Hours = TRUE;
+        else
+        {
+            /* Add information about days duration */
+            if (iDays > 1)
+                sDays.sprintf(" (%d days)", iDays);
+            iStopHours = iStopHours % 24;
+        }
+    }
+
+    if (bAllWeek24Hours == TRUE)
+        sResult = "24 hours, 7 days a week";
+    else
+    {
+        sResult.sprintf("%02d:%02d-%02d:%02d", iStartHours, iStartMinutes, iStopHours, iStopMinutes);
+        sResult += sDays;
+    }
+
+    return sResult;
+}
+
+QString
+LiveScheduleDlg::ExtractDaysFlagString(const int iDayCode)
+{
+    string strDaysFlags = "0000000";
+    for (int i = 0; i < 7; i++)
+    {
+        if ((1 << (6 - i)) & iDayCode)
+            strDaysFlags[i]++;
+    }
+
+    /* Init days string vector */
+    const QString strDayDef[] = {
+        QObject::tr("Mon"),
+        QObject::tr("Tue"),
+        QObject::tr("Wed"),
+        QObject::tr("Thu"),
+        QObject::tr("Fri"),
+        QObject::tr("Sat"),
+        QObject::tr("Sun")
+    };
+
+    QString strDaysShow = "";
+    /* First test for day constellations which allow to apply special names */
+    /* 1111111 = Mon Tue Wed Thu Fri Sat Sun = 1234567 (1 = Monday, 7 = Sunday) */
+    if (strDaysFlags == "1111111")
+        strDaysShow = QObject::tr("daily");
+    else if (strDaysFlags == "1111100")
+        strDaysShow = QObject::tr("from Mon to Fri");
+    else if (strDaysFlags == "1111110")
+        strDaysShow = QObject::tr("from Mon to Sat");
+    else
+    {
+        /* No special name could be applied, just list all active days */
+        for (size_t i = 0; i < 7; i++)
+        {
+            /* Check if day is active */
+            if (strDaysFlags[i] == CHR_ACTIVE_DAY_MARKER)
+            {
+                /* Set commas in between the days, to not set a comma at
+                   the beginning */
+                if (strDaysShow != "")
+                    strDaysShow += ",";
+
+                /* Add current day */
+                strDaysShow += strDayDef[i];
+            }
+        }
+    }
+    return strDaysShow;
+}
+
+void
+CDRMLiveSchedule::SetReceiverCoordinates(double latitude, double longitude)
+{
+    dReceiverLatitude = latitude;
+    dReceiverLongitude = longitude;
+}
+
+void
+CDRMLiveSchedule::DecodeTargets(const vector < CAltFreqRegion >
+                                vecRegions, string & strRegions,
+                                _BOOLEAN & bIntoTargetArea)
+{
+    int iCIRAF;
+    int iReceiverLatitude = int (dReceiverLatitude);
+    int iReceiverLongitude = int (dReceiverLongitude);
+    stringstream ssRegions;
+
+    bIntoTargetArea = FALSE;
+
+    for(size_t i = 0; i < vecRegions.size(); i++)
+    {
+        const int iLatitude = vecRegions[i].iLatitude;
+        const int iLongitude = vecRegions[i].iLongitude;
+
+        const int iLatitudeEx = vecRegions[i].iLatitudeEx;
+        const int iLongitudeEx = vecRegions[i].iLongitudeEx;
+
+        size_t iCIRAFSize = vecRegions[i].veciCIRAFZones.size();
+
+        if (iCIRAFSize > 0)
+        {
+            /* Targets */
+            for (size_t j = 0; j < iCIRAFSize; j++)
+            {
+                iCIRAF = vecRegions[i].veciCIRAFZones[j];
+
+                if (ssRegions.str() != "")
+                    ssRegions << ", ";
+
+                ssRegions << strTableCIRAFzones[iCIRAF];
+            }
+        }
+        else
+        {
+            /* if ciraf zones aren't defined show the latitude and
+             * longitude of the centre of the target area */
+
+            if (ssRegions.str() != "")
+                ssRegions << ", ";
+
+            int iLatitudeMed = (iLatitude + (iLatitudeEx / 2));
+
+            ssRegions << "latitude " << abs(iLatitudeMed) << UTF8_DEGREE_SIGN " ";
+
+            if (iLatitudeMed < 0)
+                ssRegions << 'S';
+            else
+                ssRegions << 'N';
+
+            int iLongitudeMed = (iLongitude + (iLongitudeEx / 2));
+
+            if (iLongitudeMed >= 180)
+                iLongitudeMed = iLongitudeMed - 360;
+
+            ssRegions << " longitude " << abs(iLongitudeMed) << UTF8_DEGREE_SIGN " ";
+
+            if (iLongitudeMed < 0)
+                ssRegions << 'W';
+            else
+                ssRegions << 'E';
+
+        }
+        /* check if receiver coordinates are inside target area
+         * TODO check if inside CIRAF zones */
+        _BOOLEAN bLongitudeOK = ((iReceiverLongitude >= iLongitude)
+                                 && (iReceiverLongitude <=
+                                     (iLongitude + iLongitudeEx)))
+                                || (((iLongitude + iLongitudeEx) >= 180)
+                                    && (iReceiverLongitude <=
+                                        (iLongitude + iLongitudeEx - 360)));
+
+        _BOOLEAN bLatitudeOK = ((iReceiverLatitude >= iLatitude)
+                                && (iReceiverLatitude <=
+                                    (iLatitude + iLatitudeEx)));
+
+        bIntoTargetArea = bIntoTargetArea || (bLongitudeOK && bLatitudeOK);
+    }
+    strRegions = ssRegions.str();
+}
+
+void
+CDRMLiveSchedule::LoadServiceDefinition(const CServiceDefinition& service,
+                                        const CAltFreqSign& AltFreqSign, const uint32_t iServiceID)
+{
+    string strRegions = "";
+    _BOOLEAN bIntoTargetArea = FALSE;
+
+    /* Region */
+    if (service.iRegionID != 0)
+        DecodeTargets(AltFreqSign.vecRegions[service.iRegionID], strRegions, bIntoTargetArea);
+
+    /* For all frequencies */
+    for (size_t j = 0; j < service.veciFrequencies.size(); j++)
+    {
+        if (service.iScheduleID > 0)
+        {
+            const vector<CAltFreqSched>& vecSchedules = AltFreqSign.vecSchedules[service.iScheduleID];
+            for (size_t k = 0; k < vecSchedules.size(); k++)
+            {
+                CLiveScheduleItem LiveScheduleItem;
+
+                /* Frequency */
+                LiveScheduleItem.strFreq = service.Frequency(j);
+
+                /* Add the target */
+                LiveScheduleItem.strTarget = strRegions;
+
+                /* Add the schedule */
+                LiveScheduleItem.Schedule = vecSchedules[k];
+
+                /* Local receiver coordinates are into target area or not */
+                LiveScheduleItem.bInsideTargetArea = bIntoTargetArea;
+
+                /* Add the system (transmission mode) */
+                LiveScheduleItem.strSystem = service.System();
+
+                /* Add the Service ID - 0 for DRM Muxes, ID of the Other Service if present */
+                LiveScheduleItem.iServiceID = iServiceID;
+
+                /* Add new item in table */
+                StationsTable.push_back(LiveScheduleItem);
+            }
+        }
+        else
+        {
+            CLiveScheduleItem LiveScheduleItem;
+
+            /* Frequency */
+            LiveScheduleItem.strFreq = service.Frequency(j);
+
+            /* Add the target */
+            LiveScheduleItem.strTarget = strRegions;
+
+            /* Local receiver coordinates are into target area or not */
+            LiveScheduleItem.bInsideTargetArea = bIntoTargetArea;
+
+            /* Add the system (transmission mode) */
+            LiveScheduleItem.strSystem = service.System();
+
+            /* Add the Service ID - 0 for DRM Muxes, ID of the Other Service if present */
+            LiveScheduleItem.iServiceID = iServiceID;
+
+            /* Add new item in table */
+            StationsTable.push_back(LiveScheduleItem);
+        }
+    }
+}
+
+void
+CDRMLiveSchedule::LoadAFSInformation(const CAltFreqSign& AltFreqSign)
+{
+    size_t i;
+
+    /* Init table for stations */
+    StationsTable.clear();
+
+    /* Add AFS information for DRM multiplexes */
+    for (i = 0; i < AltFreqSign.vecMultiplexes.size(); i++)
+    {
+        /* TODO multiplex and restrictions */
+        //service.bIsSyncMultplx;
+
+        //for ( k = 0; k < 4; k++)
+        //  service.veciServRestrict[k];
+
+        LoadServiceDefinition(AltFreqSign.vecMultiplexes[i], AltFreqSign);
+    }
+
+    /* Add AFS information for Other Services */
+    for (i = 0; i < AltFreqSign.vecOtherServices.size(); i++)
+    {
+        COtherService OtherService = AltFreqSign.vecOtherServices[i];
+
+        /* TODO same service */
+        //OtherService.bSameService;
+
+        LoadServiceDefinition(OtherService, AltFreqSign, OtherService.iServiceID);
+    }
+}
+
+LiveScheduleDlg::LiveScheduleDlg(CSettings& Settings,
+                                 QMap<QWidget*,QString>& parents):
+    CWindow(parents, Settings, "Live Schedule"),
+    smallGreenCube(":/icons/smallGreenCube.png"),
+    greenCube(":/icons/greenCube.png"), redCube(":/icons/redCube.png"),
+    orangeCube(":/icons/orangeCube.png"), pinkCube(":/icons/pinkCube.png"),
+    vecpListItems(), iColStationID(1), iWidthColStationID(0), bDisableFrequencyChange(false),
+    serviceInformation()
+{
+    setupUi(this);
+
+    /* Load settings */
+    LoadSettings();
+
+    /* Set help text for the controls */
+    AddWhatsThisHelp();
+
+    /* Clear list box for file names and set up columns */
+    ListViewStations->clear();
+	ListViewStations->setSortingEnabled(true);
+
+    connect(actionSave,  SIGNAL(triggered()), this, SLOT(OnSave()));
+
+    previewMapper = new QSignalMapper(this);
+    previewGroup = new QActionGroup(this);
+    showMapper = new QSignalMapper(this);
+    showGroup = new QActionGroup(this);
+    showGroup->addAction(actionShowOnlyActiveStations);
+    showMapper->setMapping(actionShowOnlyActiveStations, 0);
+    showGroup->addAction(actionShowAllStations);
+    showMapper->setMapping(actionShowAllStations, 1);
+    connect(actionClose, SIGNAL(triggered()), SLOT(close()));
+    connect(actionShowAllStations, SIGNAL(triggered()), showMapper, SLOT(map()));
+    connect(actionShowOnlyActiveStations, SIGNAL(triggered()), showMapper, SLOT(map()));
+    connect(showMapper, SIGNAL(mapped(int)), this, SLOT(OnShowStationsMenu(int)));
+    previewGroup->addAction(actionDisabled);
+    previewMapper->setMapping(actionDisabled, 0);
+    previewGroup->addAction(action5minutes);
+    previewMapper->setMapping(action5minutes, NUM_SECONDS_PREV_5MIN);
+    previewGroup->addAction(action15minutes);
+    previewMapper->setMapping(action15minutes, NUM_SECONDS_PREV_15MIN);
+    previewGroup->addAction(action30minutes);
+    previewMapper->setMapping(action30minutes, NUM_SECONDS_PREV_30MIN);
+    connect(actionDisabled, SIGNAL(triggered()), previewMapper, SLOT(map()));
+    connect(action5minutes, SIGNAL(triggered()), previewMapper, SLOT(map()));
+    connect(action15minutes, SIGNAL(triggered()), previewMapper, SLOT(map()));
+    connect(action30minutes, SIGNAL(triggered()), previewMapper, SLOT(map()));
+    connect(previewMapper, SIGNAL(mapped(int)), this, SLOT(OnShowPreviewMenu(int)));
+    connect(ListViewStations->header(), SIGNAL(sectionClicked(int)), this, SLOT(OnHeaderClicked(int)));
+
+    connect(buttonOk,  SIGNAL(clicked()), this, SLOT(close()));
+    //connect(actionGetUpdate, SIGNAL(triggered()), this, SLOT(OnGetUpdate()));
+
+    /* Connections ---------------------------------------------------------- */
+    connect(&TimerList, SIGNAL(timeout()), this, SLOT(OnTimerList()));
+    connect(&TimerUTCLabel, SIGNAL(timeout()), this, SLOT(OnTimerUTCLabel()));
+
+    /* Check boxes */
+    connect(CheckBoxFreeze, SIGNAL(clicked()), this, SLOT(OnCheckFreeze()));
+
+    /* Init UTC time shown with a label control */
+    OnTimerUTCLabel();
+
+    APPLY_CUSTOM_THEME();
+}
+
+LiveScheduleDlg::~LiveScheduleDlg()
+{
+}
+
+void LiveScheduleDlg::setLocation(double lat, double lng)
+{
+    DRMSchedule.SetReceiverCoordinates(lat, lng);
+}
+
+void LiveScheduleDlg::setAFS(const CAltFreqSign& altFreqSign)
+{
+    DRMSchedule.LoadAFSInformation(altFreqSign);
+}
+
+void LiveScheduleDlg::setServiceInformation(const map <uint32_t,CServiceInformation> si)
+{
+    serviceInformation = si;
+}
+
+void LiveScheduleDlg::setService(int, const CService& service)
+{
+    if(service.IsActive())
+    {
+        strStationName = QString::fromUtf8(service.strLabel.c_str());
+    }
+}
+
+void LiveScheduleDlg::setFrequency(int f)
+{
+    if (f > 30000)
+        labelFrequency->setText(QString::number((double)f / 1000) + tr(" MHz"));
+    else
+        labelFrequency->setText(QString::number(f) + tr(" kHz"));
+}
+
+void
+LiveScheduleDlg::LoadSettings()
+{
+    // save path
+
+    string sDataFilesDirectory = Settings.Get(
+                "Receiver", "datafilesdirectory", string(DEFAULT_DATA_FILES_DIRECTORY));
+    strCurrentSavePath = QString::fromUtf8(sDataFilesDirectory.c_str());
+
+    /* and make sure it exists */
+    CreateDirectories(strCurrentSavePath);
+
+    /* Set sorting behaviour of the list */
+    iCurrentSortColumn = getSetting("sortcolumn", 0);
+    bCurrentSortAscending = getSetting("sortascending", true);
+    ListViewStations->sortItems(iCurrentSortColumn, bCurrentSortAscending?Qt::AscendingOrder:Qt::DescendingOrder);
+
+    /* Set column order and size settings */
+    QString strColumnParam = getSetting("columnparam", QString());
+    ColumnParamFromStr(ListViewStations, strColumnParam);
+
+    /* Get station id column width */
+    iWidthColStationID = ListViewStations->columnWidth(iColStationID);
+
+    /* Set stations in list view which are active right now */
+    bool bShowAll = getSetting("showall", false);
+    int iPrevSecs = getSetting("preview", 0);
+
+    if(bShowAll)
+        actionShowAllStations->setChecked(true);
+    else
+        actionShowOnlyActiveStations->setChecked(true);
+    DRMSchedule.SetSecondsPreview(iPrevSecs);
+    switch (iPrevSecs)
+    {
+    case NUM_SECONDS_PREV_5MIN:
+        action5minutes->setChecked(true);
+        break;
+
+    case NUM_SECONDS_PREV_15MIN:
+        action5minutes->setChecked(true);
+        break;
+
+    case NUM_SECONDS_PREV_30MIN:
+        action30minutes->setChecked(true);
+        break;
+
+    default: /* case 0, also takes care of out of value parameters */
+        actionDisabled->setChecked(true);
+        break;
+    }
+}
+
+void
+LiveScheduleDlg::SaveSettings()
+{
+    /* Store preview settings */
+    putSetting("preview", DRMSchedule.GetSecondsPreview());
+
+    /* Store sort settings */
+    putSetting("sortcolumn", iCurrentSortColumn);
+    putSetting("sortascending", bCurrentSortAscending);
+
+    /* Restore station id column width */
+    ListViewStations->setColumnWidth(iColStationID, iWidthColStationID);
+
+    /* Store column order and size settings */
+    QString strColumnParam;
+    ColumnParamToStr(ListViewStations, strColumnParam);
+    putSetting("columnparam", strColumnParam);
+
+    /* Store preview settings */
+    putSetting("showall", showAll());
+}
+
+void
+LiveScheduleDlg::OnCheckFreeze()
+{
+    /* if CheckBoxFreeze is checked the schedule is frozen */
+    if (CheckBoxFreeze->isChecked())
+        TimerList.stop();
+    else
+    {
+        OnTimerList();
+        TimerList.start(GUI_TIMER_LIST_VIEW_UPDATE);	/* Stations list */
+    }
+}
+
+int LiveScheduleDlg::currentSortColumn()
+{
+	return ListViewStations->sortColumn();
+}
+
+bool LiveScheduleDlg::showAll()
+{
+	return actionShowAllStations->isChecked();
+}
+
+void
+LiveScheduleDlg::OnTimerUTCLabel()
+{
+    /* Get current UTC time */
+    time_t ltime;
+    time(&ltime);
+    struct tm *gmtCur = gmtime(&ltime);
+
+    /* Generate time in format "UTC 12:00" */
+    QString strUTCTime = QString().sprintf("%02d:%02d UTC",
+                                           gmtCur->tm_hour, gmtCur->tm_min);
+
+    /* Only apply if time label does not show the correct time */
+    if (TextLabelUTCTime->text().compare(strUTCTime))
+        TextLabelUTCTime->setText(strUTCTime);
+}
+
+void
+LiveScheduleDlg::OnShowStationsMenu(int iID)
+{
+    /* Update list view */
+    SetStationsView();
+    (void)iID;
+}
+
+void
+LiveScheduleDlg::OnShowPreviewMenu(int iID)
+{
+    DRMSchedule.SetSecondsPreview(iID);
+}
+
+void
+LiveScheduleDlg::OnTimerList()
+{
+    /* Update schedule and list view */
+    LoadSchedule();
+}
+
+QString
+MyListLiveViewItem::key(int column, bool ascending) const
+{
+    /* Reimplement "key()" function to get correct sorting behaviour */
+
+    const float fFreq = text(column).toFloat();
+
+    if (column == COL_FREQ)
+    {
+        /* These columns are filled with numbers. Some items may have numbers
+           after the decimal, therefore multiply with 10000 (which moves the
+           numbers in front of the comma). Afterwards append zeros at the
+           beginning so that positive integer numbers are sorted correctly */
+        return QString().setNum(long(fFreq * 10000.0)).rightJustified(20, '0');
+    }
+    else
+    {
+        /* is a text column */
+        /* sort the column and then sort for frequency */
+        float d = 0.0;
+
+        if (!ascending)
+            d = 100000.0;
+
+	const QString sFreq = QString().setNum(long((fFreq - d) * 10000.0)).rightJustified(20, '0');
+        return text(column).toLower() + "|" + sFreq;
+    }
+}
+
+void
+LiveScheduleDlg::LoadSchedule()
+{
+    bDisableFrequencyChange = true;
+
+    /* Lock mutex for modifying the vecpListItems */
+    ListItemsMutex.lock();
+
+    /* Get selected item */
+    CLiveScheduleItem liveScheduleItem;
+    QList<QTreeWidgetItem *> items =  ListViewStations->selectedItems();
+    if (items.size() == 1)
+        liveScheduleItem = ((MyListLiveViewItem*)items[0])->liveScheduleItem;
+
+    /* Prevent itemSelectionChanged() when an item is deleted */
+    ListViewStations->setCurrentIndex(QModelIndex());
+
+    /* save the state of the station id column in case we want it later */
+    int width = ListViewStations->columnWidth(iColStationID);
+    if (width)
+        iWidthColStationID = width;
+
+    /* Delete all old list view items (it is important that the vector
+       "vecpListItems" was initialized to 0 at creation of the global object
+       otherwise this may cause an segmentation fault) */
+    for (size_t i = 0; i < vecpListItems.size(); i++)
+    {
+        if (vecpListItems[i] != NULL)
+            delete vecpListItems[i];
+    }
+    vecpListItems.clear();
+
+    /* Init vector for storing the pointer to the list view items */
+    const int iNumStations = DRMSchedule.GetStationNumber();
+
+    vecpListItems.resize(iNumStations, NULL);
+
+    actionSave->setEnabled(iNumStations > 0);
+
+    /* Unlock BEFORE calling the stations view update because in this function
+       the mutex is locked, too! */
+    ListItemsMutex.unlock();
+
+    /* Update list view */
+    SetStationsView();
+
+    /* Restore selected item */
+    for (int i=0; i<ListViewStations->topLevelItemCount(); ++i)
+    {
+        MyListLiveViewItem *item = (MyListLiveViewItem*)ListViewStations->topLevelItem(i);
+        if (item->liveScheduleItem == liveScheduleItem) {
+            item->setSelected(true);
+            break;
+        }
+    }
+
+    bDisableFrequencyChange = false;
+
+    QString strTitle = tr("Live Schedule");
+
+    if (iNumStations > 0)
+    {
+        if (strStationName != "")
+            strTitle += " [" + strStationName.trimmed() + "]";
+    }
+
+	setWindowTitle(strTitle);
+}
+
+void
+LiveScheduleDlg::eventClose(QCloseEvent*)
+{
+    /* Save settings */
+    SaveSettings();
+}
+
+void
+LiveScheduleDlg::eventHide(QHideEvent*)
+{
+    /* Deactivate real-time timers */
+    TimerList.stop();
+    TimerUTCLabel.stop();
+}
+
+void
+LiveScheduleDlg::eventShow(QShowEvent*)
+{
+    /* Update window */
+    OnTimerUTCLabel();
+    TimerUTCLabel.start(GUI_TIMER_UTC_TIME_LABEL);
+
+    if (!CheckBoxFreeze->isChecked())
+    {
+        OnTimerList();
+
+        /* Activate real-time timer when window is shown */
+        TimerList.start(GUI_TIMER_LIST_VIEW_UPDATE);	/* Stations list */
+    }
+}
+
+void
+LiveScheduleDlg::SetStationsView()
+{
+    ListItemsMutex.lock();
+
+    const int iNumStations = DRMSchedule.GetStationNumber();
+
+    _BOOLEAN bListHastChanged = FALSE;
+
+    _BOOLEAN bHaveOtherServiceIDs = FALSE;
+
+    /* Add new item for each station in list view */
+    for (int i = 0; i < iNumStations; i++)
+    {
+        if (!((showAll() == false) &&
+                (DRMSchedule.CheckState(i) == CDRMLiveSchedule::IS_INACTIVE)))
+        {
+            /* Only insert item if it is not already in the list */
+            if (vecpListItems[i] == NULL)
+            {
+                /* Generate new list item with all necessary column entries */
+                const CLiveScheduleItem& item = DRMSchedule.GetItem(i);
+                QString name;
+
+                if(item.iServiceID != SERV_ID_NOT_USED)
+                {
+                    bHaveOtherServiceIDs = TRUE;
+
+                    map <uint32_t,CServiceInformation>::const_iterator
+                    si = serviceInformation.find(item.iServiceID);
+                    if(si != serviceInformation.end())
+                        name = QString::fromUtf8(si->second.label.begin()->c_str());
+                    else
+                    {
+                        ulong sid = item.iServiceID;
+                        name = QString("(%1)").arg(sid, 0, 16);
+                    }
+                }
+
+                vecpListItems[i] = new MyListLiveViewItem(ListViewStations,
+                        item /* CLiveScheduleItem item */ ,
+                        QString::fromUtf8(item.strFreq.c_str()) /* freq. */ ,
+                        name /* station name or id or blank */ ,
+                        QString::fromUtf8(item.strSystem.c_str()) /* system */ ,
+                        ExtractTime(item.Schedule) /* time */,
+                        QString::fromUtf8(item.strTarget.c_str()) /* target */ ,
+                        ExtractDaysFlagString(item.Schedule.iDayCode) /* Show list of days */ );
+
+                /* Set flag for sorting the list */
+                bListHastChanged = TRUE;
+            }
+
+            /* If receiver coordinates are within the target area add a little green cube */
+            if (DRMSchedule.GetItem(i).bInsideTargetArea == TRUE)
+                vecpListItems[i]->setIcon(COL_TARGET, smallGreenCube);
+
+            /* Check, if station is currently transmitting. If yes, set
+               special pixmap */
+            switch (DRMSchedule.CheckState(i))
+            {
+            case CDRMLiveSchedule::IS_ACTIVE:
+                vecpListItems[i]->setIcon(COL_FREQ, greenCube);
+                break;
+            case CDRMLiveSchedule::IS_PREVIEW:
+                vecpListItems[i]->setIcon(COL_FREQ, orangeCube);
+                break;
+            case CDRMLiveSchedule::IS_SOON_INACTIVE:
+                vecpListItems[i]->setIcon(COL_FREQ, pinkCube);
+                break;
+            case CDRMLiveSchedule::IS_INACTIVE:
+                vecpListItems[i]->setIcon(COL_FREQ, redCube);
+                break;
+            default:
+                vecpListItems[i]->setIcon(COL_FREQ, redCube);
+                break;
+            }
+        }
+        else
+        {
+            /* Delete this item since it is not used anymore */
+            if (vecpListItems[i] != NULL)
+            {
+                /* If one deletes a menu item in QT list view, it is
+                   automaticall removed from the list and the list gets
+                   repainted */
+                delete vecpListItems[i];
+
+                /* Reset pointer so we can distinguish if it is used or not */
+                vecpListItems[i] = NULL;
+
+                /* Set flag for sorting the list */
+                bListHastChanged = TRUE;
+            }
+        }
+    }
+
+    ListViewStations->setColumnWidth(iColStationID, bHaveOtherServiceIDs ? iWidthColStationID : 0);
+
+    /* Sort the list if items have changed */
+    if(bListHastChanged)
+        ListViewStations->sortItems(iCurrentSortColumn, bCurrentSortAscending?Qt::AscendingOrder:Qt::DescendingOrder);
+    ListItemsMutex.unlock();
+}
+
+void
+LiveScheduleDlg::OnHeaderClicked(int c)
+{
+    /* Store the "direction" of sorting */
+    if (iCurrentSortColumn == c)
+        bCurrentSortAscending = !bCurrentSortAscending;
+    else
+        bCurrentSortAscending = TRUE;
+
+    iCurrentSortColumn = c;
+}
+
+void
+LiveScheduleDlg::on_ListViewStations_itemSelectionChanged()
+{
+    if (!bDisableFrequencyChange)
+    {
+        QList<QTreeWidgetItem*> items(ListViewStations->selectedItems());
+        if (items.size() == 1)
+        {
+            double dFreq = QString(items.first()->text(0)).toDouble();
+            if (!items.first()->text(2).compare("FM"))
+                dFreq *= 1000;
+            emit frequencyChanged((int)floor(dFreq));
+        }
+    }
+}
+
+QString
+ColValue(const QString strValue)
+{
+    if (strValue == "")
+        return " ";
+    else
+        return strValue;
+}
+
+void
+LiveScheduleDlg::OnSave()
+{
+    QString strFilename;
+    QString strSchedule = "";
+
+    /* Lock mutex for use the vecpListItems */
+    ListItemsMutex.lock();
+
+    /* Force the sort for all items */
+	ListViewStations->sortItems(iCurrentSortColumn, bCurrentSortAscending?Qt::AscendingOrder:Qt::DescendingOrder);
+
+    /* Extract values from the list */
+
+	for(int i=0; i<ListViewStations->topLevelItemCount(); i++)
+	{
+		QTreeWidgetItem* myItem = ListViewStations->topLevelItem(i);
+        strSchedule += "<tr>" "<td align=\"right\">" + myItem->text(COL_FREQ) + "</td>"	/* freq */
+                       "<td>" + ColValue(myItem->text(1)) + "</td>"	/* system */
+                       "<td>" + ColValue(myItem->text(2)) + "</td>"	/* time */
+                       "<td>" + ColValue(myItem->text(3)) + "</td>"	/* target */
+                       "<td>" + ColValue(myItem->text(4)) + "</td>"	/* days */
+                       "</tr>\n";
+	}
+
+    ListItemsMutex.unlock();
+
+    if (strSchedule != "")
+    {
+        /* Save to file current schedule  */
+        QString strTitle(tr("AFS Live Schedule"));
+        QString strItems("");
+
+        /* Prepare HTML page for storing the content */
+        QString strText = "<html>\n<head>\n"
+                          "<meta http-equiv=\"content-Type\" "
+                          "content=\"text/html; charset=utf-8\">\n<title>"
+                          + strStationName + " - " + strTitle +
+                          "</title>\n</head>\n\n<body>\n"
+                          "<h4>" + strTitle + "</h4>"
+                          "<h3>" + strStationName + "</h3>"
+                          "\n<table border=\"1\"><tr>\n"
+                          "<th>" + tr("Frequency [kHz/MHz]") + "</th>"
+                          "<th>" + tr("System") + "</th>"
+                          "<th>" + tr("Time [UTC]") + "</th>"
+                          "<th>" + tr("Target") + "</th>"
+                          "<th>" + tr("Start day") + "</th>\n"
+                          "</tr>\n" + strSchedule + "</table>\n"
+                          /* Add current date and time */
+                          "<br><p align=right><font size=-2><i>" +
+                          QDateTime().currentDateTime().toString() + "</i></font></p>"
+                          "</body>\n</html>";
+
+        QString strPath = strCurrentSavePath +
+                          strStationName + "_" + "LiveSchedule.html";
+        strFilename = QFileDialog::getSaveFileName(this, "*.html", strPath);
+
+        if (!strFilename.isEmpty())
+        {
+            /* Save as a text stream */
+            QFile FileObj(strFilename);
+
+            if (FileObj.open(QIODevice::WriteOnly))
+            {
+                QTextStream TextStream(&FileObj);
+                TextStream << strText;	/* Actual writing */
+                FileObj.close();
+                strCurrentSavePath = QFileInfo(strFilename).path() + PATH_SEPARATOR;
+            }
+        }
+    }
+}
+
+void
+LiveScheduleDlg::AddWhatsThisHelp()
+{
+    /* Stations List */
+	QString strView =
+                     tr("<b>Live Schedule List:</b> In the live schedule list "
+                        "it's possible to view AFS (Alternative Frequency Signalling) "
+                        "information transmitted with the current DRM or AMSS signal.</b>"
+                        "It is possible to limit the view to active stations by changing a "
+                        "setting in the 'view' menu.<br>"
+                        "The color of the cube on the left of the "
+                        "frequency shows the current status of the transmission.<br>"
+                        "A green box shows that the transmission takes place right now "
+                        "a red cube it is shown that the transmission is offline, "
+                        "a pink cube shown that the transmission soon will be offline.<br>"
+                        "If the stations preview is active an orange box shows the stations "
+                        "that will be active.<br>"
+                        "A little green cube on the left of the target column shows that the receiver"
+                        " coordinates (latitude and longitude) stored into Dream settings are within"
+                        " the target area of this transmission.<br>"
+                        "The list can be sorted by clicking on the headline of the column.");
+
+    /* UTC time label */
+	QString strTime =
+                     tr("<b>UTC Time:</b> Shows the current Coordinated "
+                        "Universal Time (UTC) which is also known as Greenwich Mean Time "
+                        "(GMT).");
+
+    /* Check box freeze */
+	QString strFreeze = tr("<b>Freeze:</b> If this check box is selected the live schedule is frozen.");
+	ListViewStations->setWhatsThis(strView);
+    TextLabelUTCTime->setWhatsThis(strTime);
+    CheckBoxFreeze->setWhatsThis(strFreeze);
+}
+
+CDRMLiveSchedule::StationState CDRMLiveSchedule::CheckState(const int iPos)
+{
+    /* Get system time */
+    time_t
+    ltime;
+    time(&ltime);
+
+    if (IsActive(iPos, ltime) == TRUE)
+    {
+        /* Check if the station soon will be inactive */
+        if (IsActive(iPos, ltime + NUM_SECONDS_SOON_INACTIVE) == TRUE)
+            return IS_ACTIVE;
+        else
+            return IS_SOON_INACTIVE;
+    }
+    else
+    {
+        /* Station is not active, check preview condition */
+        if (iSecondsPreview > 0)
+        {
+            if (IsActive(iPos, ltime + iSecondsPreview) == TRUE)
+                return IS_PREVIEW;
+            else
+                return IS_INACTIVE;
+        }
+        else
+            return IS_INACTIVE;
+    }
+}
+
+bool
+CDRMLiveSchedule::IsActive(const int iPos, const time_t ltime)
+{
+    return StationsTable[iPos].IsActive(ltime);
+}
+
+bool
+CLiveScheduleItem::IsActive(const time_t ltime)
+{
+    return Schedule.IsActive(ltime);
+}
+
+bool
+CLiveScheduleItem::operator==(const CLiveScheduleItem& item)
+{
+	return
+	    strFreq == item.strFreq &&
+	    strTarget == item.strTarget &&
+	    iServiceID == item.iServiceID &&
+	    strSystem == item.strSystem &&
+	    bInsideTargetArea == item.bInsideTargetArea &&
+	    Schedule == item.Schedule;
+}
+
diff --git a/src/GUI-QT/LiveScheduleDlg.h b/src/GUI-QT/LiveScheduleDlg.h
new file mode 100644
index 0000000..9c43d56
--- /dev/null
+++ b/src/GUI-QT/LiveScheduleDlg.h
@@ -0,0 +1,202 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2005
+ *
+ * Author(s):
+ *	Andrea Russo
+ *
+ * Description:
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#ifndef __LiveScheduleDlg_H
+#define LiveScheduleDlg_H
+
+#include "ui_LiveScheduleWindow.h"
+#include "CWindow.h"
+#include <QTimer>
+#include <QSignalMapper>
+#include <../Parameter.h>
+
+/* Definitions ****************************************************************/
+/* Define the timer interval of updating the list view */
+#define GUI_TIMER_LIST_VIEW_UPDATE		5000 /* ms (5 seconds) */
+
+/* Define the timer interval of updating the UTC label */
+#define GUI_TIMER_UTC_TIME_LABEL		1000 /* ms (1 second) */
+
+#define COL_FREQ 0 /* frequency column */
+#define COL_TARGET 4 /* target column */
+
+/* Time definitions for preview */
+#define NUM_SECONDS_PREV_5MIN			300
+#define NUM_SECONDS_PREV_15MIN			900
+#define NUM_SECONDS_PREV_30MIN			1800
+
+#define NUM_SECONDS_SOON_INACTIVE		600
+
+/* String definitions for schedule days */
+#define CHR_ACTIVE_DAY_MARKER			'1'
+
+/* Classes ********************************************************************/
+class CLiveScheduleItem
+{
+public:
+	CLiveScheduleItem() : strFreq(""), strTarget(""), iServiceID(SERV_ID_NOT_USED),
+	strSystem(""), bInsideTargetArea(false) {}
+
+	bool IsActive(const time_t ltime);
+	bool operator==(const CLiveScheduleItem& item);
+
+	string			strFreq;
+	string			strTarget;
+	uint32_t		iServiceID;
+	string			strSystem;
+	bool			bInsideTargetArea;
+	CAltFreqSched	Schedule;
+};
+
+class CDRMLiveSchedule
+{
+public:
+	CDRMLiveSchedule():StationsTable(),iSecondsPreview(0),
+	dReceiverLatitude(0),dReceiverLongitude(0)
+	{}
+
+	virtual ~CDRMLiveSchedule() {}
+
+	enum StationState {IS_ACTIVE, IS_INACTIVE, IS_PREVIEW, IS_SOON_INACTIVE};
+	int GetStationNumber() {return StationsTable.size();}
+	CLiveScheduleItem& GetItem(const int iPos) {return StationsTable[iPos];}
+	StationState CheckState(const int iPos);
+
+    void LoadAFSInformation(const CAltFreqSign& AltFreqSign);
+
+	void LoadServiceDefinition(const CServiceDefinition& service,
+			const CAltFreqSign& AltFreqSign, const uint32_t iServiceID=SERV_ID_NOT_USED);
+
+	void DecodeTargets(const vector<CAltFreqRegion> vecAltFreqRegions,
+		string& strRegions , _BOOLEAN& bIntoTargetArea);
+
+	void SetSecondsPreview(int iSec) {iSecondsPreview = iSec;}
+	int GetSecondsPreview() {return iSecondsPreview;}
+
+	void SetReceiverCoordinates(double latitude, double longitude);
+
+protected:
+	_BOOLEAN IsActive(const int iPos, const time_t ltime);
+
+	vector<CLiveScheduleItem>	StationsTable;
+
+	/* Minutes for stations preview in seconds if zero then no active */
+	int			iSecondsPreview;
+
+	/* receiver coordinates */
+	double		dReceiverLatitude;
+	double		dReceiverLongitude;
+};
+
+class MyListLiveViewItem : public QTreeWidgetItem
+{
+public:
+	MyListLiveViewItem(QTreeWidget* parent, 
+		const CLiveScheduleItem& liveScheduleItem = CLiveScheduleItem(),
+		QString s1 = QString::null, QString s2 = QString::null,
+		QString s3 = QString::null, QString s4 = QString::null,
+		QString s5 = QString::null, QString s6 = QString::null,
+		QString s7 = QString::null, QString s8 = QString::null) :
+	QTreeWidgetItem(parent, QStringList() << s1 << s2 << s3 << s4 << s5 << s6 << s7 << s8),
+	liveScheduleItem(liveScheduleItem)
+	{}
+
+	/* Custom "key()" function for correct sorting behaviour */
+	virtual QString key(int column, bool ascending) const;
+	void setPixmap(int col, QPixmap p) { setIcon(col, p); }
+	CLiveScheduleItem liveScheduleItem;
+};
+
+class LiveScheduleDlg : public CWindow, public Ui_LiveScheduleWindow
+{
+	Q_OBJECT
+
+public:
+    LiveScheduleDlg(CSettings&, QMap<QWidget*,QString>&);
+	virtual ~LiveScheduleDlg();
+
+public slots:
+    void setLocation(double, double);
+    void setAFS(const CAltFreqSign& altFreqSign);
+    void setService(int, const CService&);
+    void setServiceInformation(const map <uint32_t,CServiceInformation>);
+    void setFrequency(int);
+
+protected:
+	virtual void	eventClose(QCloseEvent* pEvent);
+	virtual void	eventHide(QHideEvent* pEvent);
+	virtual void	eventShow(QShowEvent* pEvent);
+	void			LoadSettings();
+	void			SaveSettings();
+	void			LoadSchedule();
+	int				iCurrentSortColumn;
+	_BOOLEAN		bCurrentSortAscending;
+	void			SetStationsView();
+	void			AddWhatsThisHelp();
+	void			SetUTCTimeLabel();
+	QString			ExtractDaysFlagString(const int iDayCode);
+	QString			ExtractTime(const CAltFreqSched& schedule);
+	bool			showAll();
+	int				currentSortColumn();
+
+	CDRMLiveSchedule	DRMSchedule;
+	QTimer			TimerList;
+	QTimer			TimerUTCLabel;
+	QIcon			smallGreenCube;
+	QIcon			greenCube;
+	QIcon			redCube;
+	QIcon			orangeCube;
+	QIcon			pinkCube;
+	QSignalMapper*	previewMapper;
+	QActionGroup*	previewGroup;
+	QSignalMapper*	showMapper;
+	QActionGroup*	showGroup;
+
+	vector<MyListLiveViewItem*>	vecpListItems;
+	QMutex			ListItemsMutex;
+	QString			strCurrentSavePath;
+	int				iColStationID;
+	int				iWidthColStationID;
+	bool			bDisableFrequencyChange;
+    QString         strStationName;
+    map <uint32_t,CServiceInformation> serviceInformation;
+
+signals:
+    void frequencyChanged(int);
+
+public slots:
+	void OnTimerList();
+	void OnTimerUTCLabel();
+	void OnShowStationsMenu(int iID);
+	void OnShowPreviewMenu(int iID);
+	void OnHeaderClicked(int c);
+	void OnSave();
+	void OnCheckFreeze();
+	void on_ListViewStations_itemSelectionChanged();
+};
+
+#endif
diff --git a/src/GUI-QT/LiveScheduleWindow.ui b/src/GUI-QT/LiveScheduleWindow.ui
new file mode 100644
index 0000000..70bbe54
--- /dev/null
+++ b/src/GUI-QT/LiveScheduleWindow.ui
@@ -0,0 +1,272 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>LiveScheduleWindow</class>
+ <widget class="QMainWindow" name="LiveScheduleWindow">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>622</width>
+    <height>392</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Live Schedule</string>
+  </property>
+  <property name="windowIcon">
+   <iconset resource="res/icons.qrc">
+    <normaloff>:/icons/MainIcon.svg</normaloff>:/icons/MainIcon.svg</iconset>
+  </property>
+  <widget class="QWidget" name="centralwidget">
+   <layout class="QVBoxLayout" name="verticalLayout">
+    <item>
+     <widget class="QTreeWidget" name="ListViewStations">
+      <property name="sizePolicy">
+       <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+        <horstretch>0</horstretch>
+        <verstretch>0</verstretch>
+       </sizepolicy>
+      </property>
+      <property name="rootIsDecorated">
+       <bool>false</bool>
+      </property>
+      <property name="uniformRowHeights">
+       <bool>true</bool>
+      </property>
+      <column>
+       <property name="text">
+        <string>Frequency [kHz/MHz]</string>
+       </property>
+      </column>
+      <column>
+       <property name="text">
+        <string>Station Name/Id</string>
+       </property>
+      </column>
+      <column>
+       <property name="text">
+        <string>System</string>
+       </property>
+      </column>
+      <column>
+       <property name="text">
+        <string>Time [UTC]</string>
+       </property>
+      </column>
+      <column>
+       <property name="text">
+        <string>Target</string>
+       </property>
+      </column>
+      <column>
+       <property name="text">
+        <string>Start Day</string>
+       </property>
+      </column>
+     </widget>
+    </item>
+    <item>
+     <layout class="QHBoxLayout" name="horizontalLayout">
+      <item>
+       <widget class="QLabel" name="TextLabelUTCTime">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Minimum" vsizetype="Maximum">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="minimumSize">
+         <size>
+          <width>0</width>
+          <height>23</height>
+         </size>
+        </property>
+        <property name="frameShape">
+         <enum>QFrame::Panel</enum>
+        </property>
+        <property name="frameShadow">
+         <enum>QFrame::Sunken</enum>
+        </property>
+        <property name="text">
+         <string>UTC</string>
+        </property>
+        <property name="textFormat">
+         <enum>Qt::PlainText</enum>
+        </property>
+        <property name="wordWrap">
+         <bool>false</bool>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QLabel" name="labelFrequency">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Minimum" vsizetype="Maximum">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="minimumSize">
+         <size>
+          <width>0</width>
+          <height>23</height>
+         </size>
+        </property>
+        <property name="frameShape">
+         <enum>QFrame::Panel</enum>
+        </property>
+        <property name="frameShadow">
+         <enum>QFrame::Sunken</enum>
+        </property>
+        <property name="text">
+         <string>kHz</string>
+        </property>
+        <property name="textFormat">
+         <enum>Qt::PlainText</enum>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QCheckBox" name="CheckBoxFreeze">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="text">
+         <string>F&reeze</string>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <spacer name="Spacer4">
+        <property name="orientation">
+         <enum>Qt::Horizontal</enum>
+        </property>
+        <property name="sizeType">
+         <enum>QSizePolicy::Expanding</enum>
+        </property>
+        <property name="sizeHint" stdset="0">
+         <size>
+          <width>20</width>
+          <height>20</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+      <item>
+       <widget class="QPushButton" name="buttonOk">
+        <property name="text">
+         <string>&Close</string>
+        </property>
+        <property name="default">
+         <bool>true</bool>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </item>
+   </layout>
+  </widget>
+  <widget class="QMenuBar" name="menubar">
+   <property name="geometry">
+    <rect>
+     <x>0</x>
+     <y>0</y>
+     <width>622</width>
+     <height>25</height>
+    </rect>
+   </property>
+   <widget class="QMenu" name="menuFile">
+    <property name="title">
+     <string>&File</string>
+    </property>
+    <addaction name="actionSave"/>
+    <addaction name="separator"/>
+    <addaction name="actionClose"/>
+   </widget>
+   <widget class="QMenu" name="menu_View">
+    <property name="title">
+     <string>&View</string>
+    </property>
+    <widget class="QMenu" name="menuStations_preview">
+     <property name="title">
+      <string>Stations &preview</string>
+     </property>
+     <addaction name="actionDisabled"/>
+     <addaction name="action5minutes"/>
+     <addaction name="action15minutes"/>
+     <addaction name="action30minutes"/>
+    </widget>
+    <addaction name="actionShowOnlyActiveStations"/>
+    <addaction name="actionShowAllStations"/>
+    <addaction name="menuStations_preview"/>
+   </widget>
+   <addaction name="menuFile"/>
+   <addaction name="menu_View"/>
+  </widget>
+  <action name="actionShowOnlyActiveStations">
+   <property name="checkable">
+    <bool>true</bool>
+   </property>
+   <property name="text">
+    <string>Show only active stations</string>
+   </property>
+  </action>
+  <action name="actionShowAllStations">
+   <property name="checkable">
+    <bool>true</bool>
+   </property>
+   <property name="text">
+    <string>Show all stations</string>
+   </property>
+  </action>
+  <action name="action5minutes">
+   <property name="checkable">
+    <bool>true</bool>
+   </property>
+   <property name="text">
+    <string>5 minutes</string>
+   </property>
+  </action>
+  <action name="action15minutes">
+   <property name="checkable">
+    <bool>true</bool>
+   </property>
+   <property name="text">
+    <string>15 minutes</string>
+   </property>
+  </action>
+  <action name="action30minutes">
+   <property name="checkable">
+    <bool>true</bool>
+   </property>
+   <property name="text">
+    <string>30 minutes</string>
+   </property>
+  </action>
+  <action name="actionDisabled">
+   <property name="checkable">
+    <bool>true</bool>
+   </property>
+   <property name="text">
+    <string>&Disabled</string>
+   </property>
+  </action>
+  <action name="actionSave">
+   <property name="text">
+    <string>&Save...</string>
+   </property>
+  </action>
+  <action name="actionClose">
+   <property name="text">
+    <string>&Close</string>
+   </property>
+  </action>
+ </widget>
+ <resources>
+  <include location="res/icons.qrc"/>
+ </resources>
+ <connections/>
+</ui>
diff --git a/src/GUI-QT/Logging.cpp b/src/GUI-QT/Logging.cpp
new file mode 100644
index 0000000..33603f1
--- /dev/null
+++ b/src/GUI-QT/Logging.cpp
@@ -0,0 +1,124 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "Logging.h"
+#include "../util/Settings.h"
+
+#define SHORT_LOG_FILENAME "DreamLog.txt"
+#define LONG_LOG_FILENAME "DreamLogLong.csv"
+
+
+/* Implementation *************************************************************/
+CLogging::CLogging(CParameter& Parameters) :
+    shortLog(Parameters), longLog(Parameters),
+    iLogDelay(0), iLogCount(0), state(off)
+{
+    connect(&TimerLogFile, SIGNAL(timeout()), this, SLOT(OnTimerLogFile()));
+    connect(&TimerLogFileStart, SIGNAL(timeout()), this, SLOT(OnTimerLogFileStart()));
+}
+
+void CLogging::LoadSettings(CSettings& Settings)
+{
+    /* log file flag for storing signal strength in long log */
+    _BOOLEAN logrxl = Settings.Get("Logfile", "enablerxl", FALSE);
+    shortLog.SetRxlEnabled(logrxl);
+    longLog.SetRxlEnabled(logrxl);
+
+    /* log file flag for storing lat/long in long log */
+    bool enablepositiondata = Settings.Get("Logfile", "enablepositiondata", false);
+    shortLog.SetPositionEnabled(enablepositiondata);
+    longLog.SetPositionEnabled(enablepositiondata);
+
+    bool enabled = Settings.Get("Logfile", "enablelog", false);
+    if(enabled)
+	state = starting;
+    iLogDelay = Settings.Get("Logfile", "delay", 0);
+    SaveSettings(Settings);
+}
+
+void CLogging::start()
+{
+    /* One shot timer */
+    TimerLogFileStart.start(iLogDelay * 1000 /* ms */);
+}
+
+void CLogging::SaveSettings(CSettings& Settings)
+{
+    Settings.Put("Logfile", "enablerxl", shortLog.GetRxlEnabled());
+    Settings.Put("Logfile", "enablepositiondata", shortLog.GetPositionEnabled());
+    Settings.Put("Logfile", "enablelog", state!=off);
+    Settings.Put("Logfile", "delay", iLogDelay);
+}
+
+void CLogging::OnTimerLogFile()
+{
+    if (shortLog.restartNeeded())
+    {
+        stop(); start();
+    }
+    else
+    {
+        iLogCount++;
+        if(iLogCount == 60)
+        {
+            iLogCount = 0;
+            shortLog.Update();
+        }
+        longLog.Update();
+    }
+}
+
+void CLogging::OnTimerLogFileStart()
+{
+    iLogCount = 0;
+    state = on;
+	/* stop this timer! */
+	TimerLogFileStart.stop();
+    /* Start logging (if not already done) */
+    TimerLogFile.start(1000); /* Every second */
+    /* Open log files */
+    shortLog.Start(SHORT_LOG_FILENAME);
+    longLog.Start(LONG_LOG_FILENAME);
+    if(longLog.GetRxlEnabled())
+    {
+        emit subscribeRig();
+    }
+}
+
+void CLogging::stop()
+{
+    state = off;
+    TimerLogFileStart.stop();
+    TimerLogFile.stop();
+    shortLog.Stop();
+    longLog.Stop();
+    if(longLog.GetRxlEnabled())
+    {
+        emit unsubscribeRig();
+    }
+}
diff --git a/src/GUI-QT/Logging.h b/src/GUI-QT/Logging.h
new file mode 100644
index 0000000..9ae832f
--- /dev/null
+++ b/src/GUI-QT/Logging.h
@@ -0,0 +1,72 @@
+/******************************************************************************\
+ * British Broadcasting Corporation
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer, Julian Cable
+ *
+ * Description:
+ *
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#ifndef __LOGGING_H
+#define __LOGGING_H
+
+#include <QTimer>
+#include <QString>
+
+#include "../GlobalDefinitions.h"
+#include "../ReceptLog.h"
+
+/* Classes ********************************************************************/
+class CSettings;
+
+class CLogging: public QObject
+{
+	Q_OBJECT
+
+public:
+	CLogging(CParameter&);
+	virtual ~CLogging() {}
+	void LoadSettings(CSettings&);
+	void SaveSettings(CSettings&);
+	bool enabled() { return state!=off; }
+
+protected:
+	QTimer			TimerLogFile;
+	QTimer			TimerLogFileStart;
+
+	CShortLog		shortLog;
+	CLongLog		longLog;
+	int			iLogDelay;
+	int			iLogCount;
+	enum {off,starting,on}  state;
+
+signals:
+	void subscribeRig();
+	void unsubscribeRig();
+public slots:
+	void start();
+	void stop();
+	void OnTimerLogFile();
+	void OnTimerLogFileStart();
+};
+
+#endif
diff --git a/src/GUI-QT/MultColorLED.cpp b/src/GUI-QT/MultColorLED.cpp
new file mode 100644
index 0000000..441c57c
--- /dev/null
+++ b/src/GUI-QT/MultColorLED.cpp
@@ -0,0 +1,183 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *	Implements a multi-color LED
+ *	
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later 
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT 
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "MultColorLED.h"
+#include <QLabel>
+
+
+/* Implementation *************************************************************/
+CMultColorLED::CMultColorLED(QWidget * parent) :
+	QFrame(parent), eColorFlag(RL_GREY),
+	TimerRedLight(), TimerGreenLight(), TimerYellowLight(),
+	bFlagRedLi(false), bFlagGreenLi(false), bFlagYellowLi(false),
+	iUpdateTime(DEFAULT_UPDATE_TIME)
+{
+	green = QColor(0, 255, 0);
+	red = QColor(255, 0, 0);
+	yellow = QColor(255, 255, 0);
+	grey = palette().color(QPalette::Window);
+
+	/* Set modified style */
+	setAutoFillBackground(true);
+	setFrameShape(QFrame::Panel);
+	setFrameShadow(QFrame::Sunken);
+
+	Reset();
+
+	/* Connect timer events to the desired slots */
+	connect(&TimerRedLight, SIGNAL(timeout()), 
+		this, SLOT(OnTimerRedLight()));
+	connect(&TimerGreenLight, SIGNAL(timeout()), 
+		this, SLOT(OnTimerGreenLight()));
+	connect(&TimerYellowLight, SIGNAL(timeout()), 
+		this, SLOT(OnTimerYellowLight()));
+
+	TimerRedLight.stop();
+	TimerGreenLight.stop();
+	TimerYellowLight.stop();
+}
+
+void CMultColorLED::OnTimerRedLight() 
+{
+	bFlagRedLi = false;
+
+	UpdateColor();
+}
+
+void CMultColorLED::OnTimerGreenLight() 
+{
+	bFlagGreenLi = false;
+
+	UpdateColor();
+}
+
+void CMultColorLED::OnTimerYellowLight() 
+{
+	bFlagYellowLi = false;
+
+	UpdateColor();
+}
+
+void CMultColorLED::Reset()
+{
+	/* Reset color flags */
+	bFlagRedLi = false;
+	bFlagGreenLi = false;
+	bFlagYellowLi = false;
+
+	UpdateColor();
+}
+
+void CMultColorLED::UpdateColor()
+{
+	/* Red light has highest priority, then comes yellow and at the end, we
+	   decide to set green light. Allways check the current color of the
+	   control before setting the color to prevent flickering */
+	if (bFlagRedLi)
+	{
+		if (eColorFlag != RL_RED)
+		{
+			SetColor(red);
+			eColorFlag = RL_RED;
+		}
+		return;
+	}
+
+	if (bFlagYellowLi)
+	{
+		if (eColorFlag != RL_YELLOW)
+		{
+			SetColor(yellow);
+			eColorFlag = RL_YELLOW;
+		}
+		return;
+	}
+
+	if (bFlagGreenLi)
+	{
+		if (eColorFlag != RL_GREEN)
+		{
+			SetColor(green);
+			eColorFlag = RL_GREEN;
+		}
+		return;
+	}
+
+	/* If no color is active, set control to grey light */
+	if (eColorFlag != RL_GREY)
+	{
+		SetColor(grey);
+		eColorFlag = RL_GREY;
+	}
+}
+
+void CMultColorLED::SetLight(ELightColor color)
+{
+	switch (color)
+	{
+	case RL_GREEN:
+		/* Green light */
+		bFlagGreenLi = true;
+		TimerGreenLight.start(iUpdateTime);
+		break;
+
+	case RL_YELLOW:
+		/* Yellow light */
+		bFlagYellowLi = true;
+		TimerYellowLight.start(iUpdateTime);
+		break;
+
+	case RL_RED:
+		/* Red light */
+		bFlagRedLi = true;
+		TimerRedLight.start(iUpdateTime);
+		break;
+	case RL_GREY:
+		// TODO
+		break;
+	}
+
+	UpdateColor();
+}
+
+void CMultColorLED::SetUpdateTime(int iNUTi)
+{
+	/* Avoid too short intervals */
+	if (iNUTi < MIN_TIME_FOR_RED_LIGHT)
+		iUpdateTime = MIN_TIME_FOR_RED_LIGHT;
+	else
+		iUpdateTime = iNUTi;
+}
+
+void CMultColorLED::SetColor(const QColor& color)
+{
+	QPalette newPalette(palette());
+	newPalette.setColor(QPalette::Window, color);
+	setPalette(newPalette);
+}
diff --git a/src/GUI-QT/MultColorLED.h b/src/GUI-QT/MultColorLED.h
new file mode 100644
index 0000000..1c60457
--- /dev/null
+++ b/src/GUI-QT/MultColorLED.h
@@ -0,0 +1,93 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *
+ * SetLight():
+ *	0: Green
+ *	1: Yellow
+ *	2: Red
+ *	
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later 
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT 
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#if !defined(AFX_MULTCOLORLED_H__FD6B49B5_87DF_48DD_A873_804E1606C2AC__INCLUDED_)
+#define AFX_MULTCOLORLED_H__FD6B49B5_87DF_48DD_A873_804E1606C2AC__INCLUDED_
+
+#include <qlabel.h>
+#include <qpixmap.h>
+#include <qtimer.h>
+
+
+/* Definitions ****************************************************************/
+#define DEFAULT_UPDATE_TIME				600
+
+/* The red and yellow light should be on at least this interval */
+#define MIN_TIME_FOR_RED_LIGHT			100
+
+
+/* Classes ********************************************************************/
+class CMultColorLED : public QFrame
+{
+	Q_OBJECT
+
+public:
+	enum ELightColor {RL_GREY, RL_RED, RL_GREEN, RL_YELLOW};
+
+	CMultColorLED(QWidget* parent);
+	virtual ~CMultColorLED() {}
+
+	void SetUpdateTime(int);
+	void SetLight(ELightColor);
+	void Reset();
+
+protected:
+
+	ELightColor		eColorFlag;
+
+	QTimer			TimerRedLight;
+	QTimer			TimerGreenLight;
+	QTimer			TimerYellowLight;
+
+	bool			bFlagRedLi;
+	bool			bFlagGreenLi;
+	bool			bFlagYellowLi;
+
+	int				iUpdateTime;
+
+	QColor			green;
+	QColor			yellow;
+	QColor			red;
+	QColor			grey;
+
+	void			UpdateColor();
+	void			SetColor(const QColor& color);
+
+protected slots:
+	void OnTimerRedLight();
+	void OnTimerGreenLight();
+	void OnTimerYellowLight();
+};
+
+
+#endif // AFX_MULTCOLORLED_H__FD6B49B5_87DF_48DD_A873_804E1606C2AC__INCLUDED_
diff --git a/src/GUI-QT/MultSettingsDlg.cpp b/src/GUI-QT/MultSettingsDlg.cpp
new file mode 100644
index 0000000..e210559
--- /dev/null
+++ b/src/GUI-QT/MultSettingsDlg.cpp
@@ -0,0 +1,169 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Andrea Russo
+ *
+ * Description:
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "MultSettingsDlg.h"
+#include <QFileDialog>
+#include <QShowEvent>
+#include <QHideEvent>
+#include <QLabel>
+#include <QToolTip>
+#include "ThemeCustomizer.h"
+
+/* Implementation *************************************************************/
+
+MultSettingsDlg::MultSettingsDlg(CParameter& NP, CSettings& NSettings,
+	QWidget* parent) :
+	QDialog(parent), Parameters(NP), Settings(NSettings)
+{
+	setAttribute(Qt::WA_QuitOnClose, false);
+	setupUi(this);
+
+	/* Set help text for the controls */
+	AddWhatsThisHelp();
+
+	// TODO
+	CheckBoxAddRefresh->hide();
+	EdtSecRefresh->hide();
+
+	/* Connect buttons */
+
+	connect(PushButtonChooseDir, SIGNAL(clicked()),
+		this, SLOT(OnbuttonChooseDir()));
+
+	connect(buttonClearCacheMOT, SIGNAL(clicked()),
+		this, SLOT(OnbuttonClearCacheMOT()));
+
+	connect(buttonClearCacheEPG, SIGNAL(clicked()),
+		this, SLOT(OnbuttonClearCacheEPG()));
+
+	EdtSecRefresh->setValidator(new QIntValidator(MIN_MOT_BWS_REFRESH_TIME, MAX_MOT_BWS_REFRESH_TIME, EdtSecRefresh));
+
+	APPLY_CUSTOM_THEME();
+}
+
+MultSettingsDlg::~MultSettingsDlg()
+{
+}
+
+void MultSettingsDlg::hideEvent(QHideEvent*)
+{
+}
+
+void MultSettingsDlg::showEvent(QShowEvent*)
+{
+    SetDataDirectoryControls();
+}
+
+void MultSettingsDlg::ClearCache(string subdir, QString sFilter = "", _BOOLEAN bDeleteDirs)
+{
+    /* Delete files into sPath directory with scan recursive */
+    string p = Settings.Get("Receiver", "datafilesdirectory", string(DEFAULT_DATA_FILES_DIRECTORY));
+
+    QDir dir(QString::fromUtf8((p+PATH_SEPARATOR+subdir).c_str()));
+    ClearCache(dir, sFilter, bDeleteDirs);
+}
+
+void MultSettingsDlg::ClearCache(QDir dir, QString sFilter = "", _BOOLEAN bDeleteDirs)
+{
+    /* Check if the directory exists */
+	if (dir.exists())
+	{
+		dir.setFilter(QDir::Files | QDir::Dirs | QDir::NoSymLinks);
+
+		/* Eventually apply the filter */
+		if (sFilter != "")
+			dir.setNameFilters(QStringList(sFilter));
+
+		dir.setSorting( QDir::DirsFirst );
+		const QList<QFileInfo> list = dir.entryInfoList();
+		for(QList<QFileInfo>::const_iterator fi = list.begin(); fi!=list.end(); fi++)
+		{
+
+			/* for each file/dir */
+			/* if directory...=> scan recursive */
+			if (fi->isDir())
+			{
+				if(fi->fileName()!="." && fi->fileName()!="..")
+				{
+                    ClearCache(QDir(fi->filePath()), sFilter, bDeleteDirs);
+
+					/* Eventually delete the directory */
+					if (bDeleteDirs == TRUE)
+						dir.rmdir(fi->fileName());
+				}
+			}
+			else
+			{
+				/* Is a file so remove it */
+				dir.remove(fi->fileName());
+			}
+		}
+	}
+}
+
+void MultSettingsDlg::OnbuttonChooseDir()
+{
+	QString strFilename = QFileDialog::getExistingDirectory(this, TextLabelDir->text());
+	/* Check if user not hit the cancel button */
+	if (!strFilename.isEmpty())
+	{
+        strFilename.replace(QRegExp("/"), PATH_SEPARATOR);
+        Settings.Put("Receiver", "datafilesdirectory",
+                    string(strFilename.toUtf8().constData())
+                     );
+        SetDataDirectoryControls();
+	}
+}
+
+void MultSettingsDlg::OnbuttonClearCacheMOT()
+{
+    ClearCache("MOT", "", TRUE);
+}
+
+void MultSettingsDlg::OnbuttonClearCacheEPG()
+{
+	/* Delete all EPG files */
+    ClearCache("EPG", "*.EHA;*.EHB");
+}
+
+void MultSettingsDlg::SetDataDirectoryControls()
+{
+    QString sep(PATH_SEPARATOR);
+    /* Delete files into sPath directory with scan recursive */
+    string p = Settings.Get("Receiver", "datafilesdirectory", string(DEFAULT_DATA_FILES_DIRECTORY));
+    QString strFilename = QString::fromUtf8(p.c_str());
+    strFilename.replace(QRegExp("/"), sep);
+    if (!strFilename.isEmpty() && strFilename.at(strFilename.length()-1) == QChar(sep[0]))
+		strFilename.remove(strFilename.length()-1, 1);
+	TextLabelDir->setToolTip(strFilename);
+	TextLabelDir->setText(strFilename);
+}
+
+void MultSettingsDlg::AddWhatsThisHelp()
+{
+	//TODO
+}
diff --git a/src/GUI-QT/MultSettingsDlg.h b/src/GUI-QT/MultSettingsDlg.h
new file mode 100644
index 0000000..2c9b93d
--- /dev/null
+++ b/src/GUI-QT/MultSettingsDlg.h
@@ -0,0 +1,74 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Andrea Russo
+ *
+ * Description:
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#ifndef __MultSettingsDlg_H
+#define __MultSettingsDlg_H
+
+#include <qcheckbox.h>
+#include <qlineedit.h>
+#include <qdir.h>
+#include <qpushbutton.h>
+#include <qvalidator.h>
+
+#include "../DrmReceiver.h"
+#include "../datadecoding/epgutil.h"
+#include "../util/Settings.h"
+#include <QDialog>
+#include "ui_MultSettingsDlgbase.h"
+
+/* Definitions ****************************************************************/
+
+/* Classes ********************************************************************/
+
+class MultSettingsDlg : public QDialog, public Ui_CMultSettingsDlgBase
+{
+	Q_OBJECT
+
+public:
+	MultSettingsDlg(CParameter&, CSettings&, QWidget* parent = 0);
+	virtual ~MultSettingsDlg();
+
+protected:
+    void ClearCache(string sPath, QString sFilter, _BOOLEAN bDeleteDirs=FALSE);
+    void ClearCache(QDir dir, QString sFilter, _BOOLEAN bDeleteDirs=FALSE);
+
+	virtual void	showEvent(QShowEvent* pEvent);
+	virtual void	hideEvent(QHideEvent* pEvent);
+
+	void			SetDataDirectoryControls();
+	void			AddWhatsThisHelp();
+
+	CParameter&		Parameters;
+	CSettings&		Settings;
+
+public slots:
+	void OnbuttonChooseDir();
+	void OnbuttonClearCacheMOT();
+	void OnbuttonClearCacheEPG();
+};
+
+#endif
diff --git a/src/GUI-QT/MultSettingsDlgbase.ui b/src/GUI-QT/MultSettingsDlgbase.ui
new file mode 100644
index 0000000..1526793
--- /dev/null
+++ b/src/GUI-QT/MultSettingsDlgbase.ui
@@ -0,0 +1,340 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>CMultSettingsDlgBase</class>
+ <widget class="QDialog" name="CMultSettingsDlgBase">
+  <property name="windowModality">
+   <enum>Qt::ApplicationModal</enum>
+  </property>
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>402</width>
+    <height>311</height>
+   </rect>
+  </property>
+  <property name="sizePolicy">
+   <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+    <horstretch>0</horstretch>
+    <verstretch>0</verstretch>
+   </sizepolicy>
+  </property>
+  <property name="cursor">
+   <cursorShape>ArrowCursor</cursorShape>
+  </property>
+  <property name="windowTitle">
+   <string>Multimedia settings</string>
+  </property>
+  <property name="windowIcon">
+   <iconset resource="res/icons.qrc">
+    <normaloff>:/icons/MainIcon.svg</normaloff>:/icons/MainIcon.svg</iconset>
+  </property>
+  <property name="sizeGripEnabled">
+   <bool>true</bool>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout_4">
+   <item>
+    <widget class="QGroupBox" name="DirGroup">
+     <property name="title">
+      <string>Data Directory</string>
+     </property>
+     <layout class="QVBoxLayout" name="verticalLayout_3">
+      <item>
+       <layout class="QHBoxLayout">
+        <property name="spacing">
+         <number>6</number>
+        </property>
+        <property name="margin">
+         <number>0</number>
+        </property>
+        <item>
+         <widget class="QLabel" name="TextLabelDir">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Expanding" vsizetype="Minimum">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="text">
+           <string>TextLabelDir</string>
+          </property>
+          <property name="wordWrap">
+           <bool>false</bool>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QPushButton" name="PushButtonChooseDir">
+          <property name="text">
+           <string>Choose</string>
+          </property>
+         </widget>
+        </item>
+       </layout>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item>
+    <spacer name="verticalSpacer_3">
+     <property name="orientation">
+      <enum>Qt::Vertical</enum>
+     </property>
+     <property name="sizeHint" stdset="0">
+      <size>
+       <width>20</width>
+       <height>0</height>
+      </size>
+     </property>
+    </spacer>
+   </item>
+   <item>
+    <widget class="QGroupBox" name="MOTGroup">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
+     </property>
+     <property name="minimumSize">
+      <size>
+       <width>0</width>
+       <height>0</height>
+      </size>
+     </property>
+     <property name="title">
+      <string>MOT Broadcast Web Site</string>
+     </property>
+     <layout class="QVBoxLayout" name="verticalLayout">
+      <item>
+       <layout class="QHBoxLayout">
+        <property name="spacing">
+         <number>6</number>
+        </property>
+        <property name="margin">
+         <number>0</number>
+        </property>
+        <item>
+         <spacer name="Spacer9">
+          <property name="orientation">
+           <enum>Qt::Horizontal</enum>
+          </property>
+          <property name="sizeType">
+           <enum>QSizePolicy::Expanding</enum>
+          </property>
+          <property name="sizeHint" stdset="0">
+           <size>
+            <width>20</width>
+            <height>20</height>
+           </size>
+          </property>
+         </spacer>
+        </item>
+        <item>
+         <widget class="QPushButton" name="buttonClearCacheMOT">
+          <property name="text">
+           <string>Clear cache</string>
+          </property>
+         </widget>
+        </item>
+       </layout>
+      </item>
+      <item>
+       <layout class="QHBoxLayout" name="Refresh">
+        <property name="spacing">
+         <number>6</number>
+        </property>
+        <property name="margin">
+         <number>0</number>
+        </property>
+        <item>
+         <spacer name="horizontalSpacer">
+          <property name="orientation">
+           <enum>Qt::Horizontal</enum>
+          </property>
+          <property name="sizeHint" stdset="0">
+           <size>
+            <width>20</width>
+            <height>20</height>
+           </size>
+          </property>
+         </spacer>
+        </item>
+        <item>
+         <widget class="QCheckBox" name="CheckBoxAddRefresh">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="text">
+           <string>Add refresh header of seconds</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QLineEdit" name="EdtSecRefresh">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="text">
+           <string/>
+          </property>
+          <property name="maxLength">
+           <number>4</number>
+          </property>
+         </widget>
+        </item>
+       </layout>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item>
+    <spacer name="verticalSpacer">
+     <property name="orientation">
+      <enum>Qt::Vertical</enum>
+     </property>
+     <property name="sizeHint" stdset="0">
+      <size>
+       <width>20</width>
+       <height>0</height>
+      </size>
+     </property>
+    </spacer>
+   </item>
+   <item>
+    <widget class="QGroupBox" name="EPGGroup">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
+     </property>
+     <property name="minimumSize">
+      <size>
+       <width>0</width>
+       <height>0</height>
+      </size>
+     </property>
+     <property name="title">
+      <string>EPG - Electronic Programme Guide</string>
+     </property>
+     <layout class="QVBoxLayout" name="verticalLayout_2">
+      <item>
+       <layout class="QHBoxLayout">
+        <property name="spacing">
+         <number>6</number>
+        </property>
+        <property name="margin">
+         <number>0</number>
+        </property>
+        <item>
+         <spacer name="Spacer2">
+          <property name="orientation">
+           <enum>Qt::Horizontal</enum>
+          </property>
+          <property name="sizeType">
+           <enum>QSizePolicy::Expanding</enum>
+          </property>
+          <property name="sizeHint" stdset="0">
+           <size>
+            <width>20</width>
+            <height>20</height>
+           </size>
+          </property>
+         </spacer>
+        </item>
+        <item>
+         <widget class="QPushButton" name="buttonClearCacheEPG">
+          <property name="text">
+           <string>Clear cache</string>
+          </property>
+         </widget>
+        </item>
+       </layout>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item>
+    <spacer name="verticalSpacer_2">
+     <property name="orientation">
+      <enum>Qt::Vertical</enum>
+     </property>
+     <property name="sizeHint" stdset="0">
+      <size>
+       <width>20</width>
+       <height>0</height>
+      </size>
+     </property>
+    </spacer>
+   </item>
+   <item>
+    <layout class="QHBoxLayout" name="horizontalLayout">
+     <item>
+      <spacer name="Spacer5">
+       <property name="orientation">
+        <enum>Qt::Horizontal</enum>
+       </property>
+       <property name="sizeType">
+        <enum>QSizePolicy::Expanding</enum>
+       </property>
+       <property name="sizeHint" stdset="0">
+        <size>
+         <width>20</width>
+         <height>20</height>
+        </size>
+       </property>
+      </spacer>
+     </item>
+     <item>
+      <widget class="QPushButton" name="buttonOk">
+       <property name="text">
+        <string>&OK</string>
+       </property>
+       <property name="autoDefault">
+        <bool>false</bool>
+       </property>
+       <property name="default">
+        <bool>true</bool>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
+  </layout>
+ </widget>
+ <tabstops>
+  <tabstop>CheckBoxAddRefresh</tabstop>
+  <tabstop>EdtSecRefresh</tabstop>
+  <tabstop>buttonClearCacheMOT</tabstop>
+  <tabstop>buttonClearCacheEPG</tabstop>
+  <tabstop>buttonOk</tabstop>
+ </tabstops>
+ <resources>
+  <include location="res/icons.qrc"/>
+ </resources>
+ <connections>
+  <connection>
+   <sender>buttonOk</sender>
+   <signal>clicked()</signal>
+   <receiver>CMultSettingsDlgBase</receiver>
+   <slot>accept()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>20</x>
+     <y>20</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>20</x>
+     <y>20</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+</ui>
diff --git a/src/GUI-QT/RigDlg.cpp b/src/GUI-QT/RigDlg.cpp
new file mode 100644
index 0000000..6fd4744
--- /dev/null
+++ b/src/GUI-QT/RigDlg.cpp
@@ -0,0 +1,217 @@
+/******************************************************************************\
+ * British Broadcasting Corporation * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Julian Cable, Andrea Russo
+ *
+ * Description:
+ * Settings for the receiver
+ * Perhaps this should be Receiver Controls rather than Settings
+ * since selections take effect immediately and there is no apply/cancel
+ * feature. This makes sense, since one wants enable/disable GPS, Rig, Smeter
+ * to be instant and mute/savetofile etc.
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "RigDlg.h"
+#include "DialogUtil.h"
+#include <QTreeWidgetItem>
+#include "ThemeCustomizer.h"
+
+/* Implementation *************************************************************/
+
+RigDlg::RigDlg(CRig& nrig, QWidget* parent) :
+    QDialog(parent),
+    rig(nrig), rigmap(), bComboBoxPortMutex(FALSE)
+{
+    setAttribute(Qt::WA_QuitOnClose, false);
+    setupUi(this);
+#if QWT_VERSION < 0x060100
+    sMeter->setScalePosition(QwtThermo::TopScale);
+#else
+    sMeter->setScalePosition(QwtThermo::TrailingScale);
+#endif
+
+    map<rig_model_t,CHamlib::SDrRigCaps> r;
+
+    rig.GetRigList(r);
+    modified->setEnabled(false);
+    //rigTypes->setColumnCount(2);
+    rigTypes->setSortingEnabled(false);
+    QTreeWidgetItem* none = new QTreeWidgetItem(rigTypes);
+	none->setText(0, "None");
+	none->setData(0, Qt::UserRole, RIG_MODEL_NONE);
+    for(map<rig_model_t,CHamlib::SDrRigCaps>::const_iterator i=r.begin(); i!=r.end(); i++)
+    {
+		rig_model_t model_num = i->first;
+        CHamlib::SDrRigCaps rc =  i->second;
+        QTreeWidgetItem* mfr, *model;
+        if(rc.strManufacturer=="" || rc.strModelName=="")
+        {
+            continue;
+        }
+        QList<QTreeWidgetItem *> l = rigTypes->findItems(rc.strManufacturer.c_str(), Qt::MatchFixedString);
+        if(l.size()==0)
+        {
+            mfr = new QTreeWidgetItem(rigTypes);
+            mfr->setText(0,rc.strManufacturer.c_str());
+			mfr->setFlags(mfr->flags() & ~Qt::ItemIsSelectable);
+        }
+        else
+        {
+            mfr = l.first();
+        }
+        model = new QTreeWidgetItem(mfr);
+        model->setText(0,rc.strModelName.c_str());
+		model->setData(0, Qt::UserRole, model_num);
+		rigmap[model_num] = rc.strModelName;
+    }
+    rigTypes->setSortingEnabled(false);
+    rigTypes->sortItems(9, Qt::AscendingOrder);
+
+   	InitSMeter(this, sMeter);
+
+    APPLY_CUSTOM_THEME();
+}
+
+RigDlg::~RigDlg()
+{
+}
+
+void RigDlg::showEvent(QShowEvent*)
+{
+	/* Port selection */
+	bComboBoxPortMutex = TRUE;
+	map<string,string> ports;
+	rig.GetPortList(ports);
+	comboBoxPort->clear();
+	prev_port = rig.GetComPort();
+	int index = -1;
+	for (map<string,string>::const_iterator i=ports.begin(); i!=ports.end(); i++)
+	{
+		comboBoxPort->addItem(i->first.c_str(), i->second.c_str());
+		if (i->second.compare(prev_port) == 0)
+			index = comboBoxPort->count() - 1; /* index is zero based */
+	}
+	if (index != -1)
+	{
+		comboBoxPort->setCurrentIndex(index);
+	}
+	else
+	{	/* Add the port to the list if not found */
+		comboBoxPort->addItem(prev_port.c_str(), prev_port.c_str());
+		comboBoxPort->setCurrentIndex(comboBoxPort->findText(prev_port.c_str()));
+	}
+	bComboBoxPortMutex = FALSE;
+
+	/* Rig model selection */
+    prev_rig_model = rig.GetHamlibModelID();
+    if (prev_rig_model == RIG_MODEL_NONE)
+    {
+        rigTypes->setCurrentItem(rigTypes->topLevelItem(0)); /* None */
+    }
+    else
+    {
+        map<rig_model_t,string>::const_iterator m = rigmap.find(prev_rig_model);
+        if(m!=rigmap.end())
+        {
+            QString name(m->second.c_str());
+            QList<QTreeWidgetItem *> l = rigTypes->findItems(name, Qt::MatchExactly | Qt::MatchRecursive);
+            if(l.size()>0) {
+                rigTypes->setCurrentItem(l.front());
+                selectedRigType->setText(name);
+            }
+        }
+    }
+
+	connect(&rig, SIGNAL(sigstr(double)), this, SLOT(onSigstr(double)));
+}
+
+void RigDlg::hideEvent(QHideEvent*)
+{
+	disconnect(&rig, SIGNAL(sigstr(double)), this, SLOT(onSigstr(double)));
+}
+
+void
+RigDlg::on_rigTypes_itemSelectionChanged()
+{
+	QList<QTreeWidgetItem*> l = rigTypes->selectedItems();
+	if(l.count()==1) {
+		const QTreeWidgetItem* item = l.first();
+		selectedRigType->setText(item->text(0));
+		rig.SetHamlibModelID(item->data(0, Qt::UserRole).toInt());
+	}
+}
+
+void
+RigDlg::on_modified_stateChanged(int state)
+{
+	rig.SetEnableModRigSettings(state?false:true);
+}
+
+void
+RigDlg::on_testRig_clicked()
+{
+	rig.SetComPort(comboBoxPort->itemData(comboBoxPort->currentIndex()).toString().toStdString());
+	rig.SetHamlibModelID(rigTypes->currentItem()->data(0, Qt::UserRole).toInt());
+	rig.subscribe();
+}
+
+void
+RigDlg::on_buttonBox_accepted()
+{
+	rig.SetComPort(getComboBoxComPort().toStdString());
+	rig.SetHamlibModelID(rigTypes->currentItem()->data(0, Qt::UserRole).toInt());
+	rig.unsubscribe();
+	close();
+}
+
+void
+RigDlg::on_buttonBox_rejected()
+{
+	rig.SetComPort(prev_port);
+	rig.SetHamlibModelID(prev_rig_model);
+	rig.unsubscribe();
+	close();
+}
+
+void
+RigDlg::on_comboBoxPort_editTextChanged(const QString&)
+{
+	if (bComboBoxPortMutex == FALSE)
+		rig.SetComPort(getComboBoxComPort().toStdString());
+}
+
+QString
+RigDlg::getComboBoxComPort()
+{
+	QString strPort;
+	const int index = comboBoxPort->currentIndex();
+	if (comboBoxPort->currentText().compare(comboBoxPort->itemText(index)))
+		strPort = comboBoxPort->currentText();
+	else
+		strPort = comboBoxPort->itemData(index).toString();
+	return strPort;
+}
+
+void
+RigDlg::onSigstr(double r)
+{
+	sMeter->setValue(r);
+}
diff --git a/src/GUI-QT/RigDlg.h b/src/GUI-QT/RigDlg.h
new file mode 100644
index 0000000..d088e67
--- /dev/null
+++ b/src/GUI-QT/RigDlg.h
@@ -0,0 +1,72 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Julian Cable, Andrea Russo
+ *
+ * Description:
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#ifndef __RIGDLG_H
+#define __RIGDLG_H
+
+#include "../util/Utilities.h"
+#include "../util-QT/Rig.h"
+#include "ui_RigDlg.h"
+#include <QDialog>
+#include <QTimer>
+#include <set>
+#include <map>
+
+/* Definitions ****************************************************************/
+
+/* Classes ********************************************************************/
+
+class RigDlg : public QDialog, public Ui_RigDlg
+{
+	Q_OBJECT
+
+public:
+    RigDlg(CRig&, QWidget* parent = 0);
+    virtual ~RigDlg();
+
+protected:
+    void		showEvent(QShowEvent* pEvent);
+    void		hideEvent(QHideEvent* pEvent);
+    QString		getComboBoxComPort();
+
+    CRig&		rig;
+    rig_model_t		prev_rig_model;
+    string		prev_port;
+    map<rig_model_t,string> rigmap;
+    _BOOLEAN	bComboBoxPortMutex;
+
+public slots:
+    void		on_rigTypes_itemSelectionChanged(); 
+    void		on_modified_stateChanged(int);
+    void		on_testRig_clicked();
+    void		on_buttonBox_accepted();
+    void		on_buttonBox_rejected();
+    void		on_comboBoxPort_editTextChanged(const QString &);
+    void		onSigstr(double);
+};
+
+#endif
diff --git a/src/GUI-QT/RigDlg.ui b/src/GUI-QT/RigDlg.ui
new file mode 100644
index 0000000..8c92970
--- /dev/null
+++ b/src/GUI-QT/RigDlg.ui
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>RigDlg</class>
+ <widget class="QDialog" name="RigDlg">
+  <property name="windowModality">
+   <enum>Qt::ApplicationModal</enum>
+  </property>
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>404</width>
+    <height>465</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Rig Settings</string>
+  </property>
+  <property name="windowIcon">
+   <iconset resource="res/icons.qrc">
+    <normaloff>:/icons/MainIcon.svg</normaloff>:/icons/MainIcon.svg</iconset>
+  </property>
+  <property name="sizeGripEnabled">
+   <bool>true</bool>
+  </property>
+  <layout class="QGridLayout" name="gridLayout">
+   <item row="0" column="0" colspan="3">
+    <widget class="QTreeWidget" name="rigTypes">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Expanding" vsizetype="MinimumExpanding">
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
+     </property>
+     <column>
+      <property name="text">
+       <string notr="true">Rig Types</string>
+      </property>
+     </column>
+    </widget>
+   </item>
+   <item row="1" column="0">
+    <widget class="QLabel" name="label_2">
+     <property name="text">
+      <string>Connected Rig</string>
+     </property>
+    </widget>
+   </item>
+   <item row="1" column="1">
+    <widget class="QLineEdit" name="selectedRigType">
+     <property name="readOnly">
+      <bool>true</bool>
+     </property>
+    </widget>
+   </item>
+   <item row="1" column="2">
+    <widget class="QCheckBox" name="modified">
+     <property name="text">
+      <string>Modified for DRM</string>
+     </property>
+    </widget>
+   </item>
+   <item row="2" column="0">
+    <widget class="QLabel" name="labelPort">
+     <property name="text">
+      <string>Com Port</string>
+     </property>
+    </widget>
+   </item>
+   <item row="2" column="1">
+    <widget class="QComboBox" name="comboBoxPort">
+     <property name="editable">
+      <bool>true</bool>
+     </property>
+    </widget>
+   </item>
+   <item row="3" column="0" colspan="2">
+    <widget class="QGroupBox" name="groupBox_8">
+     <property name="title">
+      <string>S-Meter</string>
+     </property>
+     <layout class="QHBoxLayout" name="horizontalLayout_3">
+      <item>
+       <widget class="QwtThermo" name="sMeter" native="true"/>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item row="3" column="2">
+    <widget class="QPushButton" name="testRig">
+     <property name="text">
+      <string>Test</string>
+     </property>
+    </widget>
+   </item>
+   <item row="4" column="2">
+    <widget class="QDialogButtonBox" name="buttonBox">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
+     </property>
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <property name="standardButtons">
+      <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+     </property>
+     <property name="centerButtons">
+      <bool>false</bool>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>QwtThermo</class>
+   <extends>QWidget</extends>
+   <header>qwt_thermo.h</header>
+  </customwidget>
+ </customwidgets>
+ <resources>
+  <include location="res/icons.qrc"/>
+ </resources>
+ <connections/>
+</ui>
diff --git a/src/GUI-QT/Schedule.cpp b/src/GUI-QT/Schedule.cpp
new file mode 100644
index 0000000..1222688
--- /dev/null
+++ b/src/GUI-QT/Schedule.cpp
@@ -0,0 +1,561 @@
+/******************************************************************************\
+ * British Broadcasting Corporation
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer, Stephane Fillod, Tomi Manninen, Andrea Russo, Julian Cable
+ *
+ *
+ * Description: DRM and AM Schedules
+ *
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "Schedule.h"
+#include "../tables/TableStations.h"
+#include <QNetworkRequest>
+#include <QNetworkReply>
+#include <QApplication>
+#include <QDateTime>
+#include <QMessageBox>
+#include <QFileInfo>
+#include <ctime>
+#ifdef _WIN32
+#include "../windows/platform_util.h"
+#endif
+#ifdef __ANDROID_API__
+#include "../android/platform_util.h"
+#endif
+
+/* Implementation *************************************************************/
+
+CSchedule::CSchedule():
+ListTargets(), ListCountries(), ListLanguages(),
+  StationsTable(),iSecondsPreview(0)
+{
+}
+
+void CSchedule::SetSecondsPreview(int iSec)
+{
+    iSecondsPreview = iSec;
+}
+
+int CSchedule::GetSecondsPreview() const
+{
+    return iSecondsPreview;
+}
+
+void CSchedule::UpdateStringListForFilter(const CStationsItem& StationsItem)
+{
+	if (!ListTargets.contains(StationsItem.strTarget))
+		ListTargets.append(StationsItem.strTarget);
+
+	if (!ListCountries.contains(StationsItem.strCountry))
+		ListCountries.append(StationsItem.strCountry);
+
+	if (!ListLanguages.contains(StationsItem.strLanguage))
+		ListLanguages.append(StationsItem.strLanguage);
+}
+
+void CSchedule::LoadSchedule(const QString & schedFileName)
+{
+	string filename(schedFileName.toUtf8().constData());
+	QApplication::setOverrideCursor(Qt::BusyCursor);
+	ListTargets = QStringList("");
+	ListCountries = QStringList("");
+	ListLanguages = QStringList("");
+	StationsTable.clear();
+	FILE* pFile = fopen(filename.c_str(), "r");
+	if(pFile)
+	{
+		if(schedFileName.contains("ini"))
+			ReadINIFile(pFile);
+		else
+			ReadCSVFile(pFile);
+		fclose(pFile);
+	}
+	ListTargets.sort();
+	ListCountries.sort();
+	ListLanguages.sort();
+	QApplication::restoreOverrideCursor();
+}
+
+void CSchedule::ReadINIFile(FILE* pFile)
+{
+	const int	iMaxLenName = 256;
+	char	cName[iMaxLenName], *r;
+	int		iFileStat, n;
+	_BOOLEAN	bReadOK = TRUE;
+
+	r = fgets(cName, iMaxLenName, pFile); /* [DRMSchedule] */
+	do
+	{
+		CStationsItem StationsItem;
+
+		/* Start stop time */
+		int iStartTime, iStopTime;
+		iFileStat = fscanf(pFile, "StartStopTimeUTC=%04d-%04d\n",
+			&iStartTime, &iStopTime);
+
+		if (iFileStat != 2)
+			bReadOK = FALSE;
+		else
+		{
+			StationsItem.SetStartTime(iStartTime);
+			StationsItem.SetStopTime(iStopTime);
+		}
+
+		/* Days */
+		/* Init days with the "irregular" marker in case no valid string could
+		be read */
+		QString strNewDaysFlags = FLAG_STR_IRREGULAR_TRANSM;
+
+		iFileStat = fscanf(pFile, "Days[SMTWTFS]=%255[^\n|^\r]\n", cName);
+		if (iFileStat != 1)
+			n = fscanf(pFile, "\n");
+		else
+		{
+			/* Check for length of input string (must be 7) */
+			QString strTMP(cName);
+			if (strTMP.length() == 7)
+				strNewDaysFlags = strTMP;
+		}
+
+		/* Frequency */
+		iFileStat = fscanf(pFile, "Frequency=%d\n", &StationsItem.iFreq);
+		if (iFileStat != 1)
+			bReadOK = FALSE;
+
+		/* Target */
+		iFileStat = fscanf(pFile, "Target=%255[^\n|^\r]\n", cName);
+		if (iFileStat != 1)
+			n = fscanf(pFile, "\n");
+		else
+			StationsItem.strTarget = cName;
+
+		/* Power */
+		iFileStat = fscanf(pFile, "Power=%255[^\n|^\r]\n", cName);
+		if (iFileStat != 1)
+			n = fscanf(pFile, "\n");
+		else
+			StationsItem.rPower = QString(cName).toFloat();
+
+		/* Name of the station */
+		iFileStat = fscanf(pFile, "Programme=%255[^\n|^\r]\n", cName);
+		if (iFileStat != 1)
+			n = fscanf(pFile, "\n");
+		else
+			StationsItem.strName = cName;
+
+		/* Language */
+		iFileStat = fscanf(pFile, "Language=%255[^\n|^\r]\n", cName);
+		if (iFileStat != 1)
+			n = fscanf(pFile, "\n");
+		else
+			StationsItem.strLanguage = cName;
+
+		/* Site */
+		iFileStat = fscanf(pFile, "Site=%255[^\n|^\r]\n", cName);
+		if (iFileStat != 1)
+			n = fscanf(pFile, "\n");
+		else
+			StationsItem.strSite = cName;
+
+		/* Country */
+		iFileStat = fscanf(pFile, "Country=%255[^\n|^\r]\n", cName);
+		if (iFileStat != 1)
+			n = fscanf(pFile, "\n");
+		else
+			StationsItem.strCountry = cName;
+
+		iFileStat = fscanf(pFile, "\n");
+
+		/* Check for error before applying data */
+		if (bReadOK == TRUE)
+		{
+			/* Set "days flag string" and generate strings for displaying active
+			days */
+			StationsItem.SetDaysFlagString(strNewDaysFlags);
+
+			/* Add new item in table */
+			StationsTable.push_back(StationsItem);
+
+			UpdateStringListForFilter(StationsItem);
+		}
+	} while (!((iFileStat == EOF) || (bReadOK == FALSE)));
+
+	(void)r; (void)n;
+}
+
+void CSchedule::ReadCSVFile(FILE* pFile)
+{
+	const int	iMaxLenRow = 1024;
+	char		cRow[iMaxLenRow];
+	CStationData data;
+
+	do {
+		CStationsItem StationsItem;
+
+		char* r = fgets(cRow, iMaxLenRow, pFile); (void)r;
+		QStringList fields;
+		stringstream ss(cRow);
+		do {
+			string s;
+			getline(ss, s, ';');
+			fields.push_back(s.c_str());
+		} while(!ss.eof());
+
+		StationsItem.iFreq = floor(fields[0].toFloat());
+
+		if(fields[1] == "")
+		{
+			StationsItem.SetStartTime(0);
+			StationsItem.SetStopTime(2400);
+		}
+		else
+		{
+			QStringList times = fields[1].split("-");
+			if(times.count()==2)
+			{
+				StationsItem.SetStartTime(times[0].toInt());
+				StationsItem.SetStopTime(times[1].toInt());
+			}
+		}
+
+		if(fields[2].length()>0)
+		{
+			stringstream ss(fields[2].toUtf8().constData());
+			char c;
+			enum Days { Sunday=0, Monday=1, Tuesday=2, Wednesday=3,
+				Thursday=4, Friday=5, Saturday=6
+			};
+			Days first=Sunday, last=Sunday;
+			enum { no, in, done } range_state = no;
+			// Days[SMTWTFS]=1111111
+			QString strDays = "0000000";
+			while(!ss.eof())
+			{
+				ss >> c;
+				switch(c)
+				{
+				case '-':
+					range_state = in;
+					break;
+				case 'M':
+					ss >> c;
+					last = Monday;
+					break;
+				case 'T':
+					ss >> c;
+					last = (c=='u')?Tuesday:Thursday;
+					break;
+				case 'W':
+					ss >> c;
+					last = Wednesday;
+					break;
+				case 'F':
+					ss >> c;
+					last = Friday;
+					break;
+				case 'S':
+					ss >> c;
+					last = (c=='u')?Sunday:Saturday;
+					break;
+				}
+				switch(range_state)
+				{
+				case no:
+					strDays[last] = '1';
+					break;
+				case in:
+					first = last;
+					range_state = done;
+					break;
+				case done:
+					if(first<last)
+					{
+						for(int d=first; d<=last; d++)
+							strDays[d] = '1';
+					}
+					range_state = no;
+					break;
+				}
+			}
+			StationsItem.SetDaysFlagString(strDays);
+		}
+		else
+			StationsItem.SetDaysFlagString("1111111");
+
+		//StationsItem.rPower = 0.0;
+		//0   ;1        ;2    ;3  ;4               ;5;6;7;8;9;10
+		//1170;1600-1700;Mo-Fr;USA;Voice of America;E; ; ;0; ;
+		string homecountry;
+		int fieldcount = fields.size();
+		if(fieldcount>3)
+		{
+			homecountry = fields[3].toUtf8().constData();
+			string c = data.itu_r_country(homecountry);
+			if(c == "")
+				c = homecountry;
+			StationsItem.strCountry = QString::fromUtf8(c.c_str());
+		}
+
+		if(fieldcount>4)
+			StationsItem.strName = fields[4];
+
+		if(fieldcount>5)
+		{
+			string l = data.eibi_language(fields[5].toUtf8().constData());
+			StationsItem.strLanguage = QString::fromUtf8(l.c_str());
+		}
+
+		if(fieldcount>6)
+		{
+			string s = fields[6].toUtf8().constData();
+			string t = data.eibi_target(s);
+			if(t == "")
+			{
+				string c = data.itu_r_country(s);
+				if(c == "")
+					StationsItem.strTarget = QString::fromUtf8(s.c_str());
+				else
+					StationsItem.strTarget = QString::fromUtf8(c.c_str());
+			}
+			else
+			{
+				StationsItem.strTarget = QString::fromUtf8(t.c_str());
+			}
+		}
+		string country;
+		string stn;
+		if(fieldcount>7)
+		{
+			StationsItem.strSite = fields[7];
+			string s  = fields[7].toUtf8().constData();
+			if(s=="") // unknown or main Tx site of the home country
+			{
+				country = homecountry;
+			}
+			else
+			{
+				size_t i=0;
+				s += '-';
+				if(s[0]=='/') // transmitted from another country
+					i++;
+				string a,b;
+				while(s[i]!='-')
+					a += s[i++];
+				i++;
+				if(i<s.length())
+					while(s[i]!='-')
+						b += s[i++];
+				if(s[0]=='/')
+				{
+					country = a;
+					stn = b;
+				}
+				else
+				{
+					if(a.length()==3)
+					{
+						country = a;
+						stn = b;
+					}
+					else
+					{
+						country = homecountry;
+						stn = a;
+					}
+				}
+			}
+		}
+		else
+		{
+			country = homecountry;
+		}
+		QString site = QString::fromUtf8(data.eibi_station(country, stn).c_str());
+		if(site == "")
+		{
+			//cout << StationsItem.iFreq << " [" << StationsItem.strSite << "] [" << country << "] [" << stn << "]" << endl;
+		}
+		else
+		{
+			StationsItem.strSite = site;
+		}
+
+		/* Add new item in table */
+		StationsTable.push_back(StationsItem);
+
+		UpdateStringListForFilter(StationsItem);
+
+	} while(!feof(pFile));
+}
+
+Station::EState CSchedule::GetState(const int iPos)
+{
+    if((int)StationsTable.size()>iPos)
+        return StationsTable[iPos].stateAt(time(NULL), GetSecondsPreview());
+    return Station::IS_INACTIVE;
+}
+
+bool CSchedule::CheckFilter(const int iPos)
+{
+    const CStationsItem& station = StationsTable[iPos];
+    if(targetFilter != "" && targetFilter != station.strTarget)
+        return false;
+    if(countryFilter != "" && countryFilter != station.strCountry)
+        return false;
+    if(languageFilter != "" && languageFilter != station.strLanguage)
+        return false;
+    return true;
+}
+
+Station::EState CStationsItem::stateAt(time_t ltime, int previewSeconds) const
+{
+	if (activeAt(ltime) == TRUE)
+	{
+		time_t dt = ltime+NUM_SECONDS_SOON_INACTIVE;
+
+		/* Check if the station soon will be inactive */
+		if (activeAt(dt) == TRUE)
+			return Station::IS_ACTIVE;
+		else
+			return Station::IS_SOON_INACTIVE;
+	}
+	else
+	{
+		for(time_t dt = ltime; dt < ltime + previewSeconds; dt += 60)
+		{
+			if (activeAt(dt) == TRUE)
+			{
+				return Station::IS_PREVIEW;
+			}
+		}
+		return Station::IS_INACTIVE;
+	}
+}
+
+#ifdef _WIN32
+extern time_t timegm(struct tm *tm); // defined in Scheduler.cpp
+#endif
+
+_BOOLEAN CStationsItem::activeAt(time_t wantedTime) const
+{
+	struct tm ptm = *gmtime (&wantedTime);
+	ptm.tm_hour = 0;
+	ptm.tm_min = 0;
+	ptm.tm_sec = 0;
+	time_t wantedDay = timegm(&ptm); // start of daytime
+
+	/* Get start time */
+	time_t broadcastStart = wantedDay + 60*(60*iStartHour+iStartMinute);
+
+	/* Get stop time */
+	time_t broadcastStop = wantedDay + 60*(60*iStopHour+iStopMinute);
+
+	/* Check, if stop time is on next day */
+	if(broadcastStop < broadcastStart)
+	{
+		broadcastStop += 86400l;
+	}
+
+	/* Check day
+	tm_wday: day of week (0 - 6; Sunday = 0). "strDaysFlags" are coded with
+	pseudo binary representation. A one signals that day is active. The most
+	significant 1 is the sunday, then followed the monday and so on. */
+	if ((strDaysFlags[ptm.tm_wday] == CHR_ACTIVE_DAY_MARKER) ||
+		/* Check also for special case: days are 0000000. This is reserved for
+		DRM test transmissions or irregular transmissions. We define here
+		that these stations are transmitting every day */
+		(strDaysFlags == FLAG_STR_IRREGULAR_TRANSM))
+	{
+		if((broadcastStart <= wantedTime) && (wantedTime < broadcastStop))
+		{
+			return TRUE;
+		}
+		else
+		{
+			/* yesterday's broadcast might still be on */
+			int wday = ptm.tm_wday - 1;
+			if(wday < 0)
+				wday = 6;
+			if ((strDaysFlags[wday] == CHR_ACTIVE_DAY_MARKER) || (strDaysFlags == FLAG_STR_IRREGULAR_TRANSM))
+			{
+				broadcastStart -= 86400l;
+				broadcastStop -= 86400l;
+				if((broadcastStart <= wantedTime) && (wantedTime < broadcastStop))
+				{
+					return TRUE;
+				}
+			}
+		}
+	}
+	return FALSE;
+}
+
+void CStationsItem::SetDaysFlagString(const QString& strNewDaysFlags)
+{
+	/* Set internal "days flag" string and "show days" string */
+	strDaysFlags = strNewDaysFlags;
+	strDaysShow = "";
+
+	/* Init days string vector */
+	const QString strDayDef [] =
+	{
+		QObject::tr("Sun"),
+		QObject::tr("Mon"),
+		QObject::tr("Tue"),
+		QObject::tr("Wed"),
+		QObject::tr("Thu"),
+		QObject::tr("Fri"),
+		QObject::tr("Sat")
+	};
+
+	/* First test for day constellations which allow to apply special names */
+	if (strDaysFlags == FLAG_STR_IRREGULAR_TRANSM)
+		strDaysShow = QObject::tr("irregular");
+	else if (strDaysFlags == "1111111")
+		strDaysShow = QObject::tr("daily");
+	else if (strDaysFlags == "1111100")
+		strDaysShow = QObject::tr("from Sun to Thu");
+	else if (strDaysFlags == "1111110")
+		strDaysShow = QObject::tr("from Sun to Fri");
+	else if (strDaysFlags == "0111110")
+		strDaysShow = QObject::tr("from Mon to Fri");
+	else if (strDaysFlags == "0111111")
+		strDaysShow = QObject::tr("from Mon to Sat");
+	else
+	{
+		/* No special name could be applied, just list all active days */
+		for (int i = 0; i < 7; i++)
+		{
+			/* Check if day is active */
+			if (strDaysFlags[i] == CHR_ACTIVE_DAY_MARKER)
+			{
+				/* Set commas in between the days, to not set a comma at
+				the beginning */
+				if (strDaysShow != "")
+					strDaysShow += ",";
+
+				/* Add current day */
+				strDaysShow += strDayDef[i];
+			}
+		}
+	}
+}
diff --git a/src/GUI-QT/Schedule.h b/src/GUI-QT/Schedule.h
new file mode 100644
index 0000000..618129a
--- /dev/null
+++ b/src/GUI-QT/Schedule.h
@@ -0,0 +1,151 @@
+/******************************************************************************\
+ * British Broadcasting Corporation
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer, Stephane Fillod, Tomi Manninen, Andrea Russo,Julian Cable
+ *
+ *
+ * Description: DRM and AM Schedules
+ *
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+#ifndef __SCHEDULE_H
+#define __SCHEDULE_H
+
+#include <QString>
+#include <QStringList>
+#include <QUrl>
+#include "../util/Vector.h"
+
+/* Definitions ****************************************************************/
+
+#define DRM_SCHEDULE_URL	"http://www.baseportal.com/cgi-bin/baseportal.pl?htx=/drmdx/scheduleini2"
+
+/* File handle type */
+#ifdef _WIN32
+# define FILE_HANDLE					HANDLE
+#else
+# define FILE_HANDLE					int
+#endif
+
+/* Name for DRM and AM schedule file. If you change something here, make sure
+   that you also change the strings and help texts!  */
+#define DRMSCHEDULE_INI_FILE_NAME		"DRMSchedule.ini"
+#define AMSCHEDULE_INI_FILE_NAME		"AMSchedule.ini"
+#define AMSCHEDULE_CSV_FILE_NAME		"AMSchedule.csv"
+
+/* Time definitions for preview */
+#define NUM_SECONDS_PREV_5MIN			300
+#define NUM_SECONDS_PREV_15MIN			900
+#define NUM_SECONDS_PREV_30MIN			1800
+
+#define NUM_SECONDS_SOON_INACTIVE		600
+
+/* String definitions for schedule days */
+#define FLAG_STR_IRREGULAR_TRANSM		"0000000"
+#define CHR_ACTIVE_DAY_MARKER			'1'
+
+#include <iostream>
+
+namespace Station {
+	enum EState {IS_ACTIVE, IS_INACTIVE, IS_PREVIEW, IS_SOON_INACTIVE};
+}
+
+class CStationsItem
+{
+public:
+	CStationsItem() : iStartHour(0), iStartMinute(0), iStopHour(0),
+		iStopMinute(0), iFreq(0), strName(""),
+		strTarget(""), strLanguage(""), strSite(""),
+		strCountry(""), strDaysFlags(""), strDaysShow(""),
+		rPower((_REAL) 0.0) { }
+
+	Station::EState stateAt(time_t, int) const;
+	_BOOLEAN activeAt(time_t) const;
+	int StartTime() const {return iStartHour * 100 + iStartMinute;}
+	int StopTime() const{return iStopHour * 100 + iStopMinute;}
+	void SetStartTime(const int iStartTime)
+	{
+		/* Recover hours and minutes */
+		iStartHour = iStartTime / 100;
+		iStartMinute = iStartTime - iStartHour * 100;
+	}
+	void SetStopTime(const int iStopTime)
+	{
+		/* Recover hours and minutes */
+		iStopHour = iStopTime / 100;
+		iStopMinute = iStopTime - iStopHour * 100;
+	}
+
+	void SetDaysFlagString(const QString& strNewDaysFlags);
+
+	int		iStartHour;
+	int		iStartMinute;
+	int		iStopHour;
+	int		iStopMinute;
+	int		iFreq;
+	QString	strName;
+	QString	strTarget;
+	QString	strLanguage;
+	QString	strSite;
+	QString	strCountry;
+	QString	strDaysFlags;
+	QString	strDaysShow;
+	_REAL	rPower;
+};
+
+class CSchedule
+{
+public:
+    CSchedule();
+    virtual ~CSchedule() {}
+
+    void ReadINIFile(FILE* pFile);
+    void ReadCSVFile(FILE* pFile);
+
+    int GetNumberOfStations() {return StationsTable.size();}
+    CStationsItem& GetItem(const int iPos) {return StationsTable[iPos];}
+    Station::EState GetState(const int iPos);
+    bool CheckFilter(const int iPos);
+
+    void setCountryFilter(const QString& s) { countryFilter = s; }
+    QString getCountryFilter() const { return countryFilter; }
+    void setLanguageFilter(const QString& s) { languageFilter = s; }
+    QString getLanguageFilter() const { return languageFilter; }
+    void setTargetFilter(const QString& s) { targetFilter = s; }
+    QString getTargetFilter() const { return targetFilter; }
+    void SetSecondsPreview(int iSec);
+    int GetSecondsPreview() const;
+    void LoadSchedule(const QString&);
+    void clear() { StationsTable.clear(); }
+
+    QStringList		ListTargets;
+    QStringList		ListCountries;
+    QStringList		ListLanguages;
+
+protected:
+    void UpdateStringListForFilter(const CStationsItem& StationsItem);
+
+    vector<CStationsItem>	StationsTable;
+    QString                 countryFilter, targetFilter, languageFilter;
+    int                     iSecondsPreview;
+};
+
+#endif
diff --git a/src/GUI-QT/SlideShowViewer.cpp b/src/GUI-QT/SlideShowViewer.cpp
new file mode 100644
index 0000000..4e36b48
--- /dev/null
+++ b/src/GUI-QT/SlideShowViewer.cpp
@@ -0,0 +1,299 @@
+/******************************************************************************\
+ * British Broadcasting Corporation
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	 Julian Cable, David Flamand
+ *
+ * Description: SlideShow Viewer
+ *
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "SlideShowViewer.h"
+#include "../util-QT/Util.h"
+#include "../datadecoding/DABMOT.h"
+#include "../datadecoding/DataDecoder.h"
+#include <QFileDialog>
+#include "ThemeCustomizer.h"
+
+SlideShowViewer::SlideShowViewer(CSettings& Settings, QWidget* parent):
+    CWindow(parent, Settings, "SlideShow"),
+    vecImages(), vecImageNames(), iCurImagePos(-1),
+    bClearMOTCache(false),decoder(NULL)
+{
+    setupUi(this);
+
+    string p = Settings.Get(
+                "Receiver", "datafilesdirectory", string(DEFAULT_DATA_FILES_DIRECTORY));
+
+    strCurrentSavePath = QString::fromUtf8((p+PATH_SEPARATOR+"MOT").c_str());
+
+    /* Update time for color LED */
+    LEDStatus->SetUpdateTime(1000);
+
+    /* Connect controls */
+    connect(ButtonStepBack, SIGNAL(clicked()), this, SLOT(OnButtonStepBack()));
+    connect(ButtonStepForward, SIGNAL(clicked()), this, SLOT(OnButtonStepForward()));
+    connect(ButtonJumpBegin, SIGNAL(clicked()), this, SLOT(OnButtonJumpBegin()));
+    connect(ButtonJumpEnd, SIGNAL(clicked()), this, SLOT(OnButtonJumpEnd()));
+    connect(buttonOk, SIGNAL(clicked()), this, SLOT(close()));
+    connect(actionClear_All, SIGNAL(triggered()), SLOT(OnClearAll()));
+    connect(actionSave, SIGNAL(triggered()), SLOT(OnSave()));
+    connect(actionSave_All, SIGNAL(triggered()), SLOT(OnSaveAll()));
+    connect(actionClose, SIGNAL(triggered()), SLOT(close()));
+    connect(&Timer, SIGNAL(timeout()), this, SLOT(OnTimer()));
+
+    OnClearAll();
+
+    APPLY_CUSTOM_THEME();
+}
+
+SlideShowViewer::~SlideShowViewer()
+{
+}
+
+void SlideShowViewer::OnTimer()
+{
+    if(decoder==NULL)
+        return;
+
+    if (bClearMOTCache)
+    {
+        bClearMOTCache = false;
+        CMOTObject	NewObj;
+        while (decoder->GetMOTObject(NewObj, CDataDecoder::AT_MOTSLIDESHOW))
+        {
+        }
+    }
+
+    CMOTObject NewObj;
+
+    /* Poll the data decoder module for new object */
+    if (decoder->GetMOTObject(NewObj, CDataDecoder::AT_MOTSLIDESHOW) == TRUE)
+    {
+        /* Store received picture */
+        int iCurNumPict = vecImageNames.size();
+        CVector<_BYTE>& imagedata = NewObj.Body.vecData;
+
+        /* Load picture in QT format */
+        QPixmap pic;
+        if (pic.loadFromData(&imagedata[0], imagedata.size()))
+        {
+            /* Set new picture in source factory */
+            vecImages.push_back(pic);
+            vecImageNames.push_back(NewObj.strName.c_str());
+        }
+
+        /* If the last received picture was selected, automatically show
+           new picture */
+        if (iCurImagePos == iCurNumPict - 1)
+            SetImage(iCurNumPict);
+        else
+            UpdateButtons();
+    }
+}
+
+void SlideShowViewer::OnButtonStepBack()
+{
+    SetImage(iCurImagePos-1);
+}
+
+void SlideShowViewer::OnButtonStepForward()
+{
+    SetImage(iCurImagePos+1);
+}
+
+void SlideShowViewer::OnButtonJumpBegin()
+{
+    SetImage(0);
+}
+
+void SlideShowViewer::OnButtonJumpEnd()
+{
+    SetImage(vecImages.size()-1);
+}
+
+void SlideShowViewer::OnSave()
+{
+    /* Create directory for storing the file (if not exists) */
+    CreateDirectories(strCurrentSavePath);
+
+    QString strFilename = strCurrentSavePath + VerifyFilename(vecImageNames[iCurImagePos]);
+    strFilename = QFileDialog::getSaveFileName(this,
+        tr("Save File"), strFilename, tr("Images (*.png *.jpg)"));
+
+    /* Check if user not hit the cancel button */
+    if (!strFilename.isEmpty())
+    {
+        vecImages[iCurImagePos].save(strFilename);
+
+        strCurrentSavePath = QFileInfo(strFilename).path() + PATH_SEPARATOR;
+    }
+}
+
+void SlideShowViewer::OnSaveAll()
+{
+    /* Create directory for storing the files (if not exists) */
+    CreateDirectories(strCurrentSavePath);
+
+    QString strDirectory = QFileDialog::getExistingDirectory(this,
+        tr("Open Directory"), strCurrentSavePath);
+
+    /* Check if user not hit the cancel button */
+    if (!strDirectory.isEmpty())
+    {
+        strCurrentSavePath = strDirectory + PATH_SEPARATOR;
+
+        for(size_t i=0; i<vecImages.size(); i++)
+            vecImages[i].save(strCurrentSavePath + VerifyFilename(vecImageNames[i]));
+    }
+}
+
+void SlideShowViewer::OnClearAll()
+{
+    vecImages.clear();
+    vecImageNames.clear();
+    iCurImagePos = -1;
+    UpdateButtons();
+    LabelTitle->setText("");
+    bClearMOTCache = true;
+}
+
+void SlideShowViewer::eventShow(QShowEvent*)
+{
+    /* Update window */
+    OnTimer();
+
+    /* Activate real-time timer when window is shown */
+    Timer.start(GUI_CONTROL_UPDATE_TIME);
+}
+
+void SlideShowViewer::eventHide(QHideEvent*)
+{
+    /* Deactivate real-time timer so that it does not get new pictures */
+    Timer.stop();
+}
+
+void SlideShowViewer::SetImage(int pos)
+{
+    if(vecImages.size()==0)
+        return;
+    if(pos<0)
+        pos = 0;
+    if(pos>int(vecImages.size()-1))
+        pos = vecImages.size()-1;
+    iCurImagePos = pos;
+    Image->setPixmap(vecImages[pos]);
+    QString imagename = vecImageNames[pos];
+    Image->setToolTip(imagename);
+    imagename =  "<b>" + imagename + "</b>";
+    Linkify(imagename);
+    LabelTitle->setText(imagename);
+    UpdateButtons();
+}
+
+void SlideShowViewer::UpdateButtons()
+{
+    /* Set enable menu entry for saving a picture */
+    if (iCurImagePos < 0)
+    {
+        actionClear_All->setEnabled(false);
+        actionSave->setEnabled(false);
+        actionSave_All->setEnabled(false);
+    }
+    else
+    {
+        actionClear_All->setEnabled(true);
+        actionSave->setEnabled(true);
+        actionSave_All->setEnabled(true);
+    }
+
+    if (iCurImagePos <= 0)
+    {
+        /* We are already at the beginning */
+        ButtonStepBack->setEnabled(false);
+        ButtonJumpBegin->setEnabled(false);
+    }
+    else
+    {
+        ButtonStepBack->setEnabled(true);
+        ButtonJumpBegin->setEnabled(true);
+    }
+
+    if (iCurImagePos == int(vecImages.size()-1))
+    {
+        /* We are already at the end */
+        ButtonStepForward->setEnabled(false);
+        ButtonJumpEnd->setEnabled(false);
+    }
+    else
+    {
+        ButtonStepForward->setEnabled(true);
+        ButtonJumpEnd->setEnabled(true);
+    }
+
+    QString strTotImages = QString().setNum(vecImages.size());
+    QString strNumImage = QString().setNum(iCurImagePos + 1);
+
+    QString strSep("");
+
+    for (int i = 0; i < (strTotImages.length() - strNumImage.length()); i++)
+        strSep += " ";
+
+    LabelCurPicNum->setText(strSep + strNumImage + PATH_SEPARATOR + strTotImages);
+
+    /* If no picture was received, show the following text */
+    if (iCurImagePos < 0)
+    {
+        /* Init text browser window */
+        Image->setText("<center>" + tr("MOT Slideshow Viewer") + "</center>");
+        Image->setToolTip("");
+    }
+}
+
+void SlideShowViewer::setStatus(int i, ETypeRxStatus s)
+{
+    if(i==short_id)
+        SetStatus(LEDStatus, s);
+}
+
+void SlideShowViewer::setServiceInformation(int i, CService s)
+{
+    short_id = i;
+    service = s;
+    decoder = service.DataParam.pDecoder;
+    QString strTitle("MOT Slide Show");
+    QString strServiceID;
+    QString strLabel = QString::fromUtf8(service.strLabel.c_str());
+    if (service.iServiceID != 0)
+    {
+        if (strLabel != "")
+            strLabel += " - ";
+
+        /* Service ID (plot number in hexadecimal format) */
+        strServiceID = "ID:" +
+                       QString().setNum(service.iServiceID, 16).toUpper();
+    }
+
+    /* Add the description on the title of the dialog */
+    if (strLabel != "" || strServiceID != "")
+        strTitle += " [" + strLabel + strServiceID + "]";
+    setWindowTitle(strTitle);
+}
diff --git a/src/GUI-QT/SlideShowViewer.h b/src/GUI-QT/SlideShowViewer.h
new file mode 100644
index 0000000..5c9fdaf
--- /dev/null
+++ b/src/GUI-QT/SlideShowViewer.h
@@ -0,0 +1,73 @@
+/******************************************************************************\
+ * British Broadcasting Corporation
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	 Julian Cable, David Flamand
+ *
+ * Description: MOT Slide Show Viewer
+ *
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#ifndef _SLIDESHOWVIEWER_H
+#define _SLIDESHOWVIEWER_H
+
+#include "ui_SlideShowViewer.h"
+#include "CWindow.h"
+#include "../DrmReceiver.h"
+
+class SlideShowViewer : public CWindow, public Ui_SlideShowViewer
+{
+    Q_OBJECT
+
+public:
+    SlideShowViewer(CSettings&, QWidget* parent = 0);
+    virtual ~SlideShowViewer();
+public slots:
+    void setStatus(int, ETypeRxStatus);
+    void setServiceInformation(int, CService);
+
+protected:
+    virtual void            eventShow(QShowEvent*);
+    virtual void            eventHide(QHideEvent*);
+    void                    SetImage(int);
+    void                    UpdateButtons();
+    QTimer                  Timer;
+    QString                 strCurrentSavePath;
+    vector<QPixmap>         vecImages;
+    vector<QString>         vecImageNames;
+    int                     iCurImagePos;
+    bool                    bClearMOTCache;
+    CService                service;
+    int                     short_id;
+    CDataDecoder*           decoder;
+
+public slots:
+    void OnTimer();
+    void OnButtonStepBack();
+    void OnButtonStepForward();
+    void OnButtonJumpBegin();
+    void OnButtonJumpEnd();
+    void OnSave();
+    void OnSaveAll();
+    void OnClearAll();
+};
+
+#endif
diff --git a/src/GUI-QT/SlideShowViewer.ui b/src/GUI-QT/SlideShowViewer.ui
new file mode 100644
index 0000000..914609f
--- /dev/null
+++ b/src/GUI-QT/SlideShowViewer.ui
@@ -0,0 +1,380 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>SlideShowViewer</class>
+ <widget class="QMainWindow" name="SlideShowViewer">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>399</width>
+    <height>341</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>MainWindow</string>
+  </property>
+  <property name="windowIcon">
+   <iconset resource="res/icons.qrc">
+    <normaloff>:/icons/MainIcon.svg</normaloff>:/icons/MainIcon.svg</iconset>
+  </property>
+  <widget class="QWidget" name="centralwidget">
+   <layout class="QVBoxLayout" name="verticalLayout">
+    <item>
+     <widget class="QLabel" name="LabelTitle">
+      <property name="sizePolicy">
+       <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+        <horstretch>0</horstretch>
+        <verstretch>0</verstretch>
+       </sizepolicy>
+      </property>
+      <property name="lineWidth">
+       <number>0</number>
+      </property>
+      <property name="text">
+       <string><b>Title</b></string>
+      </property>
+      <property name="textFormat">
+       <enum>Qt::RichText</enum>
+      </property>
+      <property name="alignment">
+       <set>Qt::AlignCenter</set>
+      </property>
+      <property name="wordWrap">
+       <bool>true</bool>
+      </property>
+      <property name="openExternalLinks">
+       <bool>true</bool>
+      </property>
+      <property name="textInteractionFlags">
+       <set>Qt::LinksAccessibleByMouse</set>
+      </property>
+     </widget>
+    </item>
+    <item>
+     <widget class="QFrame" name="frame">
+      <property name="sizePolicy">
+       <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+        <horstretch>0</horstretch>
+        <verstretch>0</verstretch>
+       </sizepolicy>
+      </property>
+      <property name="frameShape">
+       <enum>QFrame::StyledPanel</enum>
+      </property>
+      <property name="frameShadow">
+       <enum>QFrame::Sunken</enum>
+      </property>
+      <layout class="QVBoxLayout" name="verticalLayout_2">
+       <property name="spacing">
+        <number>0</number>
+       </property>
+       <property name="margin">
+        <number>0</number>
+       </property>
+       <item>
+        <widget class="QLabel" name="Image">
+         <property name="sizePolicy">
+          <sizepolicy hsizetype="Ignored" vsizetype="Ignored">
+           <horstretch>0</horstretch>
+           <verstretch>0</verstretch>
+          </sizepolicy>
+         </property>
+         <property name="minimumSize">
+          <size>
+           <width>320</width>
+           <height>240</height>
+          </size>
+         </property>
+         <property name="baseSize">
+          <size>
+           <width>320</width>
+           <height>240</height>
+          </size>
+         </property>
+         <property name="autoFillBackground">
+          <bool>false</bool>
+         </property>
+         <property name="styleSheet">
+          <string notr="true">background: white</string>
+         </property>
+         <property name="frameShadow">
+          <enum>QFrame::Plain</enum>
+         </property>
+         <property name="lineWidth">
+          <number>0</number>
+         </property>
+         <property name="text">
+          <string>MOT Slideshow Viewer</string>
+         </property>
+         <property name="textFormat">
+          <enum>Qt::RichText</enum>
+         </property>
+         <property name="alignment">
+          <set>Qt::AlignCenter</set>
+         </property>
+         <property name="textInteractionFlags">
+          <set>Qt::NoTextInteraction</set>
+         </property>
+        </widget>
+       </item>
+      </layout>
+     </widget>
+    </item>
+    <item>
+     <layout class="QHBoxLayout" name="horizontalLayout">
+      <item>
+       <widget class="QLabel" name="TextLabel1">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="text">
+         <string>Receiving Status:</string>
+        </property>
+        <property name="wordWrap">
+         <bool>false</bool>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="CMultColorLED" name="LEDStatus" native="true">
+        <property name="minimumSize">
+         <size>
+          <width>13</width>
+          <height>13</height>
+         </size>
+        </property>
+        <property name="maximumSize">
+         <size>
+          <width>13</width>
+          <height>13</height>
+         </size>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <spacer name="Spacer5">
+        <property name="orientation">
+         <enum>Qt::Horizontal</enum>
+        </property>
+        <property name="sizeType">
+         <enum>QSizePolicy::Expanding</enum>
+        </property>
+        <property name="sizeHint" stdset="0">
+         <size>
+          <width>20</width>
+          <height>20</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+      <item>
+       <widget class="QToolButton" name="ButtonJumpBegin">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="text">
+         <string/>
+        </property>
+        <property name="icon">
+         <iconset resource="res/icons.qrc">
+          <normaloff>:/icons/JumpBegin.png</normaloff>:/icons/JumpBegin.png</iconset>
+        </property>
+        <property name="iconSize">
+         <size>
+          <width>16</width>
+          <height>16</height>
+         </size>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QToolButton" name="ButtonStepBack">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="text">
+         <string/>
+        </property>
+        <property name="icon">
+         <iconset resource="res/icons.qrc">
+          <normaloff>:/icons/StepBack.png</normaloff>:/icons/StepBack.png</iconset>
+        </property>
+        <property name="iconSize">
+         <size>
+          <width>16</width>
+          <height>16</height>
+         </size>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QLabel" name="LabelCurPicNum">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="font">
+         <font>
+          <family>Arial Black</family>
+          <pointsize>14</pointsize>
+         </font>
+        </property>
+        <property name="frameShadow">
+         <enum>QFrame::Sunken</enum>
+        </property>
+        <property name="text">
+         <string>0/0</string>
+        </property>
+        <property name="alignment">
+         <set>Qt::AlignCenter</set>
+        </property>
+        <property name="wordWrap">
+         <bool>false</bool>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QToolButton" name="ButtonStepForward">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="text">
+         <string/>
+        </property>
+        <property name="icon">
+         <iconset resource="res/icons.qrc">
+          <normaloff>:/icons/StepForw.png</normaloff>:/icons/StepForw.png</iconset>
+        </property>
+        <property name="iconSize">
+         <size>
+          <width>16</width>
+          <height>16</height>
+         </size>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QToolButton" name="ButtonJumpEnd">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="text">
+         <string/>
+        </property>
+        <property name="icon">
+         <iconset resource="res/icons.qrc">
+          <normaloff>:/icons/JumpEnd.png</normaloff>:/icons/JumpEnd.png</iconset>
+        </property>
+        <property name="iconSize">
+         <size>
+          <width>16</width>
+          <height>16</height>
+         </size>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <spacer name="Spacer5_2">
+        <property name="orientation">
+         <enum>Qt::Horizontal</enum>
+        </property>
+        <property name="sizeType">
+         <enum>QSizePolicy::Expanding</enum>
+        </property>
+        <property name="sizeHint" stdset="0">
+         <size>
+          <width>18</width>
+          <height>20</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+      <item>
+       <widget class="QPushButton" name="buttonOk">
+        <property name="text">
+         <string>&Close</string>
+        </property>
+        <property name="autoDefault">
+         <bool>true</bool>
+        </property>
+        <property name="default">
+         <bool>true</bool>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </item>
+   </layout>
+  </widget>
+  <widget class="QMenuBar" name="menubar">
+   <property name="geometry">
+    <rect>
+     <x>0</x>
+     <y>0</y>
+     <width>399</width>
+     <height>25</height>
+    </rect>
+   </property>
+   <widget class="QMenu" name="menuFile">
+    <property name="title">
+     <string>&File</string>
+    </property>
+    <addaction name="actionClear_All"/>
+    <addaction name="separator"/>
+    <addaction name="actionSave"/>
+    <addaction name="actionSave_All"/>
+    <addaction name="separator"/>
+    <addaction name="actionClose"/>
+   </widget>
+   <addaction name="menuFile"/>
+  </widget>
+  <action name="actionClear_All">
+   <property name="text">
+    <string>Cl&ear All</string>
+   </property>
+  </action>
+  <action name="actionSave">
+   <property name="text">
+    <string>&Save...</string>
+   </property>
+  </action>
+  <action name="actionSave_All">
+   <property name="text">
+    <string>Save &All...</string>
+   </property>
+  </action>
+  <action name="actionClose">
+   <property name="text">
+    <string>&Close</string>
+   </property>
+  </action>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>CMultColorLED</class>
+   <extends>QWidget</extends>
+   <header>MultColorLED.h</header>
+  </customwidget>
+ </customwidgets>
+ <resources>
+  <include location="res/icons.qrc"/>
+ </resources>
+ <connections/>
+</ui>
diff --git a/src/GUI-QT/SoundCardSelMenu.cpp b/src/GUI-QT/SoundCardSelMenu.cpp
new file mode 100644
index 0000000..dbffe47
--- /dev/null
+++ b/src/GUI-QT/SoundCardSelMenu.cpp
@@ -0,0 +1,400 @@
+/******************************************************************************\
+ * British Broadcasting Corporation
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *      Julian Cable, David Flamand
+ *
+ * Description:
+ *
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+#include "../Parameter.h"
+#include "../DRMSignalIO.h"
+#include "../DataIO.h"
+#include "../DrmReceiver.h"
+#include "../DrmTransmitter.h"
+#include "SoundCardSelMenu.h"
+#include "DialogUtil.h"
+#include <QFileDialog>
+#include "../util-QT/Util.h"
+
+#ifdef HAVE_LIBPCAP
+# define PCAP_FILES " *.pcap"
+#else
+# define PCAP_FILES ""
+#endif
+#ifdef HAVE_LIBSNDFILE
+# define SND_FILES "*.aif* *.au *.flac *.ogg *.rf64 *.snd *.wav"
+#else
+# define SND_FILES "*.if* *.iq* *.pcm* *.txt"
+#endif
+#define SND_FILE1 SND_FILES " "
+#define SND_FILE2 "Sound Files (" SND_FILES ");;"
+#define RSCI_FILES "*.rsA *.rsB *.rsC *.rsD *.rsQ *.rsM" PCAP_FILES
+#define RSCI_FILE1 RSCI_FILES " "
+#define RSCI_FILE2 "MDI/RSCI Files (" RSCI_FILES ");;"
+
+
+static const CHANSEL InputChannelTable[] =
+{
+    { "Left Channel",  CReceiveData::CS_LEFT_CHAN    },
+    { "Right Channel", CReceiveData::CS_RIGHT_CHAN   },
+    { "L + R",         CReceiveData::CS_MIX_CHAN     },
+    { "L - R",         CReceiveData::CS_SUB_CHAN     },
+    { "I/Q Pos",       CReceiveData::CS_IQ_POS       },
+    { "I/Q Neg",       CReceiveData::CS_IQ_NEG       },
+    { "I/Q Pos Zero",  CReceiveData::CS_IQ_POS_ZERO  },
+    { "I/Q Neg Zero",  CReceiveData::CS_IQ_NEG_ZERO  },
+    { "I/Q Pos Split", CReceiveData::CS_IQ_POS_SPLIT },
+    { "I/Q Neg Split", CReceiveData::CS_IQ_NEG_SPLIT },
+    { NULL, 0 } /* end of list */
+};
+
+static const CHANSEL OutputChannelTable[] =
+{
+    { "Both Channels",              CWriteData::CS_BOTH_BOTH   },
+    { "Left -> Left, Right Muted",  CWriteData::CS_LEFT_LEFT   },
+    { "Right -> Right, Left Muted", CWriteData::CS_RIGHT_RIGHT },
+    { "L + R -> Left, Right Muted", CWriteData::CS_LEFT_MIX    },
+    { "L + R -> Right, Left Muted", CWriteData::CS_RIGHT_MIX   },
+    { NULL, 0 } /* end of list */
+};
+
+static const int AudioSampleRateTable[] =
+{
+    22050, 24000, 44100, 48000, 96000, 192000, 0
+};
+
+static const int SignalSampleRateTable[] =
+{
+    -24000, -48000, -96000, -192000, 0
+};
+
+
+/* Implementation *************************************************************/
+
+/* CSoundCardSelMenu **********************************************************/
+
+CSoundCardSelMenu::CSoundCardSelMenu(CDRMTransceiver& DRMTransceiver,
+    CFileMenu* pFileMenu, QWidget* parent) : QMenu(parent),
+    DRMTransceiver(DRMTransceiver), Parameters(*DRMTransceiver.GetParameters()),
+    menuSigInput(NULL), menuSigDevice(NULL), menuSigSampleRate(NULL),
+    bReceiver(DRMTransceiver.IsReceiver()),
+    curInputDev(NULL), curOutputDev(NULL)
+{
+    setTitle(tr("Sound Card"));
+    if (bReceiver)
+    {   /* Receiver */
+        Parameters.Lock();
+            /* Menu Entries */
+            menuSigInput = addMenu(tr("Signal Input"));
+            QMenu* menuAudOutput = addMenu(tr("Audio Output"));
+            /* Device List */
+            menuSigDevice = InitDevice(NULL, menuSigInput, tr("Device"), SignalSampleRateTable, true);
+            connect(menuSigDevice, SIGNAL(triggered(QAction*)), this, SLOT(OnSoundInDevice(QAction*)));
+            connect(InitDevice(NULL, menuAudOutput, tr("Device"), AudioSampleRateTable, false), SIGNAL(triggered(QAction*)), this, SLOT(OnSoundOutDevice(QAction*)));
+            /* Sample Rate List */
+            menuSigSampleRate = InitSampleRate(menuSigInput, tr("Sample Rate"), Parameters.GetSoundCardSigSampleRate(), SignalSampleRateTable, true);
+            connect(menuSigSampleRate, SIGNAL(triggered(QAction*)), this, SLOT(OnSoundSampleRate(QAction*)));
+            QMenu* menuAudSampleRate = InitSampleRate(menuAudOutput, tr("Sample Rate"), Parameters.GetAudSampleRate(), AudioSampleRateTable, false);
+            connect(menuAudSampleRate, SIGNAL(triggered(QAction*)), this, SLOT(OnSoundSampleRate(QAction*)));
+            /* Channel List */
+            connect(InitChannel(menuSigInput, tr("Channel"), (int)((CDRMReceiver&)DRMTransceiver).GetReceiveData()->GetInChanSel(), InputChannelTable), SIGNAL(triggered(QAction*)), this, SLOT(OnSoundInChannel(QAction*)));
+            connect(InitChannel(menuAudOutput, tr("Channel"), (int)((CDRMReceiver&)DRMTransceiver).GetWriteData()->GetOutChanSel(), OutputChannelTable), SIGNAL(triggered(QAction*)), this, SLOT(OnSoundOutChannel(QAction*)));
+            /* Upscale checkbox */
+            QAction *actionUpscale = menuSigInput->addAction(tr("2:1 upscale"));
+            actionUpscale->setCheckable(true);
+            actionUpscale->setChecked(Parameters.GetSigUpscaleRatio() == 2);
+            connect(actionUpscale, SIGNAL(toggled(bool)), this, SLOT(OnSoundSignalUpscale(bool)));
+        Parameters.Unlock();
+        if (pFileMenu != NULL)
+            connect(pFileMenu, SIGNAL(soundFileChanged(CDRMReceiver::ESFStatus)), this, SLOT(OnSoundFileChanged(CDRMReceiver::ESFStatus)));
+    }
+    else
+    {   /* Transmitter */
+        /* Menu Entries */
+        QMenu* menuAudio = addMenu(tr("Audio Input"));
+        QMenu* menuSignal = addMenu(tr("Signal Output"));
+        /* Device List */
+        connect(InitDevice(NULL, menuAudio, tr("Device"), AudioSampleRateTable, true), SIGNAL(triggered(QAction*)), this, SLOT(OnSoundInDevice(QAction*)));
+        connect(InitDevice(NULL, menuSignal, tr("Device"), SignalSampleRateTable, false), SIGNAL(triggered(QAction*)), this, SLOT(OnSoundOutDevice(QAction*)));
+        /* Sample Rate List */
+        connect(InitSampleRate(menuAudio, tr("Sample Rate"), Parameters.GetAudSampleRate(), AudioSampleRateTable, true), SIGNAL(triggered(QAction*)), this, SLOT(OnSoundSampleRate(QAction*)));
+        connect(InitSampleRate(menuSignal, tr("Sample Rate"), Parameters.GetSigSampleRate(), SignalSampleRateTable, false), SIGNAL(triggered(QAction*)), this, SLOT(OnSoundSampleRate(QAction*)));
+    }
+    /* Update Sample Rate */
+    UpdateSampleRate(true);
+    UpdateSampleRate(false);
+}
+
+void CSoundCardSelMenu::OnSoundInDevice(QAction* action)
+{
+    Parameters.Lock();
+    QString inputName;
+    CSelectionInterface* pSoundInIF = DRMTransceiver.GetSoundInInterface();
+    curInputDev = AsDeviceProp(action);
+    pSoundInIF->SetDev(curInputDev->name);
+    Parameters.Unlock();
+    UpdateSampleRate(true);
+}
+
+void CSoundCardSelMenu::OnSoundOutDevice(QAction* action)
+{
+    Parameters.Lock();
+    CSelectionInterface* pSoundOutIF = DRMTransceiver.GetSoundOutInterface();
+    curOutputDev = AsDeviceProp(action);
+    pSoundOutIF->SetDev(curOutputDev->name);
+    Parameters.Unlock();
+    UpdateSampleRate(false);
+}
+
+void CSoundCardSelMenu::OnSoundInChannel(QAction* action)
+{
+    if (bReceiver)
+    {
+        Parameters.Lock();
+            CReceiveData& ReceiveData = *((CDRMReceiver&)DRMTransceiver).GetReceiveData();
+            CReceiveData::EInChanSel eInChanSel = CReceiveData::EInChanSel(action->data().toInt());
+            ReceiveData.SetInChanSel(eInChanSel);
+        Parameters.Unlock();
+    }
+}
+
+void CSoundCardSelMenu::OnSoundOutChannel(QAction* action)
+{
+    if (bReceiver)
+    {
+        Parameters.Lock();
+            CWriteData& WriteData = *((CDRMReceiver&)DRMTransceiver).GetWriteData();
+            CWriteData::EOutChanSel eOutChanSel = CWriteData::EOutChanSel(action->data().toInt());
+            WriteData.SetOutChanSel(eOutChanSel);
+        Parameters.Unlock();
+    }
+}
+
+void CSoundCardSelMenu::OnSoundSampleRate(QAction* action)
+{
+    const int iSampleRate = action->data().toInt();
+    Parameters.Lock();
+        if (iSampleRate < 0) Parameters.SetNewSigSampleRate(-iSampleRate);
+        else                 Parameters.SetNewAudSampleRate(iSampleRate);
+    Parameters.Unlock();
+    RestartTransceiver(&DRMTransceiver);
+    emit sampleRateChanged();
+}
+
+void CSoundCardSelMenu::OnSoundSignalUpscale(bool bChecked)
+{
+    Parameters.Lock();  
+        Parameters.SetNewSigSampleRate(Parameters.GetSoundCardSigSampleRate());
+        Parameters.SetNewSigUpscaleRatio(bChecked ? 2 : 1);
+    Parameters.Unlock();
+    RestartTransceiver(&DRMTransceiver);
+    emit sampleRateChanged();
+}
+
+QMenu* CSoundCardSelMenu::InitDevice(QMenu* self, QMenu* parent, const QString& text, const int* deriredsamplerate, const bool bInput)
+{
+    QMenu* menu = self != NULL ? self : parent->addMenu(text);
+    menu->clear();
+    QActionGroup* group = NULL;
+    CSelectionInterface* intf = bInput ? (CSelectionInterface*)DRMTransceiver.GetSoundInInterface() : (CSelectionInterface*)DRMTransceiver.GetSoundOutInterface();
+    vector<deviceprop>& devs(bInput ? inputDevs : outputDevs);
+    intf->Enumerate(devs, deriredsamplerate);
+    int iNumSoundDev = devs.size();
+    string sDefaultDev = intf->GetDev();
+    deviceprop** curDev = bInput ? &curInputDev : &curOutputDev;
+    *curDev = NULL;
+    for (int i = 0; i < iNumSoundDev; i++)
+    {
+        QString name(QString::fromLocal8Bit(devs[i].name.c_str()));
+        QString desc(QString::fromLocal8Bit(devs[i].desc.c_str()));
+        QAction* m = menu->addAction(name == DEFAULT_DEVICE_NAME ? tr("[default]") : name + (desc.isEmpty() ? desc : " [" + desc + "]"));
+        m->setData(qVariantFromValue((void*)&devs[i]));
+        m->setCheckable(true);
+        if (devs[i].name == sDefaultDev)
+        {
+            m->setChecked(true);
+            *curDev = &devs[i];
+        }
+        if (group == NULL)
+            group = new QActionGroup(m);
+        group->addAction(m);
+//printf("CSoundCardSelMenu::InitDevice() %s\n", devs[i].name.c_str());
+    }
+    UpdateSampleRate(bInput);
+    return menu;
+}
+
+QMenu* CSoundCardSelMenu::InitChannel(QMenu* parent, const QString& text, const int iCurrentChanSel, const CHANSEL* ChanSel)
+{
+    QMenu* menu = parent->addMenu(text);
+    QActionGroup* group = new QActionGroup(parent);
+    for (int i = 0; ChanSel[i].Name; i++)
+    {
+        QAction* m = menu->addAction(tr(ChanSel[i].Name));
+        int iChanSel = ChanSel[i].iChanSel;
+        m->setData(iChanSel);
+        m->setCheckable(true);
+        if (iChanSel == iCurrentChanSel)
+            m->setChecked(true);
+        group->addAction(m);
+    }
+    return menu;
+}
+
+QMenu* CSoundCardSelMenu::InitSampleRate(QMenu* parent, const QString& text, const int iCurrentSampleRate, const int* SampleRate, const bool bInput)
+{
+    QMenu* menu = parent->addMenu(text);
+    QActionGroup* group = new QActionGroup(parent);
+    vector<QAction*>& actionSampleRate(bInput ? inputSampleRate : outputSampleRate);
+    actionSampleRate.clear();
+    for (int i = 0; SampleRate[i]; i++)
+    {
+        const int iSampleRate = SampleRate[i];
+        const int iAbsSampleRate = abs(iSampleRate);
+        QAction* m = menu->addAction(QString::number(iAbsSampleRate) + tr(" Hz"));
+        m->setData(iSampleRate);
+        m->setCheckable(true);
+//        if (iAbsSampleRate == DEFAULT_SOUNDCRD_SAMPLE_RATE)
+//            menu->setDefaultAction(m);
+        if (iAbsSampleRate == iCurrentSampleRate)
+            m->setChecked(true);
+        group->addAction(m);
+        actionSampleRate.push_back(m);
+    }
+    return menu;
+}
+
+void CSoundCardSelMenu::OnSoundFileChanged(CDRMReceiver::ESFStatus eStatus)
+{
+    const bool bSoundFile = eStatus == CDRMReceiver::SF_SNDFILEIN;
+    const bool bRsciMdiIn = eStatus == CDRMReceiver::SF_RSCIMDIIN;
+
+    if (menuSigInput != NULL && bRsciMdiIn == menuSigInput->isEnabled())
+        menuSigInput->setEnabled(!bRsciMdiIn);
+	
+    if (menuSigDevice != NULL && bSoundFile == menuSigDevice->isEnabled())
+        menuSigDevice->setEnabled(!bSoundFile);
+
+    if (menuSigSampleRate != NULL && bSoundFile == menuSigSampleRate->isEnabled())
+        menuSigSampleRate->setEnabled(!bSoundFile);
+
+    if (eStatus == CDRMReceiver::SF_SNDCARDIN)
+    {
+        if (bReceiver)
+        {
+            Parameters.Lock();
+                InitDevice(menuSigDevice, menuSigInput, tr("Device"), SignalSampleRateTable, true);
+            Parameters.Unlock();
+        }
+    }
+}
+
+deviceprop* CSoundCardSelMenu::AsDeviceProp(QAction* action)
+{
+	return (deviceprop*)action->data().value<void*>();
+}
+
+void CSoundCardSelMenu::UpdateSampleRate(const bool bInput)
+{
+    deviceprop* dev = bInput ? curInputDev : curOutputDev;
+    if (dev)
+    {
+        vector<QAction*>& actionSampleRate(bInput ? inputSampleRate : outputSampleRate);
+        for (size_t i = 0; i < actionSampleRate.size(); i++)
+        {
+            int samplerate = abs(actionSampleRate[i]->data().toInt());
+            actionSampleRate[i]->setEnabled(dev->samplerates[samplerate] == true);
+        }
+    }
+}
+
+/* CFileMenu ******************************************************************/
+// TODO DRMTransmitter
+
+CFileMenu::CFileMenu(CDRMTransceiver& DRMTransceiver, QMainWindow* parent,
+    QMenu* menuInsertBefore)
+    : QMenu(parent), DRMTransceiver(DRMTransceiver), bReceiver(DRMTransceiver.IsReceiver())
+{
+    setTitle(tr("&File"));
+    if (bReceiver)
+    {
+        QString openFile(tr("&Open File..."));
+        QString closeFile(tr("&Close File"));
+        actionOpenFile = addAction(openFile, this, SLOT(OnOpenFile()), QKeySequence(tr("Alt+O")));
+        actionCloseFile = addAction(closeFile, this, SLOT(OnCloseFile()), QKeySequence(tr("Alt+C")));
+        addSeparator();
+    }
+    addAction(tr("&Exit"), parent, SLOT(close()), QKeySequence(tr("Alt+X")));
+    parent->menuBar()->insertMenu(menuInsertBefore->menuAction(), this);
+}
+
+
+void CFileMenu::OnOpenFile()
+{
+#define FILE_FILTER \
+	"Supported Files (" \
+	SND_FILE1 \
+	RSCI_FILE1 \
+	");;" \
+	SND_FILE2 \
+	RSCI_FILE2 \
+	"All Files (*)"
+    if (bReceiver)
+    {
+	    QString filename = QFileDialog::getOpenFileName(this, tr("Open File"), strLastSoundPath, tr(FILE_FILTER));
+	    /* Check if user not hit the cancel button */
+	    if (!filename.isEmpty())
+	    {
+			strLastSoundPath = filename;
+		    ((CDRMReceiver&)DRMTransceiver).SetInputFile(string(filename.toLocal8Bit().constData()));
+		    RestartTransceiver(&DRMTransceiver);
+            UpdateMenu();
+	    }
+    }
+}
+
+void CFileMenu::OnCloseFile()
+{
+    if (bReceiver)
+    {
+	    ((CDRMReceiver&)DRMTransceiver).ClearInputFile();
+	    RestartTransceiver(&DRMTransceiver);
+        UpdateMenu();
+    }
+}
+
+void CFileMenu::UpdateMenu()
+{
+    if (bReceiver)
+    {
+        CDRMReceiver::ESFStatus eStatus = ((CDRMReceiver&)DRMTransceiver).GetInputStatus();
+        const bool bSoundFile = eStatus == CDRMReceiver::SF_SNDFILEIN;
+        const bool bRsciMdiIn = eStatus == CDRMReceiver::SF_RSCIMDIIN;
+
+        const bool bInputFile = bSoundFile | bRsciMdiIn;
+        if (bInputFile != actionCloseFile->isEnabled())
+            actionCloseFile->setEnabled(bInputFile);
+
+        emit soundFileChanged(eStatus);
+    }
+}
+
diff --git a/src/GUI-QT/SoundCardSelMenu.h b/src/GUI-QT/SoundCardSelMenu.h
new file mode 100644
index 0000000..4b5abfe
--- /dev/null
+++ b/src/GUI-QT/SoundCardSelMenu.h
@@ -0,0 +1,114 @@
+/******************************************************************************\
+ * British Broadcasting Corporation
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *      Julian Cable, David Flamand
+ *
+ * Description:
+ *
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+#ifndef __SOUNDCARDMENU_H
+#define __SOUNDCARDMENU_H
+
+#include <QMenu>
+#include <QMenuBar>
+#include <QActionGroup>
+#include <QMainWindow>
+#include "../DrmReceiver.h"
+#include "../DrmTransceiver.h"
+#include "../sound/selectioninterface.h"
+
+
+typedef struct CHANSEL {
+    const char* Name;
+    const int iChanSel;
+} CHANSEL;
+
+class CFileMenu;
+class CSoundCardSelMenu : public QMenu
+{
+    Q_OBJECT
+
+public:
+    CSoundCardSelMenu(
+        CDRMTransceiver& DRMTransceiver,
+        CFileMenu* pFileMenu,
+        QWidget* parent = 0);
+
+protected:
+    CDRMTransceiver&	DRMTransceiver;
+    CParameter&			Parameters;
+    QMenu*				menuSigInput;
+    QMenu*				menuSigDevice;
+    QMenu*				menuSigSampleRate;
+    const bool			bReceiver;
+    vector<deviceprop>  inputDevs;
+    vector<deviceprop>  outputDevs;
+    vector<QAction*>    inputSampleRate;
+    vector<QAction*>    outputSampleRate;
+    deviceprop*         curInputDev;
+    deviceprop*         curOutputDev;
+
+    QMenu* InitDevice(QMenu* self, QMenu* parent, const QString& text, const int* deriredsamplerate, const bool bInput);
+    QMenu* InitChannel(QMenu* parent, const QString& text, const int iChanSel, const CHANSEL* ChanSel);
+    QMenu* InitSampleRate(QMenu* parent, const QString& text, const int iCurrentSampleRate, const int* SampleRate, const bool bInput);
+    deviceprop* AsDeviceProp(QAction* action);
+    void UpdateSampleRate(const bool bInput);
+
+public slots:
+    void OnSoundInChannel(QAction*);
+    void OnSoundOutChannel(QAction*);
+    void OnSoundInDevice(QAction*);
+    void OnSoundOutDevice(QAction*);
+    void OnSoundSampleRate(QAction*);
+    void OnSoundSignalUpscale(bool);
+    void OnSoundFileChanged(CDRMReceiver::ESFStatus);
+
+signals:
+    void sampleRateChanged();
+};
+
+class CFileMenu : public QMenu
+{
+    Q_OBJECT
+
+public:
+    CFileMenu(CDRMTransceiver& DRMTransceiver,
+        QMainWindow* parent, QMenu* menuInsertBefore);
+    void UpdateMenu();
+
+protected:
+    CDRMTransceiver&	DRMTransceiver;
+    QAction*			actionOpenFile;
+    QAction*			actionCloseFile;
+    const bool			bReceiver;
+	QString				strLastSoundPath;
+	QString				strLastRsciPath;
+
+public slots:
+    void OnOpenFile();
+    void OnCloseFile();
+
+signals:
+    void soundFileChanged(CDRMReceiver::ESFStatus eStatus);
+};
+
+#endif
diff --git a/src/GUI-QT/StationsDlg.cpp b/src/GUI-QT/StationsDlg.cpp
new file mode 100644
index 0000000..0959d92
--- /dev/null
+++ b/src/GUI-QT/StationsDlg.cpp
@@ -0,0 +1,631 @@
+/******************************************************************************\
+* Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+* Copyright (c) 2001-2014
+*
+* Author(s):
+*	Volker Fischer, Stephane Fillod, Tomi Manninen, Andrea Russo,
+*      Julian Cable
+*
+******************************************************************************
+*
+* This program is free software; you can redistribute it and/or modify it under
+* the terms of the GNU General Public License as published by the Free Software
+* Foundation; either version 2 of the License, or (at your option) any later
+* version.
+*
+* This program is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+* details.
+*
+* You should have received a copy of the GNU General Public License along with
+* this program; if not, write to the Free Software Foundation, Inc.,
+* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*
+\******************************************************************************/
+
+#include "StationsDlg.h"
+#include "../tables/TableStations.h"
+#include "DialogUtil.h"
+#include "stationswidget.h"
+#ifdef HAVE_LIBHAMLIB
+# include "../util-QT/Rig.h"
+# include "RigDlg.h"
+#endif
+#include "../util-QT/Util.h"
+#include <QHideEvent>
+#include <QShowEvent>
+#include <QApplication>
+#include <QDateTime>
+#include <QMessageBox>
+#include <QFileInfo>
+#include <cmath>
+#include "ThemeCustomizer.h"
+
+/* Implementation *************************************************************/
+#ifdef HAVE_LIBHAMLIB
+StationsDlg::StationsDlg(CSettings& Settings, CRig& Rig, QMap<QWidget*,QString>& parents):
+CWindow(parents, Settings, "Stations"),
+Rig(Rig), pRigDlg(NULL),
+#else
+StationsDlg::StationsDlg(CSettings& Settings, QMap<QWidget*,QString>& parents):
+CWindow(parents, Settings, "Stations"),
+#endif
+schedule(),scheduleLoader(),
+greenCube(":/icons/greenCube.png"), redCube(":/icons/redCube.png"),
+orangeCube(":/icons/orangeCube.png"), pinkCube(":/icons/pinkCube.png"),
+eRecMode(RM_NONE)
+{
+	setupUi(this);
+#if QWT_VERSION < 0x060100
+    ProgrSigStrength->setScalePosition(QwtThermo::TopScale);
+#else
+    ProgrSigStrength->setScalePosition(QwtThermo::TrailingScale);
+#endif
+
+	/* Load settings */
+	LoadSettings();
+
+	/* Set help text for the controls */
+	AddWhatsThisHelp();
+
+	ProgrSigStrength->hide();
+	TextLabelSMeter->hide();
+
+	/* Set up frequency selector control (QWTCounter control) */
+#if QWT_VERSION < 0x060100
+	QwtCounterFrequency->setRange(0.0, MAX_RF_FREQ, 1.0);
+#else
+	QwtCounterFrequency->setRange(0.0, MAX_RF_FREQ);
+	QwtCounterFrequency->setSingleStep(1.0);
+#endif
+	QwtCounterFrequency->setNumButtons(3); /* Three buttons on each side */
+	QwtCounterFrequency->setIncSteps(QwtCounter::Button1, 1); /* Increment */
+	QwtCounterFrequency->setIncSteps(QwtCounter::Button2, 10);
+	QwtCounterFrequency->setIncSteps(QwtCounter::Button3, 100);
+
+	ListViewStations->setAllColumnsShowFocus(true);
+	ListViewStations->setColumnCount(9);
+	ListViewStations->setRootIsDecorated(false);
+	ListViewStations->setSortingEnabled(true);
+	QStringList headers;
+	headers
+		<< QString() /* icon, enable sorting by online/offline */
+		<< tr("Station Name")
+		<< tr("Time [UTC]")
+		<< tr("Frequency [kHz]")
+		<< tr("Power [kW]")
+		<< tr("Target")
+		<< tr("Country")
+		<< tr("Site")
+		<< tr("Language")
+		<< tr("Days");
+	ListViewStations->setHeaderLabels(headers);
+	ListViewStations->headerItem()->setTextAlignment(2, Qt::AlignRight | Qt::AlignVCenter);
+	ListViewStations->headerItem()->setTextAlignment(3, Qt::AlignRight | Qt::AlignVCenter);
+	ListViewStations->headerItem()->setTextAlignment(4, Qt::AlignRight | Qt::AlignVCenter);
+
+	previewMapper = new QSignalMapper(this);
+	previewGroup = new QActionGroup(this);
+	showMapper = new QSignalMapper(this);
+	showGroup = new QActionGroup(this);
+	showGroup->addAction(actionShowOnlyActiveStations);
+	showMapper->setMapping(actionShowOnlyActiveStations, 0);
+	showGroup->addAction(actionShowAllStations);
+	showMapper->setMapping(actionShowAllStations, 1);
+	connect(actionClose, SIGNAL(triggered()), SLOT(close()));
+	connect(actionShowAllStations, SIGNAL(triggered()), showMapper, SLOT(map()));
+	connect(actionShowOnlyActiveStations, SIGNAL(triggered()), showMapper, SLOT(map()));
+	connect(showMapper, SIGNAL(mapped(int)), this, SLOT(OnShowStationsMenu(int)));
+	previewGroup->addAction(actionDisabled);
+	previewMapper->setMapping(actionDisabled, 0);
+	previewGroup->addAction(action5minutes);
+	previewMapper->setMapping(action5minutes, NUM_SECONDS_PREV_5MIN);
+	previewGroup->addAction(action15minutes);
+	previewMapper->setMapping(action15minutes, NUM_SECONDS_PREV_15MIN);
+	previewGroup->addAction(action30minutes);
+	previewMapper->setMapping(action30minutes, NUM_SECONDS_PREV_30MIN);
+	connect(actionDisabled, SIGNAL(triggered()), previewMapper, SLOT(map()));
+	connect(action5minutes, SIGNAL(triggered()), previewMapper, SLOT(map()));
+	connect(action15minutes, SIGNAL(triggered()), previewMapper, SLOT(map()));
+	connect(action30minutes, SIGNAL(triggered()), previewMapper, SLOT(map()));
+	connect(previewMapper, SIGNAL(mapped(int)), this, SLOT(OnShowPreviewMenu(int)));
+	connect(ListViewStations->header(), SIGNAL(sectionClicked(int)), this, SLOT(OnHeaderClicked(int)));
+
+#ifndef HAVE_LIBHAMLIB
+	actionChooseRig->setVisible(false);
+#endif
+	connect(buttonOk, SIGNAL(clicked()), this, SLOT(close()));
+
+	/* Init progress bar for input s-meter */
+	InitSMeter(this, ProgrSigStrength);
+
+	/* Connections ---------------------------------------------------------- */
+
+	connect(&Timer, SIGNAL(timeout()), this, SLOT(OnTimer()));
+	connect(QwtCounterFrequency, SIGNAL(valueChanged(double)),
+		this, SLOT(OnFreqCntNewValue(double)));
+    connect(&scheduleLoader, SIGNAL(fileReady()), this, SLOT(OnFileReady()));
+
+    APPLY_CUSTOM_THEME();
+}
+
+StationsDlg::~StationsDlg()
+{
+}
+
+void StationsDlg::on_actionGetUpdate_triggered()
+{
+    scheduleLoader.fetch(params[eRecMode].url, params[eRecMode].filename);
+}
+
+void StationsDlg::OnFileReady()
+{
+    LoadSchedule();
+    LoadScheduleView();
+    UpdateTransmissionStatus();
+}
+
+void StationsDlg::OnShowStationsMenu(int iID)
+{
+	(void)iID;
+    UpdateTransmissionStatus();
+}
+
+void StationsDlg::OnShowPreviewMenu(int iID)
+{
+	schedule.SetSecondsPreview(iID);
+    UpdateTransmissionStatus();
+}
+
+void StationsDlg::on_ComboBoxFilterTarget_activated(const QString& s)
+{
+    params[eRecMode].targetFilter = s;
+    schedule.setTargetFilter(s);
+    UpdateTransmissionStatus();
+}
+
+void StationsDlg::on_ComboBoxFilterCountry_activated(const QString& s)
+{
+    params[eRecMode].countryFilter = s;
+    schedule.setCountryFilter(s);
+    UpdateTransmissionStatus();
+}
+
+void StationsDlg::on_ComboBoxFilterLanguage_activated(const QString& s)
+{
+    params[eRecMode].languageFilter = s;
+    schedule.setLanguageFilter(s);
+    UpdateTransmissionStatus();
+}
+
+
+void StationsDlg::LoadSchedule()
+{
+    schedule.LoadSchedule(params[eRecMode].filename);
+    /* add last update information on menu item */
+    QFileInfo f = QFileInfo(params[eRecMode].filename);
+    actionGetUpdate->setText(
+       tr("&Get Update (last update: %1)...").arg(f.lastModified().date().toString())
+    );
+}
+
+void StationsDlg::SetFrequency(int f)
+{
+    QwtCounterFrequency->setValue(f);
+}
+
+void StationsDlg::OnSwitchMode(int m)
+{
+    ERecMode eNewRecMode = ERecMode(m);
+    if(eNewRecMode != eRecMode)
+    {
+        ColumnParamToStr(ListViewStations, params[eRecMode].strColumnParam);
+        eRecMode = eNewRecMode;
+        if(isVisible())
+        {
+            schedule.LoadSchedule(params[eRecMode].filename);
+            schedule.setCountryFilter(params[eRecMode].countryFilter);
+            schedule.setLanguageFilter(params[eRecMode].languageFilter);
+            schedule.setTargetFilter(params[eRecMode].targetFilter);
+        }
+        else
+        {
+            schedule.clear();
+        }
+        ColumnParamFromStr(ListViewStations, params[eRecMode].strColumnParam);
+    }
+}
+
+void StationsDlg::eventClose(QCloseEvent*)
+{
+	/* Save settings */
+	SaveSettings();
+}
+
+void StationsDlg::eventHide(QHideEvent*)
+{
+	/* Deactivate real-time timers */
+	Timer.stop();
+	DisableSMeter();
+}
+
+void StationsDlg::eventShow(QShowEvent*)
+{
+    /* Activate real-time timer when window is shown */
+    Timer.start(500 /* twice a second - nyquist for catching minute boundaries */);
+
+    if(actionEnable_S_Meter->isChecked())
+        EnableSMeter();
+    else
+        DisableSMeter();
+
+	QTimer::singleShot(1000, this, SLOT(OnUpdate()));
+}
+
+void StationsDlg::OnTimer()
+{
+	/* Get current UTC time */
+	time_t ltime;
+	time(&ltime);
+	struct tm* gmtCur = gmtime(&ltime);
+
+	/* Generate time in format "UTC 12:00" */
+	QString strUTCTime = QString().sprintf("%02d:%02d UTC",
+		gmtCur->tm_hour, gmtCur->tm_min);
+
+	/* Only apply if time label does not show the correct time */
+	if (TextLabelUTCTime->text().compare(strUTCTime))
+		TextLabelUTCTime->setText(strUTCTime);
+
+	/* reload schedule on minute boundaries */
+	if (ltime % 60 == 0)
+        UpdateTransmissionStatus();
+}
+
+void StationsDlg::OnUpdate()
+{
+    if (!isVisible())
+        return;
+
+    if (schedule.GetNumberOfStations()==0)
+    {
+        if(QFile::exists(params[eRecMode].filename))
+        {
+            LoadSchedule();
+        }
+        else
+        {
+            QMessageBox::information(this, "Dream", tr("The schedule file "
+            " could not be found or contains no data.\n"
+            "No stations can be displayed.\n"
+            "Try to download this file by using the 'Update' menu."),
+            QMessageBox::Ok);
+            actionGetUpdate->setText(tr("&Get Update ..."));
+        }
+    }
+    LoadScheduleView();
+    UpdateTransmissionStatus();
+}
+
+void StationsDlg::LoadSettings()
+{
+	/* S-meter settings */
+	bool ensmeter = Settings.Get("Hamlib", "ensmeter", false);
+
+	actionEnable_S_Meter->setChecked(ensmeter);
+
+	bool showAll = getSetting("showall", false);
+	int iPrevSecs = getSetting("preview", NUM_SECONDS_PREV_5MIN);
+	schedule.SetSecondsPreview(iPrevSecs);
+
+	if(showAll)
+		actionShowAllStations->setChecked(true);
+	else
+		actionShowOnlyActiveStations->setChecked(true);
+
+	switch (iPrevSecs)
+	{
+	case NUM_SECONDS_PREV_5MIN:
+		action5minutes->setChecked(true);
+		break;
+
+	case NUM_SECONDS_PREV_15MIN:
+		action15minutes->setChecked(true);
+		break;
+
+	case NUM_SECONDS_PREV_30MIN:
+		action30minutes->setChecked(true);
+		break;
+
+	default: /* case 0, also takes care of out of value parameters */
+		actionDisabled->setChecked(true);
+		break;
+	}
+
+    params[RM_DRM].iSortColumn = getSetting("sortcolumndrm", 0);
+    params[RM_DRM].bCurrentSortAscending = getSetting("sortascendingdrm", true);
+    params[RM_DRM].strColumnParam = getSetting("columnparamdrm", QString());
+    params[RM_AM].iSortColumn = getSetting("sortcolumnanalog", 0);
+    params[RM_AM].bCurrentSortAscending = getSetting("sortascendinganalog", true);
+    params[RM_AM].strColumnParam = getSetting("columnparamanalog", QString());
+    params[RM_DRM].url = getSetting("DRM URL", QString(DRM_SCHEDULE_URL));
+    params[RM_DRM].targetFilter = getSetting("targetfilterdrm", QString());
+    params[RM_DRM].countryFilter = getSetting("countryfilterdrm", QString());
+    params[RM_DRM].languageFilter = getSetting("languagefilterdrm", QString());
+    params[RM_AM].targetFilter = getSetting("targetfilteranalog", QString());
+    params[RM_AM].countryFilter = getSetting("countryfilteranalog", QString());
+    params[RM_AM].languageFilter = getSetting("languagefilteranalog", QString());
+    params[RM_AM].filename = getSetting("schedulefilenameanalog", QString(AMSCHEDULE_CSV_FILE_NAME));
+    params[RM_DRM].filename = getSetting("schedulefilenamedrm", QString(DRMSCHEDULE_INI_FILE_NAME));
+}
+
+void StationsDlg::SaveSettings()
+{
+    ColumnParamToStr(ListViewStations, params[eRecMode].strColumnParam);
+    Settings.Put("Hamlib", "ensmeter", actionEnable_S_Meter->isChecked());
+	putSetting("showall", actionShowAllStations->isChecked());
+    putSetting("DRM URL", params[RM_DRM].url);
+    putSetting("ANALOG URL", params[RM_AM].url);
+    putSetting("sortcolumndrm", params[RM_DRM].iSortColumn);
+    putSetting("sortascendingdrm", params[RM_DRM].bCurrentSortAscending);
+    putSetting("columnparamdrm", params[RM_DRM].strColumnParam);
+    putSetting("sortcolumnanalog", params[RM_AM].iSortColumn);
+    putSetting("sortascendinganalog", params[RM_AM].bCurrentSortAscending);
+    putSetting("columnparamanalog", params[RM_AM].strColumnParam);
+    putSetting("targetfilterdrm", params[RM_DRM].targetFilter);
+    putSetting("countryfilterdrm", params[RM_DRM].countryFilter);
+    putSetting("languagefilterdrm", params[RM_DRM].languageFilter);
+    putSetting("targetfilteranalog", params[RM_AM].targetFilter);
+    putSetting("countryfilteranalog", params[RM_AM].countryFilter);
+    putSetting("languagefilteranalog", params[RM_AM].languageFilter);
+
+	/* Store preview settings */
+	putSetting("preview", schedule.GetSecondsPreview());
+}
+
+void StationsDlg::LoadScheduleView()
+{
+    ListViewStations->clear();
+    for (int i = 0; i < schedule.GetNumberOfStations(); i++)
+	{
+		const CStationsItem& station = schedule.GetItem(i);
+
+		/* Get power of the station. We have to do a special treatment
+		* here, because we want to avoid having a "0" in the list when
+		* a "?" was in the schedule-ini-file */
+		const _REAL rPower = station.rPower;
+
+		QString strPower;
+		if (rPower == (_REAL) 0.0)
+			strPower = "?";
+		else
+			strPower.setNum(rPower);
+
+		QString strTimes = QString().sprintf("%04d-%04d", station.StartTime(), station.StopTime());
+
+		/* Generate new list station with all necessary column entries */
+		QTreeWidgetItem* item = new CaseInsensitiveTreeWidgetItem(ListViewStations);
+		item->setText(1, station.strName);
+		item->setText(2, strTimes /* time */);
+		item->setText(3, QString().setNum(station.iFreq) /* freq. */);
+		item->setText(4, strPower            /* power */);
+		item->setText(5, station.strTarget   /* target */);
+		item->setText(6, station.strCountry  /* country */);
+		item->setText(7, station.strSite     /* site */);
+		item->setText(8, station.strLanguage /* language */);
+		item->setText(9, station.strDaysShow);
+		item->setData(1, Qt::UserRole, i);
+		item->setTextAlignment(2, Qt::AlignRight | Qt::AlignVCenter);
+		item->setTextAlignment(3, Qt::AlignRight | Qt::AlignVCenter);
+		item->setTextAlignment(4, Qt::AlignRight | Qt::AlignVCenter);
+	}
+    ListViewStations->sortByColumn(
+            params[eRecMode].iSortColumn,
+            params[eRecMode].bCurrentSortAscending ? Qt::AscendingOrder : Qt::DescendingOrder
+   );
+
+    // Load Filters(
+    ComboBoxFilterTarget->clear();
+    ComboBoxFilterCountry->clear();
+    ComboBoxFilterLanguage->clear();
+    ComboBoxFilterTarget->addItems(schedule.ListTargets);
+    ComboBoxFilterCountry->addItems(schedule.ListCountries);
+    ComboBoxFilterLanguage->addItems(schedule.ListLanguages);
+
+    QString s;
+    s = schedule.getTargetFilter();
+    int i;
+    i = ComboBoxFilterTarget->findText(s);
+    ComboBoxFilterTarget->setCurrentIndex(i);
+    ComboBoxFilterCountry->setCurrentIndex(ComboBoxFilterCountry->findText(schedule.getCountryFilter()));
+    ComboBoxFilterLanguage->setCurrentIndex(ComboBoxFilterLanguage->findText(schedule.getLanguageFilter()));
+}
+
+void StationsDlg::UpdateTransmissionStatus()
+{
+	Timer.stop();
+	ListItemsMutex.lock();
+
+	bool bShowAll = showAll();
+	ListViewStations->setSortingEnabled(false);
+    for (int i = 0; i < ListViewStations->topLevelItemCount(); i++)
+	{
+		QTreeWidgetItem* item = ListViewStations->topLevelItem(i);
+		int scheduleItem = item->data(1, Qt::UserRole).toInt();
+
+		Station::EState iState = schedule.GetState(scheduleItem);
+
+		switch (iState)
+		{
+		case Station::IS_ACTIVE:
+			item->setData(0, Qt::UserRole, 1);
+			item->setIcon(0, greenCube);
+			break;
+		case Station::IS_PREVIEW:
+			item->setData(0, Qt::UserRole, 2);
+			item->setIcon(0, orangeCube);
+			break;
+		case Station::IS_SOON_INACTIVE:
+			item->setData(0, Qt::UserRole, 0);
+			item->setIcon(0, pinkCube);
+			break;
+		case Station::IS_INACTIVE:
+			item->setData(0, Qt::UserRole, 3);
+			item->setIcon(0, redCube);
+			break;
+		default:
+			item->setData(0, Qt::UserRole, 4);
+			item->setIcon(0, redCube);
+			break;
+		}
+		if(schedule.CheckFilter(scheduleItem) && (bShowAll || (iState != Station::IS_INACTIVE)))
+		{
+			item->setHidden(false);
+		}
+		else
+		{
+			item->setHidden(true);
+		}
+	}
+	ListViewStations->setSortingEnabled(true);
+	ListViewStations->sortItems(ListViewStations->sortColumn(), GetSortAscending()?Qt::AscendingOrder:Qt::DescendingOrder);
+	ListViewStations->setFocus();
+	ListItemsMutex.unlock();
+	Timer.start();
+}
+
+void StationsDlg::OnFreqCntNewValue(double dVal)
+{
+    emit frequencyChanged(floor(dVal));
+}
+
+void StationsDlg::OnHeaderClicked(int c)
+{
+	/* Store the "direction" of sorting */
+	if (currentSortColumn() == c)
+		SetSortAscending(!GetSortAscending());
+	else
+		SetSortAscending(true);
+	/* Store the column of sorting */
+    params[eRecMode].iSortColumn = c;
+}
+
+int StationsDlg::currentSortColumn()
+{
+    return params[eRecMode].iSortColumn;
+}
+
+void StationsDlg::SetSortAscending(bool b)
+{
+    params[eRecMode].bCurrentSortAscending = b;
+}
+
+bool StationsDlg::GetSortAscending()
+{
+    return params[eRecMode].bCurrentSortAscending;
+}
+
+void StationsDlg::on_ListViewStations_itemSelectionChanged()
+{
+	QList<QTreeWidgetItem *> items =  ListViewStations->selectedItems();
+	if(items.size()==1)
+	{
+        int iFreq = QString(items.first()->text(3)).toInt();
+        QwtCounterFrequency->setValue(iFreq);
+    }
+}
+
+void StationsDlg::on_actionEnable_S_Meter_triggered()
+{
+	if(actionEnable_S_Meter->isChecked())
+		EnableSMeter();
+	else
+		DisableSMeter();
+}
+
+void StationsDlg::EnableSMeter()
+{
+	TextLabelSMeter->setEnabled(TRUE);
+	ProgrSigStrength->setEnabled(TRUE);
+	TextLabelSMeter->show();
+	ProgrSigStrength->show();
+	emit subscribeRig();
+}
+
+void StationsDlg::DisableSMeter()
+{
+	TextLabelSMeter->hide();
+	ProgrSigStrength->hide();
+	emit unsubscribeRig();
+}
+
+void StationsDlg::OnSigStr(double rCurSigStr)
+{
+	ProgrSigStrength->setValue(rCurSigStr);
+}
+
+void StationsDlg::on_actionChooseRig_triggered()
+{
+#ifdef HAVE_LIBHAMLIB
+	if (pRigDlg == NULL)
+		pRigDlg = new RigDlg(Rig, this);
+	pRigDlg->show();
+#endif
+}
+
+bool StationsDlg::showAll()
+{
+	return actionShowAllStations->isChecked();
+}
+
+void StationsDlg::AddWhatsThisHelp()
+{
+	/* Stations List */
+	QString strList =
+		tr("<b>Stations List:</b> In the stations list "
+		"view all DRM stations which are stored in the schedule.ini file "
+		"are shown. It is possible to show only active stations by changing a "
+		"setting in the 'view' menu. The color of the cube on the left of a "
+		"menu item shows the current status of the DRM transmission. A green "
+		"box shows that the transmission takes place right now, a "
+		//           "yellow cube shows that this is a test transmission and with a "
+		"red cube it is shown that the transmission is offline, "
+		"a pink cube shown that the transmission soon will be offline.<br>"
+		"If the stations preview is active an orange box shows the stations "
+		"that will be active.<br>"
+		"The list can be sorted by clicking on the headline of the "
+		"column.<br>By clicking on a menu item, a remote front-end can "
+		"be automatically switched to the current frequency and the "
+		"Dream software is reset to a new acquisition (to speed up the "
+		"synchronization process). Also, the log-file frequency edit "
+		"is automatically updated.");
+
+	/* Frequency Counter */
+	QString strCounter =
+		tr("<b>Frequency Counter:</b> The current frequency "
+		"value can be changed by using this counter. The tuning steps are "
+		"100 kHz for the  buttons with three arrows, 10 kHz for the "
+		"buttons with two arrows and 1 kHz for the buttons having only "
+		"one arrow. By keeping the button pressed, the values are "
+		"increased / decreased automatically.");
+
+	/* UTC time label */
+	QString strTime =
+		tr("<b>UTC Time:</b> Shows the current Coordinated "
+		"Universal Time (UTC) which is also known as Greenwich Mean Time "
+		"(GMT).");
+
+	/* S-meter */
+	const QString strSMeter =
+		tr("<b>Signal-Meter:</b> Shows the signal strength "
+		"level in dB relative to S9.<br>Note that not all "
+		"front-ends controlled by hamlib support this feature. If the s-meter "
+		"is not available, the controls are disabled.");
+
+	ListViewStations->setWhatsThis(strList);
+	QwtCounterFrequency->setWhatsThis(strCounter);
+	TextLabelUTCTime->setWhatsThis(strTime);
+	TextLabelSMeter->setWhatsThis(strSMeter);
+	ProgrSigStrength->setWhatsThis(strSMeter);
+}
diff --git a/src/GUI-QT/StationsDlg.h b/src/GUI-QT/StationsDlg.h
new file mode 100644
index 0000000..8162c7a
--- /dev/null
+++ b/src/GUI-QT/StationsDlg.h
@@ -0,0 +1,132 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+#ifndef __StationsDlg_H
+#define __StationsDlg_H
+
+#include <QSignalMapper>
+#include <QTimer>
+#include "ui_StationsDlgbase.h"
+
+#include "DialogUtil.h"
+#include "CWindow.h"
+#include "Schedule.h"
+#include "../util-QT/scheduleloader.h"
+
+/* Definitions ****************************************************************/
+
+class RigDlg;
+
+class StationsDlg : public CWindow, public Ui_StationsDlgbase
+{
+	Q_OBJECT
+
+public:
+#ifdef HAVE_LIBHAMLIB
+    StationsDlg(CSettings&, CRig&, QMap<QWidget*,QString>&);
+#else
+    StationsDlg(CSettings&, QMap<QWidget*,QString>&);
+#endif
+	virtual ~StationsDlg();
+public slots:
+    void SetFrequency(int);
+    void OnSwitchMode(int);
+    ERecMode mode() { return eRecMode; }
+
+protected:
+    struct Params {
+        bool        bCurrentSortAscending;
+        int			iSortColumn;
+        QString		strColumnParam;
+        QString		targetFilter;
+        QString		languageFilter;
+        QString		countryFilter;
+        QString		url;
+        QString		filename;
+    };
+
+	virtual void	eventClose(QCloseEvent* pEvent);
+	virtual void	eventHide(QHideEvent* pEvent);
+	virtual void	eventShow(QShowEvent* pEvent);
+	void			LoadSettings();
+	void			SaveSettings();
+    void			LoadSchedule();
+    void			LoadScheduleView();
+    void			UpdateTransmissionStatus();
+	void			AddWhatsThisHelp();
+	void			EnableSMeter();
+	void			DisableSMeter();
+    bool    		showAll();
+    bool            GetSortAscending();
+    void			SetSortAscending(bool);
+    int				currentSortColumn();
+    Params          params[RM_NONE+1];
+
+#ifdef HAVE_LIBHAMLIB
+	CRig&			Rig;
+	RigDlg			*pRigDlg;
+#endif
+	CSchedule		schedule;
+    ScheduleLoader  scheduleLoader;
+	QIcon			greenCube;
+	QIcon			redCube;
+	QIcon			orangeCube;
+	QIcon			pinkCube;
+	QSignalMapper*	previewMapper;
+	QActionGroup*	previewGroup;
+	QSignalMapper*	showMapper;
+	QActionGroup*	showGroup;
+	QTimer			Timer;
+
+	QMutex			ListItemsMutex;
+
+	QString			okMessage, badMessage;
+    ERecMode        eRecMode;
+
+signals:
+	void subscribeRig();
+	void unsubscribeRig();
+    void frequencyChanged(int);
+
+private slots:
+	void OnSigStr(double);
+	void OnTimer();
+	void OnUpdate();
+    void OnFileReady();
+	void OnShowStationsMenu(int iID);
+	void OnShowPreviewMenu(int iID);
+	void OnFreqCntNewValue(double dVal);
+	void OnHeaderClicked(int c);
+	void on_actionGetUpdate_triggered();
+	void on_ListViewStations_itemSelectionChanged();
+	void on_ComboBoxFilterTarget_activated(const QString&);
+	void on_ComboBoxFilterCountry_activated(const QString&);
+	void on_ComboBoxFilterLanguage_activated(const QString&);
+	void on_actionEnable_S_Meter_triggered();
+	void on_actionChooseRig_triggered();
+};
+#endif
diff --git a/src/GUI-QT/StationsDlgbase.ui b/src/GUI-QT/StationsDlgbase.ui
new file mode 100644
index 0000000..5012411
--- /dev/null
+++ b/src/GUI-QT/StationsDlgbase.ui
@@ -0,0 +1,421 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>StationsDlgbase</class>
+ <widget class="QMainWindow" name="StationsDlgbase">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>621</width>
+    <height>427</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Stations</string>
+  </property>
+  <property name="windowIcon">
+   <iconset resource="res/icons.qrc">
+    <normaloff>:/icons/MainIcon.svg</normaloff>:/icons/MainIcon.svg</iconset>
+  </property>
+  <widget class="QWidget" name="centralwidget">
+   <layout class="QVBoxLayout" name="verticalLayout">
+    <item>
+     <widget class="QTreeWidget" name="ListViewStations">
+      <property name="rootIsDecorated">
+       <bool>false</bool>
+      </property>
+      <property name="uniformRowHeights">
+       <bool>true</bool>
+      </property>
+      <column>
+       <property name="text">
+        <string/>
+       </property>
+      </column>
+     </widget>
+    </item>
+    <item>
+     <widget class="QGroupBox" name="groupBox">
+      <property name="title">
+       <string>Filters</string>
+      </property>
+      <layout class="QHBoxLayout" name="horizontalLayout">
+       <item>
+        <widget class="QLabel" name="TextLabelTarget">
+         <property name="text">
+          <string>Target</string>
+         </property>
+         <property name="wordWrap">
+          <bool>false</bool>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="QComboBox" name="ComboBoxFilterTarget">
+         <property name="sizePolicy">
+          <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
+           <horstretch>0</horstretch>
+           <verstretch>0</verstretch>
+          </sizepolicy>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="QLabel" name="TextLabelCountry">
+         <property name="text">
+          <string>Country</string>
+         </property>
+         <property name="wordWrap">
+          <bool>false</bool>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="QComboBox" name="ComboBoxFilterCountry">
+         <property name="sizePolicy">
+          <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
+           <horstretch>0</horstretch>
+           <verstretch>0</verstretch>
+          </sizepolicy>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="QLabel" name="TextLabelLanguage">
+         <property name="text">
+          <string>Language</string>
+         </property>
+         <property name="wordWrap">
+          <bool>false</bool>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="QComboBox" name="ComboBoxFilterLanguage">
+         <property name="sizePolicy">
+          <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
+           <horstretch>0</horstretch>
+           <verstretch>0</verstretch>
+          </sizepolicy>
+         </property>
+        </widget>
+       </item>
+      </layout>
+     </widget>
+    </item>
+    <item>
+     <layout class="QHBoxLayout" name="horizontalLayout_3">
+      <item>
+       <layout class="QVBoxLayout" name="verticalLayout_2">
+        <property name="spacing">
+         <number>0</number>
+        </property>
+        <item>
+         <widget class="QWidget" name="widget_2" native="true">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <layout class="QHBoxLayout" name="horizontalLayout_2">
+          <property name="spacing">
+           <number>6</number>
+          </property>
+          <item>
+           <widget class="QLabel" name="TextLabelUTCTime">
+            <property name="sizePolicy">
+             <sizepolicy hsizetype="Minimum" vsizetype="Maximum">
+              <horstretch>0</horstretch>
+              <verstretch>0</verstretch>
+             </sizepolicy>
+            </property>
+            <property name="minimumSize">
+             <size>
+              <width>0</width>
+              <height>23</height>
+             </size>
+            </property>
+            <property name="frameShape">
+             <enum>QFrame::Panel</enum>
+            </property>
+            <property name="frameShadow">
+             <enum>QFrame::Sunken</enum>
+            </property>
+            <property name="text">
+             <string>UTC</string>
+            </property>
+            <property name="wordWrap">
+             <bool>false</bool>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QwtCounter" name="QwtCounterFrequency" native="true">
+            <property name="sizePolicy">
+             <sizepolicy hsizetype="Fixed" vsizetype="Maximum">
+              <horstretch>0</horstretch>
+              <verstretch>0</verstretch>
+             </sizepolicy>
+            </property>
+            <property name="minimumSize">
+             <size>
+              <width>168</width>
+              <height>0</height>
+             </size>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QLabel" name="TextLabel1">
+            <property name="sizePolicy">
+             <sizepolicy hsizetype="Minimum" vsizetype="Maximum">
+              <horstretch>0</horstretch>
+              <verstretch>0</verstretch>
+             </sizepolicy>
+            </property>
+            <property name="text">
+             <string>kHz</string>
+            </property>
+            <property name="wordWrap">
+             <bool>false</bool>
+            </property>
+            <property name="buddy">
+             <cstring>QwtCounterFrequency</cstring>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </item>
+       </layout>
+      </item>
+      <item>
+       <spacer name="horizontalSpacer_2">
+        <property name="orientation">
+         <enum>Qt::Horizontal</enum>
+        </property>
+        <property name="sizeHint" stdset="0">
+         <size>
+          <width>20</width>
+          <height>20</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+      <item>
+       <widget class="QLabel" name="TextLabelSMeter">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="text">
+         <string>S-Meter [dB]
+(relative to S9):</string>
+        </property>
+        <property name="wordWrap">
+         <bool>false</bool>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QwtThermo" name="ProgrSigStrength" native="true">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Fixed" vsizetype="Maximum">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="minimumSize">
+         <size>
+          <width>150</width>
+          <height>0</height>
+         </size>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <spacer name="horizontalSpacer">
+        <property name="orientation">
+         <enum>Qt::Horizontal</enum>
+        </property>
+        <property name="sizeType">
+         <enum>QSizePolicy::Expanding</enum>
+        </property>
+        <property name="sizeHint" stdset="0">
+         <size>
+          <width>20</width>
+          <height>20</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+      <item>
+       <layout class="QVBoxLayout" name="verticalLayout_1">
+        <property name="spacing">
+         <number>0</number>
+        </property>
+        <item>
+         <widget class="QWidget" name="widget" native="true">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QPushButton" name="buttonOk">
+          <property name="text">
+           <string>&Close</string>
+          </property>
+          <property name="default">
+           <bool>true</bool>
+          </property>
+         </widget>
+        </item>
+       </layout>
+      </item>
+     </layout>
+    </item>
+   </layout>
+  </widget>
+  <widget class="QMenuBar" name="menubar">
+   <property name="geometry">
+    <rect>
+     <x>0</x>
+     <y>0</y>
+     <width>621</width>
+     <height>25</height>
+    </rect>
+   </property>
+   <widget class="QMenu" name="menuView">
+    <property name="title">
+     <string>&View</string>
+    </property>
+    <widget class="QMenu" name="menuStations_preview">
+     <property name="title">
+      <string>Stations &preview</string>
+     </property>
+     <addaction name="actionDisabled"/>
+     <addaction name="action5minutes"/>
+     <addaction name="action15minutes"/>
+     <addaction name="action30minutes"/>
+    </widget>
+    <addaction name="actionShowOnlyActiveStations"/>
+    <addaction name="actionShowAllStations"/>
+    <addaction name="menuStations_preview"/>
+    <addaction name="separator"/>
+    <addaction name="actionClose"/>
+   </widget>
+   <widget class="QMenu" name="menuRemote">
+    <property name="title">
+     <string>&Remote</string>
+    </property>
+    <addaction name="actionChooseRig"/>
+    <addaction name="actionEnable_S_Meter"/>
+   </widget>
+   <widget class="QMenu" name="menuUpdate">
+    <property name="title">
+     <string>&Update</string>
+    </property>
+    <addaction name="actionGetUpdate"/>
+   </widget>
+   <addaction name="menuView"/>
+   <addaction name="menuRemote"/>
+   <addaction name="menuUpdate"/>
+  </widget>
+  <action name="actionShowOnlyActiveStations">
+   <property name="checkable">
+    <bool>true</bool>
+   </property>
+   <property name="text">
+    <string>Show only active stations</string>
+   </property>
+  </action>
+  <action name="actionShowAllStations">
+   <property name="checkable">
+    <bool>true</bool>
+   </property>
+   <property name="text">
+    <string>Show all stations</string>
+   </property>
+  </action>
+  <action name="action5minutes">
+   <property name="checkable">
+    <bool>true</bool>
+   </property>
+   <property name="text">
+    <string>5 minutes</string>
+   </property>
+  </action>
+  <action name="action15minutes">
+   <property name="checkable">
+    <bool>true</bool>
+   </property>
+   <property name="text">
+    <string>15 minutes</string>
+   </property>
+  </action>
+  <action name="action30minutes">
+   <property name="checkable">
+    <bool>true</bool>
+   </property>
+   <property name="text">
+    <string>30 minutes</string>
+   </property>
+  </action>
+  <action name="actionGetUpdate">
+   <property name="text">
+    <string>Get &Update...</string>
+   </property>
+  </action>
+  <action name="actionChooseRig">
+   <property name="text">
+    <string>&Rig Settings...</string>
+   </property>
+  </action>
+  <action name="actionDisabled">
+   <property name="checkable">
+    <bool>true</bool>
+   </property>
+   <property name="text">
+    <string>&Disabled</string>
+   </property>
+  </action>
+  <action name="actionEnable_S_Meter">
+   <property name="checkable">
+    <bool>true</bool>
+   </property>
+   <property name="text">
+    <string>Enable &S-Meter</string>
+   </property>
+  </action>
+  <action name="actionClose">
+   <property name="text">
+    <string>&Close</string>
+   </property>
+  </action>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>QwtCounter</class>
+   <extends>QWidget</extends>
+   <header>qwt_counter.h</header>
+  </customwidget>
+  <customwidget>
+   <class>QwtThermo</class>
+   <extends>QWidget</extends>
+   <header>qwt_thermo.h</header>
+  </customwidget>
+ </customwidgets>
+ <resources>
+  <include location="res/icons.qrc"/>
+ </resources>
+ <connections/>
+</ui>
diff --git a/src/GUI-QT/ThemeCustomizer.cpp b/src/GUI-QT/ThemeCustomizer.cpp
new file mode 100644
index 0000000..63da84c
--- /dev/null
+++ b/src/GUI-QT/ThemeCustomizer.cpp
@@ -0,0 +1,315 @@
+/******************************************************************************\
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *  David Flamand
+ *
+ * Description:
+ *  Intended to provide a way to customize appearance of widget
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "ThemeCustomizer.h"
+
+#ifdef USE_THEMECUSTOMIZER
+
+#include <QPalette>
+#include <QFont>
+#include <QFrame>
+#include <QDesktopWidget>
+#include "ui_DRMMainWindow.h"
+#include "ui_serviceselector.h"
+#include "EvaluationDlg.h"
+#include "AnalogDemDlg.h"
+#include "DialogUtil.h"
+#include "StationsDlg.h"
+#include "EPGDlg.h"
+#include "GeneralSettingsDlg.h"
+#include "MultSettingsDlg.h"
+#ifdef HAVE_QTWEBKIT
+# include "BWSViewer.h"
+#endif
+#include "JLViewer.h"
+#include "LiveScheduleDlg.h"
+#include "SlideShowViewer.h"
+#ifdef HAVE_LIBHAMLIB
+# include "RigDlg.h"
+#endif
+
+
+#define WINDOW_BORDER_MARGIN 0
+
+//
+// TODO list:
+//  light theme, only dark theme is currently inplemented.
+//  theme selection menu.
+//  scaling font with screen size.
+//
+
+static void SetFontSize(QWidget *widget, int fontSize)
+{
+	QFont font(widget->font());
+	font.setPointSize(fontSize);
+	widget->setFont(font);
+}
+
+static void ResizeWidget(QWidget *widget)
+{
+	QWidget* parent = widget->parentWidget();
+	if (parent)
+		widget->setGeometry(parent->geometry());
+}
+
+static QPalette BaseSetup(QWidget *widget)
+{
+	QPalette palette(widget->palette());
+	palette.setColor(QPalette::Base,       QColor("#212421"));
+	palette.setColor(QPalette::Text,       QColor("#FFFFFF"));
+	palette.setColor(QPalette::Window,     QColor("#000000"));
+	palette.setColor(QPalette::WindowText, QColor("#FFFFFF"));
+	palette.setColor(QPalette::Button,     QColor("#212421"));
+	palette.setColor(QPalette::ButtonText, QColor("#FFFFFF"));
+	palette.setColor(QPalette::Light,      QColor("#616361"));
+	palette.setColor(QPalette::Dark,       QColor("#616361"));
+	palette.setColor(QPalette::Disabled, QPalette::ButtonText, QColor("#616361"));
+	widget->setPalette(palette);	
+	SetFontSize(widget, 13);
+	return palette;
+}
+
+static void QFrameSetup(QFrame *widget)
+{
+	widget->setFrameShape(QFrame::Panel);
+	widget->setFrameShadow(QFrame::Sunken);
+}
+
+void ApplyCustomTheme(QWidget *widget, void* pUi)
+{
+	QString name(widget->objectName());
+	if (name == "DRMMainWindow")
+	{
+		Ui::DRMMainWindow* ui = (Ui::DRMMainWindow*)pUi;
+		QPalette prevPalette(ui->TextTextMessage->palette());
+		QPalette basePalette(BaseSetup(widget));
+		ui->centralwidget->layout()->setMargin(WINDOW_BORDER_MARGIN);
+		ui->FrameMainDisplay->layout()->setMargin(0);
+		ui->FrameMainDisplay->setFrameShape(QFrame::NoFrame);
+		ui->FrameMainDisplay->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+		ui->TextTextMessage->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Ignored);
+		QPalette palette(ui->TextTextMessage->palette());
+		palette.setColor(QPalette::Active,   QPalette::Light, prevPalette.color(QPalette::Active,   QPalette::Light));
+		palette.setColor(QPalette::Active,   QPalette::Dark,  prevPalette.color(QPalette::Active,   QPalette::Dark));
+		palette.setColor(QPalette::Inactive, QPalette::Light, prevPalette.color(QPalette::Inactive, QPalette::Light));
+		palette.setColor(QPalette::Inactive, QPalette::Dark,  prevPalette.color(QPalette::Inactive, QPalette::Dark));
+		palette.setColor(QPalette::Disabled, QPalette::Light, basePalette.color(QPalette::Disabled, QPalette::Light));
+		palette.setColor(QPalette::Disabled, QPalette::Dark,  basePalette.color(QPalette::Disabled, QPalette::Dark));
+		ui->TextTextMessage->setPalette(palette);
+		ui->onebar->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred);
+		ui->onebar->setMinimumSize(0, 6);
+		ui->onebar->setMaximumSize(16777215, 6);
+		ui->twobars->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred);
+		ui->twobars->setMinimumSize(0, 6);
+		ui->twobars->setMaximumSize(16777215, 12);
+		ui->threebars->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred);
+		ui->threebars->setMinimumSize(0, 6);
+		ui->threebars->setMaximumSize(16777215, 18);
+		ui->fourbars->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred);
+		ui->fourbars->setMinimumSize(0, 6);
+		ui->fourbars->setMaximumSize(16777215, 24);
+		ui->fivebars->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred);
+		ui->fivebars->setMinimumSize(0, 6);
+		ui->fivebars->setMaximumSize(16777215, 30);
+		SetFontSize(ui->TextLabelInputLevel, 12);
+		SetFontSize(ui->ProgrInputLevel, 15);
+		SetFontSize(ui->LabelBitrate, 15);
+		SetFontSize(ui->LabelCodec, 15);
+		SetFontSize(ui->LabelStereoMono, 15);
+		SetFontSize(ui->LabelLanguage, 15);
+		SetFontSize(ui->LabelCountryCode, 15);
+		SetFontSize(ui->LabelProgrType, 15);
+		SetFontSize(ui->LabelServiceID, 15);
+		SetFontSize(ui->labelAFS, 13);
+		SetFontSize(ui->LabelServiceLabel, 22);
+		SetFontSize(ui->lineEditFrequency, 24);
+		SetFontSize(ui->TextTextMessage, 16);
+	}
+	else if (name == "ServiceSelector")
+	{
+		Ui::ServiceSelector* ui = (Ui::ServiceSelector*)pUi;
+		QPalette palette(widget->palette());
+		QFrameSetup(ui->TextMiniService1);
+		QFrameSetup(ui->TextMiniService2);
+		QFrameSetup(ui->TextMiniService3);
+		QFrameSetup(ui->TextMiniService4);
+		widget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);
+		SetFontSize(widget, 18);
+	}
+	else if (name == "SystemEvaluationWindow")
+	{
+		systemevalDlg* ui = (systemevalDlg*)widget;
+		BaseSetup(widget);
+		ui->centralwidget->layout()->setMargin(WINDOW_BORDER_MARGIN);
+		QFrameSetup(ui->FrameParamStatusLEDs);
+		QFrameSetup(ui->FrameParamStatusLEDs_2);
+		QFrameSetup(ui->FrameFACParams);
+/*		palette.setColor(QPalette::Window, "#FFFFFF");
+		palette.setColor(QPalette::Base, "#FFFFFF");
+		palette.setColor(QPalette::Button, "#FFFFFF");
+		palette.setColor(QPalette::AlternateBase, "#FFFFFF");
+		palette.setColor(QPalette::Mid, "#FFFFFF");
+		palette.setColor(QPalette::Shadow, "#FFFFFF");
+		palette.setColor(QPalette::Midlight, "#FFFFFF");
+		palette.setColor(QPalette::Highlight, "#FFFFFF");
+		palette.setColor(QPalette::Light, "#FFFFFF");
+		palette.setColor(QPalette::Dark, "#FFFFFF");
+		palette.setColor(QPalette::NoRole, "#FFFFFF");
+		ui->ButtonGroupChanEstFreqInt->setPalette(palette);
+		ui->RadioButtonFreqWiener->setPalette(palette);
+*/		QPalette palette(ui->chartSelector->palette());
+		palette.setColor(QPalette::Base, palette.color(QPalette::Window));
+		ui->chartSelector->setPalette(palette);
+		QFrameSetup(ui->chartSelector);
+		ui->buttonOk->setDefault(false);
+		SetFontSize(ui->buttonOk, 13);
+		SetFontSize(widget, 7);
+	}
+	else if (name == "AMMainWindow")
+	{
+		AnalogDemDlg* ui = (AnalogDemDlg*)widget;
+		BaseSetup(widget);
+		ui->centralwidget->layout()->setMargin(WINDOW_BORDER_MARGIN);
+		QFrameSetup(ui->frame);
+		QFrameSetup(ui->frame_2);
+		ui->ButtonDRM->setDefault(false);
+	}
+	else if (name == "CAMSSDlgBase")
+	{
+		CAMSSDlg* ui = (CAMSSDlg*)widget;
+		BaseSetup(widget);
+		ui->centralwidget->layout()->setMargin(WINDOW_BORDER_MARGIN);
+		QFrameSetup(ui->FrameMainDisplay);
+		QColor color(ui->TextAMSSInfo->palette().color(QPalette::WindowText));
+		QPalette palette(ui->FrameMainDisplay->palette());
+		palette.setColor(QPalette::Light, color);
+		palette.setColor(QPalette::Dark, color);
+		ui->FrameMainDisplay->setPalette(palette);
+		ui->FrameMainDisplay->setLineWidth(2);
+		ui->buttonOk->setDefault(false);
+		SetFontSize(ui->TextAMSSTimeDate, 12);
+		SetFontSize(ui->TextAMSSServiceLabel, 22);
+		SetFontSize(ui->TextAMSSLanguage, 15);
+		SetFontSize(ui->TextAMSSCountryCode, 15);
+		SetFontSize(ui->TextAMSSAMCarrierMode, 15);
+		SetFontSize(ui->TextAMSSInfo, 15);
+		SetFontSize(ui->TextAMSSServiceID, 15);
+	}
+	else if (name == "CAboutDlgBase")
+	{
+		CAboutDlg* ui = (CAboutDlg*)widget;
+		BaseSetup(widget);
+		widget->layout()->setMargin(WINDOW_BORDER_MARGIN);
+		ResizeWidget(widget);
+		ui->setSizeGripEnabled(false);
+		ui->buttonOk->setDefault(false);
+	}
+	else if (name == "StationsDlgbase")
+	{
+		StationsDlg* ui = (StationsDlg*)widget;
+		BaseSetup(widget);
+		ui->centralwidget->layout()->setMargin(WINDOW_BORDER_MARGIN);
+		QFrameSetup(ui->TextLabelUTCTime);
+		ui->buttonOk->setDefault(false);
+	}
+	else if (name == "CEPGDlgbase")
+	{
+		EPGDlg* ui = (EPGDlg*)widget;
+		BaseSetup(widget);
+		ui->centralwidget->layout()->setMargin(WINDOW_BORDER_MARGIN);
+		QFrameSetup(ui->frame);
+		ui->buttonOk->setDefault(false);
+	}
+	else if (name == "CGeneralSettingsDlgBase")
+	{
+		GeneralSettingsDlg* ui = (GeneralSettingsDlg*)widget;
+		BaseSetup(widget);
+		widget->layout()->setMargin(WINDOW_BORDER_MARGIN);
+		ResizeWidget(widget);
+		ui->setSizeGripEnabled(false);
+		ui->buttonOk->setDefault(false);
+	}
+	else if (name == "CMultSettingsDlgBase")
+	{
+		MultSettingsDlg* ui = (MultSettingsDlg*)widget;
+		BaseSetup(widget);
+		widget->layout()->setMargin(WINDOW_BORDER_MARGIN);
+		ResizeWidget(widget);
+		ui->setSizeGripEnabled(false);
+		ui->buttonOk->setDefault(false);
+	}
+#ifdef HAVE_QTWEBKIT
+	else if (name == "BWSViewer")
+	{
+		BWSViewer* ui = (BWSViewer*)widget;
+		ui->centralwidget->layout()->setMargin(WINDOW_BORDER_MARGIN);
+		QPalette palette(BaseSetup(widget));
+		palette.setColor(QPalette::Base, QColor("#FFFFFF"));
+		palette.setColor(QPalette::Text, QColor("#000000"));
+		ui->webView->setPalette(palette);
+		QFrameSetup(ui->frame);
+	}
+#endif
+	else if (name == "JLViewer")
+	{
+		JLViewer* ui = (JLViewer*)widget;
+		ui->centralwidget->layout()->setMargin(WINDOW_BORDER_MARGIN);
+		QPalette palette(BaseSetup(widget));
+		palette.setColor(QPalette::Base, QColor("#FFFFFF"));
+		palette.setColor(QPalette::Text, QColor("#000000"));
+		ui->textBrowser->setPalette(palette);
+		QFrameSetup(ui->textBrowser);
+	}
+	else if (name == "LiveScheduleWindow")
+	{
+		LiveScheduleDlg* ui = (LiveScheduleDlg*)widget;
+		ui->centralwidget->layout()->setMargin(WINDOW_BORDER_MARGIN);
+		BaseSetup(widget);
+		QFrameSetup(ui->TextLabelUTCTime);
+		QFrameSetup(ui->labelFrequency);
+	}
+	else if (name == "SlideShowViewer")
+	{
+		SlideShowViewer* ui = (SlideShowViewer*)widget;
+		ui->centralwidget->layout()->setMargin(WINDOW_BORDER_MARGIN);
+		BaseSetup(widget);
+		QFrameSetup(ui->frame);
+	}
+#ifdef HAVE_LIBHAMLIB
+	else if (name == "RigDlg")
+	{
+		RigDlg* ui = (RigDlg*)widget;
+		widget->layout()->setMargin(WINDOW_BORDER_MARGIN);
+		BaseSetup(widget);
+		ResizeWidget(widget);
+		ui->setSizeGripEnabled(false);
+	}
+#endif
+// TODO CodecParams TransmDlgBase
+}
+
+#endif
diff --git a/src/GUI-QT/ThemeCustomizer.h b/src/GUI-QT/ThemeCustomizer.h
new file mode 100644
index 0000000..38741cc
--- /dev/null
+++ b/src/GUI-QT/ThemeCustomizer.h
@@ -0,0 +1,43 @@
+/******************************************************************************\
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *  David Flamand
+ *
+ * Description:
+ *  Intended to provide a way to customize appearance of widget
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+//#ifdef __ANDROID__
+//# define USE_THEMECUSTOMIZER
+//#else
+# undef USE_THEMECUSTOMIZER
+//#endif
+
+#ifdef USE_THEMECUSTOMIZER
+# define APPLY_CUSTOM_THEME() ApplyCustomTheme(this, NULL)
+# define APPLY_CUSTOM_THEME_UI() ApplyCustomTheme(this, ui)
+class QWidget;
+void ApplyCustomTheme(QWidget* widget, void* pUi);
+#else
+# define APPLY_CUSTOM_THEME()
+# define APPLY_CUSTOM_THEME_UI()
+#endif
+
diff --git a/src/GUI-QT/TransmDlg.cpp b/src/GUI-QT/TransmDlg.cpp
new file mode 100644
index 0000000..a02ad24
--- /dev/null
+++ b/src/GUI-QT/TransmDlg.cpp
@@ -0,0 +1,1538 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "TransmDlg.h"
+#include "SoundCardSelMenu.h"
+#include <QCloseEvent>
+#include <QTreeWidget>
+#include <QFileDialog>
+#include <QTextEdit>
+#include <QProgressBar>
+#include <QHeaderView>
+#include <QWhatsThis>
+
+
+TransmDialog::TransmDialog(CSettings& Settings,	QWidget* parent)
+	:
+    CWindow(parent, Settings, "Transmit"),
+	TransThread(Settings),
+	DRMTransmitter(TransThread.DRMTransmitter),
+	vecstrTextMessage(1) /* 1 for new text */,
+	pCodecDlg(NULL), pSysTray(NULL),
+	pActionStartStop(NULL), bIsStarted(FALSE),
+	iIDCurrentText(0), iServiceDescr(0),
+	bCloseRequested(FALSE), iButtonCodecState(0)
+{
+	setupUi(this);
+#if QWT_VERSION < 0x060100
+    ProgrInputLevel->setScalePosition(QwtThermo::BottomScale);
+#else
+    ProgrInputLevel->setScalePosition(QwtThermo::LeadingScale);
+#endif
+
+	/* Load transmitter settings */
+	DRMTransmitter.LoadSettings();
+
+	/* Set help text for the controls */
+	AddWhatsThisHelp();
+
+	/* Init controls with default settings */
+	ButtonStartStop->setText(tr("&Start"));
+	OnButtonClearAllText();
+	UpdateMSCProtLevCombo();
+
+	/* Init progress bar for input signal level */
+#if QWT_VERSION < 0x060100
+	ProgrInputLevel->setRange(-50.0, 0.0);
+    ProgrInputLevel->setOrientation(Qt::Horizontal, QwtThermo::BottomScale);
+#else
+	ProgrInputLevel->setScale(-50.0, 0.0);
+    ProgrInputLevel->setOrientation(Qt::Horizontal);
+    ProgrInputLevel->setScalePosition(QwtThermo::LeadingScale);
+#endif
+	ProgrInputLevel->setAlarmLevel(-5.0);
+#if QWT_VERSION < 0x060000
+	ProgrInputLevel->setAlarmColor(QColor(255, 0, 0));
+	ProgrInputLevel->setFillColor(QColor(0, 190, 0));
+#else
+	QPalette newPalette = palette();
+	newPalette.setColor(QPalette::Base, newPalette.color(QPalette::Window));
+	newPalette.setColor(QPalette::ButtonText, QColor(0, 190, 0));
+	newPalette.setColor(QPalette::Highlight,  QColor(255, 0, 0));
+	ProgrInputLevel->setPalette(newPalette);
+#endif
+
+	/* Init progress bar for current transmitted picture */
+	ProgressBarCurPict->setRange(0, 100);
+	ProgressBarCurPict->setValue(0);
+	TextLabelCurPict->setText("");
+
+	/* Output mode (real valued, I / Q or E / P) */
+	switch (TransThread.DRMTransmitter.GetTransData()->GetIQOutput())
+	{
+	case CTransmitData::OF_REAL_VAL:
+		RadioButtonOutReal->setChecked(TRUE);
+		break;
+
+	case CTransmitData::OF_IQ_POS:
+		RadioButtonOutIQPos->setChecked(TRUE);
+		break;
+
+	case CTransmitData::OF_IQ_NEG:
+		RadioButtonOutIQNeg->setChecked(TRUE);
+		break;
+
+	case CTransmitData::OF_EP:
+		RadioButtonOutEP->setChecked(TRUE);
+		break;
+	}
+
+	/* Output High Quality I/Q */
+	CheckBoxHighQualityIQ->setEnabled(TransThread.DRMTransmitter.GetTransData()->GetIQOutput() != CTransmitData::OF_REAL_VAL);
+	CheckBoxHighQualityIQ->setChecked(TransThread.DRMTransmitter.GetTransData()->GetHighQualityIQ());
+
+	/* Output Amplified */
+	CheckBoxAmplifiedOutput->setEnabled(TransThread.DRMTransmitter.GetTransData()->GetIQOutput() != CTransmitData::OF_EP);
+	CheckBoxAmplifiedOutput->setChecked(TransThread.DRMTransmitter.GetTransData()->GetAmplifiedOutput());
+
+	/* Don't lock the Parameter object since the working thread is stopped */
+	CParameter& Parameters = *DRMTransmitter.GetParameters();
+
+	/* Transmission of current time */
+	switch (Parameters.eTransmitCurrentTime)
+	{
+	case CParameter::CT_OFF:
+		RadioButtonCurTimeOff->setChecked(TRUE);
+		break;
+
+	case CParameter::CT_LOCAL:
+		RadioButtonCurTimeLocal->setChecked(TRUE);
+		break;
+
+	case CParameter::CT_UTC:
+		RadioButtonCurTimeUTC->setChecked(TRUE);
+		break;
+
+	case CParameter::CT_UTC_OFFSET:
+		RadioButtonCurTimeUTCOffset->setChecked(TRUE);
+	}
+
+	/* Robustness mode */
+	switch (Parameters.GetWaveMode())
+	{
+	case RM_ROBUSTNESS_MODE_A:
+		RadioButtonRMA->setChecked(TRUE);
+		break;
+
+	case RM_ROBUSTNESS_MODE_B:
+		RadioButtonRMB->setChecked(TRUE);
+		break;
+
+	case RM_ROBUSTNESS_MODE_C:
+		RadioButtonBandwidth45->setEnabled(FALSE);
+		RadioButtonBandwidth5->setEnabled(FALSE);
+		RadioButtonBandwidth9->setEnabled(FALSE);
+		RadioButtonBandwidth18->setEnabled(FALSE);
+		RadioButtonRMC->setChecked(TRUE);
+		break;
+
+	case RM_ROBUSTNESS_MODE_D:
+		RadioButtonBandwidth45->setEnabled(FALSE);
+		RadioButtonBandwidth5->setEnabled(FALSE);
+		RadioButtonBandwidth9->setEnabled(FALSE);
+		RadioButtonBandwidth18->setEnabled(FALSE);
+		RadioButtonRMD->setChecked(TRUE);
+		break;
+
+    case RM_ROBUSTNESS_MODE_E:
+        // TODO
+        break;
+
+	case RM_NO_MODE_DETECTED:
+		break;
+	}
+
+	/* Bandwidth */
+	switch (Parameters.GetSpectrumOccup())
+	{
+	case SO_0:
+		RadioButtonBandwidth45->setChecked(TRUE);
+		break;
+
+	case SO_1:
+		RadioButtonBandwidth5->setChecked(TRUE);
+		break;
+
+	case SO_2:
+		RadioButtonBandwidth9->setChecked(TRUE);
+		break;
+
+	case SO_3:
+		RadioButtonBandwidth10->setChecked(TRUE);
+		break;
+
+	case SO_4:
+		RadioButtonBandwidth18->setChecked(TRUE);
+		break;
+
+	case SO_5:
+		RadioButtonBandwidth20->setChecked(TRUE);
+		break;
+
+    case SO_6:
+        // TODO
+        break;
+    }
+
+	/* MSC interleaver mode */
+	ComboBoxMSCInterleaver->insertItem(0, tr("2 s (Long Interleaving)"));
+	ComboBoxMSCInterleaver->insertItem(1, tr("400 ms (Short Interleaving)"));
+
+	switch (Parameters.eSymbolInterlMode)
+	{
+    case SI_LONG:
+		ComboBoxMSCInterleaver->setCurrentIndex(0);
+		break;
+
+    case SI_SHORT:
+		ComboBoxMSCInterleaver->setCurrentIndex(1);
+		break;
+    case SI_MODE_E: // TODO
+		;
+	}
+
+	/* MSC Constellation Scheme */
+	ComboBoxMSCConstellation->insertItem(0, tr("SM 16-QAM"));
+	ComboBoxMSCConstellation->insertItem(1, tr("SM 64-QAM"));
+
+// These modes should not be used right now, TODO
+// DF: I reenabled those, because it seems to work, at least with dream
+	ComboBoxMSCConstellation->insertItem(2, tr("HMsym 64-QAM"));
+	ComboBoxMSCConstellation->insertItem(3, tr("HMmix 64-QAM"));
+
+	switch (Parameters.eMSCCodingScheme)
+	{
+	case CS_1_SM:
+		break;
+
+	case CS_2_SM:
+		ComboBoxMSCConstellation->setCurrentIndex(0);
+		break;
+
+	case CS_3_SM:
+		ComboBoxMSCConstellation->setCurrentIndex(1);
+		break;
+
+	case CS_3_HMSYM:
+		ComboBoxMSCConstellation->setCurrentIndex(2);
+		break;
+
+	case CS_3_HMMIX:
+		ComboBoxMSCConstellation->setCurrentIndex(3);
+		break;
+	}
+
+	/* SDC Constellation Scheme */
+	ComboBoxSDCConstellation->insertItem(0, tr("4-QAM"));
+	ComboBoxSDCConstellation->insertItem(1, tr("16-QAM"));
+
+	switch (Parameters.eSDCCodingScheme)
+	{
+	case CS_1_SM:
+		ComboBoxSDCConstellation->setCurrentIndex(0);
+		break;
+
+	case CS_2_SM:
+		ComboBoxSDCConstellation->setCurrentIndex(1);
+		break;
+
+	case CS_3_SM:
+	case CS_3_HMSYM:
+	case CS_3_HMMIX:
+		break;
+	}
+
+
+	/* Service parameters --------------------------------------------------- */
+	/* Service label */
+	CService& Service = Parameters.Service[0]; // TODO
+	QString label = QString::fromUtf8(Service.strLabel.c_str());
+	LineEditServiceLabel->setText(label);
+
+	/* Service ID */
+	LineEditServiceID->setText(QString().setNum((int) Service.iServiceID, 16));
+
+
+	int i;
+	/* Language */
+	for (i = 0; i < LEN_TABLE_LANGUAGE_CODE; i++)
+		ComboBoxLanguage->insertItem(i, strTableLanguageCode[i].c_str());
+
+	ComboBoxLanguage->setCurrentIndex(Service.iLanguage);
+
+	/* Program type */
+	for (i = 0; i < LEN_TABLE_PROG_TYPE_CODE; i++)
+		ComboBoxProgramType->insertItem(i, strTableProgTypCod[i].c_str());
+
+	/* Service description */
+	iServiceDescr = Service.iServiceDescr;
+	ComboBoxProgramType->setCurrentIndex(iServiceDescr);
+
+	/* Sound card IF */
+	LineEditSndCrdIF->setText(QString().number(
+		TransThread.DRMTransmitter.GetCarOffset(), 'f', 2));
+
+	/* Clear list box for file names */
+	OnButtonClearAllFileNames();
+
+	/* Disable other three services */
+	TabWidgetServices->setTabEnabled(1, FALSE);
+	TabWidgetServices->setTabEnabled(2, FALSE);
+	TabWidgetServices->setTabEnabled(3, FALSE);
+	CheckBoxEnableService->setChecked(TRUE);
+	CheckBoxEnableService->setEnabled(FALSE);
+
+	/* Setup audio codec check boxes */
+	switch (Service.AudioParam.eAudioCoding)
+	{
+	case CAudioParam::AC_AAC:
+		RadioButtonAAC->setChecked(TRUE);
+		ShowButtonCodec(FALSE, 1);
+		break;
+
+	case CAudioParam::AC_OPUS:
+		RadioButtonOPUS->setChecked(TRUE);
+		ShowButtonCodec(TRUE, 1);
+		break;
+
+	default:
+		ShowButtonCodec(FALSE, 1);
+		break;
+	}
+	CAudioSourceEncoder& AudioSourceEncoder = *DRMTransmitter.GetAudSrcEnc();
+	if (!AudioSourceEncoder.CanEncode(CAudioParam::AC_AAC)) {
+		RadioButtonAAC->setText(tr("No DRM capable AAC Codec"));
+		RadioButtonAAC->setToolTip(tr("see http://drm.sourceforge.net"));
+		RadioButtonAAC->setEnabled(false);
+		//RadioButtonAAC->hide();
+	}
+	if (!AudioSourceEncoder.CanEncode(CAudioParam::AC_OPUS)) {
+		RadioButtonOPUS->setText(tr("No Opus Codec"));
+		RadioButtonOPUS->setToolTip(tr("see http://drm.sourceforge.net"));
+		RadioButtonOPUS->setEnabled(false);
+		//RadioButtonOPUS->hide();
+	}
+	if (!AudioSourceEncoder.CanEncode(CAudioParam::AC_AAC)
+	    && !AudioSourceEncoder.CanEncode(CAudioParam::AC_OPUS)) {
+		/* Let this service be an data service */
+		CheckBoxEnableAudio->setChecked(false);
+		CheckBoxEnableAudio->setEnabled(false);
+		EnableAudio(false);
+		CheckBoxEnableData->setChecked(true);
+		EnableData(true);
+	}
+	else {
+		/* Let this service be an audio service for initialization */
+		/* Set audio enable check box */
+		CheckBoxEnableAudio->setChecked(true);
+		EnableAudio(true);
+		CheckBoxEnableData->setChecked(false);
+		EnableData(false);
+	}
+
+	/* Add example text message at startup ---------------------------------- */
+	/* Activate text message */
+	EnableTextMessage(TRUE);
+	CheckBoxEnableTextMessage->setChecked(TRUE);
+
+	/* Add example text in internal container */
+	vecstrTextMessage.Add(
+		tr("Dream DRM Transmitter\x0B\x0AThis is a test transmission").toUtf8().constData());
+
+	/* Insert item in combo box, display text and set item to our text */
+	ComboBoxTextMessage->insertItem(1, QString().setNum(1));
+	ComboBoxTextMessage->setCurrentIndex(1);
+
+	/* Update the TextEdit with the default text */
+	OnComboBoxTextMessageActivated(1);
+
+	/* Now make sure that the text message flag is activated in global struct */
+	Service.AudioParam.bTextflag = TRUE;
+
+
+	/* Enable all controls */
+	EnableAllControlsForSet();
+
+
+	/* Set check box remove path */
+	CheckBoxRemovePath->setChecked(TRUE);
+	OnToggleCheckBoxRemovePath(TRUE);
+
+
+	/* Set Menu ***************************************************************/
+	CFileMenu* pFileMenu = new CFileMenu(DRMTransmitter, this, menu_Settings);
+
+	menu_Settings->addMenu(new CSoundCardSelMenu(DRMTransmitter, pFileMenu, this));
+
+	connect(actionAbout_Dream, SIGNAL(triggered()), &AboutDlg, SLOT(show()));
+	connect(actionWhats_This, SIGNAL(triggered()), this, SLOT(OnWhatsThis()));
+
+	/* Connections ---------------------------------------------------------- */
+	/* Push buttons */
+	connect(ButtonStartStop, SIGNAL(clicked()),
+		this, SLOT(OnButtonStartStop()));
+	connect(ButtonCodec, SIGNAL(clicked()),
+		this, SLOT(OnButtonCodec()));
+	connect(PushButtonAddText, SIGNAL(clicked()),
+		this, SLOT(OnPushButtonAddText()));
+	connect(PushButtonClearAllText, SIGNAL(clicked()),
+		this, SLOT(OnButtonClearAllText()));
+	connect(PushButtonAddFile, SIGNAL(clicked()),
+		this, SLOT(OnPushButtonAddFileName()));
+	connect(PushButtonClearAllFileNames, SIGNAL(clicked()),
+		this, SLOT(OnButtonClearAllFileNames()));
+
+	/* Check boxes */
+	connect(CheckBoxHighQualityIQ, SIGNAL(toggled(bool)),
+		this, SLOT(OnToggleCheckBoxHighQualityIQ(bool)));
+	connect(CheckBoxAmplifiedOutput, SIGNAL(toggled(bool)),
+		this, SLOT(OnToggleCheckBoxAmplifiedOutput(bool)));
+	connect(CheckBoxEnableTextMessage, SIGNAL(toggled(bool)),
+		this, SLOT(OnToggleCheckBoxEnableTextMessage(bool)));
+	connect(CheckBoxEnableAudio, SIGNAL(toggled(bool)),
+		this, SLOT(OnToggleCheckBoxEnableAudio(bool)));
+	connect(CheckBoxEnableData, SIGNAL(toggled(bool)),
+		this, SLOT(OnToggleCheckBoxEnableData(bool)));
+	connect(CheckBoxRemovePath, SIGNAL(toggled(bool)),
+		this, SLOT(OnToggleCheckBoxRemovePath(bool)));
+
+	/* Combo boxes */
+	connect(ComboBoxMSCInterleaver, SIGNAL(activated(int)),
+		this, SLOT(OnComboBoxMSCInterleaverActivated(int)));
+	connect(ComboBoxMSCConstellation, SIGNAL(activated(int)),
+		this, SLOT(OnComboBoxMSCConstellationActivated(int)));
+	connect(ComboBoxSDCConstellation, SIGNAL(activated(int)),
+		this, SLOT(OnComboBoxSDCConstellationActivated(int)));
+	connect(ComboBoxLanguage, SIGNAL(activated(int)),
+		this, SLOT(OnComboBoxLanguageActivated(int)));
+	connect(ComboBoxProgramType, SIGNAL(activated(int)),
+		this, SLOT(OnComboBoxProgramTypeActivated(int)));
+	connect(ComboBoxTextMessage, SIGNAL(activated(int)),
+		this, SLOT(OnComboBoxTextMessageActivated(int)));
+	connect(ComboBoxMSCProtLev, SIGNAL(activated(int)),
+		this, SLOT(OnComboBoxMSCProtLevActivated(int)));
+
+	/* Button groups */
+	connect(ButtonGroupRobustnessMode, SIGNAL(buttonClicked(int)),
+		this, SLOT(OnRadioRobustnessMode(int)));
+	connect(ButtonGroupBandwidth, SIGNAL(buttonClicked(int)),
+		this, SLOT(OnRadioBandwidth(int)));
+	connect(ButtonGroupOutput, SIGNAL(buttonClicked(int)),
+		this, SLOT(OnRadioOutput(int)));
+	connect(ButtonGroupCodec, SIGNAL(buttonClicked(int)),
+		this, SLOT(OnRadioCodec(int)));
+	connect(ButtonGroupCurrentTime, SIGNAL(buttonClicked(int)),
+		this, SLOT(OnRadioCurrentTime(int)));
+
+	/* Line edits */
+	connect(LineEditServiceLabel, SIGNAL(textChanged(const QString&)),
+		this, SLOT(OnTextChangedServiceLabel(const QString&)));
+	connect(LineEditServiceID, SIGNAL(textChanged(const QString&)),
+		this, SLOT(OnTextChangedServiceID(const QString&)));
+	connect(LineEditSndCrdIF, SIGNAL(textChanged(const QString&)),
+		this, SLOT(OnTextChangedSndCrdIF(const QString&)));
+
+	/* Timers */
+	connect(&Timer, SIGNAL(timeout()),
+		this, SLOT(OnTimer()));
+	connect(&TimerStop, SIGNAL(timeout()),
+		this, SLOT(OnTimerStop()));
+
+    /* System tray setup */
+    pSysTray = CSysTray::Create(this,
+        SLOT(OnSysTrayActivated(QSystemTrayIcon::ActivationReason)),
+        NULL, ":/icons/MainIconTx.svg");
+	pActionStartStop = CSysTray::AddAction(pSysTray,
+		ButtonStartStop->text(), this, SLOT(OnButtonStartStop()));
+	CSysTray::AddSeparator(pSysTray);
+	CSysTray::AddAction(pSysTray, tr("&Exit"), this, SLOT(close()));
+	CSysTray::SetToolTip(pSysTray, QString(), tr("Stopped"));
+
+	/* Set timer for real-time controls */
+	Timer.start(GUI_CONTROL_UPDATE_TIME);
+}
+
+TransmDialog::~TransmDialog()
+{
+	/* Destroy codec dialog if exist */
+	if (pCodecDlg)
+		delete pCodecDlg;
+}
+
+void TransmDialog::eventClose(QCloseEvent* ce)
+{
+	bCloseRequested = TRUE;
+	if (bIsStarted == TRUE)
+	{
+		OnButtonStartStop();
+		ce->ignore();
+	}
+	else {
+		CSysTray::Destroy(&pSysTray);
+
+		/* Stop transmitter */
+		if (bIsStarted == TRUE)
+			TransThread.Stop();
+
+		/* Restore the service description, may
+		   have been reset by data service */
+		CParameter& Parameters = *DRMTransmitter.GetParameters();
+		Parameters.Lock();
+		CService& Service = Parameters.Service[0]; // TODO
+		Service.iServiceDescr = iServiceDescr;
+
+		/* Save transmitter settings */
+		DRMTransmitter.SaveSettings();
+		Parameters.Unlock();
+
+		ce->accept();
+	}
+}
+
+void TransmDialog::OnWhatsThis()
+{
+	QWhatsThis::enterWhatsThisMode();
+}
+
+void TransmDialog::OnSysTrayActivated(QSystemTrayIcon::ActivationReason reason)
+{
+	if (reason == QSystemTrayIcon::Trigger
+#if QT_VERSION < 0x050000
+		|| reason == QSystemTrayIcon::DoubleClick
+#endif
+	)
+	{
+		const Qt::WindowStates ws = windowState();
+		if (ws & Qt::WindowMinimized)
+			setWindowState((ws & ~Qt::WindowMinimized) | Qt::WindowActive);
+		else
+			toggleVisibility();
+	}
+}
+
+void TransmDialog::OnTimer()
+{
+	/* Set value for input level meter (only in "start" mode) */
+	if (bIsStarted == TRUE)
+	{
+		ProgrInputLevel->
+			setValue(TransThread.DRMTransmitter.GetReadData()->GetLevelMeter());
+
+		string strCPictureName;
+		_REAL rCPercent;
+
+		/* Activate progress bar for slide show pictures only if current state
+		   can be queried and if data service is active
+		   (check box is checked) */
+		if ((TransThread.DRMTransmitter.GetAudSrcEnc()->
+			GetTransStat(strCPictureName, rCPercent) ==	TRUE) &&
+			(CheckBoxEnableData->isChecked()))
+		{
+			/* Enable controls */
+			ProgressBarCurPict->setEnabled(TRUE);
+			TextLabelCurPict->setEnabled(TRUE);
+
+			/* We want to file name, not the complete path -> "QFileInfo" */
+			QFileInfo FileInfo(strCPictureName.c_str());
+
+			/* Show current file name and percentage */
+			TextLabelCurPict->setText(FileInfo.fileName());
+			ProgressBarCurPict->setValue((int) (rCPercent * 100)); /* % */
+		}
+		else
+		{
+			/* Disable controls */
+			ProgressBarCurPict->setEnabled(FALSE);
+			TextLabelCurPict->setEnabled(FALSE);
+		}
+	}
+}
+
+void TransmDialog::OnTimerStop()
+{
+	if (!TransThread.isRunning())
+	{
+		TimerStop.stop();
+
+		bIsStarted = FALSE;
+
+		if (bCloseRequested)
+		{
+			close();
+		}
+		else
+		{
+			ButtonStartStop->setText(tr("&Start"));
+			if (pActionStartStop)
+				pActionStartStop->setText(ButtonStartStop->text());
+			CSysTray::SetToolTip(pSysTray, QString(), tr("Stopped"));
+
+			EnableAllControlsForSet();
+		}
+	}
+}
+
+void TransmDialog::OnButtonStartStop()
+{
+	if (!TimerStop.isActive())
+	{
+		if (bIsStarted == TRUE)
+		{
+			ButtonStartStop->setText(tr("Stopping..."));
+			if (pActionStartStop)
+				pActionStartStop->setText(ButtonStartStop->text());
+			CSysTray::SetToolTip(pSysTray, QString(), ButtonStartStop->text());
+
+			/* Request a transmitter stop */
+			TransThread.Stop();
+
+			/* Start the timer for polling the thread state */
+			TimerStop.start(50);
+		}
+		else
+		{
+			int i;
+
+			/* Start transmitter */
+			/* Set text message */
+			TransThread.DRMTransmitter.GetAudSrcEnc()->ClearTextMessage();
+
+			for (i = 1; i < vecstrTextMessage.Size(); i++)
+				TransThread.DRMTransmitter.GetAudSrcEnc()->
+					SetTextMessage(vecstrTextMessage[i]);
+
+			/* Set file names for data application */
+			TransThread.DRMTransmitter.GetAudSrcEnc()->ClearPicFileNames();
+
+			/* Iteration through table widget items */
+			int count = TreeWidgetFileNames->topLevelItemCount();
+
+			for (i = 0; i <count; i++)
+			{
+				/* Complete file path is in third column */
+				QTreeWidgetItem* item = TreeWidgetFileNames->topLevelItem(i);
+				if (item)
+				{
+					/* Get the file path  */
+					const QString strFileName = item->text(2);
+
+					/* Extract format string */
+					QFileInfo FileInfo(strFileName);
+					const QString strFormat = FileInfo.suffix();
+
+					TransThread.DRMTransmitter.GetAudSrcEnc()->
+						SetPicFileName(strFileName.toUtf8().constData(), strFormat.toUtf8().constData());
+				}
+			}
+
+			TransThread.start();
+
+			ButtonStartStop->setText(tr("&Stop"));
+			if (pActionStartStop)
+				pActionStartStop->setText(ButtonStartStop->text());
+			CSysTray::SetToolTip(pSysTray, QString(), tr("Transmitting"));
+
+			DisableAllControlsForSet();
+
+			bIsStarted = TRUE;
+		}
+	}
+}
+
+void TransmDialog::OnToggleCheckBoxHighQualityIQ(bool bState)
+{
+	TransThread.DRMTransmitter.GetTransData()->SetHighQualityIQ(bState);
+}
+
+void TransmDialog::OnToggleCheckBoxAmplifiedOutput(bool bState)
+{
+	TransThread.DRMTransmitter.GetTransData()->SetAmplifiedOutput(bState);
+}
+
+void TransmDialog::OnToggleCheckBoxEnableTextMessage(bool bState)
+{
+	EnableTextMessage(bState);
+}
+
+void TransmDialog::EnableTextMessage(const _BOOLEAN bFlag)
+{
+	CParameter& Parameters = *TransThread.DRMTransmitter.GetParameters();
+
+	Parameters.Lock();
+
+	if (bFlag == TRUE)
+	{
+		/* Enable text message controls */
+		ComboBoxTextMessage->setEnabled(TRUE);
+		MultiLineEditTextMessage->setEnabled(TRUE);
+		PushButtonAddText->setEnabled(TRUE);
+		PushButtonClearAllText->setEnabled(TRUE);
+
+		/* Set text message flag in global struct */
+		Parameters.Service[0].AudioParam.bTextflag = TRUE;
+	}
+	else
+	{
+		/* Disable text message controls */
+		ComboBoxTextMessage->setEnabled(FALSE);
+		MultiLineEditTextMessage->setEnabled(FALSE);
+		PushButtonAddText->setEnabled(FALSE);
+		PushButtonClearAllText->setEnabled(FALSE);
+
+		/* Set text message flag in global struct */
+		Parameters.Service[0].AudioParam.bTextflag = FALSE;
+	}
+
+	Parameters.Unlock();
+}
+
+void TransmDialog::OnToggleCheckBoxEnableAudio(bool bState)
+{
+	EnableAudio(bState);
+
+	if (bState)
+	{
+		/* Set audio enable check box */
+		CheckBoxEnableData->setChecked(FALSE);
+		EnableData(FALSE);
+		ShowButtonCodec(TRUE, 2);
+	}
+	else
+	{
+		/* Set audio enable check box */
+		CheckBoxEnableData->setChecked(TRUE);
+		EnableData(TRUE);
+		ShowButtonCodec(FALSE, 2);
+	}
+}
+
+void TransmDialog::EnableAudio(const _BOOLEAN bFlag)
+{
+	if (bFlag == TRUE)
+	{
+		/* Enable audio controls */
+		GroupBoxCodec->setEnabled(TRUE);
+		GroupBoxTextMessage->setEnabled(TRUE);
+		ComboBoxProgramType->setEnabled(TRUE);
+
+		CParameter& Parameters = *TransThread.DRMTransmitter.GetParameters();
+
+		Parameters.Lock();
+
+		/* Only one audio service */
+		Parameters.iNumAudioService = 1;
+		Parameters.iNumDataService = 0;
+
+		/* Audio flag of this service */
+		Parameters.Service[0].eAudDataFlag = CService::SF_AUDIO;
+
+		/* Always use stream number 0 right now, TODO */
+		Parameters.Service[0].AudioParam.iStreamID = 0;
+
+		/* Programme Type code */
+		Parameters.Service[0].iServiceDescr = iServiceDescr;
+
+		Parameters.Unlock();
+	}
+	else
+	{
+		/* Disable audio controls */
+		GroupBoxCodec->setEnabled(FALSE);
+		GroupBoxTextMessage->setEnabled(FALSE);
+		ComboBoxProgramType->setEnabled(FALSE);
+	}
+}
+
+void TransmDialog::OnToggleCheckBoxEnableData(bool bState)
+{
+	EnableData(bState);
+
+	if (bState)
+	{
+		/* Set audio enable check box */
+		CheckBoxEnableAudio->setChecked(FALSE);
+		EnableAudio(FALSE);
+	}
+	else
+	{
+		/* Set audio enable check box */
+		CheckBoxEnableAudio->setChecked(TRUE);
+		EnableAudio(TRUE);
+	}
+}
+
+void TransmDialog::EnableData(const _BOOLEAN bFlag)
+{
+	/* Enable/Disable data controls */
+	CheckBoxRemovePath->setEnabled(bFlag);
+	TreeWidgetFileNames->setEnabled(bFlag);
+	PushButtonClearAllFileNames->setEnabled(bFlag);
+	PushButtonAddFile->setEnabled(bFlag);
+
+	if (bFlag == TRUE)
+	{
+		CParameter& Parameters = *TransThread.DRMTransmitter.GetParameters();
+
+		Parameters.Lock();
+
+		/* Only one data service */
+		Parameters.iNumAudioService = 0;
+		Parameters.iNumDataService = 1;
+
+		/* Data flag for this service */
+		Parameters.Service[0].eAudDataFlag = CService::SF_DATA;
+
+		/* Always use stream number 0, TODO */
+		Parameters.Service[0].DataParam.iStreamID = 0;
+
+		/* Init SlideShow application */
+		Parameters.Service[0].DataParam.iPacketLen = 45; /* TEST */
+		Parameters.Service[0].DataParam.eDataUnitInd = CDataParam::DU_DATA_UNITS;
+		Parameters.Service[0].DataParam.eAppDomain = CDataParam::AD_DAB_SPEC_APP;
+
+		/* The value 0 indicates that the application details are provided
+		   solely by SDC data entity type 5 */
+		Parameters.Service[0].iServiceDescr = 0;
+
+		Parameters.Unlock();
+	}
+}
+
+_BOOLEAN TransmDialog::GetMessageText(const int iID)
+{
+	_BOOLEAN bTextIsNotEmpty = TRUE;
+
+	/* Check if text control is not empty */
+	if (!MultiLineEditTextMessage->toPlainText().isEmpty())
+	{
+		/* Check size of container. If not enough space, enlarge */
+		if (iID == vecstrTextMessage.Size())
+			vecstrTextMessage.Enlarge(1);
+
+		/* DF: I did some test on both Qt3 and Qt4, and
+		   UTF8 char are well preserved */
+		/* Get the text from MultiLineEditTextMessage */
+		QString text = MultiLineEditTextMessage->toPlainText();
+
+		/* Each line is already separated by a newline char,
+		   so no special processing is further required */
+
+		/* Save the text */
+		vecstrTextMessage[iID] = text.toUtf8().constData();
+
+	}
+	else
+		bTextIsNotEmpty = FALSE;
+	return bTextIsNotEmpty;
+}
+
+void TransmDialog::OnPushButtonAddText()
+{
+	if (iIDCurrentText == 0)
+	{
+		/* Add new message */
+		if (GetMessageText(vecstrTextMessage.Size()) == TRUE)
+		{
+			/* If text was not empty, add new text in combo box */
+			const int iNewID = vecstrTextMessage.Size() - 1;
+			ComboBoxTextMessage->insertItem(iNewID, QString().setNum(iNewID));
+			/* Clear added text */
+			MultiLineEditTextMessage->clear();
+		}
+	}
+	else
+	{
+		/* Text was modified */
+		GetMessageText(iIDCurrentText);
+	}
+}
+
+void TransmDialog::OnButtonClearAllText()
+{
+	/* Clear container */
+	vecstrTextMessage.Init(1);
+	iIDCurrentText = 0;
+
+	/* Clear combo box */
+	ComboBoxTextMessage->clear();
+	ComboBoxTextMessage->insertItem(0, "new");
+	/* Clear multi line edit */
+	MultiLineEditTextMessage->clear();
+}
+
+void TransmDialog::OnToggleCheckBoxRemovePath(bool bState)
+{
+	TransThread.DRMTransmitter.GetAudSrcEnc()->SetPathRemoval(bState);
+}
+
+void TransmDialog::OnPushButtonAddFileName()
+{
+	/* Show "open file" dialog. Let the user select more than one file */
+	QStringList list = QFileDialog::getOpenFileNames(this, tr("Add Files"), NULL, tr("Image Files (*.png *.jpg *.jpeg *.jfif)"));
+
+	/* Check if user not hit the cancel button */
+	if (!list.isEmpty())
+	{
+		/* Insert all selected file names */
+		for (QStringList::Iterator it = list.begin(); it != list.end(); it++)
+		{
+			QFileInfo FileInfo((*it));
+
+			/* Insert tree widget item. The objects which is created
+			   here will be automatically destroyed by QT when
+			   the parent ("TreeWidgetFileNames") is destroyed */
+			QTreeWidgetItem* item = new QTreeWidgetItem();
+			if (item)
+			{
+				item->setText(0, FileInfo.fileName());
+				item->setText(1, QString().setNum((float) FileInfo.size() / 1000.0, 'f', 2));
+				item->setText(2, FileInfo.filePath());
+				TreeWidgetFileNames->addTopLevelItem(item);
+			}
+		}
+		/* Resize columns to content */
+		for (int i = 0; i < 3; i++)
+			TreeWidgetFileNames->resizeColumnToContents(i);
+	}
+}
+
+void TransmDialog::OnButtonClearAllFileNames()
+{
+	/* Remove all items */
+	TreeWidgetFileNames->clear();
+	/* Resize columns */
+	for (int i = 0; i < 3; i++)
+		TreeWidgetFileNames->resizeColumnToContents(i);
+}
+
+void TransmDialog::OnButtonCodec()
+{
+	/* Create Codec Dialog if NULL */
+	if (!pCodecDlg)
+	{
+		const int iShortID = 0; // TODO
+		CParameter& Parameters = *TransThread.DRMTransmitter.GetParameters();
+		pCodecDlg = new CodecParams(Settings, Parameters, iShortID, this);
+	}
+	/* Toggle the visibility */
+	if (pCodecDlg)
+		pCodecDlg->Toggle();
+}
+
+void TransmDialog::OnComboBoxTextMessageActivated(int iID)
+{
+	iIDCurrentText = iID;
+
+	/* Set text control with selected message */
+	MultiLineEditTextMessage->clear();
+	if (iID != 0)
+	{
+		/* Get the text */
+		QString text = QString::fromUtf8(vecstrTextMessage[iID].c_str());
+
+		/* Write stored text in multi line edit control */
+		MultiLineEditTextMessage->setText(text);
+	}
+}
+
+void TransmDialog::OnTextChangedSndCrdIF(const QString& strIF)
+{
+	/* Convert string to floating point value "toFloat()" */
+	TransThread.DRMTransmitter.SetCarOffset(strIF.toFloat());
+}
+
+void TransmDialog::OnTextChangedServiceID(const QString& strID)
+{
+	CParameter& Parameters = *TransThread.DRMTransmitter.GetParameters();
+
+	if(strID.length()<6)
+        return;
+
+	/* Convert hex string to unsigned integer "toUInt()" */
+	bool ok;
+	uint32_t iServiceID = strID.toUInt(&ok, 16);
+	if(ok == false)
+        return;
+
+	Parameters.Lock();
+
+	Parameters.Service[0].iServiceID = iServiceID;
+
+	Parameters.Unlock();
+}
+
+void TransmDialog::OnTextChangedServiceLabel(const QString& strLabel)
+{
+	CParameter& Parameters = *TransThread.DRMTransmitter.GetParameters();
+
+	Parameters.Lock();
+	/* Set additional text for log file. */
+	Parameters.Service[0].strLabel = strLabel.toUtf8().constData();
+	Parameters.Unlock();
+}
+
+void TransmDialog::OnComboBoxMSCInterleaverActivated(int iID)
+{
+	CParameter& Parameters = *TransThread.DRMTransmitter.GetParameters();
+
+	Parameters.Lock();
+	switch (iID)
+	{
+	case 0:
+        Parameters.eSymbolInterlMode = SI_LONG;
+		break;
+
+	case 1:
+        Parameters.eSymbolInterlMode = SI_SHORT;
+		break;
+	}
+	Parameters.Unlock();
+}
+
+void TransmDialog::OnComboBoxMSCConstellationActivated(int iID)
+{
+	CParameter& Parameters = *TransThread.DRMTransmitter.GetParameters();
+
+	Parameters.Lock();
+	switch (iID)
+	{
+	case 0:
+		Parameters.eMSCCodingScheme = CS_2_SM;
+		break;
+
+	case 1:
+		Parameters.eMSCCodingScheme = CS_3_SM;
+		break;
+
+	case 2:
+		Parameters.eMSCCodingScheme = CS_3_HMSYM;
+		break;
+
+	case 3:
+		Parameters.eMSCCodingScheme = CS_3_HMMIX;
+		break;
+	}
+	Parameters.Unlock();
+
+	/* Protection level must be re-adjusted when constelletion mode was
+	   changed */
+	UpdateMSCProtLevCombo();
+}
+
+void TransmDialog::OnComboBoxMSCProtLevActivated(int iID)
+{
+	CParameter& Parameters = *TransThread.DRMTransmitter.GetParameters();
+	Parameters.Lock();
+	Parameters.MSCPrLe.iPartB = iID;
+	Parameters.Unlock();
+}
+
+void TransmDialog::UpdateMSCProtLevCombo()
+{
+	CParameter& Parameters = *TransThread.DRMTransmitter.GetParameters();
+	Parameters.Lock();
+	if (Parameters.eMSCCodingScheme == CS_2_SM)
+	{
+		/* Only two protection levels possible in 16 QAM mode */
+		ComboBoxMSCProtLev->clear();
+		ComboBoxMSCProtLev->insertItem(0, "0");
+		ComboBoxMSCProtLev->insertItem(1, "1");
+		/* Set protection level to 1 if greater than 1 */
+		if (Parameters.MSCPrLe.iPartB > 1)
+			Parameters.MSCPrLe.iPartB = 1;
+	}
+	else
+	{
+		/* Four protection levels defined */
+		ComboBoxMSCProtLev->clear();
+		ComboBoxMSCProtLev->insertItem(0, "0");
+		ComboBoxMSCProtLev->insertItem(1, "1");
+		ComboBoxMSCProtLev->insertItem(2, "2");
+		ComboBoxMSCProtLev->insertItem(3, "3");
+	}
+	Parameters.Unlock();
+	ComboBoxMSCProtLev->setCurrentIndex(Parameters.MSCPrLe.iPartB);
+}
+
+void TransmDialog::OnComboBoxSDCConstellationActivated(int iID)
+{
+	CParameter& Parameters = *TransThread.DRMTransmitter.GetParameters();
+	Parameters.Lock();
+	switch (iID)
+	{
+	case 0:
+		Parameters.eSDCCodingScheme = CS_1_SM;
+		break;
+
+	case 1:
+		Parameters.eSDCCodingScheme = CS_2_SM;
+		break;
+	}
+	Parameters.Unlock();
+}
+
+void TransmDialog::OnComboBoxLanguageActivated(int iID)
+{
+	CParameter& Parameters = *TransThread.DRMTransmitter.GetParameters();
+	Parameters.Lock();
+	Parameters.Service[0].iLanguage = iID;
+	Parameters.Unlock();
+}
+
+void TransmDialog::OnComboBoxProgramTypeActivated(int iID)
+{
+	CParameter& Parameters = *TransThread.DRMTransmitter.GetParameters();
+	Parameters.Lock();
+	Parameters.Service[0].iServiceDescr = iID;
+	Parameters.Unlock();
+	iServiceDescr = iID;
+}
+
+void TransmDialog::OnRadioRobustnessMode(int iID)
+{
+	iID = -iID - 2; // TODO understand why
+	CParameter& Parameters = *TransThread.DRMTransmitter.GetParameters();
+
+	/* Set current bandwidth */
+	Parameters.Lock();
+	ESpecOcc eCurSpecOcc = Parameters.GetSpectrumOccup();
+	Parameters.Unlock();
+
+	/* Set default new robustness mode */
+	ERobMode eNewRobMode = RM_ROBUSTNESS_MODE_B;
+
+	/* Check, which bandwith's are possible with this robustness mode */
+	switch (iID)
+	{
+	case 0:
+		/* All bandwidth modes are possible */
+		RadioButtonBandwidth45->setEnabled(TRUE);
+		RadioButtonBandwidth5->setEnabled(TRUE);
+		RadioButtonBandwidth9->setEnabled(TRUE);
+		RadioButtonBandwidth18->setEnabled(TRUE);
+		/* Set new robustness mode */
+		eNewRobMode = RM_ROBUSTNESS_MODE_A;
+		break;
+
+	case 1:
+		/* All bandwidth modes are possible */
+		RadioButtonBandwidth45->setEnabled(TRUE);
+		RadioButtonBandwidth5->setEnabled(TRUE);
+		RadioButtonBandwidth9->setEnabled(TRUE);
+		RadioButtonBandwidth18->setEnabled(TRUE);
+		/* Set new robustness mode */
+		eNewRobMode = RM_ROBUSTNESS_MODE_B;
+		break;
+
+	case 2:
+		/* Only 10 and 20 kHz possible in robustness mode C */
+		RadioButtonBandwidth45->setEnabled(FALSE);
+		RadioButtonBandwidth5->setEnabled(FALSE);
+		RadioButtonBandwidth9->setEnabled(FALSE);
+		RadioButtonBandwidth18->setEnabled(FALSE);
+		/* Set check on the nearest bandwidth if "out of range" */
+		if (eCurSpecOcc == SO_0 || eCurSpecOcc == SO_1 ||
+			eCurSpecOcc == SO_2 || eCurSpecOcc == SO_4)
+		{
+			if (eCurSpecOcc == SO_4)
+				RadioButtonBandwidth20->setChecked(TRUE);
+			else
+				RadioButtonBandwidth10->setChecked(TRUE);
+			OnRadioBandwidth(ButtonGroupBandwidth->checkedId());
+		}
+		/* Set new robustness mode */
+		eNewRobMode = RM_ROBUSTNESS_MODE_C;
+		break;
+
+	case 3:
+		/* Only 10 and 20 kHz possible in robustness mode D */
+		RadioButtonBandwidth45->setEnabled(FALSE);
+		RadioButtonBandwidth5->setEnabled(FALSE);
+		RadioButtonBandwidth9->setEnabled(FALSE);
+		RadioButtonBandwidth18->setEnabled(FALSE);
+		/* Set check on the nearest bandwidth if "out of range" */
+		if (eCurSpecOcc == SO_0 || eCurSpecOcc == SO_1 ||
+			eCurSpecOcc == SO_2 || eCurSpecOcc == SO_4)
+		{
+			if (eCurSpecOcc == SO_4)
+				RadioButtonBandwidth20->setChecked(TRUE);
+			else
+				RadioButtonBandwidth10->setChecked(TRUE);
+			OnRadioBandwidth(ButtonGroupBandwidth->checkedId());
+		}
+		/* Set new robustness mode */
+		eNewRobMode = RM_ROBUSTNESS_MODE_D;
+		break;
+	}
+
+	/* Set new robustness mode */
+	Parameters.Lock();
+	Parameters.SetWaveMode(eNewRobMode);
+	Parameters.Unlock();
+}
+
+void TransmDialog::OnRadioBandwidth(int iID)
+{
+	iID = -iID - 2; // TODO understand why
+	static const int table[6] = {0, 2, 4, 1, 3, 5};
+	iID = table[(unsigned int)iID % (unsigned int)6];
+	ESpecOcc eNewSpecOcc = SO_0;
+
+	switch (iID)
+	{
+	case 0:
+		eNewSpecOcc = SO_0;
+		break;
+
+	case 1:
+		eNewSpecOcc = SO_1;
+		break;
+
+	case 2:
+		eNewSpecOcc = SO_2;
+		break;
+
+	case 3:
+		eNewSpecOcc = SO_3;
+		break;
+
+	case 4:
+		eNewSpecOcc = SO_4;
+		break;
+
+	case 5:
+		eNewSpecOcc = SO_5;
+		break;
+	}
+
+	CParameter& Parameters = *TransThread.DRMTransmitter.GetParameters();
+
+	/* Set new spectrum occupancy */
+	Parameters.Lock();
+	Parameters.SetSpectrumOccup(eNewSpecOcc);
+	Parameters.Unlock();
+}
+
+void TransmDialog::OnRadioOutput(int iID)
+{
+	iID = -iID - 2; // TODO understand why
+	switch (iID)
+	{
+	case 0:
+		/* Button "Real Valued" */
+		TransThread.DRMTransmitter.GetTransData()->
+			SetIQOutput(CTransmitData::OF_REAL_VAL);
+		CheckBoxAmplifiedOutput->setEnabled(true);
+		CheckBoxHighQualityIQ->setEnabled(false);
+		break;
+
+	case 1:
+		/* Button "I / Q (pos)" */
+		TransThread.DRMTransmitter.GetTransData()->
+			SetIQOutput(CTransmitData::OF_IQ_POS);
+		CheckBoxAmplifiedOutput->setEnabled(true);
+		CheckBoxHighQualityIQ->setEnabled(true);
+		break;
+
+	case 2:
+		/* Button "I / Q (neg)" */
+		TransThread.DRMTransmitter.GetTransData()->
+			SetIQOutput(CTransmitData::OF_IQ_NEG);
+		CheckBoxAmplifiedOutput->setEnabled(true);
+		CheckBoxHighQualityIQ->setEnabled(true);
+		break;
+
+	case 3:
+		/* Button "E / P" */
+		TransThread.DRMTransmitter.GetTransData()->
+			SetIQOutput(CTransmitData::OF_EP);
+		CheckBoxAmplifiedOutput->setEnabled(false);
+		CheckBoxHighQualityIQ->setEnabled(true);
+		break;
+	}
+}
+
+void TransmDialog::OnRadioCurrentTime(int iID)
+{
+	iID = -iID - 2; // TODO understand why
+	CParameter::ECurTime eCurTime = CParameter::CT_OFF;
+
+	switch (iID)
+	{
+	case 0:
+		eCurTime = CParameter::CT_OFF;
+		break;
+
+	case 1:
+		eCurTime = CParameter::CT_LOCAL;
+		break;
+
+	case 2:
+		eCurTime = CParameter::CT_UTC;
+		break;
+
+	case 3:
+		eCurTime = CParameter::CT_UTC_OFFSET;
+		break;
+	}
+
+	CParameter& Parameters = *TransThread.DRMTransmitter.GetParameters();
+
+	Parameters.Lock();
+
+	/* Set transmission of current time in global struct */
+	Parameters.eTransmitCurrentTime = eCurTime;
+
+	Parameters.Unlock();
+}
+
+void TransmDialog::OnRadioCodec(int iID)
+{
+	iID = -iID - 2; // TODO understand why
+	CAudioParam::EAudCod eNewAudioCoding = CAudioParam::AC_AAC;
+
+	switch (iID)
+	{
+	case 0:
+		eNewAudioCoding = CAudioParam::AC_AAC;
+		ShowButtonCodec(FALSE, 1);
+		break;
+
+	case 1:
+		eNewAudioCoding = CAudioParam::AC_OPUS;
+		ShowButtonCodec(TRUE, 1);
+		break;
+	}
+
+	CParameter& Parameters = *TransThread.DRMTransmitter.GetParameters();
+
+	Parameters.Lock();
+
+	/* Set new audio codec */
+	Parameters.Service[0].AudioParam.eAudioCoding = eNewAudioCoding;
+
+	Parameters.Unlock();
+}
+
+void TransmDialog::DisableAllControlsForSet()
+{
+	TabWidgetEnableTabs(TabWidgetParam, FALSE);
+	TabWidgetEnableTabs(TabWidgetServices, FALSE);
+
+	GroupInput->setEnabled(TRUE); /* For run-mode */
+}
+
+void TransmDialog::EnableAllControlsForSet()
+{
+	TabWidgetEnableTabs(TabWidgetParam, TRUE);
+	TabWidgetEnableTabs(TabWidgetServices, TRUE);
+
+	GroupInput->setEnabled(FALSE); /* For run-mode */
+
+	/* Reset status bars */
+	ProgrInputLevel->setValue(RET_VAL_LOG_0);
+	ProgressBarCurPict->setValue(0);
+	TextLabelCurPict->setText("");
+}
+
+void TransmDialog::TabWidgetEnableTabs(QTabWidget *tabWidget, bool enable)
+{
+	for (int i = 0; i < tabWidget->count(); i++)
+		tabWidget->widget(i)->setEnabled(enable);
+}
+
+void TransmDialog::ShowButtonCodec(_BOOLEAN bShow, int iKey)
+{
+	_BOOLEAN bLastShow = iButtonCodecState == 0;
+	if (bShow)
+		iButtonCodecState &= ~iKey;
+	else
+		iButtonCodecState |= iKey;
+	bShow = iButtonCodecState == 0;
+	if (bShow != bLastShow)
+	{
+		if (bShow)
+			ButtonCodec->show();
+		else
+			ButtonCodec->hide();
+		if (pCodecDlg)
+			pCodecDlg->Show(bShow);
+	}
+}
+
+void TransmDialog::AddWhatsThisHelp()
+{
+	/* Dream Logo */
+	const QString strPixmapLabelDreamLogo =
+		tr("<b>Dream Logo:</b> This is the official logo of "
+		"the Dream software.");
+
+	PixmapLabelDreamLogo->setWhatsThis(strPixmapLabelDreamLogo);
+
+	/* Input Level */
+	const QString strInputLevel =
+		tr("<b>Input Level:</b> The input level meter shows "
+		"the relative input signal peak level in dB. If the level is too high, "
+		"the meter turns from green to red.");
+
+	TextLabelAudioLevel->setWhatsThis(strInputLevel);
+	ProgrInputLevel->setWhatsThis(strInputLevel);
+
+	/* Progress Bar */
+	const QString strProgressBar =
+		tr("<b>Progress Bar:</b> The progress bar shows "
+		"the advancement of transmission of current file. "
+		"Only meaningful when 'Data (SlideShow Application)' "
+		"mode is enabled.");
+
+	ProgressBarCurPict->setWhatsThis(strProgressBar);
+
+	/* DRM Robustness Mode */
+	const QString strRobustnessMode =
+		tr("<b>DRM Robustness Mode:</b> In a DRM system, "
+		"four possible robustness modes are defined to adapt the system to "
+		"different channel conditions. According to the DRM standard:"
+		"<ul><li><i>Mode A:</i> Gaussian channels, with "
+		"minor fading</li><li><i>Mode B:</i> Time "
+		"and frequency selective channels, with longer delay spread"
+		"</li><li><i>Mode C:</i> As robustness mode B, "
+		"but with higher Doppler spread</li><li><i>Mode D:"
+		"</i> As robustness mode B, but with severe delay and "
+		"Doppler spread</li></ul>");
+
+	GroupBoxRobustnessMode->setWhatsThis(strRobustnessMode);
+	RadioButtonRMA->setWhatsThis(strRobustnessMode);
+	RadioButtonRMB->setWhatsThis(strRobustnessMode);
+	RadioButtonRMC->setWhatsThis(strRobustnessMode);
+	RadioButtonRMD->setWhatsThis(strRobustnessMode);
+
+	/* Bandwidth */
+	const QString strBandwidth =
+		tr("<b>DRM Bandwidth:</b> The bandwith is the gross "
+		"bandwidth of the generated DRM signal. Not all DRM robustness mode / "
+		"bandwidth constellations are possible, e.g., DRM robustness mode D "
+		"and C are only defined for the bandwidths 10 kHz and 20 kHz.");
+
+	GroupBoxBandwidth->setWhatsThis(strBandwidth);
+	RadioButtonBandwidth45->setWhatsThis(strBandwidth);
+	RadioButtonBandwidth5->setWhatsThis(strBandwidth);
+	RadioButtonBandwidth9->setWhatsThis(strBandwidth);
+	RadioButtonBandwidth10->setWhatsThis(strBandwidth);
+	RadioButtonBandwidth18->setWhatsThis(strBandwidth);
+	RadioButtonBandwidth20->setWhatsThis(strBandwidth);
+
+	/* TODO: ComboBoxMSCConstellation, ComboBoxMSCProtLev,
+	         ComboBoxSDCConstellation */
+
+	/* MSC interleaver mode */
+	const QString strInterleaver =
+		tr("<b>MSC interleaver mode:</b> The symbol "
+		"interleaver depth can be either short (approx. 400 ms) or long "
+		"(approx. 2 s). The longer the interleaver the better the channel "
+		"decoder can correct errors from slow fading signals. But the longer "
+		"the interleaver length the longer the delay until (after a "
+		"re-synchronization) audio can be heard.");
+
+	TextLabelInterleaver->setWhatsThis(strInterleaver);
+	ComboBoxMSCInterleaver->setWhatsThis(strInterleaver);
+
+	/* Output intermediate frequency of DRM signal */
+	const QString strOutputIF =
+		tr("<b>Output intermediate frequency of DRM signal:</b> "
+		"Set the output intermediate frequency (IF) of generated DRM signal "
+		"in the 'sound-card pass-band'. In some DRM modes, the IF is located "
+		"at the edge of the DRM signal, in other modes it is centered. The IF "
+		"should be chosen that the DRM signal lies entirely inside the "
+		"sound-card bandwidth.");
+
+	ButtonGroupIF->setWhatsThis(strOutputIF);
+	LineEditSndCrdIF->setWhatsThis(strOutputIF);
+	TextLabelIFUnit->setWhatsThis(strOutputIF);
+
+	/* Output format */
+	const QString strOutputFormat =
+		tr("<b>Output format:</b> Since the sound-card "
+		"outputs signals in stereo format, it is possible to output the DRM "
+		"signal in three formats:<ul><li><b>real valued"
+		"</b> output on both, left and right, sound-card "
+		"channels</li><li><b>I / Q</b> output "
+		"which is the in-phase and quadrature component of the complex "
+		"base-band signal at the desired IF. In-phase is output on the "
+		"left channel and quadrature on the right channel."
+		"</li><li><b>E / P</b> output which is the "
+		"envelope and phase on separate channels. This output type cannot "
+		"be used if the Dream transmitter is regularly compiled with a "
+		"sound-card sample rate of 48 kHz since the spectrum of these "
+		"components exceed the bandwidth of 20 kHz.<br>The envelope signal "
+		"is output on the left channel and the phase is output on the right "
+		"channel.</li></ul>");
+
+	GroupBoxOutput->setWhatsThis(strOutputFormat);
+	RadioButtonOutReal->setWhatsThis(strOutputFormat);
+	RadioButtonOutIQPos->setWhatsThis(strOutputFormat);
+	RadioButtonOutIQNeg->setWhatsThis(strOutputFormat);
+	RadioButtonOutEP->setWhatsThis(strOutputFormat);
+
+	/* Current Time Transmission */
+	const QString strCurrentTime =
+		tr("<b>Current Time Transmission:</b> The current time is transmitted, "
+		"four possible modes are defined:"
+		"<ul><li><i>Off:</i> No time information is transmitted</li>"
+		"<li><i>Local:</i> The local time is transmitted</li>"
+		"<li><i>UTC:</i> The Coordinated Universal Time is transmitted</li>"
+		"<li><i>UTC+Offset:</i> Same as UTC but with the addition of an offset "
+		"in hours from local time</li></ul>");
+
+	GroupBoxCurrentTime->setWhatsThis(strCurrentTime);
+	RadioButtonCurTimeOff->setWhatsThis(strCurrentTime);
+	RadioButtonCurTimeLocal->setWhatsThis(strCurrentTime);
+	RadioButtonCurTimeUTC->setWhatsThis(strCurrentTime);
+	RadioButtonCurTimeUTCOffset->setWhatsThis(strCurrentTime);
+
+	/* TODO: Services... */
+
+	/* Data (SlideShow Application) */
+
+	/* Remove path from filename */
+	const QString strRemovePath =
+		tr("<b>Remove path from filename:</b> Un-checking this box will "
+		"transmit the full path of the image location on your computer. "
+		"This might not be what you want.");
+
+	CheckBoxRemovePath->setWhatsThis(strRemovePath);
+}
diff --git a/src/GUI-QT/TransmDlg.h b/src/GUI-QT/TransmDlg.h
new file mode 100644
index 0000000..093cb50
--- /dev/null
+++ b/src/GUI-QT/TransmDlg.h
@@ -0,0 +1,161 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *	
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later 
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT 
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#ifndef _TRANSMDLG_H_
+#define _TRANSMDLG_H_
+
+#include "ui_TransmDlgbase.h"
+#include "CodecParams.h"
+#include "DialogUtil.h"
+#include "CWindow.h"
+#include "../DrmTransmitter.h"
+#include "../Parameter.h"
+#include <QPushButton>
+#include <QString>
+#include <QLabel>
+#include <QRadioButton>
+#include <QCheckBox>
+#include <QLineEdit>
+#include <QTabWidget>
+#include <QComboBox>
+#include <QFileInfo>
+#include <QStringList>
+#include <QMenuBar>
+#include <QLayout>
+#include <QThread>
+#include <QTimer>
+#include <QMainWindow>
+#include <QMenu>
+#include <qwt_thermo.h>
+
+
+/* Classes ********************************************************************/
+/* Thread class for the transmitter */
+class CTransmitterThread : public QThread 
+{
+public:
+	CTransmitterThread(CSettings& Settings) : DRMTransmitter(&Settings) {}
+
+	void Stop()
+	{
+		/* Stop working thread */
+		DRMTransmitter.Stop();
+	}
+
+	virtual void run()
+	{
+		try
+		{
+			/* Call receiver main routine */
+			DRMTransmitter.Start();
+		}
+
+		catch (CGenErr GenErr)
+		{
+			ErrorMessage(GenErr.strError);
+		}
+	}
+
+	CDRMTransmitter	DRMTransmitter;
+};
+
+
+class TransmDialog : public CWindow, public Ui_TransmDlgBase
+{
+	Q_OBJECT
+
+public:
+	TransmDialog(CSettings&, QWidget* parent=0);
+	virtual ~TransmDialog();
+
+protected:
+	virtual void eventClose(QCloseEvent*);
+	void DisableAllControlsForSet();
+	void EnableAllControlsForSet();
+	void TabWidgetEnableTabs(QTabWidget* tabWidget, bool enable);
+
+	CTransmitterThread	TransThread; /* Working thread object */
+	CDRMTransmitter&	DRMTransmitter;
+	CAboutDlg			AboutDlg;
+	QTimer				Timer;
+	QTimer				TimerStop;
+	CVector<string>		vecstrTextMessage;
+	QMenu*				pSettingsMenu;
+	CodecParams*		pCodecDlg;
+    CSysTray*           pSysTray;
+	QAction*			pActionStartStop;
+
+	_BOOLEAN			bIsStarted;
+	int					iIDCurrentText;
+	int					iServiceDescr;
+	_BOOLEAN			bCloseRequested;
+	int					iButtonCodecState;
+
+	void				ShowButtonCodec(_BOOLEAN bShow, int iKey);
+	_BOOLEAN			GetMessageText(const int iID);
+	void				UpdateMSCProtLevCombo();
+	void				EnableTextMessage(const _BOOLEAN bFlag);
+	void				EnableAudio(const _BOOLEAN bFlag);
+	void				EnableData(const _BOOLEAN bFlag);
+	void				AddWhatsThisHelp();
+
+public slots:
+	void OnButtonStartStop();
+	void OnPushButtonAddText();
+	void OnButtonClearAllText();
+	void OnPushButtonAddFileName();
+	void OnButtonClearAllFileNames();
+	void OnButtonCodec();
+	void OnToggleCheckBoxHighQualityIQ(bool bState);
+	void OnToggleCheckBoxAmplifiedOutput(bool bState);
+	void OnToggleCheckBoxEnableData(bool bState);
+	void OnToggleCheckBoxEnableAudio(bool bState);
+	void OnToggleCheckBoxEnableTextMessage(bool bState);
+	void OnToggleCheckBoxRemovePath(bool bState);
+	void OnComboBoxMSCInterleaverActivated(int iID);
+	void OnComboBoxMSCConstellationActivated(int iID);
+	void OnComboBoxSDCConstellationActivated(int iID);
+	void OnComboBoxLanguageActivated(int iID);
+	void OnComboBoxProgramTypeActivated(int iID);
+	void OnComboBoxTextMessageActivated(int iID);
+	void OnComboBoxMSCProtLevActivated(int iID);
+	void OnRadioRobustnessMode(int iID);
+	void OnRadioBandwidth(int iID);
+	void OnRadioOutput(int iID);
+	void OnRadioCodec(int iID);
+	void OnRadioCurrentTime(int iID);
+	void OnTextChangedServiceLabel(const QString& strLabel);
+	void OnTextChangedServiceID(const QString& strID);
+	void OnTextChangedSndCrdIF(const QString& strIF);
+	void OnTimer();
+	void OnTimerStop();
+	void OnSysTrayActivated(QSystemTrayIcon::ActivationReason);
+	void OnWhatsThis();
+};
+
+#endif // _TRANSMDLG_H_
diff --git a/src/GUI-QT/TransmDlgbase.ui b/src/GUI-QT/TransmDlgbase.ui
new file mode 100644
index 0000000..233dc49
--- /dev/null
+++ b/src/GUI-QT/TransmDlgbase.ui
@@ -0,0 +1,1478 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>TransmDlgBase</class>
+ <widget class="QMainWindow" name="TransmDlgBase">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>967</width>
+    <height>803</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Dream DRM Transmitter</string>
+  </property>
+  <property name="windowIcon">
+   <iconset resource="res/icons.qrc">
+    <normaloff>:/icons/MainIconTx.svg</normaloff>:/icons/MainIconTx.svg</iconset>
+  </property>
+  <widget class="QWidget" name="centralwidget">
+   <layout class="QVBoxLayout" name="verticalLayout_5">
+    <property name="spacing">
+     <number>6</number>
+    </property>
+    <property name="margin">
+     <number>11</number>
+    </property>
+    <item>
+     <layout class="QHBoxLayout" name="horizontalLayout">
+      <item>
+       <layout class="QVBoxLayout" name="verticalLayout_2">
+        <property name="spacing">
+         <number>6</number>
+        </property>
+        <property name="margin">
+         <number>11</number>
+        </property>
+        <item>
+         <layout class="QHBoxLayout">
+          <property name="spacing">
+           <number>6</number>
+          </property>
+          <property name="margin">
+           <number>0</number>
+          </property>
+          <item>
+           <widget class="QLabel" name="PixmapLabelDreamLogo">
+            <property name="enabled">
+             <bool>true</bool>
+            </property>
+            <property name="sizePolicy">
+             <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+              <horstretch>0</horstretch>
+              <verstretch>0</verstretch>
+             </sizepolicy>
+            </property>
+            <property name="pixmap">
+             <pixmap resource="res/icons.qrc">:/icons/LogoSmall.png</pixmap>
+            </property>
+            <property name="scaledContents">
+             <bool>false</bool>
+            </property>
+            <property name="wordWrap">
+             <bool>false</bool>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <layout class="QVBoxLayout">
+            <property name="spacing">
+             <number>6</number>
+            </property>
+            <property name="margin">
+             <number>11</number>
+            </property>
+            <item>
+             <widget class="QLabel" name="TextLabelMainAuthors">
+              <property name="sizePolicy">
+               <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+                <horstretch>0</horstretch>
+                <verstretch>0</verstretch>
+               </sizepolicy>
+              </property>
+              <property name="text">
+               <string>Volker Fischer, Alexander Kurpiers</string>
+              </property>
+              <property name="wordWrap">
+               <bool>false</bool>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QLabel" name="TextLabelCompany">
+              <property name="sizePolicy">
+               <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+                <horstretch>0</horstretch>
+                <verstretch>0</verstretch>
+               </sizepolicy>
+              </property>
+              <property name="text">
+               <string>Darmstadt University of Technology
+Institute for Communication Technology</string>
+              </property>
+              <property name="wordWrap">
+               <bool>false</bool>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </item>
+         </layout>
+        </item>
+        <item>
+         <spacer name="Spacer4">
+          <property name="orientation">
+           <enum>Qt::Vertical</enum>
+          </property>
+          <property name="sizeType">
+           <enum>QSizePolicy::Preferred</enum>
+          </property>
+          <property name="sizeHint" stdset="0">
+           <size>
+            <width>20</width>
+            <height>24</height>
+           </size>
+          </property>
+         </spacer>
+        </item>
+        <item>
+         <widget class="QGroupBox" name="GroupInput">
+          <property name="title">
+           <string>Indicators</string>
+          </property>
+          <layout class="QVBoxLayout">
+           <property name="spacing">
+            <number>6</number>
+           </property>
+           <property name="margin">
+            <number>11</number>
+           </property>
+           <item>
+            <layout class="QHBoxLayout">
+             <property name="spacing">
+              <number>6</number>
+             </property>
+             <property name="margin">
+              <number>0</number>
+             </property>
+             <item>
+              <widget class="QLabel" name="TextLabelAudioLevel">
+               <property name="text">
+                <string>Audio Level [dB]:</string>
+               </property>
+               <property name="wordWrap">
+                <bool>false</bool>
+               </property>
+              </widget>
+             </item>
+             <item>
+              <widget class="QwtThermo" name="ProgrInputLevel" native="true"/>
+             </item>
+            </layout>
+           </item>
+           <item>
+            <spacer name="verticalSpacer">
+             <property name="orientation">
+              <enum>Qt::Vertical</enum>
+             </property>
+             <property name="sizeType">
+              <enum>QSizePolicy::Fixed</enum>
+             </property>
+             <property name="sizeHint" stdset="0">
+              <size>
+               <width>20</width>
+               <height>8</height>
+              </size>
+             </property>
+            </spacer>
+           </item>
+           <item>
+            <widget class="QLabel" name="TextLabelCurPict">
+             <property name="text">
+              <string>TextLabelCurPict</string>
+             </property>
+             <property name="wordWrap">
+              <bool>false</bool>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="QProgressBar" name="ProgressBarCurPict"/>
+           </item>
+          </layout>
+         </widget>
+        </item>
+       </layout>
+      </item>
+      <item>
+       <spacer name="Spacer6">
+        <property name="orientation">
+         <enum>Qt::Horizontal</enum>
+        </property>
+        <property name="sizeType">
+         <enum>QSizePolicy::Expanding</enum>
+        </property>
+        <property name="sizeHint" stdset="0">
+         <size>
+          <width>20</width>
+          <height>20</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+      <item>
+       <widget class="QTabWidget" name="TabWidgetParam">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Expanding" vsizetype="Minimum">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="currentIndex">
+         <number>0</number>
+        </property>
+        <widget class="QWidget" name="tabChannelParameters">
+         <attribute name="title">
+          <string>Channel Parameters</string>
+         </attribute>
+         <layout class="QVBoxLayout" name="verticalLayout">
+          <property name="spacing">
+           <number>6</number>
+          </property>
+          <property name="margin">
+           <number>11</number>
+          </property>
+          <item>
+           <widget class="QGroupBox" name="GroupBoxRobustnessMode">
+            <property name="title">
+             <string>Robustness Mode</string>
+            </property>
+            <property name="radioButtonExclusive" stdset="0">
+             <bool>true</bool>
+            </property>
+            <layout class="QHBoxLayout">
+             <property name="spacing">
+              <number>6</number>
+             </property>
+             <property name="margin">
+              <number>11</number>
+             </property>
+             <item>
+              <widget class="QRadioButton" name="RadioButtonRMA">
+               <property name="text">
+                <string>A</string>
+               </property>
+               <attribute name="buttonGroup">
+                <string notr="true">ButtonGroupRobustnessMode</string>
+               </attribute>
+              </widget>
+             </item>
+             <item>
+              <widget class="QRadioButton" name="RadioButtonRMB">
+               <property name="text">
+                <string>B</string>
+               </property>
+               <attribute name="buttonGroup">
+                <string notr="true">ButtonGroupRobustnessMode</string>
+               </attribute>
+              </widget>
+             </item>
+             <item>
+              <widget class="QRadioButton" name="RadioButtonRMC">
+               <property name="text">
+                <string>C</string>
+               </property>
+               <attribute name="buttonGroup">
+                <string notr="true">ButtonGroupRobustnessMode</string>
+               </attribute>
+              </widget>
+             </item>
+             <item>
+              <widget class="QRadioButton" name="RadioButtonRMD">
+               <property name="text">
+                <string>D</string>
+               </property>
+               <attribute name="buttonGroup">
+                <string notr="true">ButtonGroupRobustnessMode</string>
+               </attribute>
+              </widget>
+             </item>
+            </layout>
+           </widget>
+          </item>
+          <item>
+           <widget class="QGroupBox" name="GroupBoxBandwidth">
+            <property name="title">
+             <string>Bandwidth</string>
+            </property>
+            <property name="radioButtonExclusive" stdset="0">
+             <bool>true</bool>
+            </property>
+            <layout class="QVBoxLayout">
+             <property name="spacing">
+              <number>6</number>
+             </property>
+             <property name="margin">
+              <number>11</number>
+             </property>
+             <item>
+              <layout class="QHBoxLayout">
+               <property name="spacing">
+                <number>6</number>
+               </property>
+               <property name="margin">
+                <number>0</number>
+               </property>
+               <item>
+                <widget class="QRadioButton" name="RadioButtonBandwidth45">
+                 <property name="text">
+                  <string>4.5 kHz</string>
+                 </property>
+                 <attribute name="buttonGroup">
+                  <string notr="true">ButtonGroupBandwidth</string>
+                 </attribute>
+                </widget>
+               </item>
+               <item>
+                <widget class="QRadioButton" name="RadioButtonBandwidth9">
+                 <property name="text">
+                  <string>9 kHz</string>
+                 </property>
+                 <attribute name="buttonGroup">
+                  <string notr="true">ButtonGroupBandwidth</string>
+                 </attribute>
+                </widget>
+               </item>
+               <item>
+                <widget class="QRadioButton" name="RadioButtonBandwidth18">
+                 <property name="text">
+                  <string>18 kHz</string>
+                 </property>
+                 <attribute name="buttonGroup">
+                  <string notr="true">ButtonGroupBandwidth</string>
+                 </attribute>
+                </widget>
+               </item>
+              </layout>
+             </item>
+             <item>
+              <layout class="QHBoxLayout">
+               <property name="spacing">
+                <number>6</number>
+               </property>
+               <property name="margin">
+                <number>0</number>
+               </property>
+               <item>
+                <widget class="QRadioButton" name="RadioButtonBandwidth5">
+                 <property name="text">
+                  <string>5 kHz</string>
+                 </property>
+                 <attribute name="buttonGroup">
+                  <string notr="true">ButtonGroupBandwidth</string>
+                 </attribute>
+                </widget>
+               </item>
+               <item>
+                <widget class="QRadioButton" name="RadioButtonBandwidth10">
+                 <property name="text">
+                  <string>10 kHz</string>
+                 </property>
+                 <attribute name="buttonGroup">
+                  <string notr="true">ButtonGroupBandwidth</string>
+                 </attribute>
+                </widget>
+               </item>
+               <item>
+                <widget class="QRadioButton" name="RadioButtonBandwidth20">
+                 <property name="text">
+                  <string>20 kHz</string>
+                 </property>
+                 <attribute name="buttonGroup">
+                  <string notr="true">ButtonGroupBandwidth</string>
+                 </attribute>
+                </widget>
+               </item>
+              </layout>
+             </item>
+            </layout>
+           </widget>
+          </item>
+          <item>
+           <layout class="QHBoxLayout">
+            <property name="spacing">
+             <number>6</number>
+            </property>
+            <property name="margin">
+             <number>0</number>
+            </property>
+            <item>
+             <layout class="QHBoxLayout">
+              <property name="spacing">
+               <number>6</number>
+              </property>
+              <property name="margin">
+               <number>0</number>
+              </property>
+              <item>
+               <widget class="QLabel" name="TextLabelMSCConst">
+                <property name="text">
+                 <string>MSC Constellation Scheme:</string>
+                </property>
+                <property name="wordWrap">
+                 <bool>false</bool>
+                </property>
+               </widget>
+              </item>
+              <item>
+               <widget class="QComboBox" name="ComboBoxMSCConstellation"/>
+              </item>
+             </layout>
+            </item>
+            <item>
+             <layout class="QHBoxLayout">
+              <property name="spacing">
+               <number>6</number>
+              </property>
+              <property name="margin">
+               <number>0</number>
+              </property>
+              <item>
+               <widget class="QLabel" name="TextLabelProtLev">
+                <property name="text">
+                 <string>MSC Protection Level:</string>
+                </property>
+                <property name="wordWrap">
+                 <bool>false</bool>
+                </property>
+               </widget>
+              </item>
+              <item>
+               <widget class="QComboBox" name="ComboBoxMSCProtLev"/>
+              </item>
+             </layout>
+            </item>
+           </layout>
+          </item>
+          <item>
+           <layout class="QHBoxLayout">
+            <property name="spacing">
+             <number>6</number>
+            </property>
+            <property name="margin">
+             <number>0</number>
+            </property>
+            <item>
+             <layout class="QHBoxLayout">
+              <property name="spacing">
+               <number>6</number>
+              </property>
+              <property name="margin">
+               <number>0</number>
+              </property>
+              <item>
+               <widget class="QLabel" name="TextLabelSDCConst">
+                <property name="text">
+                 <string>SDC Constellation Scheme:</string>
+                </property>
+                <property name="wordWrap">
+                 <bool>false</bool>
+                </property>
+               </widget>
+              </item>
+              <item>
+               <widget class="QComboBox" name="ComboBoxSDCConstellation"/>
+              </item>
+             </layout>
+            </item>
+            <item>
+             <layout class="QHBoxLayout">
+              <property name="spacing">
+               <number>6</number>
+              </property>
+              <property name="margin">
+               <number>0</number>
+              </property>
+              <item>
+               <widget class="QLabel" name="TextLabelInterleaver">
+                <property name="text">
+                 <string>MSC Interleaver Mode:</string>
+                </property>
+                <property name="wordWrap">
+                 <bool>false</bool>
+                </property>
+               </widget>
+              </item>
+              <item>
+               <widget class="QComboBox" name="ComboBoxMSCInterleaver"/>
+              </item>
+             </layout>
+            </item>
+           </layout>
+          </item>
+         </layout>
+        </widget>
+        <widget class="QWidget" name="tabOutput">
+         <attribute name="title">
+          <string>Output</string>
+         </attribute>
+         <layout class="QVBoxLayout" name="verticalLayout_3">
+          <property name="spacing">
+           <number>6</number>
+          </property>
+          <property name="margin">
+           <number>11</number>
+          </property>
+          <item>
+           <widget class="QGroupBox" name="ButtonGroupIF">
+            <property name="sizePolicy">
+             <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+              <horstretch>0</horstretch>
+              <verstretch>0</verstretch>
+             </sizepolicy>
+            </property>
+            <property name="title">
+             <string>Intermediate Frequency</string>
+            </property>
+            <layout class="QHBoxLayout" name="horizontalLayout_2">
+             <item>
+              <widget class="QLineEdit" name="LineEditSndCrdIF">
+               <property name="sizePolicy">
+                <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+                 <horstretch>0</horstretch>
+                 <verstretch>0</verstretch>
+                </sizepolicy>
+               </property>
+               <property name="minimumSize">
+                <size>
+                 <width>90</width>
+                 <height>0</height>
+                </size>
+               </property>
+               <property name="maxLength">
+                <number>24</number>
+               </property>
+              </widget>
+             </item>
+             <item>
+              <widget class="QLabel" name="TextLabelIFUnit">
+               <property name="sizePolicy">
+                <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+                 <horstretch>0</horstretch>
+                 <verstretch>0</verstretch>
+                </sizepolicy>
+               </property>
+               <property name="text">
+                <string> Hz</string>
+               </property>
+               <property name="wordWrap">
+                <bool>false</bool>
+               </property>
+               <property name="indent">
+                <number>-1</number>
+               </property>
+              </widget>
+             </item>
+            </layout>
+           </widget>
+          </item>
+          <item>
+           <widget class="QGroupBox" name="GroupBoxOutput">
+            <property name="sizePolicy">
+             <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+              <horstretch>0</horstretch>
+              <verstretch>0</verstretch>
+             </sizepolicy>
+            </property>
+            <property name="title">
+             <string>Format</string>
+            </property>
+            <property name="radioButtonExclusive" stdset="0">
+             <bool>true</bool>
+            </property>
+            <layout class="QVBoxLayout" name="verticalLayout_7">
+             <item>
+              <layout class="QHBoxLayout" name="horizontalLayout_3">
+               <item>
+                <widget class="QRadioButton" name="RadioButtonOutReal">
+                 <property name="sizePolicy">
+                  <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+                   <horstretch>0</horstretch>
+                   <verstretch>0</verstretch>
+                  </sizepolicy>
+                 </property>
+                 <property name="text">
+                  <string>Real val.</string>
+                 </property>
+                 <attribute name="buttonGroup">
+                  <string notr="true">ButtonGroupOutput</string>
+                 </attribute>
+                </widget>
+               </item>
+               <item>
+                <widget class="QRadioButton" name="RadioButtonOutIQPos">
+                 <property name="sizePolicy">
+                  <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+                   <horstretch>0</horstretch>
+                   <verstretch>0</verstretch>
+                  </sizepolicy>
+                 </property>
+                 <property name="text">
+                  <string>I / Q (pos)</string>
+                 </property>
+                 <attribute name="buttonGroup">
+                  <string notr="true">ButtonGroupOutput</string>
+                 </attribute>
+                </widget>
+               </item>
+               <item>
+                <widget class="QRadioButton" name="RadioButtonOutIQNeg">
+                 <property name="sizePolicy">
+                  <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+                   <horstretch>0</horstretch>
+                   <verstretch>0</verstretch>
+                  </sizepolicy>
+                 </property>
+                 <property name="text">
+                  <string>I / Q (neg)</string>
+                 </property>
+                 <attribute name="buttonGroup">
+                  <string notr="true">ButtonGroupOutput</string>
+                 </attribute>
+                </widget>
+               </item>
+               <item>
+                <widget class="QRadioButton" name="RadioButtonOutEP">
+                 <property name="sizePolicy">
+                  <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+                   <horstretch>0</horstretch>
+                   <verstretch>0</verstretch>
+                  </sizepolicy>
+                 </property>
+                 <property name="text">
+                  <string>E / P</string>
+                 </property>
+                 <attribute name="buttonGroup">
+                  <string notr="true">ButtonGroupOutput</string>
+                 </attribute>
+                </widget>
+               </item>
+              </layout>
+             </item>
+            </layout>
+           </widget>
+          </item>
+          <item>
+           <widget class="QGroupBox" name="GroupBoxOutputOption">
+            <property name="sizePolicy">
+             <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+              <horstretch>0</horstretch>
+              <verstretch>0</verstretch>
+             </sizepolicy>
+            </property>
+            <property name="title">
+             <string>Options</string>
+            </property>
+            <layout class="QHBoxLayout" name="horizontalLayout_7">
+             <item>
+              <widget class="QCheckBox" name="CheckBoxAmplifiedOutput">
+               <property name="sizePolicy">
+                <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+                 <horstretch>0</horstretch>
+                 <verstretch>0</verstretch>
+                </sizepolicy>
+               </property>
+               <property name="text">
+                <string>+12 dB</string>
+               </property>
+              </widget>
+             </item>
+             <item>
+              <widget class="QCheckBox" name="CheckBoxHighQualityIQ">
+               <property name="sizePolicy">
+                <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+                 <horstretch>0</horstretch>
+                 <verstretch>0</verstretch>
+                </sizepolicy>
+               </property>
+               <property name="text">
+                <string>High quality I / Q</string>
+               </property>
+              </widget>
+             </item>
+            </layout>
+           </widget>
+          </item>
+          <item>
+           <spacer name="verticalSpacer_3">
+            <property name="orientation">
+             <enum>Qt::Vertical</enum>
+            </property>
+            <property name="sizeHint" stdset="0">
+             <size>
+              <width>20</width>
+              <height>0</height>
+             </size>
+            </property>
+           </spacer>
+          </item>
+         </layout>
+        </widget>
+        <widget class="QWidget" name="tabMiscellaneous">
+         <attribute name="title">
+          <string>Miscellaneous</string>
+         </attribute>
+         <layout class="QVBoxLayout" name="verticalLayout_4">
+          <property name="spacing">
+           <number>6</number>
+          </property>
+          <property name="margin">
+           <number>11</number>
+          </property>
+          <item>
+           <widget class="QGroupBox" name="GroupBoxCurrentTime">
+            <property name="sizePolicy">
+             <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+              <horstretch>0</horstretch>
+              <verstretch>0</verstretch>
+             </sizepolicy>
+            </property>
+            <property name="title">
+             <string>Current Time Transmission</string>
+            </property>
+            <layout class="QHBoxLayout" name="horizontalLayout_4">
+             <item>
+              <widget class="QRadioButton" name="RadioButtonCurTimeOff">
+               <property name="sizePolicy">
+                <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+                 <horstretch>0</horstretch>
+                 <verstretch>0</verstretch>
+                </sizepolicy>
+               </property>
+               <property name="text">
+                <string>Off</string>
+               </property>
+               <attribute name="buttonGroup">
+                <string notr="true">ButtonGroupCurrentTime</string>
+               </attribute>
+              </widget>
+             </item>
+             <item>
+              <widget class="QRadioButton" name="RadioButtonCurTimeLocal">
+               <property name="sizePolicy">
+                <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+                 <horstretch>0</horstretch>
+                 <verstretch>0</verstretch>
+                </sizepolicy>
+               </property>
+               <property name="text">
+                <string>Local</string>
+               </property>
+               <attribute name="buttonGroup">
+                <string notr="true">ButtonGroupCurrentTime</string>
+               </attribute>
+              </widget>
+             </item>
+             <item>
+              <widget class="QRadioButton" name="RadioButtonCurTimeUTC">
+               <property name="sizePolicy">
+                <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+                 <horstretch>0</horstretch>
+                 <verstretch>0</verstretch>
+                </sizepolicy>
+               </property>
+               <property name="text">
+                <string>UTC</string>
+               </property>
+               <attribute name="buttonGroup">
+                <string notr="true">ButtonGroupCurrentTime</string>
+               </attribute>
+              </widget>
+             </item>
+             <item>
+              <widget class="QRadioButton" name="RadioButtonCurTimeUTCOffset">
+               <property name="sizePolicy">
+                <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+                 <horstretch>0</horstretch>
+                 <verstretch>0</verstretch>
+                </sizepolicy>
+               </property>
+               <property name="text">
+                <string>UTC+Offset</string>
+               </property>
+               <attribute name="buttonGroup">
+                <string notr="true">ButtonGroupCurrentTime</string>
+               </attribute>
+              </widget>
+             </item>
+            </layout>
+           </widget>
+          </item>
+          <item>
+           <spacer name="verticalSpacer_4">
+            <property name="orientation">
+             <enum>Qt::Vertical</enum>
+            </property>
+            <property name="sizeHint" stdset="0">
+             <size>
+              <width>20</width>
+              <height>162</height>
+             </size>
+            </property>
+           </spacer>
+          </item>
+         </layout>
+        </widget>
+       </widget>
+      </item>
+     </layout>
+    </item>
+    <item>
+     <widget class="QTabWidget" name="TabWidgetServices">
+      <property name="enabled">
+       <bool>true</bool>
+      </property>
+      <property name="tabPosition">
+       <enum>QTabWidget::North</enum>
+      </property>
+      <property name="currentIndex">
+       <number>0</number>
+      </property>
+      <widget class="QWidget" name="tabService1">
+       <attribute name="title">
+        <string>Service 1</string>
+       </attribute>
+       <layout class="QHBoxLayout" name="horizontalLayout_5">
+        <item>
+         <layout class="QVBoxLayout" name="verticalLayout_6">
+          <item>
+           <widget class="QCheckBox" name="CheckBoxEnableService">
+            <property name="enabled">
+             <bool>true</bool>
+            </property>
+            <property name="sizePolicy">
+             <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+              <horstretch>0</horstretch>
+              <verstretch>0</verstretch>
+             </sizepolicy>
+            </property>
+            <property name="text">
+             <string>Enable</string>
+            </property>
+            <property name="checked">
+             <bool>false</bool>
+            </property>
+            <property name="tristate">
+             <bool>false</bool>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <layout class="QVBoxLayout">
+            <property name="spacing">
+             <number>6</number>
+            </property>
+            <property name="margin">
+             <number>11</number>
+            </property>
+            <item>
+             <layout class="QHBoxLayout">
+              <property name="spacing">
+               <number>6</number>
+              </property>
+              <property name="margin">
+               <number>0</number>
+              </property>
+              <item>
+               <widget class="QLabel" name="TextLabelServiceLabel">
+                <property name="text">
+                 <string>Label:</string>
+                </property>
+                <property name="wordWrap">
+                 <bool>false</bool>
+                </property>
+               </widget>
+              </item>
+              <item>
+               <widget class="QLineEdit" name="LineEditServiceLabel">
+                <property name="sizePolicy">
+                 <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+                  <horstretch>0</horstretch>
+                  <verstretch>0</verstretch>
+                 </sizepolicy>
+                </property>
+               </widget>
+              </item>
+             </layout>
+            </item>
+            <item>
+             <layout class="QHBoxLayout">
+              <property name="spacing">
+               <number>6</number>
+              </property>
+              <property name="margin">
+               <number>0</number>
+              </property>
+              <item>
+               <widget class="QLabel" name="TextLabelServiceID">
+                <property name="text">
+                 <string>Service ID:</string>
+                </property>
+                <property name="wordWrap">
+                 <bool>false</bool>
+                </property>
+               </widget>
+              </item>
+              <item>
+               <widget class="QLineEdit" name="LineEditServiceID">
+                <property name="sizePolicy">
+                 <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+                  <horstretch>0</horstretch>
+                  <verstretch>0</verstretch>
+                 </sizepolicy>
+                </property>
+               </widget>
+              </item>
+             </layout>
+            </item>
+            <item>
+             <layout class="QHBoxLayout">
+              <property name="spacing">
+               <number>6</number>
+              </property>
+              <property name="margin">
+               <number>0</number>
+              </property>
+              <item>
+               <widget class="QLabel" name="TextLabelServiceLanguage">
+                <property name="text">
+                 <string>Language:</string>
+                </property>
+                <property name="wordWrap">
+                 <bool>false</bool>
+                </property>
+               </widget>
+              </item>
+              <item>
+               <widget class="QComboBox" name="ComboBoxLanguage"/>
+              </item>
+             </layout>
+            </item>
+            <item>
+             <spacer name="Spacer3">
+              <property name="orientation">
+               <enum>Qt::Vertical</enum>
+              </property>
+              <property name="sizeType">
+               <enum>QSizePolicy::MinimumExpanding</enum>
+              </property>
+              <property name="sizeHint" stdset="0">
+               <size>
+                <width>20</width>
+                <height>20</height>
+               </size>
+              </property>
+             </spacer>
+            </item>
+           </layout>
+          </item>
+         </layout>
+        </item>
+        <item>
+         <widget class="QGroupBox" name="GroupBoxAudio">
+          <property name="title">
+           <string>Audio</string>
+          </property>
+          <layout class="QVBoxLayout">
+           <property name="spacing">
+            <number>6</number>
+           </property>
+           <property name="margin">
+            <number>11</number>
+           </property>
+           <item>
+            <widget class="QCheckBox" name="CheckBoxEnableAudio">
+             <property name="enabled">
+              <bool>true</bool>
+             </property>
+             <property name="text">
+              <string>Enable</string>
+             </property>
+             <property name="checked">
+              <bool>false</bool>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <layout class="QHBoxLayout">
+             <property name="spacing">
+              <number>6</number>
+             </property>
+             <property name="margin">
+              <number>0</number>
+             </property>
+             <item>
+              <widget class="QLabel" name="TextLabelProgramType">
+               <property name="text">
+                <string>Program Type:</string>
+               </property>
+               <property name="wordWrap">
+                <bool>false</bool>
+               </property>
+              </widget>
+             </item>
+             <item>
+              <widget class="QComboBox" name="ComboBoxProgramType"/>
+             </item>
+            </layout>
+           </item>
+           <item>
+            <widget class="QGroupBox" name="GroupBoxCodec">
+             <property name="title">
+              <string>Codec</string>
+             </property>
+             <layout class="QHBoxLayout">
+              <item>
+               <widget class="QRadioButton" name="RadioButtonAAC">
+                <property name="text">
+                 <string>AAC</string>
+                </property>
+                <attribute name="buttonGroup">
+                 <string notr="true">ButtonGroupCodec</string>
+                </attribute>
+               </widget>
+              </item>
+              <item>
+               <widget class="QRadioButton" name="RadioButtonOPUS">
+                <property name="text">
+                 <string>Opus</string>
+                </property>
+                <attribute name="buttonGroup">
+                 <string notr="true">ButtonGroupCodec</string>
+                </attribute>
+               </widget>
+              </item>
+              <item>
+               <spacer name="horizontalSpacer_2">
+                <property name="orientation">
+                 <enum>Qt::Horizontal</enum>
+                </property>
+                <property name="sizeType">
+                 <enum>QSizePolicy::Minimum</enum>
+                </property>
+                <property name="sizeHint" stdset="0">
+                 <size>
+                  <width>0</width>
+                  <height>20</height>
+                 </size>
+                </property>
+               </spacer>
+              </item>
+             </layout>
+            </widget>
+           </item>
+           <item>
+            <widget class="QGroupBox" name="GroupBoxTextMessage">
+             <property name="title">
+              <string>Text Message</string>
+             </property>
+             <layout class="QVBoxLayout">
+              <property name="spacing">
+               <number>6</number>
+              </property>
+              <property name="margin">
+               <number>11</number>
+              </property>
+              <item>
+               <widget class="QCheckBox" name="CheckBoxEnableTextMessage">
+                <property name="enabled">
+                 <bool>true</bool>
+                </property>
+                <property name="text">
+                 <string>Enable</string>
+                </property>
+                <property name="checked">
+                 <bool>false</bool>
+                </property>
+               </widget>
+              </item>
+              <item>
+               <widget class="QComboBox" name="ComboBoxTextMessage"/>
+              </item>
+              <item>
+               <widget class="QTextEdit" name="MultiLineEditTextMessage">
+                <property name="tabChangesFocus">
+                 <bool>true</bool>
+                </property>
+                <property name="acceptRichText">
+                 <bool>false</bool>
+                </property>
+               </widget>
+              </item>
+              <item>
+               <layout class="QHBoxLayout">
+                <property name="spacing">
+                 <number>6</number>
+                </property>
+                <property name="margin">
+                 <number>0</number>
+                </property>
+                <item>
+                 <widget class="QPushButton" name="PushButtonClearAllText">
+                  <property name="text">
+                   <string>&Clear All</string>
+                  </property>
+                 </widget>
+                </item>
+                <item>
+                 <spacer name="Spacer2">
+                  <property name="orientation">
+                   <enum>Qt::Horizontal</enum>
+                  </property>
+                  <property name="sizeType">
+                   <enum>QSizePolicy::Expanding</enum>
+                  </property>
+                  <property name="sizeHint" stdset="0">
+                   <size>
+                    <width>20</width>
+                    <height>20</height>
+                   </size>
+                  </property>
+                 </spacer>
+                </item>
+                <item>
+                 <widget class="QPushButton" name="PushButtonAddText">
+                  <property name="text">
+                   <string>&Add / Modify</string>
+                  </property>
+                 </widget>
+                </item>
+               </layout>
+              </item>
+             </layout>
+            </widget>
+           </item>
+          </layout>
+         </widget>
+        </item>
+        <item>
+         <widget class="QGroupBox" name="GroupBoxData">
+          <property name="title">
+           <string>Data (SlideShow Application)</string>
+          </property>
+          <layout class="QVBoxLayout">
+           <property name="spacing">
+            <number>6</number>
+           </property>
+           <property name="margin">
+            <number>11</number>
+           </property>
+           <item>
+            <widget class="QCheckBox" name="CheckBoxEnableData">
+             <property name="enabled">
+              <bool>true</bool>
+             </property>
+             <property name="text">
+              <string>Enable</string>
+             </property>
+             <property name="checked">
+              <bool>false</bool>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="QCheckBox" name="CheckBoxRemovePath">
+             <property name="text">
+              <string>Remove path from filename</string>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="QTreeWidget" name="TreeWidgetFileNames">
+             <property name="autoScroll">
+              <bool>false</bool>
+             </property>
+             <property name="editTriggers">
+              <set>QAbstractItemView::NoEditTriggers</set>
+             </property>
+             <property name="alternatingRowColors">
+              <bool>true</bool>
+             </property>
+             <property name="selectionMode">
+              <enum>QAbstractItemView::NoSelection</enum>
+             </property>
+             <property name="selectionBehavior">
+              <enum>QAbstractItemView::SelectRows</enum>
+             </property>
+             <property name="verticalScrollMode">
+              <enum>QAbstractItemView::ScrollPerPixel</enum>
+             </property>
+             <property name="horizontalScrollMode">
+              <enum>QAbstractItemView::ScrollPerPixel</enum>
+             </property>
+             <property name="indentation">
+              <number>0</number>
+             </property>
+             <property name="rootIsDecorated">
+              <bool>false</bool>
+             </property>
+             <property name="uniformRowHeights">
+              <bool>true</bool>
+             </property>
+             <attribute name="headerVisible">
+              <bool>true</bool>
+             </attribute>
+             <attribute name="headerStretchLastSection">
+              <bool>false</bool>
+             </attribute>
+             <column>
+              <property name="text">
+               <string>File Name</string>
+              </property>
+             </column>
+             <column>
+              <property name="text">
+               <string>Size [KB]</string>
+              </property>
+             </column>
+             <column>
+              <property name="text">
+               <string>Full Path</string>
+              </property>
+             </column>
+            </widget>
+           </item>
+           <item>
+            <layout class="QHBoxLayout">
+             <property name="spacing">
+              <number>6</number>
+             </property>
+             <property name="margin">
+              <number>0</number>
+             </property>
+             <item>
+              <widget class="QPushButton" name="PushButtonClearAllFileNames">
+               <property name="text">
+                <string>&Clear All</string>
+               </property>
+              </widget>
+             </item>
+             <item>
+              <spacer name="Spacer2_2">
+               <property name="orientation">
+                <enum>Qt::Horizontal</enum>
+               </property>
+               <property name="sizeType">
+                <enum>QSizePolicy::Expanding</enum>
+               </property>
+               <property name="sizeHint" stdset="0">
+                <size>
+                 <width>20</width>
+                 <height>20</height>
+                </size>
+               </property>
+              </spacer>
+             </item>
+             <item>
+              <widget class="QPushButton" name="PushButtonAddFile">
+               <property name="text">
+                <string>&Add</string>
+               </property>
+              </widget>
+             </item>
+            </layout>
+           </item>
+          </layout>
+         </widget>
+        </item>
+       </layout>
+      </widget>
+      <widget class="QWidget" name="tabService2">
+       <attribute name="title">
+        <string>Service 2</string>
+       </attribute>
+      </widget>
+      <widget class="QWidget" name="tabService3">
+       <attribute name="title">
+        <string>Service 3</string>
+       </attribute>
+      </widget>
+      <widget class="QWidget" name="tabService4">
+       <attribute name="title">
+        <string>Service 4</string>
+       </attribute>
+      </widget>
+     </widget>
+    </item>
+    <item>
+     <layout class="QHBoxLayout" name="horizontalLayout_6">
+      <item>
+       <widget class="QPushButton" name="ButtonStartStop">
+        <property name="text">
+         <string>&Start</string>
+        </property>
+        <property name="default">
+         <bool>true</bool>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <spacer name="Horizontal Spacing2">
+        <property name="orientation">
+         <enum>Qt::Horizontal</enum>
+        </property>
+        <property name="sizeType">
+         <enum>QSizePolicy::Minimum</enum>
+        </property>
+        <property name="sizeHint" stdset="0">
+         <size>
+          <width>20</width>
+          <height>20</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+      <item>
+       <widget class="QPushButton" name="ButtonCodec">
+        <property name="text">
+         <string>Codec &Parameters</string>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <spacer name="horizontalSpacer">
+        <property name="orientation">
+         <enum>Qt::Horizontal</enum>
+        </property>
+        <property name="sizeHint" stdset="0">
+         <size>
+          <width>40</width>
+          <height>20</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+      <item>
+       <widget class="QPushButton" name="ButtonClose">
+        <property name="text">
+         <string>&Close</string>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </item>
+   </layout>
+  </widget>
+  <widget class="QMenuBar" name="menubar">
+   <property name="geometry">
+    <rect>
+     <x>0</x>
+     <y>0</y>
+     <width>967</width>
+     <height>25</height>
+    </rect>
+   </property>
+   <widget class="QMenu" name="menu_Settings">
+    <property name="title">
+     <string>&Settings</string>
+    </property>
+   </widget>
+   <widget class="QMenu" name="menuHelp">
+    <property name="title">
+     <string>Help</string>
+    </property>
+    <addaction name="actionWhats_This"/>
+    <addaction name="separator"/>
+    <addaction name="actionAbout_Dream"/>
+   </widget>
+   <addaction name="menu_Settings"/>
+   <addaction name="menuHelp"/>
+  </widget>
+  <action name="actionWhats_This">
+   <property name="text">
+    <string>Whats This</string>
+   </property>
+   <property name="shortcut">
+    <string>Shift+F1</string>
+   </property>
+  </action>
+  <action name="actionAbout_Dream">
+   <property name="text">
+    <string>About Dream...</string>
+   </property>
+  </action>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>QwtThermo</class>
+   <extends>QWidget</extends>
+   <header>qwt_thermo.h</header>
+  </customwidget>
+ </customwidgets>
+ <tabstops>
+  <tabstop>TabWidgetParam</tabstop>
+  <tabstop>RadioButtonRMA</tabstop>
+  <tabstop>RadioButtonRMB</tabstop>
+  <tabstop>RadioButtonRMC</tabstop>
+  <tabstop>RadioButtonRMD</tabstop>
+  <tabstop>RadioButtonBandwidth45</tabstop>
+  <tabstop>RadioButtonBandwidth5</tabstop>
+  <tabstop>RadioButtonBandwidth9</tabstop>
+  <tabstop>RadioButtonBandwidth10</tabstop>
+  <tabstop>RadioButtonBandwidth18</tabstop>
+  <tabstop>RadioButtonBandwidth20</tabstop>
+  <tabstop>ComboBoxMSCConstellation</tabstop>
+  <tabstop>ComboBoxMSCProtLev</tabstop>
+  <tabstop>ComboBoxSDCConstellation</tabstop>
+  <tabstop>ComboBoxMSCInterleaver</tabstop>
+  <tabstop>LineEditSndCrdIF</tabstop>
+  <tabstop>RadioButtonOutReal</tabstop>
+  <tabstop>RadioButtonOutIQPos</tabstop>
+  <tabstop>RadioButtonOutIQNeg</tabstop>
+  <tabstop>RadioButtonOutEP</tabstop>
+  <tabstop>RadioButtonCurTimeOff</tabstop>
+  <tabstop>RadioButtonCurTimeLocal</tabstop>
+  <tabstop>RadioButtonCurTimeUTC</tabstop>
+  <tabstop>RadioButtonCurTimeUTCOffset</tabstop>
+  <tabstop>TabWidgetServices</tabstop>
+  <tabstop>LineEditServiceLabel</tabstop>
+  <tabstop>LineEditServiceID</tabstop>
+  <tabstop>ComboBoxLanguage</tabstop>
+  <tabstop>CheckBoxEnableAudio</tabstop>
+  <tabstop>ComboBoxProgramType</tabstop>
+  <tabstop>RadioButtonAAC</tabstop>
+  <tabstop>RadioButtonOPUS</tabstop>
+  <tabstop>CheckBoxEnableTextMessage</tabstop>
+  <tabstop>ComboBoxTextMessage</tabstop>
+  <tabstop>MultiLineEditTextMessage</tabstop>
+  <tabstop>PushButtonClearAllText</tabstop>
+  <tabstop>PushButtonAddText</tabstop>
+  <tabstop>CheckBoxEnableData</tabstop>
+  <tabstop>CheckBoxRemovePath</tabstop>
+  <tabstop>TreeWidgetFileNames</tabstop>
+  <tabstop>PushButtonClearAllFileNames</tabstop>
+  <tabstop>PushButtonAddFile</tabstop>
+  <tabstop>ButtonStartStop</tabstop>
+  <tabstop>ButtonCodec</tabstop>
+  <tabstop>ButtonClose</tabstop>
+ </tabstops>
+ <resources>
+  <include location="res/icons.qrc"/>
+ </resources>
+ <connections>
+  <connection>
+   <sender>ButtonClose</sender>
+   <signal>clicked()</signal>
+   <receiver>TransmDlgBase</receiver>
+   <slot>close()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>20</x>
+     <y>20</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>20</x>
+     <y>20</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+ <buttongroups>
+  <buttongroup name="ButtonGroupCurrentTime"/>
+  <buttongroup name="ButtonGroupOutput"/>
+  <buttongroup name="ButtonGroupRobustnessMode"/>
+  <buttongroup name="ButtonGroupCodec"/>
+  <buttongroup name="ButtonGroupBandwidth"/>
+ </buttongroups>
+</ui>
diff --git a/src/GUI-QT/afswidget.cpp b/src/GUI-QT/afswidget.cpp
new file mode 100644
index 0000000..81dffb2
--- /dev/null
+++ b/src/GUI-QT/afswidget.cpp
@@ -0,0 +1,80 @@
+#include "afswidget.h"
+#include "receivercontroller.h"
+
+AFSWidget::AFSWidget(ReceiverController* rc, QWidget *parent) :
+    QTreeWidget(parent)
+{
+}
+
+void sdItem(QTreeWidgetItem* w, const CServiceDefinition& sd, const CAltFreqSign& a)
+{
+    for(size_t i=0; i<sd.veciFrequencies.size(); i++)
+    {
+        int f = sd.veciFrequencies[i];
+        QStringList l;
+        l << QString("%1 MHz").arg(double(f)/1000.0);
+        QTreeWidgetItem* item = new QTreeWidgetItem(l);
+        w->addChild(item);
+    }
+            //sd. iRegionID;
+            //sd. iScheduleID;
+            //sd. iSystemID;
+}
+
+void AFSWidget::setAFS(const CAltFreqSign& a)
+{
+    clear();
+    vector<size_t> sfn;
+    for(size_t i=0; i<a.vecMultiplexes.size(); i++)
+    {
+        if(a.vecMultiplexes[i].bIsSyncMultplx)
+        {
+            sfn.push_back(i);
+        }
+    }
+    if(sfn.size()>0)
+    {
+        QStringList l;
+        l << "This SFN";
+        QTreeWidgetItem* item = new QTreeWidgetItem(l);
+        addTopLevelItem(item);
+        for(size_t i=0; i<sfn.size(); i++)
+        {
+            sdItem(item, a.vecMultiplexes[sfn[i]], a);
+        }
+    }
+    vector<size_t> mfn;
+    for(size_t i=0; i<a.vecMultiplexes.size(); i++)
+    {
+        if(a.vecMultiplexes[i].bIsSyncMultplx==FALSE)
+        {
+            mfn.push_back(i);
+        }
+    }
+    if(mfn.size()>0)
+    {
+        QStringList l;
+        l << "Related Networks";
+        QTreeWidgetItem* item = new QTreeWidgetItem(l);
+        addTopLevelItem(item);
+        for(size_t i=0; i<sfn.size(); i++)
+        {
+            sdItem(item, a.vecMultiplexes[sfn[i]], a);
+            //vector<int> veciServRestrict;
+        }
+    }
+    if(a.vecOtherServices.size()>0)
+    {
+        QStringList l;
+        l << "Other";
+        QTreeWidgetItem* item = new QTreeWidgetItem(l);
+        addTopLevelItem(item);
+        for(vector < COtherService >::const_iterator i=a.vecOtherServices.begin(); i!=a.vecOtherServices.end(); i++)
+        {
+            sdItem(item, *i, a);
+            //_BOOLEAN bSameService;
+            //int iShortID;
+            //uint32_t iServiceID;
+        }
+    }
+}
diff --git a/src/GUI-QT/afswidget.h b/src/GUI-QT/afswidget.h
new file mode 100644
index 0000000..553d0cb
--- /dev/null
+++ b/src/GUI-QT/afswidget.h
@@ -0,0 +1,21 @@
+#ifndef AFSWIDGET_H
+#define AFSWIDGET_H
+#include <../Parameter.h>
+
+#include <QTreeWidget>
+class ReceiverController;
+
+class AFSWidget : public QTreeWidget
+{
+    Q_OBJECT
+public:
+    explicit AFSWidget(ReceiverController*, QWidget *parent = 0);
+
+signals:
+
+public slots:
+    void setAFS(const CAltFreqSign&);
+
+};
+
+#endif // AFSWIDGET_H
diff --git a/src/GUI-QT/amwidget.cpp b/src/GUI-QT/amwidget.cpp
new file mode 100644
index 0000000..0451411
--- /dev/null
+++ b/src/GUI-QT/amwidget.cpp
@@ -0,0 +1,345 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer, Andrew Murphy, Julian Cable
+ *
+ * Description:
+ *
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+#include "amwidget.h"
+#include "ui_amwidget.h"
+#include "receivercontroller.h"
+
+#include "DRMPlot.h"
+#include <qwt_plot_layout.h>
+#include "receivercontroller.h"
+#include <QInputDialog>
+
+AMWidget::AMWidget(ReceiverController* rc, QWidget *parent) :
+    QWidget(parent),
+    ui(new Ui::AMWidget),
+    controller(rc)
+{
+    ui->setupUi(this);
+
+    /* Set help text for the controls */
+    AddWhatsThisHelp();
+
+    ui->sliderBandwidth->setTickPosition(QSlider::TicksBothSides);
+    MainPlot = new CDRMPlot(NULL, ui->plot, controller);
+
+    /* Init main plot */
+    bool waterfall = false; // TODO getSetting("waterfall", false);
+    ui->checkBoxWaterFall->setChecked(waterfall);
+    if(MainPlot)
+    {
+        //TODOMainPlot->SetPlotStyle(getSetting("plotstyle", 0, true));
+        MainPlot->SetupChart(waterfall?CDRMPlot::INP_SPEC_WATERF:CDRMPlot::INPUT_SIG_PSD_ANALOG);
+    }
+
+    /* Add tool tip to show the user the possibility of choosing the AM IF */
+    QString ptt = tr("Click on the plot to set the demodulation frequency");
+    if(MainPlot)
+    {
+        MainPlot->plot->setToolTip(ptt);
+    }
+
+    /* Init bandwidth slider */
+    // TODO from settings
+    ui->sliderBandwidth->setTickPosition(QSlider::TicksBothSides);
+    ui->sliderBandwidth->setTickInterval(1000); /* Each kHz a tick */
+    ui->sliderBandwidth->setPageStep(1000); /* Hz */
+    ui->buttonGroupDemodulation->setId(ui->radioButtonDemAM, CAMDemodulation::DT_AM);
+    ui->buttonGroupDemodulation->setId(ui->radioButtonDemLSB, CAMDemodulation::DT_LSB);
+    ui->buttonGroupDemodulation->setId(ui->radioButtonDemUSB, CAMDemodulation::DT_USB);
+    ui->buttonGroupDemodulation->setId(ui->radioButtonDemCW, CAMDemodulation::DT_CW);
+    ui->buttonGroupDemodulation->setId(ui->radioButtonDemFM, CAMDemodulation::DT_FM);
+    ui->buttonGroupAGC->setId(ui->radioButtonAGCSlow, CAGC::AT_SLOW);
+    ui->buttonGroupAGC->setId(ui->radioButtonAGCMed, CAGC::AT_MEDIUM);
+    ui->buttonGroupAGC->setId(ui->radioButtonAGCFast, CAGC::AT_FAST);
+    ui->buttonGroupNoiseReduction->setId(ui->radioButtonNoiRedOff, CAMDemodulation::NR_OFF);
+    ui->buttonGroupNoiseReduction->setId(ui->radioButtonNoiRedLow, CAMDemodulation::NR_LOW);
+    ui->buttonGroupNoiseReduction->setId(ui->radioButtonNoiRedMed, CAMDemodulation::NR_MEDIUM);
+    ui->buttonGroupNoiseReduction->setId(ui->radioButtonNoiRedHigh, CAMDemodulation::NR_HIGH);
+    ui->buttonGroupNoiseReduction->setId(ui->radioButtonNoiRedSpeex, CAMDemodulation::NR_SPEEX);
+
+#ifdef HAVE_SPEEX
+    ui->spinBoxNoiRedLevel->setValue(controller->getReceiver()->GetAMDemod()->GetNoiRedLevel());
+#else
+    ui->radioButtonNoiRedSpeex->hide();
+    ui->spinBoxNoiRedLevel->hide();
+#endif
+
+    connect(MainPlot, SIGNAL(xAxisValSet(double)),
+        this, SLOT(OnChartxAxisValSet(double)));
+
+    /* Button groups */
+    connect(ui->buttonGroupDemodulation, SIGNAL(buttonClicked(int)),
+        this, SLOT(OnRadioDemodulation(int)));
+    connect(ui->buttonGroupAGC, SIGNAL(buttonClicked(int)),
+        this, SLOT(OnRadioAGC(int)));
+    connect(ui->buttonGroupNoiseReduction, SIGNAL(buttonClicked(int)),
+        this, SLOT(OnRadioNoiRed(int)));
+
+    connectController(controller);
+}
+
+AMWidget::~AMWidget()
+{
+    delete ui;
+}
+
+void AMWidget::connectController(ReceiverController* controller)
+{
+    connect(this, SIGNAL(AGC(int)), controller, SLOT(setAnalogAGC(int)));
+    connect(this, SIGNAL(modulation(int)), controller, SLOT(setAnalogModulation(int)));
+    connect(this, SIGNAL(noiseReductionType(int)), controller, SLOT(setAnalogNoiseReduction(int)));
+    connect(this, SIGNAL(noiseReductionLevel(int)), controller, SLOT(setNoiRedLevel(int)));
+    connect(this, SIGNAL(AMFilterBW(int)), controller, SLOT(setAMFilterBW(int)));
+    connect(this, SIGNAL(enableAutoFreqAcq(bool)), controller, SLOT(setEnableAutoFreqAcq(bool)));
+    connect(this, SIGNAL(enablePLL(bool)), controller, SLOT(setEnablePLL(bool)));
+    connect(this, SIGNAL(AMDemodAcq(double)), controller, SLOT(setAMDemodAcq(double)));
+}
+
+void AMWidget::showEvent(QShowEvent*)
+{
+    /* Notify the MainPlot of showEvent */
+    if(MainPlot) MainPlot->activate();
+}
+
+void AMWidget::hideEvent(QHideEvent*)
+{
+    /* Notify the MainPlot of hideEvent */
+    if(MainPlot) MainPlot->deactivate();
+
+    bool waterfall = ui->checkBoxWaterFall->isChecked();
+    // TODO putSetting("waterfall", waterfall);
+}
+
+void AMWidget::UpdatePlotStyle(int iPlotstyle)
+{
+    /* Update main plot window */
+    if(MainPlot)
+        MainPlot->SetPlotStyle(iPlotstyle);
+}
+
+void AMWidget::OnSampleRateChanged()
+{
+    // TODO
+}
+
+//controller->getReceiver()->GetAMDemod()->SetDemodType();
+void AMWidget::OnRadioDemodulation(int iID)
+{
+    emit modulation(iID);
+}
+
+//controller->getReceiver()->GetAMDemod()->SetAGCType(CAGC::AT_NO_AGC);
+void AMWidget::OnRadioAGC(int iID)
+{
+    emit AGC(iID);
+}
+
+//controller->getReceiver()->GetAMDemod()->SetNoiRedType(CAMDemodulation::NR_OFF);
+void AMWidget::OnRadioNoiRed(int iID)
+{
+    emit noiseReductionType(iID);
+#ifdef HAVE_SPEEX
+    /* Set speex spinbox enable state */
+    ui->spinBoxNoiRedLevel->setEnabled(ui->radioButtonNoiRedSpeex->isChecked());
+#endif
+}
+
+//controller->getReceiver()->SetAMFilterBW(value);
+void AMWidget::on_sliderBandwidth_valueChanged(int value)
+{
+    /* Set new filter in processing module */
+    emit AMFilterBW(value);
+    ui->textLabelBandWidth->setText(QString().setNum(value) + tr(" Hz"));
+
+    /* Update chart */
+    if(MainPlot) MainPlot->UpdateAnalogBWMarker();
+}
+
+void AMWidget::on_checkBoxAutoFreqAcq_stateChanged(int i)
+{
+    emit enableAutoFreqAcq(i==Qt::Checked);
+}
+
+void AMWidget::on_checkBoxPLL_stateChanged(int i)
+{
+    emit enablePLL(i==Qt::Checked);
+}
+
+void AMWidget::OnChartxAxisValSet(double dVal)
+{
+    /* Perform range check */
+    if (dVal < 0.0)
+        dVal = 0.0;
+    else if (dVal > 1.0)
+        dVal = 1.0;
+
+    /* Set new frequency in receiver module */
+    emit AMDemodAcq(dVal);
+
+    /* Update chart */
+    if(MainPlot) MainPlot->UpdateAnalogBWMarker();
+}
+
+void AMWidget::on_checkBoxWaterFall_stateChanged(int)
+{
+    /* Toggle between normal spectrum plot and waterfall spectrum plot */
+    if (MainPlot && ui->checkBoxWaterFall->isChecked())
+        MainPlot->SetupChart(CDRMPlot::INP_SPEC_WATERF);
+    else
+        MainPlot->SetupChart(CDRMPlot::INPUT_SIG_PSD_ANALOG);
+}
+
+/* Manual carrier frequency input box */
+void AMWidget::on_buttonFreqOffset_clicked()
+{
+    bool ok = false;
+    const double prev_freq =
+        controller->getReceiver()->GetReceiveData()->ConvertFrequency(
+            controller->getReceiver()->GetAMDemod()->GetCurMixFreqOffs());
+    const double new_freq = QInputDialog::getDouble(this, this->windowTitle(),
+        ui->labelFreqOffset->text(), prev_freq, -1e6, 1e6, 2, &ok);
+    if (ok)
+    {
+        const _REAL conv_freq =
+            controller->getReceiver()->GetReceiveData()->ConvertFrequency(new_freq, TRUE);
+        const double dVal = conv_freq /
+            (controller->getReceiver()->GetParameters()->GetSigSampleRate() / 2);
+        OnChartxAxisValSet(dVal);
+    }
+}
+
+void AMWidget::on_spinBoxNoiRedLevel_valueChanged(int value)
+{
+    emit noiseReductionLevel(value);
+}
+
+void AMWidget::AddWhatsThisHelp()
+{
+    /* Noise Reduction */
+    const QString strNoiseReduction =
+        tr("<b>Noise Reduction:</b> The noise suppression is a frequency "
+        "domain optimal filter design based algorithm. The noise PSD is "
+        "estimated utilizing a minimum statistic. A problem of this type of "
+        "algorithm is that it produces the so called \"musical tones\". The "
+        "noise becomes coloured and sounds a bit strange. At the same time, "
+        "the useful signal (which might be speech or music) is also "
+        "distorted by the algorithm. By selecting the level of noise "
+        "reduction, a compromise between distortion of the useful signal "
+        "and actual noise reduction can be made.");
+
+    /* Automatic Gain Control */
+    const QString strAGC =
+        tr("<b>AGC (Automatic Gain Control):</b> Input signals can have a "
+        "large variation in power due to channel impairments. To compensate "
+        "for that, an automatic gain control can be applied. The AGC has "
+        "four settings: Off, Slow, Medium and Fast.");
+
+    /* Filter Bandwidth */
+    const QString strFilterBW =
+        tr("<b>Filter Bandwidth:</b> A band-pass filter is applied before "
+        "the actual demodulation process. With this filter, adjacent signals "
+        "are attenuated. The bandwidth of this filter can be chosen in steps "
+        "of 1 Hz by using the slider bar. Clicking on the right or left side "
+        "of the slider leveler will increase/decrease the bandwidth by 1 kHz. "
+        "<br>The current filter bandwidth is indicated in the spectrum plot "
+        "by a selection bar.");
+
+    /* Demodulation type */
+    const QString strDemodType =
+        tr("<b>Demodulation Type:</b> The following analog "
+        "demodulation types are available:<ul>"
+        "<li><b>AM:</b> This analog demodulation type is used in most of "
+        "the hardware radios. The envelope of the complex base-band signal "
+        "is used followed by a high-pass filter to remove the DC offset. "
+        "Additionally, a low pass filter with the same bandwidth as the "
+        "pass-band filter is applied to reduce the noise caused by "
+        "non-linear distortions.</li>"
+        "<li><b>LSB / USB:</b> These are single-side-band (SSB) demodulation "
+        "types. Only one side of the spectrum is evaluated, the upper side "
+        "band is used in USB and the lower side band with LSB. It is "
+        "important for SSB demodulation that the DC frequency of the analog "
+        "signal is known to get satisfactory results. The DC frequency is "
+        "automatically estimated by starting a new acquisition or by "
+        "clicking on the plot.</li>"
+        "<li><b>CW:</b> This demodulation type can be used to receive "
+        "CW signals. Only a narrow frequency band in a fixed distance "
+        "to the mixing frequency is used. By clicking on the spectrum "
+        "plot, the center position of the band pass filter can be set.</li>"
+        "<li><b>FM:</b> This is a narrow band frequency demodulation.</li>"
+        "</ul>");
+
+    /* Carrier Frequency */
+    QString strTextFreqOffset =
+        tr("<b>Carrier Frequency:</b> The (estimated) carrier frequency of the "
+        "analog signal is shown. (The estimation of this parameter can be done "
+        "by the Autom Frequency Acquisition which uses the estimated PSD of "
+        "the input signal and applies a maximum search.)");
+
+    /* Phase lock loop */
+    const QString strPLL =
+        tr("<b>PLL:</b> The Phase-Lock-Loop (PLL) tracks the carrier of the "
+        "modulated received signal. The resulting phase offset between the "
+        "reference oscillator and the received carrier is displayed in "
+        "a dial control. If the pointer is almost steady, the PLL is locked. "
+        "If the pointer of the dial control turns quickly, the PLL is "
+        "out of lock. To get the PLL locked, the frequency offset to "
+        "the true carrier frequency must not exceed a few Hz.");
+
+    /* Auto frequency acquisition */
+    const QString strAutoFreqAcqu =
+        tr("<b>Auto Frequency Acquisition:</b> Clicking on the "
+        "input spectrum plot changes the mixing frequency for demodulation. "
+        "If the Auto Frequency Acquisition is enabled, the largest peak "
+        "near the curser is selected.");
+
+    ui->radioButtonNoiRedOff->setWhatsThis(strNoiseReduction);
+    ui->radioButtonNoiRedLow->setWhatsThis(strNoiseReduction);
+    ui->radioButtonNoiRedMed->setWhatsThis(strNoiseReduction);
+    ui->radioButtonNoiRedHigh->setWhatsThis(strNoiseReduction);
+    ui->radioButtonAGCOff->setWhatsThis(strAGC);
+    ui->radioButtonAGCSlow->setWhatsThis(strAGC);
+    ui->radioButtonAGCMed->setWhatsThis(strAGC);
+    ui->radioButtonAGCFast->setWhatsThis(strAGC);
+    ui->textLabelBandWidth->setWhatsThis(strFilterBW);
+    ui->sliderBandwidth->setWhatsThis(strFilterBW);
+    ui->radioButtonDemAM->setWhatsThis(strDemodType);
+    ui->radioButtonDemLSB->setWhatsThis(strDemodType);
+    ui->radioButtonDemUSB->setWhatsThis(strDemodType);
+    ui->radioButtonDemCW->setWhatsThis(strDemodType);
+    ui->radioButtonDemFM->setWhatsThis(strDemodType);
+    ui->GroupBoxAutoFreqAcq->setWhatsThis(strAutoFreqAcqu);
+    ui->checkBoxAutoFreqAcq->setWhatsThis(strAutoFreqAcqu);
+    ui->GroupBoxPLL->setWhatsThis(strPLL);
+    ui->checkBoxPLL->setWhatsThis(strPLL);
+    ui->labelFreqOffset->setWhatsThis(strTextFreqOffset);
+    ui->buttonFreqOffset->setWhatsThis(strTextFreqOffset);
+    ui->groupBoxNoiseReduction->setWhatsThis(strNoiseReduction);
+    ui->groupBoxAGC->setWhatsThis(strAGC);
+    ui->groupBoxDemodulation->setWhatsThis(strDemodType);
+    ui->groupBoxBW->setWhatsThis(strFilterBW);
+}
diff --git a/src/GUI-QT/amwidget.h b/src/GUI-QT/amwidget.h
new file mode 100644
index 0000000..46e4231
--- /dev/null
+++ b/src/GUI-QT/amwidget.h
@@ -0,0 +1,57 @@
+#ifndef AMWIDGET_H
+#define AMWIDGET_H
+
+#include <QWidget>
+
+namespace Ui {
+class AMWidget;
+}
+
+class ReceiverController;
+class QShowEvent;
+class QHideEvent;
+class CDRMPlot;
+
+class AMWidget : public QWidget
+{
+    Q_OBJECT
+
+public:
+    explicit AMWidget(ReceiverController*, QWidget *parent = 0);
+    ~AMWidget();
+    void connectController(ReceiverController*);
+
+private:
+    Ui::AMWidget *ui;
+    CDRMPlot* MainPlot;
+    ReceiverController* controller;
+    void AddWhatsThisHelp();
+    void showEvent(QShowEvent* pEvent);
+    void hideEvent(QHideEvent* pEvent);
+
+public slots:
+    void UpdatePlotStyle(int);
+    void OnSampleRateChanged();
+    void OnRadioDemodulation(int iID);
+    void OnRadioAGC(int iID);
+    void OnChartxAxisValSet(double dVal);
+    void on_sliderBandwidth_valueChanged(int value);
+    void OnRadioNoiRed(int iID);
+    void on_checkBoxWaterFall_stateChanged(int);
+    void on_checkBoxAutoFreqAcq_stateChanged(int);
+    void on_checkBoxPLL_stateChanged(int);
+    void on_buttonFreqOffset_clicked();
+    void on_spinBoxNoiRedLevel_valueChanged(int value);
+
+signals:
+    void modulation(int);
+    void noiseReductionType(int);
+    void noiseReductionLevel(int);
+    void AGC(int);
+    void AMFilterBW(int);
+    void enableAutoFreqAcq(bool);
+    void enablePLL(bool);
+    void AMDemodAcq(double);
+};
+
+#endif // AMWIDGET_H
diff --git a/src/GUI-QT/amwidget.ui b/src/GUI-QT/amwidget.ui
new file mode 100644
index 0000000..cc7b482
--- /dev/null
+++ b/src/GUI-QT/amwidget.ui
@@ -0,0 +1,423 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>AMWidget</class>
+ <widget class="QWidget" name="AMWidget">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>715</width>
+    <height>433</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Form</string>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout_5">
+   <item>
+    <widget class="QFrame" name="frame">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
+     </property>
+     <property name="frameShape">
+      <enum>QFrame::StyledPanel</enum>
+     </property>
+     <property name="frameShadow">
+      <enum>QFrame::Raised</enum>
+     </property>
+     <layout class="QHBoxLayout" name="horizontalLayout_4">
+      <item>
+       <widget class="QwtPlot" name="plot">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="MinimumExpanding" vsizetype="Expanding">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item>
+    <widget class="QGroupBox" name="groupBoxBW">
+     <property name="title">
+      <string>Filter Bandwidth</string>
+     </property>
+     <layout class="QHBoxLayout" name="horizontalLayout_12">
+      <item>
+       <widget class="QLabel" name="textLabelBandWidth">
+        <property name="minimumSize">
+         <size>
+          <width>70</width>
+          <height>0</height>
+         </size>
+        </property>
+        <property name="text">
+         <string>TextLabelBandWidth</string>
+        </property>
+        <property name="wordWrap">
+         <bool>false</bool>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QSlider" name="sliderBandwidth">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="orientation">
+         <enum>Qt::Horizontal</enum>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item>
+    <layout class="QHBoxLayout" name="_10">
+     <property name="spacing">
+      <number>6</number>
+     </property>
+     <property name="leftMargin">
+      <number>0</number>
+     </property>
+     <property name="topMargin">
+      <number>0</number>
+     </property>
+     <property name="rightMargin">
+      <number>0</number>
+     </property>
+     <property name="bottomMargin">
+      <number>0</number>
+     </property>
+     <item>
+      <widget class="QGroupBox" name="groupBoxDemodulation">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="title">
+        <string>Demodulation</string>
+       </property>
+       <layout class="QHBoxLayout" name="horizontalLayout_13">
+        <item>
+         <widget class="QRadioButton" name="radioButtonDemAM">
+          <property name="text">
+           <string>AM</string>
+          </property>
+          <attribute name="buttonGroup">
+           <string notr="true">buttonGroupDemodulation</string>
+          </attribute>
+         </widget>
+        </item>
+        <item>
+         <widget class="QRadioButton" name="radioButtonDemLSB">
+          <property name="text">
+           <string>LSB</string>
+          </property>
+          <attribute name="buttonGroup">
+           <string notr="true">buttonGroupDemodulation</string>
+          </attribute>
+         </widget>
+        </item>
+        <item>
+         <widget class="QRadioButton" name="radioButtonDemUSB">
+          <property name="text">
+           <string>USB</string>
+          </property>
+          <attribute name="buttonGroup">
+           <string notr="true">buttonGroupDemodulation</string>
+          </attribute>
+         </widget>
+        </item>
+        <item>
+         <widget class="QRadioButton" name="radioButtonDemCW">
+          <property name="text">
+           <string>CW</string>
+          </property>
+          <attribute name="buttonGroup">
+           <string notr="true">buttonGroupDemodulation</string>
+          </attribute>
+         </widget>
+        </item>
+        <item>
+         <widget class="QRadioButton" name="radioButtonDemFM">
+          <property name="text">
+           <string>FM</string>
+          </property>
+          <attribute name="buttonGroup">
+           <string notr="true">buttonGroupDemodulation</string>
+          </attribute>
+         </widget>
+        </item>
+       </layout>
+      </widget>
+     </item>
+     <item>
+      <widget class="QGroupBox" name="groupBoxAGC">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="title">
+        <string>AGC</string>
+       </property>
+       <layout class="QHBoxLayout" name="horizontalLayout_14">
+        <item>
+         <widget class="QRadioButton" name="radioButtonAGCOff">
+          <property name="text">
+           <string>Off</string>
+          </property>
+          <attribute name="buttonGroup">
+           <string notr="true">buttonGroupAGC</string>
+          </attribute>
+         </widget>
+        </item>
+        <item>
+         <widget class="QRadioButton" name="radioButtonAGCSlow">
+          <property name="text">
+           <string>Slow</string>
+          </property>
+          <attribute name="buttonGroup">
+           <string notr="true">buttonGroupAGC</string>
+          </attribute>
+         </widget>
+        </item>
+        <item>
+         <widget class="QRadioButton" name="radioButtonAGCMed">
+          <property name="text">
+           <string>Med</string>
+          </property>
+          <attribute name="buttonGroup">
+           <string notr="true">buttonGroupAGC</string>
+          </attribute>
+         </widget>
+        </item>
+        <item>
+         <widget class="QRadioButton" name="radioButtonAGCFast">
+          <property name="text">
+           <string>Fast</string>
+          </property>
+          <attribute name="buttonGroup">
+           <string notr="true">buttonGroupAGC</string>
+          </attribute>
+         </widget>
+        </item>
+       </layout>
+      </widget>
+     </item>
+     <item>
+      <widget class="QGroupBox" name="groupBoxNoiseReduction">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="title">
+        <string>Noise Reduction</string>
+       </property>
+       <layout class="QGridLayout" name="gridLayout_8">
+        <item row="0" column="0">
+         <widget class="QRadioButton" name="radioButtonNoiRedOff">
+          <property name="text">
+           <string>Off</string>
+          </property>
+          <attribute name="buttonGroup">
+           <string notr="true">buttonGroupNoiseReduction</string>
+          </attribute>
+         </widget>
+        </item>
+        <item row="0" column="1">
+         <widget class="QRadioButton" name="radioButtonNoiRedLow">
+          <property name="text">
+           <string>Low</string>
+          </property>
+          <attribute name="buttonGroup">
+           <string notr="true">buttonGroupNoiseReduction</string>
+          </attribute>
+         </widget>
+        </item>
+        <item row="0" column="2">
+         <widget class="QRadioButton" name="radioButtonNoiRedMed">
+          <property name="text">
+           <string>Med</string>
+          </property>
+          <attribute name="buttonGroup">
+           <string notr="true">buttonGroupNoiseReduction</string>
+          </attribute>
+         </widget>
+        </item>
+        <item row="0" column="3">
+         <widget class="QRadioButton" name="radioButtonNoiRedHigh">
+          <property name="text">
+           <string>High</string>
+          </property>
+          <attribute name="buttonGroup">
+           <string notr="true">buttonGroupNoiseReduction</string>
+          </attribute>
+         </widget>
+        </item>
+        <item row="1" column="0">
+         <widget class="QRadioButton" name="radioButtonNoiRedSpeex">
+          <property name="text">
+           <string>Speex</string>
+          </property>
+          <attribute name="buttonGroup">
+           <string notr="true">buttonGroupNoiseReduction</string>
+          </attribute>
+         </widget>
+        </item>
+        <item row="1" column="1">
+         <widget class="QSpinBox" name="spinBoxNoiRedLevel">
+          <property name="suffix">
+           <string> dB</string>
+          </property>
+          <property name="minimum">
+           <number>-96</number>
+          </property>
+          <property name="maximum">
+           <number>-1</number>
+          </property>
+          <property name="value">
+           <number>-1</number>
+          </property>
+         </widget>
+        </item>
+       </layout>
+      </widget>
+     </item>
+    </layout>
+   </item>
+   <item>
+    <layout class="QHBoxLayout" name="horizontalLayout_9">
+     <item>
+      <widget class="QGroupBox" name="GroupBoxPLL">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="title">
+        <string>PLL</string>
+       </property>
+       <layout class="QGridLayout" name="gridLayout_6">
+        <item row="0" column="0">
+         <widget class="QCheckBox" name="checkBoxPLL">
+          <property name="text">
+           <string>Enable</string>
+          </property>
+         </widget>
+        </item>
+       </layout>
+      </widget>
+     </item>
+     <item>
+      <widget class="QGroupBox" name="GroupBoxAutoFreqAcq">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="title">
+        <string>Auto Frequency Acquisition</string>
+       </property>
+       <layout class="QGridLayout" name="gridLayout_7">
+        <item row="0" column="0">
+         <widget class="QCheckBox" name="checkBoxAutoFreqAcq">
+          <property name="text">
+           <string>Enable</string>
+          </property>
+         </widget>
+        </item>
+       </layout>
+      </widget>
+     </item>
+     <item>
+      <widget class="QGroupBox" name="groupBoxPlot">
+       <property name="title">
+        <string>Plot</string>
+       </property>
+       <layout class="QGridLayout" name="gridLayout">
+        <item row="0" column="0">
+         <widget class="QCheckBox" name="checkBoxWaterFall">
+          <property name="text">
+           <string>Waterfall</string>
+          </property>
+         </widget>
+        </item>
+       </layout>
+      </widget>
+     </item>
+     <item>
+      <widget class="QGroupBox" name="groupBox">
+       <property name="title">
+        <string>Carrier Offset</string>
+       </property>
+       <layout class="QHBoxLayout" name="horizontalLayout">
+        <item>
+         <widget class="QLabel" name="labelFreqOffset">
+          <property name="text">
+           <string>Carrier Offset</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QPushButton" name="buttonFreqOffset">
+          <property name="text">
+           <string>Enter</string>
+          </property>
+         </widget>
+        </item>
+       </layout>
+      </widget>
+     </item>
+     <item>
+      <spacer name="Spacer6_2">
+       <property name="orientation">
+        <enum>Qt::Horizontal</enum>
+       </property>
+       <property name="sizeType">
+        <enum>QSizePolicy::MinimumExpanding</enum>
+       </property>
+       <property name="sizeHint" stdset="0">
+        <size>
+         <width>20</width>
+         <height>20</height>
+        </size>
+       </property>
+      </spacer>
+     </item>
+    </layout>
+   </item>
+  </layout>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>QwtPlot</class>
+   <extends>QFrame</extends>
+   <header>qwt_plot.h</header>
+   <container>1</container>
+  </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+ <buttongroups>
+  <buttongroup name="buttonGroupAGC"/>
+  <buttongroup name="buttonGroupNoiseReduction"/>
+  <buttongroup name="buttonGroupDemodulation"/>
+ </buttongroups>
+</ui>
diff --git a/src/GUI-QT/audiodetailwidget.cpp b/src/GUI-QT/audiodetailwidget.cpp
new file mode 100644
index 0000000..09fb6dc
--- /dev/null
+++ b/src/GUI-QT/audiodetailwidget.cpp
@@ -0,0 +1,148 @@
+#include "audiodetailwidget.h"
+#include "ui_audiodetailwidget.h"
+#include <../util-QT/Util.h>
+#include <../tables/TableFAC.h>
+#include <../DrmReceiver.h>
+#include "DRMPlot.h"
+#include <QFileDialog>
+
+AudioDetailWidget::AudioDetailWidget(ReceiverController* rc, QWidget *parent) :
+    QWidget(parent),
+    ui(new Ui::AudioDetailWidget),short_id(-1),
+    engineeringMode(false),pMainPlot(NULL),controller(rc),iPlotStyle(0)
+{
+    ui->setupUi(this);
+    QSizePolicy sizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+    connect(rc, SIGNAL(serviceChanged(int,CService)), this, SLOT(updateDisplay(int,CService)));
+}
+
+AudioDetailWidget::~AudioDetailWidget()
+{
+    delete ui;
+}
+
+void AudioDetailWidget::addItem(const QString& key, const QString& val)
+{
+    ui->treeWidget->addTopLevelItem((new QTreeWidgetItem(QStringList() << key << val)));
+}
+
+void AudioDetailWidget::setEngineering(bool eng)
+{
+    engineeringMode = eng;
+    if(eng)
+    {
+        if(pMainPlot==NULL)
+        {
+            pMainPlot = new CDRMPlot(NULL, ui->plot, controller);
+            pMainPlot->SetPlotStyle(iPlotStyle);
+            pMainPlot->SetupChart(CDRMPlot::AUDIO_SPECTRUM);
+        }
+        pMainPlot->activate();
+    }
+    else
+    {
+        if(pMainPlot)
+            pMainPlot->deactivate();
+    }
+    update();
+}
+
+void AudioDetailWidget::setTextMessage(const QString& s)
+{
+    ui->textMessage->setText(s);
+}
+
+void AudioDetailWidget::setRxStatus(int sid, ETypeRxStatus s)
+{
+    if(sid == short_id)
+    {
+
+    }
+}
+
+void AudioDetailWidget::updateDisplay(int id, CService s)
+{
+    short_id = id;
+    if(engineeringMode)
+        updateEngineeringModeDisplay(id, s);
+    else
+        updateUserModeDisplay(id,s);
+}
+
+void AudioDetailWidget::updateUserModeDisplay(int, const CService&)
+{
+    ui->stackedWidget->setCurrentIndex(0);
+}
+
+void AudioDetailWidget::updateEngineeringModeDisplay(int id, const CService& s)
+{
+    ui->stackedWidget->setCurrentIndex(1);
+    ui->treeWidget->clear();
+    addItem( tr("Codec"),  GetCodecString(s));
+    addItem( tr("Mode"),  GetTypeString(s));
+    addItem( tr("Decodable"),  s.AudioParam.bCanDecode?tr("Yes"):tr("No"));
+    addItem( tr("Text Messages"),  s.AudioParam.bTextflag?tr("Yes"):tr("No"));
+    addItem( tr("Language Code"),  s.strLanguageCode.c_str());
+    addItem( tr("Language"),  GetISOLanguageName(s.strLanguageCode).c_str());
+    addItem( tr("Country"),  GetISOCountryName(s.strCountryCode).c_str());
+    addItem( tr("Service ID"), QString("%1").arg(s.iServiceID, 6, 16));
+    addItem( tr("Conditional Access"),  s.AudioParam.bCA?tr("Yes"):tr("No"));
+    addItem( tr("Stream ID"),  QString("%1").arg(s.AudioParam.iStreamID));
+    addItem( tr("Short ID"),  QString("%1").arg(id));
+
+    ui->buttonListen->setEnabled(s.AudioParam.bCanDecode);
+}
+
+void AudioDetailWidget::on_buttonListen_clicked()
+{
+    emit listen(short_id);
+}
+
+void AudioDetailWidget::on_mute_stateChanged(int state)
+{
+    /* Set parameter in working thread module */
+    controller->getReceiver()->GetWriteData()->MuteAudio(state == Qt::Checked);
+}
+
+void AudioDetailWidget::on_reverb_stateChanged(int state)
+{
+    /* Set parameter in working thread module */
+    controller->getReceiver()->GetAudSorceDec()->SetReverbEffect(state == Qt::Checked);
+}
+
+void AudioDetailWidget::on_save_stateChanged(int state)
+{
+    /*
+        This code is copied in AnalogDemDlg.cpp. If you do changes here, you should
+        apply the changes in the other file, too
+    */
+    if (state == Qt::Checked)
+    {
+        /* Show "save file" dialog */
+        QString strFileName =
+            QFileDialog::getSaveFileName(this, "*.wav", tr("DreamOut.wav"));
+
+        /* Check if user not hit the cancel button */
+        if (!strFileName.isEmpty())
+        {
+            string s = strFileName.toUtf8().constData();
+            controller->getReceiver()->GetWriteData()->StartWriteWaveFile(s);
+        }
+        else
+        {
+            /* User hit the cancel button, uncheck the button */
+            ui->save->setChecked(false);
+        }
+    }
+    else
+        controller->getReceiver()->GetWriteData()->StopWriteWaveFile();
+}
+
+void AudioDetailWidget::setPlotStyle(int n)
+{
+    /* Save the new style */
+    iPlotStyle = n;
+    /* Update main plot window */
+    if(pMainPlot)
+        pMainPlot->SetPlotStyle(iPlotStyle);
+}
diff --git a/src/GUI-QT/audiodetailwidget.h b/src/GUI-QT/audiodetailwidget.h
new file mode 100644
index 0000000..9d3e05f
--- /dev/null
+++ b/src/GUI-QT/audiodetailwidget.h
@@ -0,0 +1,47 @@
+#ifndef AUDIODETAILWIDGET_H
+#define AUDIODETAILWIDGET_H
+
+#include <QWidget>
+#include "../Parameter.h"
+
+namespace Ui {
+class AudioDetailWidget;
+}
+
+class CDRMPlot;
+class ReceiverController;
+
+class AudioDetailWidget : public QWidget
+{
+    Q_OBJECT
+
+public:
+    explicit AudioDetailWidget(ReceiverController*, QWidget * = 0);
+    ~AudioDetailWidget();
+
+signals:
+    void listen(int);
+public slots:
+    void setPlotStyle(int);
+    void setRxStatus(int, ETypeRxStatus);
+    void setTextMessage(const QString&);
+    void updateDisplay(int, CService);
+    void setEngineering(bool);
+private:
+    Ui::AudioDetailWidget *ui;
+    int short_id;
+    bool engineeringMode;
+    CDRMPlot *pMainPlot;
+    ReceiverController* controller;
+    int iPlotStyle;
+    void updateEngineeringModeDisplay(int, const CService&);
+    void updateUserModeDisplay(int, const CService&);
+    void addItem(const QString&, const QString&);
+private slots:
+    void on_buttonListen_clicked();
+    void on_mute_stateChanged(int);
+    void on_reverb_stateChanged(int);
+    void on_save_stateChanged(int);
+};
+
+#endif // AUDIODETAILWIDGET_H
diff --git a/src/GUI-QT/audiodetailwidget.ui b/src/GUI-QT/audiodetailwidget.ui
new file mode 100644
index 0000000..22ca511
--- /dev/null
+++ b/src/GUI-QT/audiodetailwidget.ui
@@ -0,0 +1,177 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>AudioDetailWidget</class>
+ <widget class="QWidget" name="AudioDetailWidget">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>367</width>
+    <height>268</height>
+   </rect>
+  </property>
+  <property name="sizePolicy">
+   <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+    <horstretch>0</horstretch>
+    <verstretch>0</verstretch>
+   </sizepolicy>
+  </property>
+  <property name="windowTitle">
+   <string>Form</string>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <item>
+    <widget class="QStackedWidget" name="stackedWidget">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
+     </property>
+     <property name="currentIndex">
+      <number>1</number>
+     </property>
+     <widget class="QWidget" name="userMode">
+      <layout class="QGridLayout" name="gridLayout">
+       <item row="0" column="0">
+        <widget class="QLabel" name="textMessage">
+         <property name="sizePolicy">
+          <sizepolicy hsizetype="Ignored" vsizetype="Ignored">
+           <horstretch>0</horstretch>
+           <verstretch>0</verstretch>
+          </sizepolicy>
+         </property>
+         <property name="text">
+          <string>TextLabel</string>
+         </property>
+         <property name="textFormat">
+          <enum>Qt::RichText</enum>
+         </property>
+         <property name="wordWrap">
+          <bool>true</bool>
+         </property>
+         <property name="openExternalLinks">
+          <bool>true</bool>
+         </property>
+        </widget>
+       </item>
+      </layout>
+     </widget>
+     <widget class="QWidget" name="engineeringMode">
+      <property name="sizePolicy">
+       <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+        <horstretch>0</horstretch>
+        <verstretch>0</verstretch>
+       </sizepolicy>
+      </property>
+      <layout class="QHBoxLayout" name="horizontalLayout_3">
+       <item>
+        <widget class="QTreeWidget" name="treeWidget">
+         <property name="sizePolicy">
+          <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+           <horstretch>0</horstretch>
+           <verstretch>0</verstretch>
+          </sizepolicy>
+         </property>
+         <column>
+          <property name="text">
+           <string>Item</string>
+          </property>
+         </column>
+         <column>
+          <property name="text">
+           <string>Value</string>
+          </property>
+         </column>
+        </widget>
+       </item>
+       <item>
+        <widget class="QwtPlot" name="plot">
+         <property name="sizePolicy">
+          <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+           <horstretch>0</horstretch>
+           <verstretch>0</verstretch>
+          </sizepolicy>
+         </property>
+         <property name="minimumSize">
+          <size>
+           <width>100</width>
+           <height>100</height>
+          </size>
+         </property>
+         <property name="maximumSize">
+          <size>
+           <width>400</width>
+           <height>400</height>
+          </size>
+         </property>
+         <property name="frameShape">
+          <enum>QFrame::StyledPanel</enum>
+         </property>
+         <property name="frameShadow">
+          <enum>QFrame::Raised</enum>
+         </property>
+        </widget>
+       </item>
+      </layout>
+     </widget>
+    </widget>
+   </item>
+   <item>
+    <layout class="QHBoxLayout" name="horizontalLayout_2">
+     <item>
+      <widget class="QCheckBox" name="mute">
+       <property name="text">
+        <string>Mute</string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QCheckBox" name="reverb">
+       <property name="text">
+        <string>Reverb</string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QCheckBox" name="save">
+       <property name="text">
+        <string>Save</string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <spacer name="horizontalSpacer">
+       <property name="orientation">
+        <enum>Qt::Horizontal</enum>
+       </property>
+       <property name="sizeHint" stdset="0">
+        <size>
+         <width>40</width>
+         <height>20</height>
+        </size>
+       </property>
+      </spacer>
+     </item>
+     <item>
+      <widget class="QPushButton" name="buttonListen">
+       <property name="text">
+        <string>Listen</string>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
+  </layout>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>QwtPlot</class>
+   <extends>QFrame</extends>
+   <header>qwt_plot.h</header>
+   <container>1</container>
+  </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/GUI-QT/bwsviewerwidget.cpp b/src/GUI-QT/bwsviewerwidget.cpp
new file mode 100644
index 0000000..d9782c8
--- /dev/null
+++ b/src/GUI-QT/bwsviewerwidget.cpp
@@ -0,0 +1,635 @@
+/******************************************************************************\
+ * British Broadcasting Corporation
+ * Copyright (c) 2001-2014, 2001-2014
+ *
+ * Author(s):
+ *	 Julian Cable, David Flamand (rewrite)
+ *
+ * Description: MOT Broadcast Website Viewer
+ *
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "bwsviewerwidget.h"
+#include "ui_bwsviewerwidget.h"
+#include "../DrmReceiver.h"
+#include "../util-QT/Util.h"
+#include "../datadecoding/DataDecoder.h"
+#include <QDir>
+#include <QFile>
+#include <QMessageBox>
+#include <QWebHistory>
+
+#undef ENABLE_HACK
+#define ENABLE_HACK /* Do we really need these hack unless for vtc trial sample? */
+
+BWSViewerWidget::BWSViewerWidget(QWidget* parent):
+    QWidget(parent),
+    ui(new Ui::BWSViewerWidget),
+    short_id(-1),decoder(NULL),
+    nam(this, cache, waitobjs, bAllowExternalContent, strCacheHost),
+    bHomeSet(false), bPageLoading(false),
+    bSaveFileToDisk(false), bRestrictedProfile(false), bAllowExternalContent(true),
+    bClearCacheOnNewService(true), bDirectoryIndexChanged(false),
+    iLastAwaitingOjects(0), strCacheHost("127.0.0.1"),
+    bLastServiceValid(false), iLastServiceID(0), iCurrentDataServiceID(0), iLastValidServiceID(0),
+    Timer()
+{
+    ui->setupUi(this);
+
+    /* Setup webView */
+    ui->webView->page()->setNetworkAccessManager(&nam);
+    ui->webView->pageAction(QWebPage::OpenLinkInNewWindow)->setVisible(false);
+    ui->webView->pageAction(QWebPage::DownloadLinkToDisk)->setVisible(false);
+    ui->webView->pageAction(QWebPage::OpenImageInNewWindow)->setVisible(false);
+    ui->webView->pageAction(QWebPage::DownloadImageToDisk)->setVisible(false);
+
+    /* Update time for color LED */
+    ui->LEDStatus->SetUpdateTime(1000);
+
+    /* Update various buttons and labels */
+    ui->buttonClearCache->setEnabled(false);
+    ui->labelTitle->setText("");
+    Update();
+
+    /* Connect controls */
+    connect(ui->buttonStepBack, SIGNAL(clicked()), this, SLOT(OnBack()));
+    connect(ui->buttonStepForward, SIGNAL(clicked()), this, SLOT(OnForward()));
+    connect(ui->buttonHome, SIGNAL(clicked()), this, SLOT(OnHome()));
+    connect(ui->buttonStopRefresh, SIGNAL(clicked()), this, SLOT(OnStopRefresh()));
+    connect(ui->buttonClearCache, SIGNAL(clicked()), this, SLOT(OnClearCache()));
+    connect(ui->webView, SIGNAL(loadStarted()), this, SLOT(OnWebViewLoadStarted()));
+    connect(ui->webView, SIGNAL(loadFinished(bool)), this, SLOT(OnWebViewLoadFinished(bool)));
+    connect(ui->webView, SIGNAL(titleChanged(const QString &)), this, SLOT(OnWebViewTitleChanged(const QString &)));
+    connect(&Timer, SIGNAL(timeout()), this, SLOT(OnTimer()));
+}
+
+BWSViewerWidget::~BWSViewerWidget()
+{
+    delete ui;
+}
+
+void BWSViewerWidget::UpdateButtons()
+{
+    ui->buttonStepBack->setEnabled(ui->webView->history()->canGoBack());
+    ui->buttonStepForward->setEnabled(ui->webView->history()->canGoForward());
+    ui->buttonHome->setEnabled(bHomeSet);
+    ui->buttonStopRefresh->setEnabled(bHomeSet);
+    ui->buttonStopRefresh->setChecked(!bPageLoading);
+    //ui->buttonStopRefresh->setIcon(QIcon(bPageLoading ? ICON_STOP : ICON_REFRESH));
+}
+
+QString BWSViewerWidget::ObjectStr(unsigned int count)
+{
+    return QString(count > 1 ? tr("objects") : tr("object"));
+}
+
+void BWSViewerWidget::UpdateStatus()
+{
+    unsigned int count, size;
+    cache.GetObjectCountAndSize(count, size);
+    if (count == 0)
+        ui->labelStatus->setText("");
+    else
+    {
+        QString text(tr("%1 %2 cached, %3 kB"));
+        text = text.arg(count).arg(ObjectStr(count)).arg((size+999) / 1000);
+        iLastAwaitingOjects = waitobjs;
+        if (iLastAwaitingOjects)
+            text += tr("  |  %1 %2 pending").arg(iLastAwaitingOjects).arg(ObjectStr(iLastAwaitingOjects));
+        if (bAllowExternalContent && ui->webView->url().isValid() && ui->webView->url().host() != strCacheHost)
+            text += "  |  " + ui->webView->url().toString();
+        ui->labelStatus->setText(text);
+    }
+}
+
+void BWSViewerWidget::UpdateWindowTitle(const uint32_t iServiceID, const bool bServiceValid, QString strLabel)
+{
+    QString strTitle("MOT Broadcast Website");
+    iLastServiceID = iServiceID;
+    bLastServiceValid = bServiceValid;
+    QString strLastLabel = strLabel;
+    if (bServiceValid)
+    {
+        if (strLabel != "")
+            strLabel += " - ";
+
+        /* Service ID (plot number in hexadecimal format) */
+        QString strServiceID = "ID:" +
+                       QString().setNum(iServiceID, 16).toUpper();
+
+        /* Add the description on the title of the dialog */
+        if (strLabel != "" || strServiceID != "")
+            strTitle += " [" + strLabel + strServiceID + "]";
+    }
+    setWindowTitle(strTitle);
+}
+
+void BWSViewerWidget::Update()
+{
+    UpdateStatus();
+    UpdateButtons();
+}
+
+void BWSViewerWidget::OnTimer()
+{
+    QString strLastLabel;
+
+    /* Get current service parameters */
+    uint32_t iServiceID; bool bServiceValid; QString strLabel; ETypeRxStatus eStatus;
+    GetServiceParams(&iServiceID, &bServiceValid, &strLabel, &eStatus);
+
+    /* Set current data service ID */
+    iCurrentDataServiceID = bServiceValid ? iServiceID : 0;
+
+    /* Check for new valid data service */
+    if (bServiceValid && iLastValidServiceID != iServiceID)
+    {
+        iLastValidServiceID = iServiceID;
+        if (bClearCacheOnNewService)
+            OnClearCache();
+    }
+
+    /* Update the window title if something have changed */
+    if (iLastServiceID != iServiceID || bLastServiceValid != bServiceValid || strLastLabel != strLabel)
+        UpdateWindowTitle(iServiceID, bServiceValid, strLabel);
+
+    SetStatus(ui->LEDStatus, eStatus);
+
+    if (Changed())
+    {
+        if (bDirectoryIndexChanged)
+        {
+            bDirectoryIndexChanged = false;
+            if (!bHomeSet)
+            {
+                bHomeSet = true;
+                OnHome();
+            }
+        }
+        Update();
+        ui->buttonClearCache->setEnabled(true);
+        //actionClear_Cache->setEnabled(true);
+    }
+    else
+    {
+        unsigned int iAwaitingOjects = waitobjs;
+        if (iLastAwaitingOjects != iAwaitingOjects)
+        {
+            iLastAwaitingOjects = iAwaitingOjects;
+            UpdateStatus();
+        }
+    }
+}
+
+void BWSViewerWidget::OnHome()
+{
+    ui->webView->load("http://" + strCacheHost);
+}
+
+void BWSViewerWidget::OnStopRefresh()
+{
+    if (bPageLoading)
+        ui->webView->stop();
+    else
+    {
+        if (ui->webView->url().isEmpty())
+            OnHome();
+        else
+            ui->webView->reload();
+    }
+}
+
+void BWSViewerWidget::OnBack()
+{
+    ui->webView->history()->back();
+}
+
+void BWSViewerWidget::OnForward()
+{
+    ui->webView->history()->forward();
+}
+
+void BWSViewerWidget::OnClearCache()
+{
+    ui->webView->setHtml("");
+    ui->webView->history()->clear();
+    cache.ClearAll();
+    bHomeSet = false;
+    bPageLoading = false;
+    bDirectoryIndexChanged = false;
+    ui->buttonClearCache->setEnabled(false);
+    Update();
+}
+
+void BWSViewerWidget::OnWebViewLoadStarted()
+{
+    bPageLoading = true;
+    QTimer::singleShot(20, this, SLOT(Update()));
+}
+
+void BWSViewerWidget::OnWebViewLoadFinished(bool ok)
+{
+    (void)ok;
+    bPageLoading = false;
+    QTimer::singleShot(20, this, SLOT(Update()));
+}
+
+void BWSViewerWidget::OnWebViewTitleChanged(const QString& title)
+{
+    ui->labelTitle->setText("<b>" + title + "</b>");
+}
+
+void BWSViewerWidget::OnAllowExternalContent(bool isChecked)
+{
+    bAllowExternalContent = isChecked;
+}
+
+void BWSViewerWidget::OnSetProfile(bool isChecked)
+{
+    bRestrictedProfile = isChecked;
+}
+
+void BWSViewerWidget::OnSaveFileToDisk(bool isChecked)
+{
+    bSaveFileToDisk = isChecked;
+}
+
+void BWSViewerWidget::OnClearCacheOnNewService(bool isChecked)
+{
+    bClearCacheOnNewService = isChecked;
+}
+
+void BWSViewerWidget::showEvent(QShowEvent*)
+{
+
+    /* Update window title */
+    uint32_t iServiceID; bool bServiceValid; QString strLabel;
+    GetServiceParams(&iServiceID, &bServiceValid, &strLabel);
+    UpdateWindowTitle(iServiceID, bServiceValid, strLabel);
+
+    /* Update window content */
+    OnTimer();
+
+    /* Activate real-time timer when window is shown */
+    Timer.start(GUI_CONTROL_UPDATE_TIME);
+}
+
+void BWSViewerWidget::hideEvent(QHideEvent*)
+{
+    /* Deactivate real-time timer so that it does not get new pictures */
+    Timer.stop();
+}
+
+bool BWSViewerWidget::Changed()
+{
+    bool bChanged = false;
+    if (decoder != NULL)
+    {
+        CMOTObject obj;
+
+        /* Poll the data decoder module for new object */
+        while (decoder->GetMOTObject(obj, CDataDecoder::AT_BROADCASTWEBSITE) == TRUE)
+        {
+            /* Get the current directory */
+            CMOTDirectory MOTDir;
+            if (decoder->GetMOTDirectory(MOTDir, CDataDecoder::AT_BROADCASTWEBSITE) == TRUE)
+            {
+                /* ETSI TS 101 498-1 Section 5.5.1 */
+
+                /* Checks if the DirectoryIndex has values */
+                if (MOTDir.DirectoryIndex.size() > 0)
+                {
+                    QString strNewDirectoryIndex;
+                    /* TODO proper profile handling */
+                    if(MOTDir.DirectoryIndex.find(UNRESTRICTED_PC_PROFILE) != MOTDir.DirectoryIndex.end())
+                        strNewDirectoryIndex =
+                            MOTDir.DirectoryIndex[UNRESTRICTED_PC_PROFILE].c_str();
+                    else if(MOTDir.DirectoryIndex.find(BASIC_PROFILE) != MOTDir.DirectoryIndex.end())
+                        strNewDirectoryIndex =
+                            MOTDir.DirectoryIndex[BASIC_PROFILE].c_str();
+#ifdef ENABLE_HACK
+                    if (strNewDirectoryIndex == "not_here.html") /* Hack needed for vtc trial sample */
+                        strNewDirectoryIndex = "index.html";
+#endif
+                    if (!strNewDirectoryIndex.isNull())
+                        bDirectoryIndexChanged |= cache.SetDirectoryIndex(strNewDirectoryIndex);
+                }
+            }
+
+            /* Get object name */
+            QString strObjName(obj.strName.c_str());
+
+            /* Get ContentType */
+            QString strContentType(obj.strMimeType.c_str());
+#ifdef ENABLE_HACK
+            /* Hack needed for vtc trial sample */
+            if (strObjName.endsWith(".stm", Qt::CaseInsensitive) && !strContentType.compare("application/octet-stream", Qt::CaseInsensitive))
+                strContentType = "text/html";
+#endif
+            /* Add received MOT object to webView */
+            cache.AddObject(strObjName, strContentType, obj.Body.vecData);
+
+            /* Store received MOT object on disk */
+            if (bSaveFileToDisk)
+                SaveMOTObject(strObjName, obj);
+
+            /* Set changed flag */
+            bChanged = true;
+        }
+    }
+    return bChanged;
+}
+
+void BWSViewerWidget::SaveMOTObject(const QString& strObjName,
+                              const CMOTObject& obj)
+{
+    const CVector<_BYTE>& vecbRawData = obj.Body.vecData;
+
+    QString strCurrentSavePath;
+
+    /* Set up save path */
+    //SetupSavePath(strCurrentSavePath);
+
+    /* Generate safe filename */
+    QString strFileName = strCurrentSavePath + VerifyHtmlPath(strObjName);
+
+    /* First, create directory for storing the file (if not exists) */
+    CreateDirectories(strFileName);
+
+    /* Open file */
+    QFile file(strFileName);
+    if (file.open(QIODevice::WriteOnly))// | QIODevice::Truncate))
+    {
+        int i, written, size;
+        size = vecbRawData.Size();
+
+        /* Write data */
+        for (i = 0, written = 0; size > 0 && written >= 0; i+=written, size-=written)
+            written = file.write((const char*)&vecbRawData.at(i), size);
+
+        /* Close the file afterwards */
+        file.close();
+    }
+    else
+    {
+        QMessageBox::information(this, file.errorString(), strFileName);
+    }
+}
+
+void BWSViewerWidget::SetupSavePath(QString& s)
+{
+    s=strCurrentSavePath+s;
+}
+
+void BWSViewerWidget::GetServiceParams(uint32_t* iServiceID, bool* bServiceValid, QString* strLabel, ETypeRxStatus* eStatus)
+{
+    if (eStatus)
+        *eStatus = status;
+    if (iServiceID)
+        *iServiceID = service.iServiceID;
+    if (bServiceValid)
+        *bServiceValid = service.IsActive() && service.eAudDataFlag == CService::SF_DATA;
+    /* Do UTF-8 to QString (UNICODE) conversion with the label strings */
+    if (strLabel)
+        *strLabel = QString().fromUtf8(service.strLabel.c_str()).trimmed();
+}
+
+void BWSViewerWidget::setDecoder(CDataDecoder* dec)
+{
+    decoder = dec;
+}
+
+void BWSViewerWidget::setServiceInformation(int i, CService s)
+{
+    short_id = i;
+    service = s;
+}
+
+void BWSViewerWidget::setStatus(int, ETypeRxStatus s)
+{
+    status = s;
+}
+
+void BWSViewerWidget::setSavePath(const QString&)
+{
+
+}
+
+//////////////////////////////////////////////////////////////////
+// CWebsiteCache implementation
+
+void CWebsiteCache::GetObjectCountAndSize(unsigned int& count, unsigned int& size)
+{
+    mutex.lock();
+        count = objects.size();
+        size = total_size;
+    mutex.unlock();
+}
+
+void CWebsiteCache::ClearAll()
+{
+    mutex.lock();
+        strDirectoryIndex = QString(); /* NULL string, not empty string! */
+        objects.clear();
+        total_size = 0;
+    mutex.unlock();
+}
+
+void CWebsiteCache::AddObject(QString strObjName, QString strContentType, CVector<_BYTE>& vecbData)
+{
+    mutex.lock();
+        /* increment id counter, 0 is reserved for error */
+        id_counter++; if (!id_counter) id_counter++;
+
+        /* Get the object name */
+        strObjName = UrlEncodePath(strObjName);
+
+        /* Erase previous object if any */
+        map<QString,CWebsiteObject>::iterator it;
+        it = objects.find(strObjName);
+        if (it != objects.end())
+        {
+            total_size -= it->second.data.size();
+            objects.erase(it);
+        }
+
+        /* Insert the new object */
+        objects.insert(pair<QString,CWebsiteObject>(strObjName, CWebsiteObject(id_counter, strContentType, vecbData)));
+        total_size += vecbData.Size();
+    mutex.unlock();
+
+    /* Signal that a new object is added */
+    emit ObjectAdded(strObjName);
+}
+
+int CWebsiteCache::GetObjectContentType(const QString& strObjName, QString& strContentType)
+{
+    int id = 0;
+    mutex.lock();
+        CWebsiteObject* obj = FindObject(strObjName);
+        if (obj)
+        {
+            id = obj->id;
+            strContentType = obj->strContentType;
+        }
+    mutex.unlock();
+    return id;
+}
+
+int CWebsiteCache::GetObjectSize(const QString& strObjName, const unsigned int id)
+{
+    int size = 0;
+    mutex.lock();
+        CWebsiteObject* obj = FindObject(strObjName);
+        if (obj && obj->id == id)
+        {
+            size = obj->data.size();
+        }
+    mutex.unlock();
+    return size;
+}
+
+int CWebsiteCache::CopyObjectData(const QString& strObjName, const unsigned int id, char *buffer, int maxsize, int offset)
+{
+    int size = -1;
+    if (maxsize >= 0 && offset >= 0)
+    {
+        mutex.lock();
+            CWebsiteObject* obj = FindObject(strObjName);
+            if (obj && obj->id == id)
+            {
+                size = obj->data.size();
+                if (offset < size)
+                {
+                    size -= offset;
+                    if (size > maxsize)
+                        size = maxsize;
+                    memcpy(buffer, &obj->data.data()[offset], size);
+                }
+            }
+        mutex.unlock();
+    }
+    return size;
+}
+
+CWebsiteObject* CWebsiteCache::FindObject(const QString& strObjName)
+{
+    map<QString,CWebsiteObject>::iterator it;
+    it = objects.find(strObjName);
+    return it != objects.end() ? &it->second : NULL;
+}
+
+bool CWebsiteCache::SetDirectoryIndex(const QString strNewDirectoryIndex)
+{
+    bool bChanged;
+    mutex.lock();
+        bChanged = strDirectoryIndex != strNewDirectoryIndex;
+        if (bChanged)
+            strDirectoryIndex = strNewDirectoryIndex;
+    mutex.unlock();
+    return bChanged;
+}
+
+QString CWebsiteCache::GetDirectoryIndex()
+{
+    mutex.lock();
+        QString str = strDirectoryIndex;
+    mutex.unlock();
+    return str;
+}
+
+
+//////////////////////////////////////////////////////////////////
+// CNetworkReplyCache implementation
+
+CNetworkReplyCache::CNetworkReplyCache(QNetworkAccessManager::Operation op,
+    const QNetworkRequest& req, CWebsiteCache& cache, CCounter& waitobjs)
+    : cache(cache), waitobjs(waitobjs),
+    readOffset(0), emitted(false), id(0)
+{
+    /* ETSI TS 101 498-1 Section 6.2.3 */
+    QString strUrl(req.url().toString());
+    QString strDirectoryIndex;
+    if (IsUrlDirectory(strUrl))
+        strDirectoryIndex = cache.GetDirectoryIndex();
+    path = UrlEncodePath(strUrl + strDirectoryIndex);
+
+    connect(&cache, SIGNAL(ObjectAdded(QString)), this, SLOT(CheckObject(QString)));
+    setOperation(op);
+    setRequest(req);
+    setUrl(req.url());
+    open(QIODevice::ReadOnly);
+    QCoreApplication::postEvent(this, new QEvent(QEvent::User));
+    waitobjs++;
+};
+
+CNetworkReplyCache::~CNetworkReplyCache()
+{
+    waitobjs--;
+};
+
+void CNetworkReplyCache::customEvent(QEvent* event)
+{
+    if (event->type() == QEvent::User)
+        CheckObject(path);
+}
+
+qint64 CNetworkReplyCache::bytesAvailable() const
+{
+    return cache.GetObjectSize(path, id);
+}
+
+qint64 CNetworkReplyCache::readData(char * data, qint64 maxSize)
+{
+    int len = cache.CopyObjectData(path, id, data, maxSize, readOffset);
+    if (len > 0)
+        readOffset += len;
+    return len;
+}
+
+void CNetworkReplyCache::CheckObject(QString strObjName)
+{
+    if (!emitted && path == strObjName)
+    {
+        QString strContentType;
+        unsigned int new_id = cache.GetObjectContentType(path, strContentType);
+        if (new_id)
+        {
+            id = new_id;
+            setRawHeader(QByteArray("Content-Type"), strContentType.toUtf8());
+            emitted = true;
+            emit readyRead(); /* needed for Qt 4.6 */
+            emit finished();
+        }
+    }
+}
+
+
+//////////////////////////////////////////////////////////////////
+// CNetworkAccessManager implementation
+
+QNetworkReply* CNetworkAccessManager::createRequest(Operation op, const QNetworkRequest& req, QIODevice* outgoingData)
+{
+    if (!bAllowExternalContent || req.url().host() == strCacheHost)
+        return new CNetworkReplyCache(op, req, cache, waitobjs);
+    else
+        return QNetworkAccessManager::createRequest(op, req, outgoingData);
+}
+
diff --git a/src/GUI-QT/bwsviewerwidget.h b/src/GUI-QT/bwsviewerwidget.h
new file mode 100644
index 0000000..3ca650f
--- /dev/null
+++ b/src/GUI-QT/bwsviewerwidget.h
@@ -0,0 +1,174 @@
+#ifndef BWSVIEWER_H
+#define BWSVIEWER_H
+
+#include <QWidget>
+#include <QTimer>
+#include <../Parameter.h>
+#include "../util/Utilities.h"
+#include <QNetworkAccessManager>
+#include <QNetworkReply>
+#include <QNetworkRequest>
+
+namespace Ui {
+class BWSViewerWidget;
+}
+
+class CDataDecoder;
+class CMOTObject;
+class QShowEvent;
+class QHideEvent;
+
+
+class CWebsiteObject
+{
+public:
+    CWebsiteObject(unsigned int id, const QString& strContentType, CVector<_BYTE>& vecbData)
+        : id(id), strContentType(strContentType),
+        data(QByteArray((const char*)&vecbData[0], vecbData.Size())) {}
+    virtual ~CWebsiteObject() {}
+    unsigned int    id;
+    QString         strContentType;
+    QByteArray      data;
+};
+
+
+class CWebsiteCache : public QObject
+{
+    Q_OBJECT
+
+public:
+    CWebsiteCache() : id_counter(0), total_size(0) {}
+    virtual ~CWebsiteCache() {}
+    void GetObjectCountAndSize(unsigned int& count, unsigned int& size);
+    void ClearAll();
+    void AddObject(QString strObjName, QString strContentType, CVector<_BYTE>& vecbData);
+    int GetObjectContentType(const QString& strObjName, QString& strContentType);
+    int GetObjectSize(const QString& strObjName, const unsigned int id);
+    int CopyObjectData(const QString& strObjName, const unsigned int id, char *buffer, int maxsize, int offset);
+    bool SetDirectoryIndex(const QString strNewDirectoryIndex);
+    QString GetDirectoryIndex();
+
+protected:
+    CWebsiteObject* FindObject(const QString& strObjName);
+    std::map<QString,CWebsiteObject> objects;
+    QMutex          mutex;
+    QString         strDirectoryIndex;
+    unsigned int    id_counter;
+    unsigned int    total_size;
+
+signals:
+    void ObjectAdded(QString strObjName);
+};
+
+
+class CNetworkReplyCache : public QNetworkReply
+{
+    Q_OBJECT
+
+public:
+    CNetworkReplyCache(QNetworkAccessManager::Operation op,
+        const QNetworkRequest& req, CWebsiteCache& cache, CCounter& waitobjs);
+    virtual ~CNetworkReplyCache();
+    void abort() { id = 0; }
+    qint64 bytesAvailable() const;
+    bool isSequential() const { return true; }
+
+protected:
+    qint64 readData(char * data, qint64 maxSize);
+    void customEvent(QEvent* event);
+    CWebsiteCache&      cache;
+    CCounter&           waitobjs;
+    QString             path;
+    int                 readOffset;
+    bool                emitted;
+    unsigned int        id;
+
+public slots:
+    void CheckObject(QString strObjName);
+};
+
+
+class CNetworkAccessManager : public QNetworkAccessManager
+{
+    Q_OBJECT
+
+public:
+    CNetworkAccessManager(QObject* parent, CWebsiteCache& cache,
+        CCounter& waitobjs, const bool& bAllowExternalContent, const QString& strCacheHost)
+        : QNetworkAccessManager(parent), cache(cache), waitobjs(waitobjs),
+        bAllowExternalContent(bAllowExternalContent), strCacheHost(strCacheHost) {}
+    virtual ~CNetworkAccessManager() {}
+
+protected:
+    QNetworkReply *createRequest(Operation op, const QNetworkRequest & req, QIODevice *);
+    CWebsiteCache&  cache;
+    CCounter&       waitobjs;
+    const bool&     bAllowExternalContent;
+    const QString&  strCacheHost;
+};
+
+class BWSViewerWidget : public QWidget
+{
+    Q_OBJECT
+
+public:
+    explicit BWSViewerWidget(QWidget* parent = 0);
+    ~BWSViewerWidget();
+public slots:
+    void setDecoder(CDataDecoder*);
+    void setServiceInformation(int, CService);
+    void setStatus(int, ETypeRxStatus);
+    void setSavePath(const QString&);
+private:
+    Ui::BWSViewerWidget* ui;
+    int             short_id;
+    CDataDecoder*   decoder;
+    CService        service;
+    CNetworkAccessManager nam;
+    CWebsiteCache   cache;
+    bool            bHomeSet;
+    bool            bPageLoading;
+    bool            bSaveFileToDisk;
+    bool            bRestrictedProfile;
+    bool            bAllowExternalContent;
+    bool            bClearCacheOnNewService;
+    bool            bDirectoryIndexChanged;
+    unsigned int    iLastAwaitingOjects;
+    CCounter        waitobjs;
+    const QString   strCacheHost;
+    bool            bLastServiceValid;
+    uint32_t        iLastServiceID, iCurrentDataServiceID, iLastValidServiceID;
+    QString         strCurrentSavePath;
+    QTimer          Timer;
+    ETypeRxStatus   status;
+
+    bool Changed();
+    void SaveMOTObject(const QString& strObjName, const CMOTObject& obj);
+    bool RemoveDir(const QString &dirName, int level = 0);
+    void UpdateButtons();
+    void UpdateStatus();
+    void UpdateWindowTitle(const uint32_t iServiceID, const bool bServiceValid, QString strLabel);
+    QString ObjectStr(unsigned int count);
+    void SetupSavePath(QString& strSavePath);
+    void GetServiceParams(uint32_t* iServiceID, bool* bServiceValid, QString* strLabel, ETypeRxStatus* eStatus=0);
+    void showEvent(QShowEvent *);
+    void hideEvent(QHideEvent *);
+
+private slots:
+    void OnClearCache();
+    void OnHome();
+    void OnStopRefresh();
+    void OnBack();
+    void OnForward();
+    void OnSetProfile(bool);
+    void OnSaveFileToDisk(bool);
+    void OnAllowExternalContent(bool);
+    void OnClearCacheOnNewService(bool);
+    void OnWebViewLoadStarted();
+    void OnWebViewLoadFinished(bool ok);
+    void OnWebViewTitleChanged(const QString& title);
+    void Update();
+    void OnTimer();
+};
+
+#endif // BWSVIEWER_H
diff --git a/src/GUI-QT/bwsviewerwidget.ui b/src/GUI-QT/bwsviewerwidget.ui
new file mode 100644
index 0000000..f84da18
--- /dev/null
+++ b/src/GUI-QT/bwsviewerwidget.ui
@@ -0,0 +1,351 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>BWSViewerWidget</class>
+ <widget class="QWidget" name="BWSViewerWidget">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>413</width>
+    <height>300</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Form</string>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <item>
+    <widget class="QLabel" name="labelTitle">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
+     </property>
+     <property name="frameShape">
+      <enum>QFrame::NoFrame</enum>
+     </property>
+     <property name="frameShadow">
+      <enum>QFrame::Plain</enum>
+     </property>
+     <property name="lineWidth">
+      <number>0</number>
+     </property>
+     <property name="text">
+      <string><b>Title</b></string>
+     </property>
+     <property name="textFormat">
+      <enum>Qt::RichText</enum>
+     </property>
+     <property name="alignment">
+      <set>Qt::AlignCenter</set>
+     </property>
+     <property name="wordWrap">
+      <bool>true</bool>
+     </property>
+     <property name="textInteractionFlags">
+      <set>Qt::NoTextInteraction</set>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QFrame" name="frame">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
+     </property>
+     <property name="frameShape">
+      <enum>QFrame::StyledPanel</enum>
+     </property>
+     <property name="frameShadow">
+      <enum>QFrame::Sunken</enum>
+     </property>
+     <layout class="QVBoxLayout" name="verticalLayout_4">
+      <property name="spacing">
+       <number>0</number>
+      </property>
+      <property name="leftMargin">
+       <number>0</number>
+      </property>
+      <property name="topMargin">
+       <number>0</number>
+      </property>
+      <property name="rightMargin">
+       <number>0</number>
+      </property>
+      <property name="bottomMargin">
+       <number>0</number>
+      </property>
+      <item>
+       <widget class="QWebView" name="webView">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Ignored" vsizetype="Ignored">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item>
+    <widget class="QLabel" name="labelStatus">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
+     </property>
+     <property name="frameShape">
+      <enum>QFrame::NoFrame</enum>
+     </property>
+     <property name="frameShadow">
+      <enum>QFrame::Plain</enum>
+     </property>
+     <property name="lineWidth">
+      <number>0</number>
+     </property>
+     <property name="text">
+      <string>Status</string>
+     </property>
+     <property name="textFormat">
+      <enum>Qt::PlainText</enum>
+     </property>
+     <property name="wordWrap">
+      <bool>true</bool>
+     </property>
+     <property name="textInteractionFlags">
+      <set>Qt::NoTextInteraction</set>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="Line" name="line">
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <layout class="QHBoxLayout" name="_4">
+     <property name="spacing">
+      <number>6</number>
+     </property>
+     <property name="leftMargin">
+      <number>0</number>
+     </property>
+     <property name="topMargin">
+      <number>0</number>
+     </property>
+     <property name="rightMargin">
+      <number>0</number>
+     </property>
+     <property name="bottomMargin">
+      <number>0</number>
+     </property>
+     <item>
+      <widget class="QLabel" name="TextLabel1">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="text">
+        <string>Receiving Status:</string>
+       </property>
+       <property name="wordWrap">
+        <bool>false</bool>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="CMultColorLED" name="LEDStatus" native="true">
+       <property name="minimumSize">
+        <size>
+         <width>13</width>
+         <height>13</height>
+        </size>
+       </property>
+       <property name="maximumSize">
+        <size>
+         <width>13</width>
+         <height>13</height>
+        </size>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <spacer name="z">
+       <property name="orientation">
+        <enum>Qt::Horizontal</enum>
+       </property>
+       <property name="sizeType">
+        <enum>QSizePolicy::Expanding</enum>
+       </property>
+       <property name="sizeHint" stdset="0">
+        <size>
+         <width>20</width>
+         <height>20</height>
+        </size>
+       </property>
+      </spacer>
+     </item>
+     <item>
+      <widget class="QToolButton" name="buttonStepBack">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="text">
+        <string/>
+       </property>
+       <property name="icon">
+        <iconset resource="res/icons.qrc">
+         <normaloff>:/icons/StepBack.png</normaloff>:/icons/StepBack.png</iconset>
+       </property>
+       <property name="iconSize">
+        <size>
+         <width>16</width>
+         <height>16</height>
+        </size>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QToolButton" name="buttonStepForward">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="text">
+        <string/>
+       </property>
+       <property name="icon">
+        <iconset resource="res/icons.qrc">
+         <normaloff>:/icons/StepForw.png</normaloff>:/icons/StepForw.png</iconset>
+       </property>
+       <property name="iconSize">
+        <size>
+         <width>16</width>
+         <height>16</height>
+        </size>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QToolButton" name="buttonHome">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="text">
+        <string/>
+       </property>
+       <property name="icon">
+        <iconset resource="res/icons.qrc">
+         <normaloff>:/icons/Home.png</normaloff>:/icons/Home.png</iconset>
+       </property>
+       <property name="iconSize">
+        <size>
+         <width>16</width>
+         <height>16</height>
+        </size>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QToolButton" name="buttonStopRefresh">
+       <property name="enabled">
+        <bool>true</bool>
+       </property>
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="text">
+        <string/>
+       </property>
+       <property name="icon">
+        <iconset resource="res/icons.qrc">
+         <normaloff>:/icons/Refresh.png</normaloff>
+         <normalon>:/icons/Stop.png</normalon>:/icons/Refresh.png</iconset>
+       </property>
+       <property name="iconSize">
+        <size>
+         <width>16</width>
+         <height>16</height>
+        </size>
+       </property>
+       <property name="checkable">
+        <bool>true</bool>
+       </property>
+       <property name="checked">
+        <bool>false</bool>
+       </property>
+       <property name="autoRaise">
+        <bool>false</bool>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <spacer name="Spacer5_6">
+       <property name="orientation">
+        <enum>Qt::Horizontal</enum>
+       </property>
+       <property name="sizeType">
+        <enum>QSizePolicy::Expanding</enum>
+       </property>
+       <property name="sizeHint" stdset="0">
+        <size>
+         <width>20</width>
+         <height>20</height>
+        </size>
+       </property>
+      </spacer>
+     </item>
+     <item>
+      <widget class="QPushButton" name="buttonClearCache">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Maximum" vsizetype="Maximum">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="text">
+        <string>Cl&ear Cache</string>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
+  </layout>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>QWebView</class>
+   <extends>QWidget</extends>
+   <header>QtWebKitWidgets/QWebView</header>
+  </customwidget>
+  <customwidget>
+   <class>CMultColorLED</class>
+   <extends>QWidget</extends>
+   <header location="global">MultColorLED.h</header>
+  </customwidget>
+ </customwidgets>
+ <resources>
+  <include location="res/icons.qrc"/>
+ </resources>
+ <connections/>
+</ui>
diff --git a/src/GUI-QT/channelwidget.cpp b/src/GUI-QT/channelwidget.cpp
new file mode 100644
index 0000000..4bb441a
--- /dev/null
+++ b/src/GUI-QT/channelwidget.cpp
@@ -0,0 +1,200 @@
+#include "channelwidget.h"
+#include "ui_channelwidget.h"
+#include <QTabBar>
+#include "DRMPlot.h"
+
+ChannelWidget::ChannelWidget(ReceiverController* c, QWidget *parent) :
+    QWidget(parent),
+    ui(new Ui::ChannelWidget),
+    pMainPlot(NULL)
+{
+    ui->setupUi(this);
+    pMainPlot = new CDRMPlot(NULL, ui->plot, c); // must be after setupUi
+    pMainPlot->setupTreeWidget(ui->chartSelector);
+    pMainPlot->SetupChart(CDRMPlot::INPUT_SIG_PSD);
+    ui->drmDetail->hideMSCParams(true);
+    connectController(c);
+}
+
+ChannelWidget::~ChannelWidget()
+{
+    delete ui;
+}
+
+void ChannelWidget::connectController(ReceiverController* controller)
+{
+    // Display
+    connect(controller, SIGNAL(MSCChanged(ETypeRxStatus)), ui->drmDetail, SLOT(setLEDMSC(ETypeRxStatus)));
+    connect(controller, SIGNAL(SDCChanged(ETypeRxStatus)), ui->drmDetail, SLOT(setLEDSDC(ETypeRxStatus)));
+    connect(controller, SIGNAL(FACChanged(ETypeRxStatus)), ui->drmDetail, SLOT(setLEDFAC(ETypeRxStatus)));
+    connect(controller, SIGNAL(FSyncChanged(ETypeRxStatus)), ui->drmDetail, SLOT(setLEDFrameSync(ETypeRxStatus)));
+    connect(controller, SIGNAL(TSyncChanged(ETypeRxStatus)), ui->drmDetail, SLOT(setLEDTimeSync(ETypeRxStatus)));
+    connect(controller, SIGNAL(InputStatusChanged(ETypeRxStatus)), ui->drmDetail, SLOT(setLEDIOInterface(ETypeRxStatus)));
+    connect(controller, SIGNAL(channelConfigurationChanged(ChannelConfiguration)), this, SLOT(on_channelConfigurationChanged(ChannelConfiguration)));
+    connect(controller, SIGNAL(channelReceptionChanged(Reception)), this, SLOT(on_channelReceptionChanged(Reception)));
+
+    // Controls
+    connect(ui->drmOptions, SIGNAL(recFilter(bool)), controller, SLOT(setRecFilter(bool)));
+    connect(ui->drmOptions, SIGNAL(flipSpectrum(bool)), controller, SLOT(setFlippedSpectrum(bool)));
+    connect(ui->drmOptions, SIGNAL(modiMetric(bool)), controller, SLOT(setIntCons(bool)));
+    connect(ui->drmOptions, SIGNAL(noOfIterationsChanged(int)), controller, SLOT(setNumMSCMLCIterations(int)));
+    connect(ui->drmOptions, SIGNAL(timeIntChanged(int)), controller, SLOT(setTimeInt(int)));
+    connect(ui->drmOptions, SIGNAL(freqIntChanged(int)), controller, SLOT(setFreqInt(int)));
+    connect(ui->drmOptions, SIGNAL(timeSyncChanged(int)), controller, SLOT(setTiSyncTracType(int)));
+    // Control revertives
+    connect(controller, SIGNAL(numMSCMLCIterationsChanged(int)), this, SLOT(setNumIterations(int)));
+    connect(controller, SIGNAL(timeIntChanged(int)), this, SLOT(setTimeInt(int)));
+    connect(controller, SIGNAL(freqIntChanged(int)), this, SLOT(setFreqInt(int)));
+    connect(controller, SIGNAL(tiSyncTracTypeChanged(int)), this, SLOT(setTiSyncTrac(int)));
+    connect(controller, SIGNAL(recFilterChanged(bool)), this, SLOT(setRecFilterEnabled(bool)));
+    connect(controller, SIGNAL(intConsChanged(bool)), this, SLOT(setIntConsEnabled(bool)));
+    connect(controller, SIGNAL(flippedSpectrumChanged(bool)), this, SLOT(setFlipSpectrumEnabled(bool)));
+}
+
+
+void ChannelWidget::showEvent(QShowEvent*)
+{
+    on_chartSelector_currentItemChanged(ui->chartSelector->currentItem());
+    pMainPlot->activate();
+}
+
+void ChannelWidget::hideEvent(QHideEvent*)
+{
+    pMainPlot->deactivate();
+}
+
+void ChannelWidget::on_showOptions_toggled(bool enabled)
+{
+    if(enabled)
+        ui->drmOptions->show();
+    else
+        ui->drmOptions->hide();
+}
+
+void ChannelWidget::on_channelConfigurationChanged(ChannelConfiguration c)
+{
+    setChannel(ERobMode(c.robm), ESpecOcc(c.mode), ESymIntMod(c.interl),
+               ECodScheme(c.sdcConst), ECodScheme(c.mscConst));
+    setCodeRate(c.protLev.iPartA, c.protLev.iPartB);
+}
+
+void ChannelWidget::on_channelReceptionChanged(Reception r)
+{
+    setSNR(r.snr);
+    setMER(r.mer, r.wmer);
+    setDelay_Doppler(r.sigmaEstimate, r.minDelay);
+    setSampleFrequencyOffset(r.sampleOffset, r.sampleRate);
+    setFrequencyOffset(r.dcOffset);
+}
+
+void ChannelWidget::on_chartSelector_currentItemChanged(QTreeWidgetItem *curr)
+{
+    /* Make sure we have a non root item */
+    if (curr && curr->parent())
+    {
+        /* Get chart type from selected item */
+         CDRMPlot::ECharType eCurCharType = CDRMPlot::ECharType(curr->data(0, Qt::UserRole).toInt());
+        /* Setup chart */
+        pMainPlot->SetupChart(eCurCharType);
+    }
+}
+
+void ChannelWidget::setLEDFAC(ETypeRxStatus status)
+{
+    ui->drmDetail->setLEDFAC(status);
+}
+
+void ChannelWidget::setLEDSDC(ETypeRxStatus status)
+{
+    ui->drmDetail->setLEDSDC(status);
+}
+
+void ChannelWidget::setLEDFrameSync(ETypeRxStatus status)
+{
+    ui->drmDetail->setLEDFrameSync(status);
+}
+
+void ChannelWidget::setLEDTimeSync(ETypeRxStatus status)
+{
+    ui->drmDetail->setLEDTimeSync(status);
+}
+
+void ChannelWidget::setLEDIOInterface(ETypeRxStatus status)
+{
+    ui->drmDetail->setLEDIOInterface(status);
+}
+
+void ChannelWidget::setSNR(double rSNR)
+{
+    ui->drmDetail->setSNR(rSNR);
+}
+
+void ChannelWidget::setMER(double rMER, double rWMERMSC)
+{
+    ui->drmDetail->setMER(rMER, rWMERMSC);
+}
+
+void ChannelWidget::setDelay_Doppler(double rSigmaEstimate, double rMinDelay)
+{
+    ui->drmDetail->setDelay_Doppler(rSigmaEstimate, rMinDelay);
+}
+
+void ChannelWidget::setSampleFrequencyOffset(double rCurSamROffs, double rSampleRate)
+{
+    ui->drmDetail->setSampleFrequencyOffset(rCurSamROffs, rSampleRate);
+}
+
+void ChannelWidget::setFrequencyOffset(double rOffset)
+{
+    ui->drmDetail->setFrequencyOffset(rOffset);
+}
+
+void ChannelWidget::setChannel(ERobMode robm, ESpecOcc specocc, ESymIntMod eSymbolInterlMode, ECodScheme eSDCCodingScheme, ECodScheme eMSCCodingScheme)
+{
+    ui->drmDetail->setChannel(robm, specocc, eSymbolInterlMode, eSDCCodingScheme, eMSCCodingScheme);
+}
+
+void ChannelWidget::setCodeRate(int b, int a)
+{
+    ui->drmDetail->setCodeRate(b, a);
+}
+
+void ChannelWidget::setNumIterations(int n)
+{
+    ui->drmOptions->setNumIterations(n);
+}
+
+void ChannelWidget::setTimeInt(int e)
+{
+    ui->drmOptions->setTimeInt(CChannelEstimation::ETypeIntTime(e));
+}
+
+void ChannelWidget::setFreqInt(int e)
+{
+    ui->drmOptions->setFreqInt(CChannelEstimation::ETypeIntFreq(e));
+}
+
+void ChannelWidget::setTiSyncTrac(int e)
+{
+    ui->drmOptions->setTiSyncTrac(CTimeSyncTrack::ETypeTiSyncTrac(e));
+}
+
+void ChannelWidget::setRecFilterEnabled(bool b)
+{
+    ui->drmOptions->setRecFilterEnabled(b);
+}
+
+void ChannelWidget::setIntConsEnabled(bool b)
+{
+    ui->drmOptions->setIntConsEnabled(b);
+}
+
+void ChannelWidget::setFlipSpectrumEnabled(bool b)
+{
+    ui->drmOptions->setFlipSpectrumEnabled(b);
+}
+
+void ChannelWidget::setPlotStyle(int n)
+{
+    pMainPlot->SetPlotStyle(n);
+}
diff --git a/src/GUI-QT/channelwidget.h b/src/GUI-QT/channelwidget.h
new file mode 100644
index 0000000..4a6a7ec
--- /dev/null
+++ b/src/GUI-QT/channelwidget.h
@@ -0,0 +1,61 @@
+#ifndef CHANNELWIDGET_H
+#define CHANNELWIDGET_H
+
+#include <QWidget>
+#include <QTreeWidgetItem>
+#include <../Parameter.h>
+#include "receivercontroller.h"
+
+class CDRMPlot;
+class ReceiverController;
+
+namespace Ui {
+class ChannelWidget;
+}
+
+class ChannelWidget : public QWidget
+{
+    Q_OBJECT
+
+public:
+    explicit ChannelWidget(ReceiverController*, QWidget *parent = 0);
+    ~ChannelWidget();
+    void connectController(ReceiverController*);
+
+private:
+    Ui::ChannelWidget *ui;
+    CDRMPlot *pMainPlot;
+public slots:
+    void setLEDFAC(ETypeRxStatus);
+    void setLEDSDC(ETypeRxStatus);
+    void setLEDFrameSync(ETypeRxStatus status);
+    void setLEDTimeSync(ETypeRxStatus status);
+    void setLEDIOInterface(ETypeRxStatus status);
+    void setSNR(double rSNR);
+    void setMER(double rMER, double rWMERMSC);
+    void setDelay_Doppler(double rSigmaEstimate, double rMinDelay);
+    void setSampleFrequencyOffset(double rCurSamROffs, double rSampleRate);
+    void setFrequencyOffset(double);
+    void setChannel(ERobMode, ESpecOcc, ESymIntMod, ECodScheme, ECodScheme);
+    void setCodeRate(int,int);
+    void setPlotStyle(int);
+    void on_channelConfigurationChanged(ChannelConfiguration);
+    void on_channelReceptionChanged(Reception);
+    void setNumIterations(int);
+    void setTimeInt(int);
+    void setFreqInt(int);
+    void setTiSyncTrac(int);
+    void setRecFilterEnabled(bool);
+    void setIntConsEnabled(bool);
+    void setFlipSpectrumEnabled(bool);
+
+private slots:
+    void on_chartSelector_currentItemChanged(QTreeWidgetItem *);
+    void on_showOptions_toggled(bool);
+    void showEvent(QShowEvent*);
+    void hideEvent(QHideEvent*);
+
+signals:
+};
+
+#endif // ChannelWidget_H
diff --git a/src/GUI-QT/channelwidget.ui b/src/GUI-QT/channelwidget.ui
new file mode 100644
index 0000000..00a2a4f
--- /dev/null
+++ b/src/GUI-QT/channelwidget.ui
@@ -0,0 +1,330 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>ChannelWidget</class>
+ <widget class="QWidget" name="ChannelWidget">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>623</width>
+    <height>231</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Form</string>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <item>
+    <layout class="QHBoxLayout" name="horizontalLayout_2">
+     <item>
+      <widget class="DRMDetail" name="drmDetail" native="true">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <spacer name="horizontalSpacer">
+       <property name="orientation">
+        <enum>Qt::Horizontal</enum>
+       </property>
+       <property name="sizeHint" stdset="0">
+        <size>
+         <width>40</width>
+         <height>20</height>
+        </size>
+       </property>
+      </spacer>
+     </item>
+    </layout>
+   </item>
+   <item>
+    <layout class="QGridLayout" name="gridLayout">
+     <item row="0" column="0">
+      <widget class="QTreeWidget" name="chartSelector">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="showDropIndicator" stdset="0">
+        <bool>false</bool>
+       </property>
+       <property name="iconSize">
+        <size>
+         <width>16</width>
+         <height>16</height>
+        </size>
+       </property>
+       <property name="verticalScrollMode">
+        <enum>QAbstractItemView::ScrollPerPixel</enum>
+       </property>
+       <property name="indentation">
+        <number>10</number>
+       </property>
+       <property name="rootIsDecorated">
+        <bool>true</bool>
+       </property>
+       <attribute name="headerVisible">
+        <bool>false</bool>
+       </attribute>
+       <column>
+        <property name="text">
+         <string>Chart Selector</string>
+        </property>
+       </column>
+       <item>
+        <property name="text">
+         <string>Spectrum</string>
+        </property>
+        <property name="flags">
+         <set>ItemIsDragEnabled|ItemIsUserCheckable|ItemIsEnabled</set>
+        </property>
+        <item>
+         <property name="text">
+          <string>Input PSD</string>
+         </property>
+         <property name="icon">
+          <iconset resource="res/icons.qrc">
+           <normaloff>:/icons/CSSpectrumInpPSD.png</normaloff>:/icons/CSSpectrumInpPSD.png</iconset>
+         </property>
+        </item>
+        <item>
+         <property name="text">
+          <string>Input Spectrum</string>
+         </property>
+         <property name="icon">
+          <iconset resource="res/icons.qrc">
+           <normaloff>:/icons/CSSpectrumInpSpectr.png</normaloff>:/icons/CSSpectrumInpSpectr.png</iconset>
+         </property>
+        </item>
+        <item>
+         <property name="text">
+          <string>Waterfall Input Spectrum</string>
+         </property>
+         <property name="icon">
+          <iconset resource="res/icons.qrc">
+           <normaloff>:/icons/CSSpectrumWaterf.png</normaloff>:/icons/CSSpectrumWaterf.png</iconset>
+         </property>
+        </item>
+        <item>
+         <property name="text">
+          <string>Shifted PSD</string>
+         </property>
+         <property name="icon">
+          <iconset resource="res/icons.qrc">
+           <normaloff>:/icons/CSSpectrumShiftedPSD.png</normaloff>:/icons/CSSpectrumShiftedPSD.png</iconset>
+         </property>
+        </item>
+        <item>
+         <property name="text">
+          <string>SNR Spectrum</string>
+         </property>
+         <property name="icon">
+          <iconset resource="res/icons.qrc">
+           <normaloff>:/icons/CSSpectrumSNR.png</normaloff>:/icons/CSSpectrumSNR.png</iconset>
+         </property>
+        </item>
+       </item>
+       <item>
+        <property name="text">
+         <string>Channel</string>
+        </property>
+        <property name="flags">
+         <set>ItemIsDragEnabled|ItemIsUserCheckable|ItemIsEnabled</set>
+        </property>
+        <item>
+         <property name="text">
+          <string>Impulse Response</string>
+         </property>
+         <property name="icon">
+          <iconset resource="res/icons.qrc">
+           <normaloff>:/icons/CSChannel.png</normaloff>:/icons/CSChannel.png</iconset>
+         </property>
+        </item>
+        <item>
+         <property name="text">
+          <string>Transfer Function</string>
+         </property>
+         <property name="icon">
+          <iconset resource="res/icons.qrc">
+           <normaloff>:/icons/CSTF.png</normaloff>:/icons/CSTF.png</iconset>
+         </property>
+        </item>
+       </item>
+       <item>
+        <property name="text">
+         <string>Constellation</string>
+        </property>
+        <property name="flags">
+         <set>ItemIsDragEnabled|ItemIsUserCheckable|ItemIsEnabled</set>
+        </property>
+        <item>
+         <property name="text">
+          <string>FAC / SDC / MSC</string>
+         </property>
+         <property name="icon">
+          <iconset resource="res/icons.qrc">
+           <normaloff>:/icons/CSConstellation.png</normaloff>:/icons/CSConstellation.png</iconset>
+         </property>
+        </item>
+        <item>
+         <property name="text">
+          <string>FAC</string>
+         </property>
+         <property name="icon">
+          <iconset resource="res/icons.qrc">
+           <normaloff>:/icons/CSFAC.png</normaloff>:/icons/CSFAC.png</iconset>
+         </property>
+        </item>
+        <item>
+         <property name="text">
+          <string>SDC</string>
+         </property>
+         <property name="icon">
+          <iconset resource="res/icons.qrc">
+           <normaloff>:/icons/CSSDC.png</normaloff>:/icons/CSSDC.png</iconset>
+         </property>
+        </item>
+        <item>
+         <property name="text">
+          <string>MSC</string>
+         </property>
+         <property name="icon">
+          <iconset resource="res/icons.qrc">
+           <normaloff>:/icons/CSMSC.png</normaloff>:/icons/CSMSC.png</iconset>
+         </property>
+        </item>
+       </item>
+       <item>
+        <property name="text">
+         <string>History</string>
+        </property>
+        <property name="flags">
+         <set>ItemIsDragEnabled|ItemIsUserCheckable|ItemIsEnabled</set>
+        </property>
+        <item>
+         <property name="text">
+          <string>SNR / Audio</string>
+         </property>
+         <property name="icon">
+          <iconset resource="res/icons.qrc">
+           <normaloff>:/icons/CSAudSNRHist.png</normaloff>:/icons/CSAudSNRHist.png</iconset>
+         </property>
+        </item>
+        <item>
+         <property name="text">
+          <string>Delay / Doppler</string>
+         </property>
+         <property name="icon">
+          <iconset resource="res/icons.qrc">
+           <normaloff>:/icons/CSHistoryDelDopp.png</normaloff>:/icons/CSHistoryDelDopp.png</iconset>
+         </property>
+        </item>
+        <item>
+         <property name="text">
+          <string>Frequency / Sample Rate</string>
+         </property>
+         <property name="icon">
+          <iconset resource="res/icons.qrc">
+           <normaloff>:/icons/CSHistoryFreqSam.png</normaloff>:/icons/CSHistoryFreqSam.png</iconset>
+         </property>
+        </item>
+       </item>
+      </widget>
+     </item>
+     <item row="0" column="1" rowspan="2">
+      <widget class="QwtPlot" name="plot">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="frameShape">
+        <enum>QFrame::NoFrame</enum>
+       </property>
+       <property name="frameShadow">
+        <enum>QFrame::Plain</enum>
+       </property>
+       <property name="lineWidth">
+        <number>0</number>
+       </property>
+      </widget>
+     </item>
+     <item row="1" column="0">
+      <widget class="QToolButton" name="showOptions">
+       <property name="text">
+        <string>...</string>
+       </property>
+       <property name="checkable">
+        <bool>true</bool>
+       </property>
+       <property name="checked">
+        <bool>true</bool>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
+   <item>
+    <layout class="QHBoxLayout" name="horizontalLayout">
+     <item>
+      <widget class="DRMOptions" name="drmOptions" native="true">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="autoFillBackground">
+        <bool>false</bool>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <spacer name="horizontalSpacer_2">
+       <property name="orientation">
+        <enum>Qt::Horizontal</enum>
+       </property>
+       <property name="sizeHint" stdset="0">
+        <size>
+         <width>40</width>
+         <height>20</height>
+        </size>
+       </property>
+      </spacer>
+     </item>
+    </layout>
+   </item>
+  </layout>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>DRMOptions</class>
+   <extends>QWidget</extends>
+   <header>drmoptions.h</header>
+   <container>1</container>
+  </customwidget>
+  <customwidget>
+   <class>DRMDetail</class>
+   <extends>QWidget</extends>
+   <header>drmdetail.h</header>
+   <container>1</container>
+  </customwidget>
+  <customwidget>
+   <class>QwtPlot</class>
+   <extends>QFrame</extends>
+   <header>qwt_plot.h</header>
+   <container>1</container>
+  </customwidget>
+ </customwidgets>
+ <resources>
+  <include location="res/icons.qrc"/>
+ </resources>
+ <connections/>
+</ui>
diff --git a/src/GUI-QT/dreamtabwidget.cpp b/src/GUI-QT/dreamtabwidget.cpp
new file mode 100644
index 0000000..3c0da85
--- /dev/null
+++ b/src/GUI-QT/dreamtabwidget.cpp
@@ -0,0 +1,250 @@
+#include "dreamtabwidget.h"
+#include <QLabel>
+#include <QVariant>
+#include <QTabBar>
+#include "../Parameter.h"
+#include <../util-QT/Util.h>
+#include "journalineviewer.h"
+#ifdef QT_WEBKIT_LIB
+# include "bwsviewerwidget.h"
+#endif
+#include "slideshowwidget.h"
+#include "audiodetailwidget.h"
+#include "EPGDlg.h"
+#include "channelwidget.h"
+#include "streamwidget.h"
+#include "gpswidget.h"
+#include "afswidget.h"
+#include "amwidget.h"
+#include <../datadecoding/DataDecoder.h>
+#include "receivercontroller.h"
+#include "stationswidget.h"
+
+#define CHANNEL_POS 128
+#define STREAM_POS 129
+#define AFS_POS 130
+#define GPS_POS 131
+#define AM_POS 132
+#define AMSS_POS 133
+#define MAX_ENGINEERING_POS 192
+#define STATIONS_POS 193
+#define LIVE_STATIONS_POS 194
+#define AM_POS 132
+
+DreamTabWidget::DreamTabWidget(ReceiverController* rc, QWidget *parent) :
+    QTabWidget(parent),controller(rc),
+    stations(new StationsWidget(rc)),
+    eng(false)
+{
+    add(stations, "Stations", STATIONS_POS);
+    connect(this, SIGNAL(currentChanged(int)), this, SLOT(on_currentChanged(int)));
+}
+
+void DreamTabWidget::onServiceChanged(int short_id, const CService& service)
+{
+    // label can be updated independently of other service parameters
+    QString l;
+    if(service.strLabel=="")
+        l = QString("%1").arg(service.iServiceID,4,16,QChar('0'));
+    else
+        l = QString::fromUtf8(service.strLabel.c_str());
+
+    // ? is count() always the same as tabBar->count() ???????????
+    QTabBar* tb = tabBar();
+    // if this is an audio service, create it or update the label
+    if(service.AudioParam.iStreamID!=STREAM_ID_NOT_USED)
+    {
+        int audioIndex = -1;
+        for(int i=0; i<tb->count(); i++)
+        {
+            if(tb->tabData(i).toInt()==short_id)
+                audioIndex = i;
+        }
+        if(audioIndex==-1)
+        {
+            AudioDetailWidget* pApp = new AudioDetailWidget(controller);
+            pApp->setEngineering(eng);
+            add(pApp, l, short_id);
+        }
+        else
+        {
+            setTabText(audioIndex, l);
+        }
+    }
+    if(service.DataParam.iStreamID!=STREAM_ID_NOT_USED)
+    {
+        // if this is an audio service wih a data component, add the app name to the label
+        if(service.eAudDataFlag==CService::SF_AUDIO)
+        {
+            l = l + " " + GetDataTypeString(service);
+        }
+        int dataIndex = -1;
+        for(int i=0; i<tb->count(); i++)
+        {
+            if((tb->tabData(i).toInt())==(4+short_id))
+                dataIndex = i;
+        }
+        // if there is a data component, create it or update the label
+        if(dataIndex==-1)
+        {
+            add(makeDataApp(short_id, service), l, 4+short_id);
+        }
+        else
+        {
+            setTabText(dataIndex, l);
+        }
+    }
+}
+
+void DreamTabWidget::removeServices()
+{
+    for(int i=tabBar()->count()-1; i>=0; --i)
+    {
+        int n = tabBar()->tabData(i).toInt();
+        if(n<CHANNEL_POS)
+        {
+            removeTab(i);
+        }
+    }
+}
+
+void DreamTabWidget::on_currentChanged(int index)
+{
+    int short_id = tabBar()->tabData(index).toInt();
+    if(short_id>=CHANNEL_POS)
+        return; // it is not a service tab
+    if(short_id<4)
+        emit audioServiceSelected(short_id);
+    else
+        emit dataServiceSelected(short_id-4);
+}
+
+void DreamTabWidget::add(QWidget* w, const QString& l, int ordering)
+{
+    int before = tabBar()->count();
+    for(int i=0; i<tabBar()->count(); i++)
+    {
+        if(tabBar()->tabData(i).toInt()>ordering)
+        {
+            before=i;
+            break;
+        }
+    }
+    int index = insertTab(before, w, l);
+    tabBar()->setTabData(index, ordering);
+}
+
+QWidget* DreamTabWidget::makeDataApp(int short_id, const CService& service) const
+{
+    QWidget* pApp = NULL;
+    if (service.DataParam.ePacketModInd == CDataParam::PM_PACKET_MODE)
+        pApp = makePacketApp(short_id, service);
+    if(pApp==NULL)
+    {
+        pApp = new QLabel(QString("short id %1 stream %2 packet id %3")
+                                       .arg(short_id)
+                                       .arg(service.DataParam.iStreamID)
+                                       .arg(service.DataParam.iPacketID));
+    }
+    return pApp;
+}
+
+QWidget* DreamTabWidget::makePacketApp(int short_id, const CService& service) const
+{
+    QWidget *pApp = NULL;
+    if (service.DataParam.eAppDomain == CDataParam::AD_DAB_SPEC_APP)
+    {
+        switch (service.DataParam.iUserAppIdent)
+        {
+        case DAB_AT_MOTSLIDESHOW:
+        {
+            SlideShowWidget* p = new SlideShowWidget();
+            p->setServiceInformation(short_id, service);
+            connect(controller, SIGNAL(dataStatusChanged(int, ETypeRxStatus)), p, SLOT(setStatus(int, ETypeRxStatus)));
+            pApp = p;
+        }
+            break;
+
+        case DAB_AT_BROADCASTWEBSITE:
+        {
+#ifdef QT_WEBKIT_LIB
+            BWSViewerWidget* p = new BWSViewerWidget();
+            p->setDecoder(service.DataParam.pDecoder);
+            p->setServiceInformation(short_id, service);
+            connect(controller, SIGNAL(dataStatusChanged(int, ETypeRxStatus)), p, SLOT(setStatus(int, ETypeRxStatus)));
+            pApp = p;
+#endif
+        }
+            break;
+
+        case DAB_AT_EPG:
+            break;
+
+        case DAB_AT_JOURNALINE:
+        {
+            JournalineViewer* p = new JournalineViewer(short_id);
+            p->setDecoder(service.DataParam.pDecoder);
+            p->setServiceInformation(service, service.iServiceID);
+            connect(controller, SIGNAL(dataStatusChanged(int, ETypeRxStatus)), p, SLOT(setStatus(int, ETypeRxStatus)));
+            pApp = p;
+        }
+        break;
+
+        default:
+            ;
+        }
+    }
+    return pApp;
+}
+
+void DreamTabWidget::setText(int short_id, const QString& text)
+{
+    QString t(text);
+    Linkify(t);
+    QTabBar* tb = tabBar();
+    for(int i=0; i<tb->count(); i++)
+    {
+        int n = tb->tabData(i).toInt();
+        if(short_id==n)
+        {
+            AudioDetailWidget* adw = dynamic_cast<AudioDetailWidget*>(widget(i));
+            if(adw)
+                adw->setTextMessage(t);
+        }
+    }
+}
+
+void DreamTabWidget::on_engineeringMode(bool b)
+{
+    if(eng==b)
+        return;
+    eng = b;
+    if(eng)
+    {
+        int iPlotStyle = 0;// TODO set from menu
+        ChannelWidget* pCh = new ChannelWidget(controller);
+        pCh->setPlotStyle(iPlotStyle);
+        //connect(parent, SIGNAL(plotStyleChanged(int)), pCh, SLOT(setPlotStyle(int)));
+        add(pCh, "Channel", CHANNEL_POS);
+        add(new StreamWidget(controller), "Streams", STREAM_POS);
+        add(new AFSWidget(controller), "AFS", AFS_POS);
+        add(new GPSWidget(controller), "GPS", GPS_POS);
+        add(new AMWidget(controller), "AM", AM_POS);
+        controller->setControls(); // new controls so fill their values from the receiver controller
+    }
+    else
+    {
+        for(int i=tabBar()->count()-1; i>=0; --i)
+        {
+            int n = tabBar()->tabData(i).toInt();
+            if((CHANNEL_POS<=n) && (n<=MAX_ENGINEERING_POS))
+            {
+                removeTab(i);
+            }
+        }
+    }
+    QList<AudioDetailWidget*> list = findChildren<AudioDetailWidget*>();
+    for (int i = 0; i < list.size(); ++i) {
+       list[i]->setEngineering(eng);
+    }
+}
diff --git a/src/GUI-QT/dreamtabwidget.h b/src/GUI-QT/dreamtabwidget.h
new file mode 100644
index 0000000..7f60063
--- /dev/null
+++ b/src/GUI-QT/dreamtabwidget.h
@@ -0,0 +1,35 @@
+#ifndef DREAMTABWIDGET_H
+#define DREAMTABWIDGET_H
+
+#include <QTabWidget>
+class CService;
+class ReceiverController;
+class StationsWidget;
+
+class DreamTabWidget : public QTabWidget
+{
+    Q_OBJECT
+public:
+    explicit DreamTabWidget(ReceiverController*, QWidget *parent = 0);
+signals:
+    void audioServiceSelected(int);
+    void dataServiceSelected(int);
+
+public slots:
+    void onServiceChanged(int, const CService&);
+    void setText(int, const QString&);
+    void on_engineeringMode(bool);
+    void removeServices();
+private slots:
+    void on_currentChanged(int);
+private:
+    ReceiverController* controller;
+    StationsWidget*     stations;
+    bool eng;
+
+    QWidget* makeDataApp(int short_id, const CService& service) const;
+    QWidget* makePacketApp(int short_id, const CService& service) const;
+    void add(QWidget* w, const QString& l, int ordering);
+};
+
+#endif // DREAMTABWIDGET_H
diff --git a/src/GUI-QT/drmdetail.cpp b/src/GUI-QT/drmdetail.cpp
new file mode 100644
index 0000000..169cbd8
--- /dev/null
+++ b/src/GUI-QT/drmdetail.cpp
@@ -0,0 +1,504 @@
+#include "drmdetail.h"
+#include "ui_drmdetail.h"
+#include <../util-QT/Util.h>
+
+DRMDetail::DRMDetail(QWidget *parent) :
+    QWidget(parent),
+    ui(new Ui::DRMDetail)
+{
+    ui->setupUi(this);
+    /* Update times for colour LEDs */
+    ui->LEDFAC->SetUpdateTime(1500);
+    ui->LEDSDC->SetUpdateTime(1500);
+    ui->LEDMSC->SetUpdateTime(1500);
+    ui->LEDFrameSync->SetUpdateTime(600);
+    ui->LEDTimeSync->SetUpdateTime(600);
+    ui->LEDIOInterface->SetUpdateTime(2000); /* extra long -> red light stays long */
+}
+
+DRMDetail::~DRMDetail()
+{
+    delete ui;
+}
+
+void DRMDetail::setLEDFAC(ETypeRxStatus status)
+{
+    SetStatus(ui->LEDFAC, status);
+}
+
+void DRMDetail::setLEDSDC(ETypeRxStatus status)
+{
+    SetStatus(ui->LEDSDC, status);
+}
+
+void DRMDetail::setLEDMSC(ETypeRxStatus status)
+{
+    SetStatus(ui->LEDMSC, status);
+}
+
+void DRMDetail::setLEDFrameSync(ETypeRxStatus status)
+{
+    SetStatus(ui->LEDFrameSync, status);
+}
+
+void DRMDetail::setLEDTimeSync(ETypeRxStatus status)
+{
+    SetStatus(ui->LEDTimeSync, status);
+}
+
+void DRMDetail::setLEDIOInterface(ETypeRxStatus status)
+{
+    SetStatus(ui->LEDIOInterface, status);
+}
+
+void DRMDetail::setNumServices(int aud, int data)
+{
+    QString strFACInfo;
+    strFACInfo = tr("Audio: ");
+    if(aud>=0)
+        strFACInfo += QString().setNum(aud);
+    else
+        strFACInfo += "-";
+    strFACInfo += tr(" / Data: ");
+    if(data>=0)
+        strFACInfo += QString().setNum(data);
+    else
+        strFACInfo += "-";
+    ui->FACNumServicesV->setText(strFACInfo);
+}
+
+void DRMDetail::setSNR(double rSNR)
+{
+    if (rSNR >= 0.0)
+    {
+        /* SNR */
+        ui->ValueSNR->setText("<b>" +
+                          QString().setNum(rSNR, 'f', 1) + " dB</b>");
+    }
+    else
+    {
+        ui->ValueSNR->setText("<b>---</b>");
+    }
+}
+
+void DRMDetail::setMER(double rMER, double rWMERMSC)
+{
+    if (rMER >= 0.0 )
+    {
+        ui->ValueMERWMER->setText(QString().
+                              setNum(rWMERMSC, 'f', 1) + " dB / "
+                              + QString().setNum(rMER, 'f', 1) + " dB");
+    }
+    else
+    {
+        ui->ValueMERWMER->setText("---");
+    }
+}
+
+void DRMDetail::setDelay_Doppler(double rSigmaEstimate, double rMinDelay)
+{
+    /* Doppler estimation (assuming Gaussian doppler spectrum) */
+    if (rSigmaEstimate >= 0.0)
+    {
+        /* Plot delay and Doppler values */
+        ui->ValueWiener->setText(
+                    QString("%1 Hz / %2 ms")
+                    .arg(rSigmaEstimate, 0, 'f', 2)
+                    .arg(rMinDelay, 0, 'f', 2)
+        );
+    }
+    else
+    {
+        /* Plot only delay, Doppler not available */
+        ui->ValueWiener->setText("--- / "
+                             + QString().setNum(rMinDelay, 'f', 2) + " ms");
+    }
+}
+
+void DRMDetail::setSampleFrequencyOffset(double rCurSamROffs, double rSampleRate)
+{
+    /* Display value in [Hz] and [ppm] (parts per million) */
+    ui->ValueSampFreqOffset->setText(
+                QString("%1 Hz (%2 ppm)")
+                    .arg(rCurSamROffs, 0, 'f', 2)
+                    .arg((int) (rCurSamROffs / rSampleRate * 1e6))
+                );
+}
+
+void DRMDetail::setFrequencyOffset(double rOffset)
+{
+    if(rOffset<0.0)
+        ui->ValueFreqOffset->setText("---");
+    else
+        ui->ValueFreqOffset->setText(QString().setNum(rOffset, 'f', 2) + " Hz");
+}
+
+void DRMDetail::setChannel(ERobMode robm, ESpecOcc specocc, ESymIntMod eSymbolInterlMode, ECodScheme eSDCCodingScheme, ECodScheme eMSCCodingScheme)
+{
+    QString strFACInfo;
+    ERobMode er = robm;
+    if(specocc == SO_6)
+        er = RM_ROBUSTNESS_MODE_E;
+
+    ui->FACDRMModeBWV->setText(GetRobModeStr(er) + " / " + GetSpecOccStr(specocc));
+
+    /* Interleaver Depth #################### */
+    switch (eSymbolInterlMode)
+    {
+    case SI_LONG:
+        strFACInfo = tr("2 s (Long Interleaving)");
+        break;
+
+    case SI_SHORT:
+        strFACInfo = tr("400 ms (Short Interleaving)");
+        break;
+    case SI_MODE_E:
+        strFACInfo = tr("600 ms");
+        break;
+
+    default:
+        strFACInfo = "?";
+    }
+
+    ui->FACInterleaverDepthV->setText(strFACInfo);
+
+
+    /* SDC, MSC mode #################### */
+    /* SDC */
+    switch (eSDCCodingScheme)
+    {
+    case CS_1_SM:
+        strFACInfo = "4-QAM / ";
+        break;
+
+    case CS_2_SM:
+        strFACInfo = "16-QAM / ";
+        break;
+
+    default:
+        strFACInfo = "? / ?";
+    }
+
+    /* MSC */
+    switch (eMSCCodingScheme)
+    {
+    case CS_2_SM:
+        strFACInfo += "SM 16-QAM";
+        break;
+
+    case CS_3_SM:
+        strFACInfo += "SM 64-QAM";
+        break;
+
+    case CS_3_HMSYM:
+        strFACInfo += "HMsym 64-QAM";
+        break;
+
+    case CS_3_HMMIX:
+        strFACInfo += "HMmix 64-QAM";
+        break;
+
+    default:
+        strFACInfo += "?";
+    }
+
+    ui->FACSDCMSCModeV->setText(strFACInfo); /* Value */
+}
+
+void DRMDetail::setCodeRate(int iPartB, int iPartA)
+{
+    if(iPartB<0)
+        ui->FACCodeRateV->setText("-----");
+    else
+        ui->FACCodeRateV->setText(QString("%1 / %2").arg(iPartB).arg(iPartA));
+}
+
+QString	DRMDetail::GetRobModeStr(ERobMode e)
+{
+    switch (e)
+    {
+    case RM_ROBUSTNESS_MODE_A:
+        return "A";
+        break;
+
+    case RM_ROBUSTNESS_MODE_B:
+        return "B";
+        break;
+
+    case RM_ROBUSTNESS_MODE_C:
+        return "C";
+        break;
+
+    case RM_ROBUSTNESS_MODE_D:
+        return "D";
+        break;
+
+    case RM_ROBUSTNESS_MODE_E:
+        return "E";
+        break;
+
+    default:
+        return "?";
+    }
+}
+
+QString	DRMDetail::GetSpecOccStr(ESpecOcc e)
+{
+    switch (e)
+    {
+    case SO_0:
+        return "4.5 kHz";
+        break;
+
+    case SO_1:
+        return "5 kHz";
+        break;
+
+    case SO_2:
+        return "9 kHz";
+        break;
+
+    case SO_3:
+        return "10 kHz";
+        break;
+
+    case SO_4:
+        return "18 kHz";
+        break;
+
+    case SO_5:
+        return "20 kHz";
+        break;
+
+    case SO_6:
+        return "100 kHz";
+        break;
+
+    default:
+        return "?";
+    }
+}
+
+void DRMDetail::hideMSCParams(bool h)
+{
+    if(h)
+    {
+        ui->LEDMSC->hide();
+        ui->TextLabelLEDMSCCRC->hide();
+        ui->FACNumServicesL->hide();
+        ui->FACNumServicesV->hide();
+    }
+    else
+    {
+        ui->LEDMSC->show();
+        ui->TextLabelLEDMSCCRC->show();
+        ui->FACNumServicesL->show();
+        ui->FACNumServicesV->show();
+    }
+}
+
+void DRMDetail::AddWhatsThisHelp()
+{
+    /*
+        This text was taken from the only documentation of Dream software
+    */
+    /* DC Frequency Offset */
+    const QString strDCFreqOffs =
+        tr("<b>DC Frequency Offset:</b> This is the "
+           "estimation of the DC frequency offset. This offset corresponds "
+           "to the resulting sound card intermedia frequency of the front-end. "
+           "This frequency is not restricted to a certain value. The only "
+           "restriction is that the DRM spectrum must be completely inside the "
+           "bandwidth of the sound card.");
+
+    ui->TextFreqOffset->setWhatsThis(strDCFreqOffs);
+    ui->ValueFreqOffset->setWhatsThis(strDCFreqOffs);
+
+    /* Sample Frequency Offset */
+    const QString strFreqOffset =
+        tr("<b>Sample Frequency Offset:</b> This is the "
+           "estimation of the sample rate offset between the sound card sample "
+           "rate of the local computer and the sample rate of the D / A (digital "
+           "to analog) converter in the transmitter. Usually the sample rate "
+           "offset is very constant for a given sound card. Therefore it is "
+           "useful to inform the Dream software about this value at application "
+           "startup to increase the acquisition speed and reliability.");
+
+    ui->TextSampFreqOffset->setWhatsThis(strFreqOffset);
+    ui->ValueSampFreqOffset->setWhatsThis(strFreqOffset);
+
+    /* Doppler / Delay */
+    const QString strDopplerDelay =
+        tr("<b>Doppler / Delay:</b> The Doppler frequency "
+           "of the channel is estimated for the Wiener filter design of channel "
+           "estimation in time direction. If linear interpolation is set for "
+           "channel estimation in time direction, this estimation is not updated. "
+           "The Doppler frequency is an indication of how fast the channel varies "
+           "with time. The higher the frequency, the faster the channel changes "
+           "are.<br>The total delay of the Power Delay Spectrum "
+           "(PDS) is estimated from the impulse response estimation derived from "
+           "the channel estimation. This delay corresponds to the range between "
+           "the two vertical dashed black lines in the Impulse Response (IR) "
+           "plot.");
+
+    ui->TextWiener->setWhatsThis(strDopplerDelay);
+    ui->ValueWiener->setWhatsThis(strDopplerDelay);
+
+    /* I / O Interface LED */
+    const QString strLEDIOInterface =
+        tr("<b>I / O Interface LED:</b> This LED shows the "
+           "current status of the sound card interface. The yellow light shows "
+           "that the audio output was corrected. Since the sample rate of the "
+           "transmitter and local computer are different, from time to time the "
+           "audio buffers will overflow or under run and a correction is "
+           "necessary. When a correction occurs, a \"click\" sound can be heard. "
+           "The red light shows that a buffer was lost in the sound card input "
+           "stream. This can happen if a thread with a higher priority is at "
+           "100% and the Dream software cannot read the provided blocks fast "
+           "enough. In this case, the Dream software will instantly loose the "
+           "synchronization and has to re-synchronize. Another reason for red "
+           "light is that the processor is too slow for running the Dream "
+           "software.");
+
+    ui->TextLabelLEDIOInterface->setWhatsThis(strLEDIOInterface);
+    ui->LEDIOInterface->setWhatsThis(strLEDIOInterface);
+
+    /* Time Sync Acq LED */
+    const QString strLEDTimeSyncAcq =
+        tr("<b>Time Sync Acq LED:</b> This LED shows the "
+           "state of the timing acquisition (search for the beginning of an OFDM "
+           "symbol). If the acquisition is done, this LED will stay green.");
+
+    ui->TextLabelLEDTimeSyncAcq->setWhatsThis(strLEDTimeSyncAcq);
+    ui->LEDTimeSync->setWhatsThis(strLEDTimeSyncAcq);
+
+    /* Frame Sync LED */
+    const QString strLEDFrameSync =
+        tr("<b>Frame Sync LED:</b> The DRM frame "
+           "synchronization status is shown with this LED. This LED is also only "
+           "active during acquisition state of the Dream receiver. In tracking "
+           "mode, this LED is always green.");
+
+    ui->TextLabelLEDFrameSync->setWhatsThis(strLEDFrameSync);
+    ui->LEDFrameSync->setWhatsThis(strLEDFrameSync);
+
+    /* FAC CRC LED */
+    const QString strLEDFACCRC =
+        tr("<b>FAC CRC LED:</b> This LED shows the Cyclic "
+           "Redundancy Check (CRC) of the Fast Access Channel (FAC) of DRM. FAC "
+           "is one of the three logical channels and is always modulated with a "
+           "4-QAM. If the FAC CRC check was successful, the receiver changes to "
+           "tracking mode. The FAC LED is the indication whether the receiver "
+           "is synchronized to a DRM transmission or not.<br>"
+           "The bandwidth of the DRM signal, the constellation scheme of MSC and "
+           "SDC channels and the interleaver depth are some of the parameters "
+           "which are provided by the FAC.");
+
+    ui->TextLabelLEDFACCRC->setWhatsThis(strLEDFACCRC);
+    ui->LEDFAC->setWhatsThis(strLEDFACCRC);
+
+    /* SDC CRC LED */
+    const QString strLEDSDCCRC =
+        tr("<b>SDC CRC LED:</b> This LED shows the CRC "
+           "check result of the Service Description Channel (SDC) which is one "
+           "logical channel of the DRM stream. This data is transmitted in "
+           "approx. 1 second intervals and contains information about station "
+           "label, audio and data format, etc. The error protection is normally "
+           "lower than the protection of the FAC. Therefore this LED will turn "
+           "to red earlier than the FAC LED in general.<br>If the CRC check "
+           "is ok but errors in the content were detected, the LED turns "
+           "yellow.");
+
+    ui->TextLabelLEDSDCCRC->setWhatsThis(strLEDSDCCRC);
+    ui->LEDSDC->setWhatsThis(strLEDSDCCRC);
+
+    /* SNR */
+    const QString strSNREst =
+        tr("<b>SNR:</b> Signal to Noise Ratio (SNR) "
+           "estimation based on FAC cells. Since the FAC cells are only "
+           "located approximately in the region 0-5 kHz relative to the DRM DC "
+           "frequency, it may happen that the SNR value is very high "
+           "although the DRM spectrum on the left side of the DRM DC frequency "
+           "is heavily distorted or disturbed by an interferer so that the true "
+           "overall SNR is lower as indicated by the SNR value. Similarly, "
+           "the SNR value might show a very low value but audio can still be "
+           "decoded if only the right side of the DRM spectrum is degraded "
+           "by an interferer.");
+
+    ui->ValueSNR->setWhatsThis(strSNREst);
+    ui->TextSNRText->setWhatsThis(strSNREst);
+
+    /* MSC WMER / MSC MER */
+    const QString strMERWMEREst =
+        tr("<b>MSC WMER / MSC MER:</b> Modulation Error Ratio (MER) and "
+           "weighted MER (WMER) calculated on the MSC cells is shown. The MER is "
+           "calculated as follows: For each equalized MSC cell (only MSC cells, "
+           "no FAC cells, no SDC cells, no pilot cells), the error vector from "
+           "the nearest ideal point of the constellation diagram is measured. The "
+           "squared magnitude of this error is found, and a mean of the squared "
+           "errors is calculated (over one frame). The MER is the ratio in [dB] "
+           "of the mean of the squared magnitudes of the ideal points of the "
+           "constellation diagram to the mean squared error. This gives an "
+           "estimate of the ratio of the total signal power to total noise "
+           "power at the input to the equalizer for channels with flat frequency "
+           "response.<br> In case of the WMER, the calculations of the means are "
+           "multiplied by the squared magnitude of the estimated channel "
+           "response.<br>For more information see ETSI TS 102 349.");
+
+    ui->ValueMERWMER->setWhatsThis(strMERWMEREst);
+    ui->TextMERWMER->setWhatsThis(strMERWMEREst);
+
+    /* DRM Mode / Bandwidth */
+    const QString strRobustnessMode =
+        tr("<b>DRM Mode / Bandwidth:</b> In a DRM system, "
+           "four possible robustness modes are defined to adapt the system to "
+           "different channel conditions. According to the DRM standard:<ul>"
+           "<li><i>Mode A:</i> Gaussian channels, with "
+           "minor fading</li><li><i>Mode B:</i> Time "
+           "and frequency selective channels, with longer delay spread</li>"
+           "<li><i>Mode C:</i> As robustness mode B, but "
+           "with higher Doppler spread</li>"
+           "<li><i>Mode D:</i> As robustness mode B, but "
+           "with severe delay and Doppler spread</li></ul>The "
+           "bandwith is the gross bandwidth of the current DRM signal");
+
+    ui->FACDRMModeBWL->setWhatsThis(strRobustnessMode);
+    ui->FACDRMModeBWV->setWhatsThis(strRobustnessMode);
+
+    /* Interleaver Depth */
+    const QString strInterleaver =
+        tr("<b>Interleaver Depth:</b> The symbol "
+           "interleaver depth can be either short (approx. 400 ms) or long "
+           "(approx. 2 s). The longer the interleaver the better the channel "
+           "decoder can correct errors from slow fading signals. But the "
+           "longer the interleaver length the longer the delay until (after a "
+           "re-synchronization) audio can be heard.");
+
+    ui->FACInterleaverDepthL->setWhatsThis(strInterleaver);
+    ui->FACInterleaverDepthV->setWhatsThis(strInterleaver);
+
+    /* SDC / MSC Mode */
+    const QString strSDCMSCMode =
+        tr("<b>SDC / MSC Mode:</b> Shows the modulation "
+           "type of the SDC and MSC channel. For the MSC channel, some "
+           "hierarchical modes are defined which can provide a very strong "
+           "protected service channel.");
+
+    ui->FACSDCMSCModeL->setWhatsThis(strSDCMSCMode);
+    ui->FACSDCMSCModeV->setWhatsThis(strSDCMSCMode);
+
+    /* Prot. Level (B/A) */
+    const QString strProtLevel =
+        tr("<b>Prot. Level (B/A):</b> The error protection "
+           "level of the channel coder. For 64-QAM, there are four protection "
+           "levels defined in the DRM standard. Protection level 0 has the "
+           "highest protection whereas level 3 has the lowest protection. The "
+           "letters A and B are the names of the higher and lower protected parts "
+           "of a DRM block when Unequal Error Protection (UEP) is used. If Equal "
+           "Error Protection (EEP) is used, only the protection level of part B "
+           "is valid.");
+
+    ui->FACCodeRateL->setWhatsThis(strProtLevel);
+    ui->FACCodeRateV->setWhatsThis(strProtLevel);
+
+}
diff --git a/src/GUI-QT/drmdetail.h b/src/GUI-QT/drmdetail.h
new file mode 100644
index 0000000..573332c
--- /dev/null
+++ b/src/GUI-QT/drmdetail.h
@@ -0,0 +1,45 @@
+#ifndef DRMDETAIL_H
+#define DRMDETAIL_H
+
+#include <QWidget>
+#include <../Parameter.h>
+#include "MultColorLED.h"
+
+namespace Ui {
+class DRMDetail;
+}
+
+class DRMDetail : public QWidget
+{
+    Q_OBJECT
+
+public:
+    explicit DRMDetail(QWidget *parent = 0);
+    ~DRMDetail();
+    void updateDisplay(CParameter& Parameters, _REAL freqOffset, EAcqStat acqState, bool rsciMode);
+    void hideMSCParams(bool);
+
+public slots:
+    void setLEDFAC(ETypeRxStatus);
+    void setLEDSDC(ETypeRxStatus status);
+    void setLEDMSC(ETypeRxStatus status);
+    void setLEDFrameSync(ETypeRxStatus status);
+    void setLEDTimeSync(ETypeRxStatus status);
+    void setLEDIOInterface(ETypeRxStatus status);
+    void setNumServices(int, int);
+    void setSNR(double rSNR);
+    void setMER(double rMER, double rWMERMSC);
+    void setDelay_Doppler(double rSigmaEstimate, double rMinDelay);
+    void setSampleFrequencyOffset(double rCurSamROffs, double rSampleRate);
+    void setFrequencyOffset(double);
+    void setChannel(ERobMode, ESpecOcc, ESymIntMod, ECodScheme, ECodScheme);
+    void setCodeRate(int iPartB, int iPartA);
+
+private:
+    Ui::DRMDetail *ui;
+    QString	GetRobModeStr(ERobMode e);
+    QString	GetSpecOccStr(ESpecOcc e);
+    void AddWhatsThisHelp();
+};
+
+#endif // DRMDETAIL_H
diff --git a/src/GUI-QT/drmdetail.ui b/src/GUI-QT/drmdetail.ui
new file mode 100644
index 0000000..aaf9cd3
--- /dev/null
+++ b/src/GUI-QT/drmdetail.ui
@@ -0,0 +1,881 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>DRMDetail</class>
+ <widget class="QWidget" name="DRMDetail">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>656</width>
+    <height>158</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Form</string>
+  </property>
+  <layout class="QGridLayout" name="gridLayout">
+   <property name="leftMargin">
+    <number>0</number>
+   </property>
+   <property name="topMargin">
+    <number>0</number>
+   </property>
+   <property name="rightMargin">
+    <number>0</number>
+   </property>
+   <property name="bottomMargin">
+    <number>0</number>
+   </property>
+   <item row="0" column="2">
+    <widget class="QFrame" name="FrameFACParams">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
+     </property>
+     <property name="frameShape">
+      <enum>QFrame::Box</enum>
+     </property>
+     <property name="frameShadow">
+      <enum>QFrame::Sunken</enum>
+     </property>
+     <layout class="QHBoxLayout" name="_13">
+      <property name="spacing">
+       <number>6</number>
+      </property>
+      <property name="leftMargin">
+       <number>6</number>
+      </property>
+      <property name="topMargin">
+       <number>4</number>
+      </property>
+      <property name="rightMargin">
+       <number>6</number>
+      </property>
+      <property name="bottomMargin">
+       <number>4</number>
+      </property>
+      <item>
+       <layout class="QVBoxLayout" name="_14">
+        <property name="spacing">
+         <number>0</number>
+        </property>
+        <property name="leftMargin">
+         <number>0</number>
+        </property>
+        <property name="topMargin">
+         <number>0</number>
+        </property>
+        <property name="rightMargin">
+         <number>0</number>
+        </property>
+        <property name="bottomMargin">
+         <number>0</number>
+        </property>
+        <item>
+         <widget class="QLabel" name="FACDRMModeBWL">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="text">
+           <string>DRM Mode / Bandwidth:</string>
+          </property>
+          <property name="wordWrap">
+           <bool>false</bool>
+          </property>
+          <property name="indent">
+           <number>-1</number>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QLabel" name="FACInterleaverDepthL">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="text">
+           <string>Interleaver Depth:</string>
+          </property>
+          <property name="wordWrap">
+           <bool>false</bool>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QLabel" name="FACSDCMSCModeL">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="text">
+           <string>SDC / MSC Mode:</string>
+          </property>
+          <property name="wordWrap">
+           <bool>false</bool>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QLabel" name="FACCodeRateL">
+          <property name="text">
+           <string>Prot. Level (B/A):</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QLabel" name="FACNumServicesL">
+          <property name="text">
+           <string>Number of Services:</string>
+          </property>
+         </widget>
+        </item>
+       </layout>
+      </item>
+      <item>
+       <layout class="QVBoxLayout" name="_15">
+        <property name="spacing">
+         <number>0</number>
+        </property>
+        <property name="leftMargin">
+         <number>0</number>
+        </property>
+        <property name="topMargin">
+         <number>0</number>
+        </property>
+        <property name="rightMargin">
+         <number>0</number>
+        </property>
+        <property name="bottomMargin">
+         <number>0</number>
+        </property>
+        <item>
+         <widget class="QLabel" name="FACDRMModeBWV">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="text">
+           <string>FACDRMModeBWV</string>
+          </property>
+          <property name="wordWrap">
+           <bool>false</bool>
+          </property>
+          <property name="indent">
+           <number>-1</number>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QLabel" name="FACInterleaverDepthV">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="text">
+           <string>FACInterleaverDepthV</string>
+          </property>
+          <property name="wordWrap">
+           <bool>false</bool>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QLabel" name="FACSDCMSCModeV">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="text">
+           <string>FACSDCMSCModeV</string>
+          </property>
+          <property name="wordWrap">
+           <bool>false</bool>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QLabel" name="FACCodeRateV">
+          <property name="text">
+           <string>TextLabel</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QLabel" name="FACNumServicesV">
+          <property name="text">
+           <string>TextLabel</string>
+          </property>
+         </widget>
+        </item>
+       </layout>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item row="0" column="0">
+    <widget class="QFrame" name="FrameSignalValues">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
+     </property>
+     <property name="frameShape">
+      <enum>QFrame::Box</enum>
+     </property>
+     <property name="frameShadow">
+      <enum>QFrame::Sunken</enum>
+     </property>
+     <layout class="QHBoxLayout" name="_2">
+      <property name="spacing">
+       <number>6</number>
+      </property>
+      <property name="leftMargin">
+       <number>6</number>
+      </property>
+      <property name="topMargin">
+       <number>4</number>
+      </property>
+      <property name="rightMargin">
+       <number>6</number>
+      </property>
+      <property name="bottomMargin">
+       <number>4</number>
+      </property>
+      <item>
+       <layout class="QVBoxLayout" name="_3">
+        <property name="spacing">
+         <number>6</number>
+        </property>
+        <property name="leftMargin">
+         <number>0</number>
+        </property>
+        <property name="topMargin">
+         <number>0</number>
+        </property>
+        <property name="rightMargin">
+         <number>0</number>
+        </property>
+        <property name="bottomMargin">
+         <number>0</number>
+        </property>
+        <item>
+         <widget class="QLabel" name="TextSNRText">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="minimumSize">
+           <size>
+            <width>0</width>
+            <height>0</height>
+           </size>
+          </property>
+          <property name="text">
+           <string>SNR:</string>
+          </property>
+          <property name="wordWrap">
+           <bool>false</bool>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QLabel" name="TextMERWMER">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="minimumSize">
+           <size>
+            <width>0</width>
+            <height>0</height>
+           </size>
+          </property>
+          <property name="text">
+           <string>MSC WMER / MSC MER:</string>
+          </property>
+          <property name="wordWrap">
+           <bool>false</bool>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QLabel" name="TextFreqOffset">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="minimumSize">
+           <size>
+            <width>0</width>
+            <height>0</height>
+           </size>
+          </property>
+          <property name="text">
+           <string>DC Frequency of DRM Signal:</string>
+          </property>
+          <property name="wordWrap">
+           <bool>false</bool>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QLabel" name="TextSampFreqOffset">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="text">
+           <string>Sample Frequency Offset:</string>
+          </property>
+          <property name="wordWrap">
+           <bool>false</bool>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QLabel" name="TextWiener">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="minimumSize">
+           <size>
+            <width>0</width>
+            <height>0</height>
+           </size>
+          </property>
+          <property name="text">
+           <string>Doppler / Delay:</string>
+          </property>
+          <property name="wordWrap">
+           <bool>false</bool>
+          </property>
+         </widget>
+        </item>
+       </layout>
+      </item>
+      <item>
+       <layout class="QVBoxLayout" name="_4">
+        <property name="spacing">
+         <number>6</number>
+        </property>
+        <property name="leftMargin">
+         <number>0</number>
+        </property>
+        <property name="topMargin">
+         <number>0</number>
+        </property>
+        <property name="rightMargin">
+         <number>0</number>
+        </property>
+        <property name="bottomMargin">
+         <number>0</number>
+        </property>
+        <item>
+         <widget class="QLabel" name="ValueSNR">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="minimumSize">
+           <size>
+            <width>0</width>
+            <height>0</height>
+           </size>
+          </property>
+          <property name="text">
+           <string>SNR</string>
+          </property>
+          <property name="wordWrap">
+           <bool>false</bool>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QLabel" name="ValueMERWMER">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="minimumSize">
+           <size>
+            <width>0</width>
+            <height>0</height>
+           </size>
+          </property>
+          <property name="text">
+           <string>MER</string>
+          </property>
+          <property name="wordWrap">
+           <bool>false</bool>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QLabel" name="ValueFreqOffset">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="minimumSize">
+           <size>
+            <width>0</width>
+            <height>0</height>
+           </size>
+          </property>
+          <property name="text">
+           <string>FreqOffset</string>
+          </property>
+          <property name="wordWrap">
+           <bool>false</bool>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QLabel" name="ValueSampFreqOffset">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="text">
+           <string>SampFreqOffset</string>
+          </property>
+          <property name="wordWrap">
+           <bool>false</bool>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QLabel" name="ValueWiener">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="minimumSize">
+           <size>
+            <width>100</width>
+            <height>0</height>
+           </size>
+          </property>
+          <property name="text">
+           <string>Wiener</string>
+          </property>
+          <property name="wordWrap">
+           <bool>false</bool>
+          </property>
+         </widget>
+        </item>
+       </layout>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item row="0" column="1">
+    <widget class="QFrame" name="FrameStatusLEDs">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
+     </property>
+     <property name="frameShape">
+      <enum>QFrame::Box</enum>
+     </property>
+     <property name="frameShadow">
+      <enum>QFrame::Sunken</enum>
+     </property>
+     <layout class="QVBoxLayout" name="verticalLayout">
+      <item>
+       <layout class="QHBoxLayout" name="horizontalLayout">
+        <item>
+         <widget class="QLabel" name="TextLabelLEDMSCCRC">
+          <property name="text">
+           <string>MSC CRC:</string>
+          </property>
+          <property name="alignment">
+           <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="CMultColorLED" name="LEDMSC" native="true">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="minimumSize">
+           <size>
+            <width>13</width>
+            <height>13</height>
+           </size>
+          </property>
+         </widget>
+        </item>
+       </layout>
+      </item>
+      <item>
+       <layout class="QHBoxLayout" name="_8">
+        <property name="spacing">
+         <number>6</number>
+        </property>
+        <property name="leftMargin">
+         <number>0</number>
+        </property>
+        <property name="topMargin">
+         <number>0</number>
+        </property>
+        <property name="rightMargin">
+         <number>0</number>
+        </property>
+        <property name="bottomMargin">
+         <number>0</number>
+        </property>
+        <item>
+         <widget class="QLabel" name="TextLabelLEDSDCCRC">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Minimum" vsizetype="Maximum">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="text">
+           <string>SDC CRC:</string>
+          </property>
+          <property name="alignment">
+           <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+          </property>
+          <property name="wordWrap">
+           <bool>false</bool>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="CMultColorLED" name="LEDSDC" native="true">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="minimumSize">
+           <size>
+            <width>13</width>
+            <height>13</height>
+           </size>
+          </property>
+          <property name="maximumSize">
+           <size>
+            <width>13</width>
+            <height>13</height>
+           </size>
+          </property>
+         </widget>
+        </item>
+       </layout>
+      </item>
+      <item>
+       <layout class="QHBoxLayout" name="_9">
+        <property name="spacing">
+         <number>6</number>
+        </property>
+        <property name="leftMargin">
+         <number>0</number>
+        </property>
+        <property name="topMargin">
+         <number>0</number>
+        </property>
+        <property name="rightMargin">
+         <number>0</number>
+        </property>
+        <property name="bottomMargin">
+         <number>0</number>
+        </property>
+        <item>
+         <widget class="QLabel" name="TextLabelLEDFACCRC">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Minimum" vsizetype="Maximum">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="text">
+           <string>FAC CRC:</string>
+          </property>
+          <property name="alignment">
+           <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+          </property>
+          <property name="wordWrap">
+           <bool>false</bool>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="CMultColorLED" name="LEDFAC" native="true">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="minimumSize">
+           <size>
+            <width>13</width>
+            <height>13</height>
+           </size>
+          </property>
+          <property name="maximumSize">
+           <size>
+            <width>13</width>
+            <height>13</height>
+           </size>
+          </property>
+         </widget>
+        </item>
+       </layout>
+      </item>
+      <item>
+       <layout class="QHBoxLayout" name="_10">
+        <property name="spacing">
+         <number>6</number>
+        </property>
+        <property name="leftMargin">
+         <number>0</number>
+        </property>
+        <property name="topMargin">
+         <number>0</number>
+        </property>
+        <property name="rightMargin">
+         <number>0</number>
+        </property>
+        <property name="bottomMargin">
+         <number>0</number>
+        </property>
+        <item>
+         <widget class="QLabel" name="TextLabelLEDFrameSync">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Minimum" vsizetype="Maximum">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="text">
+           <string>Frame Sync:</string>
+          </property>
+          <property name="alignment">
+           <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+          </property>
+          <property name="wordWrap">
+           <bool>false</bool>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="CMultColorLED" name="LEDFrameSync" native="true">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="minimumSize">
+           <size>
+            <width>13</width>
+            <height>13</height>
+           </size>
+          </property>
+          <property name="maximumSize">
+           <size>
+            <width>13</width>
+            <height>13</height>
+           </size>
+          </property>
+         </widget>
+        </item>
+       </layout>
+      </item>
+      <item>
+       <layout class="QHBoxLayout" name="_11">
+        <property name="spacing">
+         <number>6</number>
+        </property>
+        <property name="leftMargin">
+         <number>0</number>
+        </property>
+        <property name="topMargin">
+         <number>0</number>
+        </property>
+        <property name="rightMargin">
+         <number>0</number>
+        </property>
+        <property name="bottomMargin">
+         <number>0</number>
+        </property>
+        <item>
+         <widget class="QLabel" name="TextLabelLEDTimeSyncAcq">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Minimum" vsizetype="Maximum">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="text">
+           <string>Time Sync Acq:</string>
+          </property>
+          <property name="alignment">
+           <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+          </property>
+          <property name="wordWrap">
+           <bool>false</bool>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="CMultColorLED" name="LEDTimeSync" native="true">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="minimumSize">
+           <size>
+            <width>13</width>
+            <height>13</height>
+           </size>
+          </property>
+          <property name="maximumSize">
+           <size>
+            <width>13</width>
+            <height>13</height>
+           </size>
+          </property>
+         </widget>
+        </item>
+       </layout>
+      </item>
+      <item>
+       <layout class="QHBoxLayout" name="_12">
+        <property name="spacing">
+         <number>6</number>
+        </property>
+        <property name="leftMargin">
+         <number>0</number>
+        </property>
+        <property name="topMargin">
+         <number>0</number>
+        </property>
+        <property name="rightMargin">
+         <number>0</number>
+        </property>
+        <property name="bottomMargin">
+         <number>0</number>
+        </property>
+        <item>
+         <widget class="QLabel" name="TextLabelLEDIOInterface">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Minimum" vsizetype="Maximum">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="text">
+           <string>I/O Interface:</string>
+          </property>
+          <property name="alignment">
+           <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+          </property>
+          <property name="wordWrap">
+           <bool>false</bool>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="CMultColorLED" name="LEDIOInterface" native="true">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="minimumSize">
+           <size>
+            <width>13</width>
+            <height>13</height>
+           </size>
+          </property>
+          <property name="maximumSize">
+           <size>
+            <width>13</width>
+            <height>13</height>
+           </size>
+          </property>
+         </widget>
+        </item>
+       </layout>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item row="0" column="3">
+    <spacer name="horizontalSpacer">
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <property name="sizeHint" stdset="0">
+      <size>
+       <width>40</width>
+       <height>20</height>
+      </size>
+     </property>
+    </spacer>
+   </item>
+  </layout>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>CMultColorLED</class>
+   <extends>QWidget</extends>
+   <header>MultColorLED.h</header>
+  </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/GUI-QT/drmdisplay.cpp b/src/GUI-QT/drmdisplay.cpp
new file mode 100644
index 0000000..4fc4b38
--- /dev/null
+++ b/src/GUI-QT/drmdisplay.cpp
@@ -0,0 +1,350 @@
+#include "drmdisplay.h"
+#include "ui_drmdisplay.h"
+#include <../util-QT/Util.h>
+
+DRMDisplay::DRMDisplay(QWidget *parent) :
+    QWidget(parent),
+    ui(new Ui::DRMDisplay)
+{
+    ui->setupUi(this);
+    /* Init progress bar for input signal level */
+#if QWT_VERSION < 0x060100
+    ui->ProgrInputLevel->setRange(-50.0, 0.0);
+    ui->ProgrInputLevel->setOrientation(Qt::Vertical, QwtThermo::LeftScale);
+#else
+    ui->ProgrInputLevel->setScale(-50.0, 0.0);
+    ui->ProgrInputLevel->setOrientation(Qt::Vertical);
+    ui->ProgrInputLevel->setScalePosition(QwtThermo::TrailingScale);
+#endif
+    ui->ProgrInputLevel->setAlarmLevel(-12.5);
+    QColor alarmColor(QColor(255, 0, 0));
+    QColor fillColor(QColor(0, 190, 0));
+#if QWT_VERSION < 0x060000
+    ui->ProgrInputLevel->setAlarmColor(alarmColor);
+    ui->ProgrInputLevel->setFillColor(fillColor);
+#else
+    QPalette newPalette = ui->ProgrInputLevel->palette();
+    newPalette.setColor(QPalette::Base, newPalette.color(QPalette::Window));
+    newPalette.setColor(QPalette::ButtonText, fillColor);
+    newPalette.setColor(QPalette::Highlight, alarmColor);
+    ui->ProgrInputLevel->setPalette(newPalette);
+#endif
+    /* Update times for color LEDs */
+    ui->CLED_FAC->SetUpdateTime(1500);
+    ui->CLED_SDC->SetUpdateTime(1500);
+    ui->CLED_MSC->SetUpdateTime(600);
+    AddWhatsThisHelp();
+}
+
+DRMDisplay::~DRMDisplay()
+{
+    delete ui;
+}
+
+void DRMDisplay::setBars(int bars)
+{
+    ui->onebar->setAutoFillBackground(bars>0);
+    ui->twobars->setAutoFillBackground(bars>1);
+    ui->threebars->setAutoFillBackground(bars>2);
+    ui->fourbars->setAutoFillBackground(bars>3);
+    ui->fivebars->setAutoFillBackground(bars>4);
+}
+
+void DRMDisplay::setLevel(_REAL level)
+{
+    /* Input level meter */
+    ui->ProgrInputLevel->setValue(level);
+}
+
+void DRMDisplay::showReceptionStatus(ETypeRxStatus fac, ETypeRxStatus sdc, ETypeRxStatus msc)
+{
+    SetStatus(ui->CLED_FAC, fac);
+    SetStatus(ui->CLED_SDC, sdc);
+    SetStatus(ui->CLED_MSC, msc);
+}
+
+void DRMDisplay::showTextMessage(const QString& textMessage)
+{
+    /* Activate text window */
+    ui->TextTextMessage->setEnabled(TRUE);
+
+    QString formattedMessage = "";
+    for (int i = 0; i < (int)textMessage.length(); i++)
+    {
+        switch (textMessage.at(i).unicode())
+        {
+        case 0x0A:
+            /* Code 0x0A may be inserted to indicate a preferred
+               line break */
+        case 0x1F:
+            /* Code 0x1F (hex) may be inserted to indicate a
+               preferred word break. This code may be used to
+                   display long words comprehensibly */
+            formattedMessage += "<br>";
+            break;
+
+        case 0x0B:
+            /* End of a headline */
+            formattedMessage = "<b><u>"
+                               + formattedMessage
+                               + "</u></b></center><br><center>";
+            break;
+
+        case '<':
+            formattedMessage += "<";
+            break;
+
+        case '>':
+            formattedMessage += ">";
+            break;
+
+        default:
+            formattedMessage += textMessage[int(i)];
+        }
+    }
+    Linkify(formattedMessage);
+    formattedMessage = "<center>" + formattedMessage + "</center>";
+    ui->TextTextMessage->setText(formattedMessage);
+
+}
+
+void DRMDisplay::showServiceInfo(const CService& service)
+{
+    /* Service label (UTF-8 encoded string -> convert) */
+    QString ServiceLabel(QString::fromUtf8(service.strLabel.c_str()));
+    ui->LabelServiceLabel->setText(ServiceLabel);
+
+    /* Service ID (plot number in hexadecimal format) */
+    const long iServiceID = (long) service.iServiceID;
+
+    if (iServiceID != 0)
+    {
+        ui->LabelServiceID->setText(QString("ID:%1").arg(iServiceID,4,16).toUpper());
+    }
+    else
+        ui->LabelServiceID->setText("");
+
+    /* Codec label */
+    ui->LabelCodec->setText(GetCodecString(service));
+
+    /* Type (Mono / Stereo) label */
+    ui->LabelStereoMono->setText(GetTypeString(service));
+
+    /* Language and program type labels (only for audio service) */
+    if (service.eAudDataFlag == CService::SF_AUDIO)
+    {
+        /* SDC Language */
+        const string strLangCode = service.strLanguageCode;
+
+        if ((!strLangCode.empty()) && (strLangCode != "---"))
+        {
+            ui->LabelLanguage->
+            setText(QString(GetISOLanguageName(strLangCode).c_str()));
+        }
+        else
+        {
+            /* FAC Language */
+            const int iLanguageID = service.iLanguage;
+
+            if ((iLanguageID > 0) &&
+                    (iLanguageID < LEN_TABLE_LANGUAGE_CODE))
+            {
+                ui->LabelLanguage->setText(
+                    strTableLanguageCode[iLanguageID].c_str());
+            }
+            else
+                ui->LabelLanguage->setText("");
+        }
+
+        /* Program type */
+        const int iProgrammTypeID = service.iServiceDescr;
+
+        if ((iProgrammTypeID > 0) &&
+                (iProgrammTypeID < LEN_TABLE_PROG_TYPE_CODE))
+        {
+            ui->LabelProgrType->setText(
+                strTableProgTypCod[iProgrammTypeID].c_str());
+        }
+        else
+            ui->LabelProgrType->setText("");
+    }
+
+    /* Country code */
+    const string strCntryCode = service.strCountryCode;
+
+    if ((!strCntryCode.empty()) && (strCntryCode != "--"))
+    {
+        ui->LabelCountryCode->
+        setText(QString(GetISOCountryName(strCntryCode).c_str()));
+    }
+    else
+        ui->LabelCountryCode->setText("");
+}
+
+/* Bit-rate */
+void
+DRMDisplay::setBitRate(_REAL rBitRate, _REAL rPartABLenRat)
+{
+    QString strBitrate = QString().setNum(rBitRate, 'f', 2) + tr(" kbps");
+
+    /* Equal or unequal error protection */
+    if (rPartABLenRat != (_REAL) 0.0)
+    {
+        /* Print out the percentage of part A length to total length */
+        strBitrate += " UEP (" +
+                      QString().setNum(rPartABLenRat * 100, 'f', 1) + " %)";
+    }
+    else
+    {
+        /* If part A is zero, equal error protection (EEP) is used */
+        strBitrate += " EEP";
+    }
+    ui->LabelBitrate->setText(strBitrate);
+
+}
+
+
+void
+DRMDisplay::clearDisplay(const QString& serviceLabel)
+{
+    ui->LabelServiceLabel->setText(serviceLabel);
+    ui->LabelBitrate->setText("");
+    ui->LabelCodec->setText("");
+    ui->LabelStereoMono->setText("");
+    ui->LabelProgrType->setText("");
+    ui->LabelLanguage->setText("");
+    ui->LabelCountryCode->setText("");
+    ui->LabelServiceID->setText("");
+}
+
+void DRMDisplay::SetDisplayColor(const QColor& newColor)
+{
+    /* Collect pointers to the desired controls in a vector */
+    vector<QWidget*> vecpWidgets;
+    vecpWidgets.push_back(ui->TextTextMessage);
+    vecpWidgets.push_back(ui->LabelBitrate);
+    vecpWidgets.push_back(ui->LabelCodec);
+    vecpWidgets.push_back(ui->LabelStereoMono);
+    vecpWidgets.push_back(ui->FrameAudioDataParams);
+    vecpWidgets.push_back(ui->LabelProgrType);
+    vecpWidgets.push_back(ui->LabelLanguage);
+    vecpWidgets.push_back(ui->LabelCountryCode);
+    vecpWidgets.push_back(ui->LabelServiceID);
+    vecpWidgets.push_back(ui->TextLabelInputLevel);
+    vecpWidgets.push_back(ui->ProgrInputLevel);
+    vecpWidgets.push_back(ui->CLED_FAC);
+    vecpWidgets.push_back(ui->CLED_SDC);
+    vecpWidgets.push_back(ui->CLED_MSC);
+    //vecpWidgets.push_back(ui->FrameMainDisplay);
+
+    for (size_t i = 0; i < vecpWidgets.size(); i++)
+    {
+        /* Request old palette */
+        QPalette CurPal(vecpWidgets[i]->palette());
+
+        /* Change colors */
+        if (vecpWidgets[i] != ui->TextTextMessage)
+        {
+            CurPal.setColor(QPalette::Active, QPalette::Text, newColor);
+            CurPal.setColor(QPalette::Active, QPalette::Foreground, newColor);
+            CurPal.setColor(QPalette::Inactive, QPalette::Text, newColor);
+            CurPal.setColor(QPalette::Inactive, QPalette::Foreground, newColor);
+        }
+        CurPal.setColor(QPalette::Active, QPalette::Button, newColor);
+        CurPal.setColor(QPalette::Active, QPalette::Light, newColor);
+        CurPal.setColor(QPalette::Active, QPalette::Dark, newColor);
+
+        CurPal.setColor(QPalette::Inactive, QPalette::Button, newColor);
+        CurPal.setColor(QPalette::Inactive, QPalette::Light, newColor);
+        CurPal.setColor(QPalette::Inactive, QPalette::Dark, newColor);
+
+        /* Special treatment for text message window */
+        if (vecpWidgets[i] == ui->TextTextMessage)
+        {
+            /* We need to specify special color for disabled */
+            CurPal.setColor(QPalette::Disabled, QPalette::Light, Qt::black);
+            CurPal.setColor(QPalette::Disabled, QPalette::Dark, Qt::black);
+        }
+
+        /* Set new palette */
+        vecpWidgets[i]->setPalette(CurPal);
+    }
+}
+
+
+
+void DRMDisplay::AddWhatsThisHelp()
+{
+    /*
+        This text was taken from the only documentation of Dream software
+    */
+    /* Text Message */
+    QString strTextMessage =
+        tr("<b>Text Message:</b> On the top right the text "
+           "message label is shown. This label only appears when an actual text "
+           "message is transmitted. If the current service does not transmit a "
+           "text message, the label will be disabled.");
+
+    /* Input Level */
+    const QString strInputLevel =
+        tr("<b>Input Level:</b> The input level meter shows "
+           "the relative input signal peak level in dB. If the level is too high, "
+           "the meter turns from green to red. The red region should be avoided "
+           "since overload causes distortions which degrade the reception "
+           "performance. Too low levels should be avoided too, since in this case "
+           "the Signal-to-Noise Ratio (SNR) degrades.");
+
+
+    /* Status LEDs */
+    const QString strStatusLEDS =
+        tr("<b>Status LEDs:</b> The three status LEDs show "
+           "the current CRC status of the three logical channels of a DRM stream. "
+           "These LEDs are the same as the top LEDs on the Evaluation Dialog.");
+
+
+    /* Station Label and Info Display */
+    const QString strStationLabelOther =
+        tr("<b>Station Label and Info Display:</b> In the "
+           "big label with the black background the station label and some other "
+           "information about the current selected service is displayed. The "
+           "magenta text on the top shows the bit-rate of the current selected "
+           "service (The abbreviations EEP and "
+           "UEP stand for Equal Error Protection and Unequal Error Protection. "
+           "UEP is a feature of DRM for a graceful degradation of the decoded "
+           "audio signal in case of a bad reception situation. UEP means that "
+           "some parts of the audio is higher protected and some parts are lower "
+           "protected (the ratio of higher protected part length to total length "
+           "is shown in the brackets)), the audio compression format "
+           "(e.g. AAC), if SBR is used and what audio mode is used (Mono, Stereo, "
+           "P-Stereo -> low-complexity or parametric stereo). In case SBR is "
+           "used, the actual sample rate is twice the sample rate of the core AAC "
+           "decoder. The next two types of information are the language and the "
+           "program type of the service (e.g. German / News).<br>The big "
+           "turquoise text in the middle is the station label. This label may "
+           "appear later than the magenta text since this information is "
+           "transmitted in a different logical channel of a DRM stream. On the "
+           "right, the ID number connected with this service is shown.");
+
+    ui->TextTextMessage->setWhatsThis(strTextMessage);
+    ui->TextLabelInputLevel->setWhatsThis(strInputLevel);
+    ui->ProgrInputLevel->setWhatsThis(strInputLevel);
+    ui->CLED_MSC->setWhatsThis(strStatusLEDS);
+    ui->CLED_SDC->setWhatsThis(strStatusLEDS);
+    ui->CLED_FAC->setWhatsThis(strStatusLEDS);
+    ui->LabelBitrate->setWhatsThis(strStationLabelOther);
+    ui->LabelCodec->setWhatsThis(strStationLabelOther);
+    ui->LabelStereoMono->setWhatsThis(strStationLabelOther);
+    ui->LabelServiceLabel->setWhatsThis(strStationLabelOther);
+    ui->LabelProgrType->setWhatsThis(strStationLabelOther);
+    ui->LabelServiceID->setWhatsThis(strStationLabelOther);
+    ui->LabelLanguage->setWhatsThis(strStationLabelOther);
+    ui->LabelCountryCode->setWhatsThis(strStationLabelOther);
+    ui->FrameAudioDataParams->setWhatsThis(strStationLabelOther);
+
+    const QString strBars = tr("from 1 to 5 bars indicates WMER in the range 8 to 24 dB");
+    ui->onebar->setWhatsThis(strBars);
+    ui->twobars->setWhatsThis(strBars);
+    ui->threebars->setWhatsThis(strBars);
+    ui->fourbars->setWhatsThis(strBars);
+    ui->fivebars->setWhatsThis(strBars);
+}
diff --git a/src/GUI-QT/drmdisplay.h b/src/GUI-QT/drmdisplay.h
new file mode 100644
index 0000000..50924cf
--- /dev/null
+++ b/src/GUI-QT/drmdisplay.h
@@ -0,0 +1,33 @@
+#ifndef DRMDISPLAY_H
+#define DRMDISPLAY_H
+
+#include <QWidget>
+#include <../Parameter.h>
+#include <MultColorLED.h>
+
+namespace Ui {
+class DRMDisplay;
+}
+
+class DRMDisplay : public QWidget
+{
+    Q_OBJECT
+
+public:
+    explicit DRMDisplay(QWidget *parent = 0);
+    ~DRMDisplay();
+    void setBars(int);
+    void setLevel(_REAL);
+    void showReceptionStatus(ETypeRxStatus fac, ETypeRxStatus sdc, ETypeRxStatus msc);
+    void showTextMessage(const QString&);
+    void showServiceInfo(const CService&);
+    void setBitRate(_REAL rBitRate, _REAL rPartABLenRat);
+    void clearDisplay(const QString& serviceLabel);
+    void SetDisplayColor(const QColor&);
+
+private:
+    Ui::DRMDisplay *ui;
+    void AddWhatsThisHelp();
+};
+
+#endif // DRMDISPLAY_H
diff --git a/src/GUI-QT/drmdisplay.ui b/src/GUI-QT/drmdisplay.ui
new file mode 100644
index 0000000..42d2146
--- /dev/null
+++ b/src/GUI-QT/drmdisplay.ui
@@ -0,0 +1,9073 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>DRMDisplay</class>
+ <widget class="QWidget" name="DRMDisplay">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>466</width>
+    <height>170</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Form</string>
+  </property>
+  <layout class="QHBoxLayout" name="horizontalLayout_2">
+   <item>
+    <widget class="QFrame" name="FrameMainDisplay">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Expanding" vsizetype="Minimum">
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
+     </property>
+     <property name="palette">
+      <palette>
+       <active>
+        <colorrole role="WindowText">
+         <brush brushstyle="SolidPattern">
+          <color alpha="255">
+           <red>255</red>
+           <green>0</green>
+           <blue>0</blue>
+          </color>
+         </brush>
+        </colorrole>
+        <colorrole role="Button">
+         <brush brushstyle="SolidPattern">
+          <color alpha="255">
+           <red>255</red>
+           <green>0</green>
+           <blue>0</blue>
+          </color>
+         </brush>
+        </colorrole>
+        <colorrole role="Light">
+         <brush brushstyle="SolidPattern">
+          <color alpha="255">
+           <red>255</red>
+           <green>127</green>
+           <blue>127</blue>
+          </color>
+         </brush>
+        </colorrole>
+        <colorrole role="Midlight">
+         <brush brushstyle="SolidPattern">
+          <color alpha="255">
+           <red>255</red>
+           <green>63</green>
+           <blue>63</blue>
+          </color>
+         </brush>
+        </colorrole>
+        <colorrole role="Dark">
+         <brush brushstyle="SolidPattern">
+          <color alpha="255">
+           <red>127</red>
+           <green>0</green>
+           <blue>0</blue>
+          </color>
+         </brush>
+        </colorrole>
+        <colorrole role="Mid">
+         <brush brushstyle="SolidPattern">
+          <color alpha="255">
+           <red>170</red>
+           <green>0</green>
+           <blue>0</blue>
+          </color>
+         </brush>
+        </colorrole>
+        <colorrole role="Text">
+         <brush brushstyle="SolidPattern">
+          <color alpha="255">
+           <red>0</red>
+           <green>0</green>
+           <blue>0</blue>
+          </color>
+         </brush>
+        </colorrole>
+        <colorrole role="BrightText">
+         <brush brushstyle="SolidPattern">
+          <color alpha="255">
+           <red>255</red>
+           <green>255</green>
+           <blue>255</blue>
+          </color>
+         </brush>
+        </colorrole>
+        <colorrole role="ButtonText">
+         <brush brushstyle="SolidPattern">
+          <color alpha="255">
+           <red>0</red>
+           <green>0</green>
+           <blue>0</blue>
+          </color>
+         </brush>
+        </colorrole>
+        <colorrole role="Base">
+         <brush brushstyle="SolidPattern">
+          <color alpha="255">
+           <red>255</red>
+           <green>255</green>
+           <blue>255</blue>
+          </color>
+         </brush>
+        </colorrole>
+        <colorrole role="Window">
+         <brush brushstyle="SolidPattern">
+          <color alpha="255">
+           <red>0</red>
+           <green>0</green>
+           <blue>0</blue>
+          </color>
+         </brush>
+        </colorrole>
+        <colorrole role="Shadow">
+         <brush brushstyle="SolidPattern">
+          <color alpha="255">
+           <red>0</red>
+           <green>0</green>
+           <blue>0</blue>
+          </color>
+         </brush>
+        </colorrole>
+        <colorrole role="Highlight">
+         <brush brushstyle="SolidPattern">
+          <color alpha="255">
+           <red>0</red>
+           <green>0</green>
+           <blue>128</blue>
+          </color>
+         </brush>
+        </colorrole>
+        <colorrole role="HighlightedText">
+         <brush brushstyle="SolidPattern">
+          <color alpha="255">
+           <red>255</red>
+           <green>255</green>
+           <blue>255</blue>
+          </color>
+         </brush>
+        </colorrole>
+       </active>
+       <inactive>
+        <colorrole role="WindowText">
+         <brush brushstyle="SolidPattern">
+          <color alpha="255">
+           <red>255</red>
+           <green>0</green>
+           <blue>0</blue>
+          </color>
+         </brush>
+        </colorrole>
+        <colorrole role="Button">
+         <brush brushstyle="SolidPattern">
+          <color alpha="255">
+           <red>255</red>
+           <green>0</green>
+           <blue>0</blue>
+          </color>
+         </brush>
+        </colorrole>
+        <colorrole role="Light">
+         <brush brushstyle="SolidPattern">
+          <color alpha="255">
+           <red>255</red>
+           <green>127</green>
+           <blue>127</blue>
+          </color>
+         </brush>
+        </colorrole>
+        <colorrole role="Midlight">
+         <brush brushstyle="SolidPattern">
+          <color alpha="255">
+           <red>255</red>
+           <green>38</green>
+           <blue>38</blue>
+          </color>
+         </brush>
+        </colorrole>
+        <colorrole role="Dark">
+         <brush brushstyle="SolidPattern">
+          <color alpha="255">
+           <red>127</red>
+           <green>0</green>
+           <blue>0</blue>
+          </color>
+         </brush>
+        </colorrole>
+        <colorrole role="Mid">
+         <brush brushstyle="SolidPattern">
+          <color alpha="255">
+           <red>170</red>
+           <green>0</green>
+           <blue>0</blue>
+          </color>
+         </brush>
+        </colorrole>
+        <colorrole role="Text">
+         <brush brushstyle="SolidPattern">
+          <color alpha="255">
+           <red>0</red>
+           <green>0</green>
+           <blue>0</blue>
+          </color>
+         </brush>
+        </colorrole>
+        <colorrole role="BrightText">
+         <brush brushstyle="SolidPattern">
+          <color alpha="255">
+           <red>255</red>
+           <green>255</green>
+           <blue>255</blue>
+          </color>
+         </brush>
+        </colorrole>
+        <colorrole role="ButtonText">
+         <brush brushstyle="SolidPattern">
+          <color alpha="255">
+           <red>0</red>
+           <green>0</green>
+           <blue>0</blue>
+          </color>
+         </brush>
+        </colorrole>
+        <colorrole role="Base">
+         <brush brushstyle="SolidPattern">
+          <color alpha="255">
+           <red>255</red>
+           <green>255</green>
+           <blue>255</blue>
+          </color>
+         </brush>
+        </colorrole>
+        <colorrole role="Window">
+         <brush brushstyle="SolidPattern">
+          <color alpha="255">
+           <red>0</red>
+           <green>0</green>
+           <blue>0</blue>
+          </color>
+         </brush>
+        </colorrole>
+        <colorrole role="Shadow">
+         <brush brushstyle="SolidPattern">
+          <color alpha="255">
+           <red>0</red>
+           <green>0</green>
+           <blue>0</blue>
+          </color>
+         </brush>
+        </colorrole>
+        <colorrole role="Highlight">
+         <brush brushstyle="SolidPattern">
+          <color alpha="255">
+           <red>0</red>
+           <green>0</green>
+           <blue>128</blue>
+          </color>
+         </brush>
+        </colorrole>
+        <colorrole role="HighlightedText">
+         <brush brushstyle="SolidPattern">
+          <color alpha="255">
+           <red>255</red>
+           <green>255</green>
+           <blue>255</blue>
+          </color>
+         </brush>
+        </colorrole>
+       </inactive>
+       <disabled>
+        <colorrole role="WindowText">
+         <brush brushstyle="SolidPattern">
+          <color alpha="255">
+           <red>128</red>
+           <green>128</green>
+           <blue>128</blue>
+          </color>
+         </brush>
+        </colorrole>
+        <colorrole role="Button">
+         <brush brushstyle="SolidPattern">
+          <color alpha="255">
+           <red>255</red>
+           <green>0</green>
+           <blue>0</blue>
+          </color>
+         </brush>
+        </colorrole>
+        <colorrole role="Light">
+         <brush brushstyle="SolidPattern">
+          <color alpha="255">
+           <red>255</red>
+           <green>127</green>
+           <blue>127</blue>
+          </color>
+         </brush>
+        </colorrole>
+        <colorrole role="Midlight">
+         <brush brushstyle="SolidPattern">
+          <color alpha="255">
+           <red>255</red>
+           <green>38</green>
+           <blue>38</blue>
+          </color>
+         </brush>
+        </colorrole>
+        <colorrole role="Dark">
+         <brush brushstyle="SolidPattern">
+          <color alpha="255">
+           <red>127</red>
+           <green>0</green>
+           <blue>0</blue>
+          </color>
+         </brush>
+        </colorrole>
+        <colorrole role="Mid">
+         <brush brushstyle="SolidPattern">
+          <color alpha="255">
+           <red>170</red>
+           <green>0</green>
+           <blue>0</blue>
+          </color>
+         </brush>
+        </colorrole>
+        <colorrole role="Text">
+         <brush brushstyle="SolidPattern">
+          <color alpha="255">
+           <red>0</red>
+           <green>0</green>
+           <blue>0</blue>
+          </color>
+         </brush>
+        </colorrole>
+        <colorrole role="BrightText">
+         <brush brushstyle="SolidPattern">
+          <color alpha="255">
+           <red>255</red>
+           <green>255</green>
+           <blue>255</blue>
+          </color>
+         </brush>
+        </colorrole>
+        <colorrole role="ButtonText">
+         <brush brushstyle="SolidPattern">
+          <color alpha="255">
+           <red>128</red>
+           <green>128</green>
+           <blue>128</blue>
+          </color>
+         </brush>
+        </colorrole>
+        <colorrole role="Base">
+         <brush brushstyle="SolidPattern">
+          <color alpha="255">
+           <red>255</red>
+           <green>255</green>
+           <blue>255</blue>
+          </color>
+         </brush>
+        </colorrole>
+        <colorrole role="Window">
+         <brush brushstyle="SolidPattern">
+          <color alpha="255">
+           <red>0</red>
+           <green>0</green>
+           <blue>0</blue>
+          </color>
+         </brush>
+        </colorrole>
+        <colorrole role="Shadow">
+         <brush brushstyle="SolidPattern">
+          <color alpha="255">
+           <red>0</red>
+           <green>0</green>
+           <blue>0</blue>
+          </color>
+         </brush>
+        </colorrole>
+        <colorrole role="Highlight">
+         <brush brushstyle="SolidPattern">
+          <color alpha="255">
+           <red>0</red>
+           <green>0</green>
+           <blue>128</blue>
+          </color>
+         </brush>
+        </colorrole>
+        <colorrole role="HighlightedText">
+         <brush brushstyle="SolidPattern">
+          <color alpha="255">
+           <red>255</red>
+           <green>255</green>
+           <blue>255</blue>
+          </color>
+         </brush>
+        </colorrole>
+       </disabled>
+      </palette>
+     </property>
+     <property name="autoFillBackground">
+      <bool>true</bool>
+     </property>
+     <property name="frameShape">
+      <enum>QFrame::StyledPanel</enum>
+     </property>
+     <property name="frameShadow">
+      <enum>QFrame::Raised</enum>
+     </property>
+     <property name="lineWidth">
+      <number>1</number>
+     </property>
+     <layout class="QGridLayout" name="gridLayout">
+      <item row="0" column="1" rowspan="2">
+       <layout class="QVBoxLayout" name="_10">
+        <property name="spacing">
+         <number>1</number>
+        </property>
+        <property name="leftMargin">
+         <number>0</number>
+        </property>
+        <property name="topMargin">
+         <number>0</number>
+        </property>
+        <property name="rightMargin">
+         <number>0</number>
+        </property>
+        <property name="bottomMargin">
+         <number>0</number>
+        </property>
+        <item>
+         <widget class="QFrame" name="FrameAudioDataParams">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="palette">
+           <palette>
+            <active>
+             <colorrole role="WindowText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Button">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Light">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>127</green>
+                <blue>127</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Midlight">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>63</green>
+                <blue>63</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Dark">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>127</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Mid">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>170</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Text">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="BrightText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="ButtonText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Base">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Window">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Shadow">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Highlight">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>128</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="HighlightedText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+            </active>
+            <inactive>
+             <colorrole role="WindowText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Button">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Light">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>127</green>
+                <blue>127</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Midlight">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>38</green>
+                <blue>38</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Dark">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>127</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Mid">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>170</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Text">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="BrightText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="ButtonText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Base">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Window">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Shadow">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Highlight">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>128</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="HighlightedText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+            </inactive>
+            <disabled>
+             <colorrole role="WindowText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>128</red>
+                <green>128</green>
+                <blue>128</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Button">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Light">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>127</green>
+                <blue>127</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Midlight">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>38</green>
+                <blue>38</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Dark">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>127</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Mid">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>170</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Text">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="BrightText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="ButtonText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>128</red>
+                <green>128</green>
+                <blue>128</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Base">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Window">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Shadow">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Highlight">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>128</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="HighlightedText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+            </disabled>
+           </palette>
+          </property>
+          <property name="frameShape">
+           <enum>QFrame::Box</enum>
+          </property>
+          <property name="frameShadow">
+           <enum>QFrame::Plain</enum>
+          </property>
+          <property name="lineWidth">
+           <number>2</number>
+          </property>
+          <layout class="QHBoxLayout" name="_11">
+           <property name="spacing">
+            <number>6</number>
+           </property>
+           <property name="leftMargin">
+            <number>5</number>
+           </property>
+           <property name="topMargin">
+            <number>5</number>
+           </property>
+           <property name="rightMargin">
+            <number>5</number>
+           </property>
+           <property name="bottomMargin">
+            <number>5</number>
+           </property>
+           <item>
+            <widget class="QLabel" name="LabelBitrate">
+             <property name="palette">
+              <palette>
+               <active>
+                <colorrole role="WindowText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Button">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>212</red>
+                   <green>208</green>
+                   <blue>200</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Light">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>255</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Midlight">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>233</red>
+                   <green>231</green>
+                   <blue>227</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Dark">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>106</red>
+                   <green>104</green>
+                   <blue>100</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Mid">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>141</red>
+                   <green>138</green>
+                   <blue>133</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Text">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="BrightText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>255</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="ButtonText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Base">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>255</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Window">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Shadow">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Highlight">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>10</red>
+                   <green>36</green>
+                   <blue>106</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="HighlightedText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>255</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+               </active>
+               <inactive>
+                <colorrole role="WindowText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Button">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>212</red>
+                   <green>208</green>
+                   <blue>200</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Light">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>255</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Midlight">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>243</red>
+                   <green>239</green>
+                   <blue>230</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Dark">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>106</red>
+                   <green>104</green>
+                   <blue>100</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Mid">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>141</red>
+                   <green>138</green>
+                   <blue>133</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Text">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="BrightText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>255</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="ButtonText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Base">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>255</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Window">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Shadow">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Highlight">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>10</red>
+                   <green>36</green>
+                   <blue>106</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="HighlightedText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>255</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+               </inactive>
+               <disabled>
+                <colorrole role="WindowText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>128</red>
+                   <green>128</green>
+                   <blue>128</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Button">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>212</red>
+                   <green>208</green>
+                   <blue>200</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Light">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>255</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Midlight">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>243</red>
+                   <green>239</green>
+                   <blue>230</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Dark">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>106</red>
+                   <green>104</green>
+                   <blue>100</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Mid">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>141</red>
+                   <green>138</green>
+                   <blue>133</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Text">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="BrightText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>255</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="ButtonText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>128</red>
+                   <green>128</green>
+                   <blue>128</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Base">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>255</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Window">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Shadow">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Highlight">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>10</red>
+                   <green>36</green>
+                   <blue>106</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="HighlightedText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>255</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+               </disabled>
+              </palette>
+             </property>
+             <property name="font">
+              <font>
+               <family>Arial</family>
+               <pointsize>10</pointsize>
+               <weight>75</weight>
+               <bold>true</bold>
+              </font>
+             </property>
+             <property name="text">
+              <string>15 kbps</string>
+             </property>
+             <property name="alignment">
+              <set>Qt::AlignCenter</set>
+             </property>
+             <property name="wordWrap">
+              <bool>false</bool>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="QLabel" name="LabelCodec">
+             <property name="palette">
+              <palette>
+               <active>
+                <colorrole role="WindowText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Button">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>212</red>
+                   <green>208</green>
+                   <blue>200</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Light">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>255</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Midlight">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>233</red>
+                   <green>231</green>
+                   <blue>227</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Dark">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>106</red>
+                   <green>104</green>
+                   <blue>100</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Mid">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>141</red>
+                   <green>138</green>
+                   <blue>133</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Text">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="BrightText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>255</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="ButtonText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Base">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>255</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Window">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Shadow">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Highlight">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>10</red>
+                   <green>36</green>
+                   <blue>106</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="HighlightedText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>255</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+               </active>
+               <inactive>
+                <colorrole role="WindowText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Button">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>212</red>
+                   <green>208</green>
+                   <blue>200</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Light">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>255</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Midlight">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>243</red>
+                   <green>239</green>
+                   <blue>230</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Dark">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>106</red>
+                   <green>104</green>
+                   <blue>100</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Mid">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>141</red>
+                   <green>138</green>
+                   <blue>133</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Text">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="BrightText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>255</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="ButtonText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Base">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>255</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Window">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Shadow">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Highlight">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>10</red>
+                   <green>36</green>
+                   <blue>106</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="HighlightedText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>255</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+               </inactive>
+               <disabled>
+                <colorrole role="WindowText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>128</red>
+                   <green>128</green>
+                   <blue>128</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Button">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>212</red>
+                   <green>208</green>
+                   <blue>200</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Light">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>255</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Midlight">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>243</red>
+                   <green>239</green>
+                   <blue>230</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Dark">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>106</red>
+                   <green>104</green>
+                   <blue>100</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Mid">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>141</red>
+                   <green>138</green>
+                   <blue>133</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Text">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="BrightText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>255</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="ButtonText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>128</red>
+                   <green>128</green>
+                   <blue>128</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Base">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>255</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Window">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Shadow">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Highlight">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>10</red>
+                   <green>36</green>
+                   <blue>106</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="HighlightedText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>255</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+               </disabled>
+              </palette>
+             </property>
+             <property name="font">
+              <font>
+               <family>Arial</family>
+               <pointsize>10</pointsize>
+               <weight>75</weight>
+               <bold>true</bold>
+              </font>
+             </property>
+             <property name="text">
+              <string>AAC+</string>
+             </property>
+             <property name="alignment">
+              <set>Qt::AlignCenter</set>
+             </property>
+             <property name="wordWrap">
+              <bool>false</bool>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="QLabel" name="LabelStereoMono">
+             <property name="palette">
+              <palette>
+               <active>
+                <colorrole role="WindowText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Button">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>212</red>
+                   <green>208</green>
+                   <blue>200</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Light">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>255</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Midlight">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>233</red>
+                   <green>231</green>
+                   <blue>227</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Dark">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>106</red>
+                   <green>104</green>
+                   <blue>100</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Mid">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>141</red>
+                   <green>138</green>
+                   <blue>133</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Text">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="BrightText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>255</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="ButtonText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Base">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>255</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Window">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Shadow">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Highlight">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>10</red>
+                   <green>36</green>
+                   <blue>106</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="HighlightedText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>255</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+               </active>
+               <inactive>
+                <colorrole role="WindowText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Button">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>212</red>
+                   <green>208</green>
+                   <blue>200</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Light">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>255</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Midlight">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>243</red>
+                   <green>239</green>
+                   <blue>230</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Dark">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>106</red>
+                   <green>104</green>
+                   <blue>100</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Mid">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>141</red>
+                   <green>138</green>
+                   <blue>133</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Text">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="BrightText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>255</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="ButtonText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Base">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>255</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Window">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Shadow">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Highlight">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>10</red>
+                   <green>36</green>
+                   <blue>106</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="HighlightedText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>255</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+               </inactive>
+               <disabled>
+                <colorrole role="WindowText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>128</red>
+                   <green>128</green>
+                   <blue>128</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Button">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>212</red>
+                   <green>208</green>
+                   <blue>200</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Light">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>255</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Midlight">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>243</red>
+                   <green>239</green>
+                   <blue>230</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Dark">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>106</red>
+                   <green>104</green>
+                   <blue>100</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Mid">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>141</red>
+                   <green>138</green>
+                   <blue>133</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Text">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="BrightText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>255</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="ButtonText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>128</red>
+                   <green>128</green>
+                   <blue>128</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Base">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>255</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Window">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Shadow">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="Highlight">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>10</red>
+                   <green>36</green>
+                   <blue>106</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="HighlightedText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>255</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+               </disabled>
+              </palette>
+             </property>
+             <property name="font">
+              <font>
+               <family>Arial</family>
+               <pointsize>10</pointsize>
+               <weight>75</weight>
+               <bold>true</bold>
+              </font>
+             </property>
+             <property name="text">
+              <string>Stereo</string>
+             </property>
+             <property name="alignment">
+              <set>Qt::AlignCenter</set>
+             </property>
+             <property name="wordWrap">
+              <bool>false</bool>
+             </property>
+            </widget>
+           </item>
+          </layout>
+         </widget>
+        </item>
+        <item>
+         <widget class="QLabel" name="LabelServiceLabel">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Expanding" vsizetype="Minimum">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="palette">
+           <palette>
+            <active>
+             <colorrole role="WindowText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>85</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Button">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>169</red>
+                <green>134</green>
+                <blue>107</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Light">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>253</red>
+                <green>200</green>
+                <blue>160</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Midlight">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>211</red>
+                <green>167</green>
+                <blue>133</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Dark">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>84</red>
+                <green>66</green>
+                <blue>53</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Mid">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>112</red>
+                <green>89</green>
+                <blue>71</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Text">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="BrightText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="ButtonText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Base">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Window">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Shadow">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Highlight">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>128</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="HighlightedText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+            </active>
+            <inactive>
+             <colorrole role="WindowText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>85</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Button">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>169</red>
+                <green>134</green>
+                <blue>107</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Light">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>253</red>
+                <green>200</green>
+                <blue>160</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Midlight">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>194</red>
+                <green>153</green>
+                <blue>122</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Dark">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>84</red>
+                <green>66</green>
+                <blue>53</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Mid">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>112</red>
+                <green>89</green>
+                <blue>71</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Text">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="BrightText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="ButtonText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Base">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Window">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Shadow">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Highlight">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>128</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="HighlightedText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+            </inactive>
+            <disabled>
+             <colorrole role="WindowText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>128</red>
+                <green>128</green>
+                <blue>128</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Button">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>169</red>
+                <green>134</green>
+                <blue>107</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Light">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>253</red>
+                <green>200</green>
+                <blue>160</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Midlight">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>194</red>
+                <green>153</green>
+                <blue>122</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Dark">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>84</red>
+                <green>66</green>
+                <blue>53</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Mid">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>112</red>
+                <green>89</green>
+                <blue>71</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Text">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="BrightText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="ButtonText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>128</red>
+                <green>128</green>
+                <blue>128</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Base">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Window">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Shadow">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Highlight">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>128</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="HighlightedText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+            </disabled>
+           </palette>
+          </property>
+          <property name="font">
+           <font>
+            <family>Arial</family>
+            <pointsize>14</pointsize>
+            <weight>75</weight>
+            <bold>true</bold>
+           </font>
+          </property>
+          <property name="text">
+           <string>Deutsche Welle</string>
+          </property>
+          <property name="alignment">
+           <set>Qt::AlignBottom|Qt::AlignHCenter</set>
+          </property>
+          <property name="wordWrap">
+           <bool>false</bool>
+          </property>
+          <property name="margin">
+           <number>0</number>
+          </property>
+          <property name="indent">
+           <number>5</number>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <layout class="QHBoxLayout" name="_12">
+          <property name="spacing">
+           <number>2</number>
+          </property>
+          <property name="leftMargin">
+           <number>0</number>
+          </property>
+          <property name="topMargin">
+           <number>0</number>
+          </property>
+          <property name="rightMargin">
+           <number>0</number>
+          </property>
+          <property name="bottomMargin">
+           <number>0</number>
+          </property>
+          <item>
+           <widget class="QLabel" name="LabelLanguage">
+            <property name="sizePolicy">
+             <sizepolicy hsizetype="Expanding" vsizetype="Minimum">
+              <horstretch>0</horstretch>
+              <verstretch>0</verstretch>
+             </sizepolicy>
+            </property>
+            <property name="palette">
+             <palette>
+              <active>
+               <colorrole role="WindowText">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>255</red>
+                  <green>0</green>
+                  <blue>0</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Button">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>169</red>
+                  <green>134</green>
+                  <blue>107</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Light">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>253</red>
+                  <green>200</green>
+                  <blue>160</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Midlight">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>211</red>
+                  <green>167</green>
+                  <blue>133</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Dark">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>84</red>
+                  <green>66</green>
+                  <blue>53</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Mid">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>112</red>
+                  <green>89</green>
+                  <blue>71</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Text">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>0</red>
+                  <green>0</green>
+                  <blue>0</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="BrightText">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>255</red>
+                  <green>255</green>
+                  <blue>255</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="ButtonText">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>0</red>
+                  <green>0</green>
+                  <blue>0</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Base">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>255</red>
+                  <green>255</green>
+                  <blue>255</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Window">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>0</red>
+                  <green>0</green>
+                  <blue>0</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Shadow">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>0</red>
+                  <green>0</green>
+                  <blue>0</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Highlight">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>0</red>
+                  <green>0</green>
+                  <blue>128</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="HighlightedText">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>255</red>
+                  <green>255</green>
+                  <blue>255</blue>
+                 </color>
+                </brush>
+               </colorrole>
+              </active>
+              <inactive>
+               <colorrole role="WindowText">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>255</red>
+                  <green>0</green>
+                  <blue>0</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Button">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>169</red>
+                  <green>134</green>
+                  <blue>107</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Light">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>253</red>
+                  <green>200</green>
+                  <blue>160</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Midlight">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>194</red>
+                  <green>153</green>
+                  <blue>122</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Dark">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>84</red>
+                  <green>66</green>
+                  <blue>53</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Mid">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>112</red>
+                  <green>89</green>
+                  <blue>71</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Text">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>0</red>
+                  <green>0</green>
+                  <blue>0</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="BrightText">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>255</red>
+                  <green>255</green>
+                  <blue>255</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="ButtonText">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>0</red>
+                  <green>0</green>
+                  <blue>0</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Base">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>255</red>
+                  <green>255</green>
+                  <blue>255</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Window">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>0</red>
+                  <green>0</green>
+                  <blue>0</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Shadow">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>0</red>
+                  <green>0</green>
+                  <blue>0</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Highlight">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>0</red>
+                  <green>0</green>
+                  <blue>128</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="HighlightedText">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>255</red>
+                  <green>255</green>
+                  <blue>255</blue>
+                 </color>
+                </brush>
+               </colorrole>
+              </inactive>
+              <disabled>
+               <colorrole role="WindowText">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>128</red>
+                  <green>128</green>
+                  <blue>128</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Button">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>169</red>
+                  <green>134</green>
+                  <blue>107</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Light">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>253</red>
+                  <green>200</green>
+                  <blue>160</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Midlight">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>194</red>
+                  <green>153</green>
+                  <blue>122</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Dark">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>84</red>
+                  <green>66</green>
+                  <blue>53</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Mid">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>112</red>
+                  <green>89</green>
+                  <blue>71</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Text">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>0</red>
+                  <green>0</green>
+                  <blue>0</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="BrightText">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>255</red>
+                  <green>255</green>
+                  <blue>255</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="ButtonText">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>128</red>
+                  <green>128</green>
+                  <blue>128</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Base">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>255</red>
+                  <green>255</green>
+                  <blue>255</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Window">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>0</red>
+                  <green>0</green>
+                  <blue>0</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Shadow">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>0</red>
+                  <green>0</green>
+                  <blue>0</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Highlight">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>0</red>
+                  <green>0</green>
+                  <blue>128</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="HighlightedText">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>255</red>
+                  <green>255</green>
+                  <blue>255</blue>
+                 </color>
+                </brush>
+               </colorrole>
+              </disabled>
+             </palette>
+            </property>
+            <property name="font">
+             <font>
+              <family>Arial</family>
+              <pointsize>10</pointsize>
+              <weight>75</weight>
+              <bold>true</bold>
+             </font>
+            </property>
+            <property name="lineWidth">
+             <number>1</number>
+            </property>
+            <property name="text">
+             <string>German</string>
+            </property>
+            <property name="alignment">
+             <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+            </property>
+            <property name="wordWrap">
+             <bool>false</bool>
+            </property>
+            <property name="margin">
+             <number>0</number>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QLabel" name="LabelCountryCode">
+            <property name="sizePolicy">
+             <sizepolicy hsizetype="Expanding" vsizetype="Minimum">
+              <horstretch>0</horstretch>
+              <verstretch>0</verstretch>
+             </sizepolicy>
+            </property>
+            <property name="palette">
+             <palette>
+              <active>
+               <colorrole role="WindowText">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>255</red>
+                  <green>0</green>
+                  <blue>0</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Button">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>169</red>
+                  <green>134</green>
+                  <blue>107</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Light">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>253</red>
+                  <green>200</green>
+                  <blue>160</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Midlight">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>211</red>
+                  <green>167</green>
+                  <blue>133</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Dark">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>84</red>
+                  <green>66</green>
+                  <blue>53</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Mid">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>112</red>
+                  <green>89</green>
+                  <blue>71</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Text">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>0</red>
+                  <green>0</green>
+                  <blue>0</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="BrightText">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>255</red>
+                  <green>255</green>
+                  <blue>255</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="ButtonText">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>0</red>
+                  <green>0</green>
+                  <blue>0</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Base">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>255</red>
+                  <green>255</green>
+                  <blue>255</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Window">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>0</red>
+                  <green>0</green>
+                  <blue>0</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Shadow">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>0</red>
+                  <green>0</green>
+                  <blue>0</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Highlight">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>0</red>
+                  <green>0</green>
+                  <blue>128</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="HighlightedText">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>255</red>
+                  <green>255</green>
+                  <blue>255</blue>
+                 </color>
+                </brush>
+               </colorrole>
+              </active>
+              <inactive>
+               <colorrole role="WindowText">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>255</red>
+                  <green>0</green>
+                  <blue>0</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Button">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>169</red>
+                  <green>134</green>
+                  <blue>107</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Light">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>253</red>
+                  <green>200</green>
+                  <blue>160</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Midlight">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>194</red>
+                  <green>153</green>
+                  <blue>122</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Dark">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>84</red>
+                  <green>66</green>
+                  <blue>53</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Mid">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>112</red>
+                  <green>89</green>
+                  <blue>71</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Text">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>0</red>
+                  <green>0</green>
+                  <blue>0</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="BrightText">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>255</red>
+                  <green>255</green>
+                  <blue>255</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="ButtonText">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>0</red>
+                  <green>0</green>
+                  <blue>0</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Base">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>255</red>
+                  <green>255</green>
+                  <blue>255</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Window">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>0</red>
+                  <green>0</green>
+                  <blue>0</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Shadow">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>0</red>
+                  <green>0</green>
+                  <blue>0</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Highlight">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>0</red>
+                  <green>0</green>
+                  <blue>128</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="HighlightedText">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>255</red>
+                  <green>255</green>
+                  <blue>255</blue>
+                 </color>
+                </brush>
+               </colorrole>
+              </inactive>
+              <disabled>
+               <colorrole role="WindowText">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>128</red>
+                  <green>128</green>
+                  <blue>128</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Button">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>169</red>
+                  <green>134</green>
+                  <blue>107</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Light">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>253</red>
+                  <green>200</green>
+                  <blue>160</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Midlight">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>194</red>
+                  <green>153</green>
+                  <blue>122</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Dark">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>84</red>
+                  <green>66</green>
+                  <blue>53</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Mid">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>112</red>
+                  <green>89</green>
+                  <blue>71</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Text">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>0</red>
+                  <green>0</green>
+                  <blue>0</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="BrightText">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>255</red>
+                  <green>255</green>
+                  <blue>255</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="ButtonText">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>128</red>
+                  <green>128</green>
+                  <blue>128</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Base">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>255</red>
+                  <green>255</green>
+                  <blue>255</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Window">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>0</red>
+                  <green>0</green>
+                  <blue>0</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Shadow">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>0</red>
+                  <green>0</green>
+                  <blue>0</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Highlight">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>0</red>
+                  <green>0</green>
+                  <blue>128</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="HighlightedText">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>255</red>
+                  <green>255</green>
+                  <blue>255</blue>
+                 </color>
+                </brush>
+               </colorrole>
+              </disabled>
+             </palette>
+            </property>
+            <property name="font">
+             <font>
+              <family>Arial</family>
+              <pointsize>10</pointsize>
+              <weight>75</weight>
+              <bold>true</bold>
+             </font>
+            </property>
+            <property name="lineWidth">
+             <number>1</number>
+            </property>
+            <property name="text">
+             <string>DE</string>
+            </property>
+            <property name="alignment">
+             <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+            </property>
+            <property name="wordWrap">
+             <bool>false</bool>
+            </property>
+            <property name="margin">
+             <number>0</number>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </item>
+        <item>
+         <layout class="QHBoxLayout" name="_13">
+          <property name="spacing">
+           <number>2</number>
+          </property>
+          <property name="leftMargin">
+           <number>0</number>
+          </property>
+          <property name="topMargin">
+           <number>0</number>
+          </property>
+          <property name="rightMargin">
+           <number>0</number>
+          </property>
+          <property name="bottomMargin">
+           <number>0</number>
+          </property>
+          <item>
+           <widget class="QLabel" name="LabelProgrType">
+            <property name="sizePolicy">
+             <sizepolicy hsizetype="Expanding" vsizetype="Minimum">
+              <horstretch>0</horstretch>
+              <verstretch>0</verstretch>
+             </sizepolicy>
+            </property>
+            <property name="palette">
+             <palette>
+              <active>
+               <colorrole role="WindowText">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>255</red>
+                  <green>0</green>
+                  <blue>0</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Button">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>169</red>
+                  <green>134</green>
+                  <blue>107</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Light">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>253</red>
+                  <green>200</green>
+                  <blue>160</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Midlight">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>211</red>
+                  <green>167</green>
+                  <blue>133</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Dark">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>84</red>
+                  <green>66</green>
+                  <blue>53</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Mid">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>112</red>
+                  <green>89</green>
+                  <blue>71</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Text">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>0</red>
+                  <green>0</green>
+                  <blue>0</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="BrightText">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>255</red>
+                  <green>255</green>
+                  <blue>255</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="ButtonText">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>0</red>
+                  <green>0</green>
+                  <blue>0</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Base">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>255</red>
+                  <green>255</green>
+                  <blue>255</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Window">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>0</red>
+                  <green>0</green>
+                  <blue>0</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Shadow">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>0</red>
+                  <green>0</green>
+                  <blue>0</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Highlight">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>0</red>
+                  <green>0</green>
+                  <blue>128</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="HighlightedText">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>255</red>
+                  <green>255</green>
+                  <blue>255</blue>
+                 </color>
+                </brush>
+               </colorrole>
+              </active>
+              <inactive>
+               <colorrole role="WindowText">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>255</red>
+                  <green>0</green>
+                  <blue>0</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Button">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>169</red>
+                  <green>134</green>
+                  <blue>107</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Light">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>253</red>
+                  <green>200</green>
+                  <blue>160</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Midlight">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>194</red>
+                  <green>153</green>
+                  <blue>122</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Dark">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>84</red>
+                  <green>66</green>
+                  <blue>53</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Mid">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>112</red>
+                  <green>89</green>
+                  <blue>71</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Text">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>0</red>
+                  <green>0</green>
+                  <blue>0</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="BrightText">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>255</red>
+                  <green>255</green>
+                  <blue>255</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="ButtonText">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>0</red>
+                  <green>0</green>
+                  <blue>0</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Base">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>255</red>
+                  <green>255</green>
+                  <blue>255</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Window">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>0</red>
+                  <green>0</green>
+                  <blue>0</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Shadow">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>0</red>
+                  <green>0</green>
+                  <blue>0</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Highlight">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>0</red>
+                  <green>0</green>
+                  <blue>128</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="HighlightedText">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>255</red>
+                  <green>255</green>
+                  <blue>255</blue>
+                 </color>
+                </brush>
+               </colorrole>
+              </inactive>
+              <disabled>
+               <colorrole role="WindowText">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>128</red>
+                  <green>128</green>
+                  <blue>128</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Button">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>169</red>
+                  <green>134</green>
+                  <blue>107</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Light">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>253</red>
+                  <green>200</green>
+                  <blue>160</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Midlight">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>194</red>
+                  <green>153</green>
+                  <blue>122</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Dark">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>84</red>
+                  <green>66</green>
+                  <blue>53</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Mid">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>112</red>
+                  <green>89</green>
+                  <blue>71</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Text">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>0</red>
+                  <green>0</green>
+                  <blue>0</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="BrightText">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>255</red>
+                  <green>255</green>
+                  <blue>255</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="ButtonText">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>128</red>
+                  <green>128</green>
+                  <blue>128</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Base">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>255</red>
+                  <green>255</green>
+                  <blue>255</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Window">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>0</red>
+                  <green>0</green>
+                  <blue>0</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Shadow">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>0</red>
+                  <green>0</green>
+                  <blue>0</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Highlight">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>0</red>
+                  <green>0</green>
+                  <blue>128</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="HighlightedText">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>255</red>
+                  <green>255</green>
+                  <blue>255</blue>
+                 </color>
+                </brush>
+               </colorrole>
+              </disabled>
+             </palette>
+            </property>
+            <property name="font">
+             <font>
+              <family>Arial</family>
+              <pointsize>10</pointsize>
+              <weight>75</weight>
+              <bold>true</bold>
+             </font>
+            </property>
+            <property name="lineWidth">
+             <number>1</number>
+            </property>
+            <property name="text">
+             <string>Information</string>
+            </property>
+            <property name="alignment">
+             <set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
+            </property>
+            <property name="wordWrap">
+             <bool>false</bool>
+            </property>
+            <property name="margin">
+             <number>0</number>
+            </property>
+            <property name="indent">
+             <number>-1</number>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QLabel" name="LabelServiceID">
+            <property name="sizePolicy">
+             <sizepolicy hsizetype="Expanding" vsizetype="Minimum">
+              <horstretch>0</horstretch>
+              <verstretch>0</verstretch>
+             </sizepolicy>
+            </property>
+            <property name="palette">
+             <palette>
+              <active>
+               <colorrole role="WindowText">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>255</red>
+                  <green>0</green>
+                  <blue>0</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Button">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>169</red>
+                  <green>134</green>
+                  <blue>107</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Light">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>253</red>
+                  <green>200</green>
+                  <blue>160</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Midlight">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>211</red>
+                  <green>167</green>
+                  <blue>133</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Dark">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>84</red>
+                  <green>66</green>
+                  <blue>53</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Mid">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>112</red>
+                  <green>89</green>
+                  <blue>71</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Text">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>0</red>
+                  <green>0</green>
+                  <blue>0</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="BrightText">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>255</red>
+                  <green>255</green>
+                  <blue>255</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="ButtonText">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>0</red>
+                  <green>0</green>
+                  <blue>0</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Base">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>255</red>
+                  <green>255</green>
+                  <blue>255</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Window">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>0</red>
+                  <green>0</green>
+                  <blue>0</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Shadow">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>0</red>
+                  <green>0</green>
+                  <blue>0</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Highlight">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>0</red>
+                  <green>0</green>
+                  <blue>128</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="HighlightedText">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>255</red>
+                  <green>255</green>
+                  <blue>255</blue>
+                 </color>
+                </brush>
+               </colorrole>
+              </active>
+              <inactive>
+               <colorrole role="WindowText">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>255</red>
+                  <green>0</green>
+                  <blue>0</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Button">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>169</red>
+                  <green>134</green>
+                  <blue>107</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Light">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>253</red>
+                  <green>200</green>
+                  <blue>160</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Midlight">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>194</red>
+                  <green>153</green>
+                  <blue>122</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Dark">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>84</red>
+                  <green>66</green>
+                  <blue>53</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Mid">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>112</red>
+                  <green>89</green>
+                  <blue>71</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Text">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>0</red>
+                  <green>0</green>
+                  <blue>0</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="BrightText">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>255</red>
+                  <green>255</green>
+                  <blue>255</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="ButtonText">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>0</red>
+                  <green>0</green>
+                  <blue>0</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Base">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>255</red>
+                  <green>255</green>
+                  <blue>255</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Window">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>0</red>
+                  <green>0</green>
+                  <blue>0</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Shadow">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>0</red>
+                  <green>0</green>
+                  <blue>0</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Highlight">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>0</red>
+                  <green>0</green>
+                  <blue>128</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="HighlightedText">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>255</red>
+                  <green>255</green>
+                  <blue>255</blue>
+                 </color>
+                </brush>
+               </colorrole>
+              </inactive>
+              <disabled>
+               <colorrole role="WindowText">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>128</red>
+                  <green>128</green>
+                  <blue>128</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Button">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>169</red>
+                  <green>134</green>
+                  <blue>107</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Light">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>253</red>
+                  <green>200</green>
+                  <blue>160</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Midlight">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>194</red>
+                  <green>153</green>
+                  <blue>122</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Dark">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>84</red>
+                  <green>66</green>
+                  <blue>53</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Mid">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>112</red>
+                  <green>89</green>
+                  <blue>71</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Text">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>0</red>
+                  <green>0</green>
+                  <blue>0</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="BrightText">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>255</red>
+                  <green>255</green>
+                  <blue>255</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="ButtonText">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>128</red>
+                  <green>128</green>
+                  <blue>128</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Base">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>255</red>
+                  <green>255</green>
+                  <blue>255</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Window">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>0</red>
+                  <green>0</green>
+                  <blue>0</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Shadow">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>0</red>
+                  <green>0</green>
+                  <blue>0</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="Highlight">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>0</red>
+                  <green>0</green>
+                  <blue>128</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="HighlightedText">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>255</red>
+                  <green>255</green>
+                  <blue>255</blue>
+                 </color>
+                </brush>
+               </colorrole>
+              </disabled>
+             </palette>
+            </property>
+            <property name="font">
+             <font>
+              <family>Arial</family>
+              <pointsize>10</pointsize>
+              <weight>75</weight>
+              <bold>true</bold>
+             </font>
+            </property>
+            <property name="lineWidth">
+             <number>1</number>
+            </property>
+            <property name="text">
+             <string>1001</string>
+            </property>
+            <property name="alignment">
+             <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+            </property>
+            <property name="wordWrap">
+             <bool>false</bool>
+            </property>
+            <property name="margin">
+             <number>0</number>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </item>
+       </layout>
+      </item>
+      <item row="0" column="2" rowspan="2">
+       <widget class="QLabel" name="TextTextMessage">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="minimumSize">
+         <size>
+          <width>160</width>
+          <height>80</height>
+         </size>
+        </property>
+        <property name="palette">
+         <palette>
+          <active>
+           <colorrole role="WindowText">
+            <brush brushstyle="SolidPattern">
+             <color alpha="255">
+              <red>0</red>
+              <green>0</green>
+              <blue>0</blue>
+             </color>
+            </brush>
+           </colorrole>
+           <colorrole role="Button">
+            <brush brushstyle="SolidPattern">
+             <color alpha="255">
+              <red>255</red>
+              <green>0</green>
+              <blue>0</blue>
+             </color>
+            </brush>
+           </colorrole>
+           <colorrole role="Light">
+            <brush brushstyle="SolidPattern">
+             <color alpha="255">
+              <red>255</red>
+              <green>127</green>
+              <blue>127</blue>
+             </color>
+            </brush>
+           </colorrole>
+           <colorrole role="Midlight">
+            <brush brushstyle="SolidPattern">
+             <color alpha="255">
+              <red>255</red>
+              <green>63</green>
+              <blue>63</blue>
+             </color>
+            </brush>
+           </colorrole>
+           <colorrole role="Dark">
+            <brush brushstyle="SolidPattern">
+             <color alpha="255">
+              <red>127</red>
+              <green>0</green>
+              <blue>0</blue>
+             </color>
+            </brush>
+           </colorrole>
+           <colorrole role="Mid">
+            <brush brushstyle="SolidPattern">
+             <color alpha="255">
+              <red>170</red>
+              <green>0</green>
+              <blue>0</blue>
+             </color>
+            </brush>
+           </colorrole>
+           <colorrole role="Text">
+            <brush brushstyle="SolidPattern">
+             <color alpha="255">
+              <red>255</red>
+              <green>0</green>
+              <blue>255</blue>
+             </color>
+            </brush>
+           </colorrole>
+           <colorrole role="BrightText">
+            <brush brushstyle="SolidPattern">
+             <color alpha="255">
+              <red>255</red>
+              <green>255</green>
+              <blue>255</blue>
+             </color>
+            </brush>
+           </colorrole>
+           <colorrole role="ButtonText">
+            <brush brushstyle="SolidPattern">
+             <color alpha="255">
+              <red>0</red>
+              <green>0</green>
+              <blue>0</blue>
+             </color>
+            </brush>
+           </colorrole>
+           <colorrole role="Base">
+            <brush brushstyle="SolidPattern">
+             <color alpha="255">
+              <red>255</red>
+              <green>255</green>
+              <blue>255</blue>
+             </color>
+            </brush>
+           </colorrole>
+           <colorrole role="Window">
+            <brush brushstyle="SolidPattern">
+             <color alpha="255">
+              <red>255</red>
+              <green>255</green>
+              <blue>255</blue>
+             </color>
+            </brush>
+           </colorrole>
+           <colorrole role="Shadow">
+            <brush brushstyle="SolidPattern">
+             <color alpha="255">
+              <red>0</red>
+              <green>0</green>
+              <blue>0</blue>
+             </color>
+            </brush>
+           </colorrole>
+           <colorrole role="Highlight">
+            <brush brushstyle="SolidPattern">
+             <color alpha="255">
+              <red>10</red>
+              <green>36</green>
+              <blue>106</blue>
+             </color>
+            </brush>
+           </colorrole>
+           <colorrole role="HighlightedText">
+            <brush brushstyle="SolidPattern">
+             <color alpha="255">
+              <red>255</red>
+              <green>255</green>
+              <blue>255</blue>
+             </color>
+            </brush>
+           </colorrole>
+          </active>
+          <inactive>
+           <colorrole role="WindowText">
+            <brush brushstyle="SolidPattern">
+             <color alpha="255">
+              <red>0</red>
+              <green>0</green>
+              <blue>0</blue>
+             </color>
+            </brush>
+           </colorrole>
+           <colorrole role="Button">
+            <brush brushstyle="SolidPattern">
+             <color alpha="255">
+              <red>255</red>
+              <green>0</green>
+              <blue>0</blue>
+             </color>
+            </brush>
+           </colorrole>
+           <colorrole role="Light">
+            <brush brushstyle="SolidPattern">
+             <color alpha="255">
+              <red>255</red>
+              <green>127</green>
+              <blue>127</blue>
+             </color>
+            </brush>
+           </colorrole>
+           <colorrole role="Midlight">
+            <brush brushstyle="SolidPattern">
+             <color alpha="255">
+              <red>255</red>
+              <green>38</green>
+              <blue>38</blue>
+             </color>
+            </brush>
+           </colorrole>
+           <colorrole role="Dark">
+            <brush brushstyle="SolidPattern">
+             <color alpha="255">
+              <red>127</red>
+              <green>0</green>
+              <blue>0</blue>
+             </color>
+            </brush>
+           </colorrole>
+           <colorrole role="Mid">
+            <brush brushstyle="SolidPattern">
+             <color alpha="255">
+              <red>170</red>
+              <green>0</green>
+              <blue>0</blue>
+             </color>
+            </brush>
+           </colorrole>
+           <colorrole role="Text">
+            <brush brushstyle="SolidPattern">
+             <color alpha="255">
+              <red>255</red>
+              <green>0</green>
+              <blue>255</blue>
+             </color>
+            </brush>
+           </colorrole>
+           <colorrole role="BrightText">
+            <brush brushstyle="SolidPattern">
+             <color alpha="255">
+              <red>255</red>
+              <green>255</green>
+              <blue>255</blue>
+             </color>
+            </brush>
+           </colorrole>
+           <colorrole role="ButtonText">
+            <brush brushstyle="SolidPattern">
+             <color alpha="255">
+              <red>0</red>
+              <green>0</green>
+              <blue>0</blue>
+             </color>
+            </brush>
+           </colorrole>
+           <colorrole role="Base">
+            <brush brushstyle="SolidPattern">
+             <color alpha="255">
+              <red>255</red>
+              <green>255</green>
+              <blue>255</blue>
+             </color>
+            </brush>
+           </colorrole>
+           <colorrole role="Window">
+            <brush brushstyle="SolidPattern">
+             <color alpha="255">
+              <red>255</red>
+              <green>255</green>
+              <blue>255</blue>
+             </color>
+            </brush>
+           </colorrole>
+           <colorrole role="Shadow">
+            <brush brushstyle="SolidPattern">
+             <color alpha="255">
+              <red>0</red>
+              <green>0</green>
+              <blue>0</blue>
+             </color>
+            </brush>
+           </colorrole>
+           <colorrole role="Highlight">
+            <brush brushstyle="SolidPattern">
+             <color alpha="255">
+              <red>10</red>
+              <green>36</green>
+              <blue>106</blue>
+             </color>
+            </brush>
+           </colorrole>
+           <colorrole role="HighlightedText">
+            <brush brushstyle="SolidPattern">
+             <color alpha="255">
+              <red>255</red>
+              <green>255</green>
+              <blue>255</blue>
+             </color>
+            </brush>
+           </colorrole>
+          </inactive>
+          <disabled>
+           <colorrole role="WindowText">
+            <brush brushstyle="SolidPattern">
+             <color alpha="255">
+              <red>128</red>
+              <green>128</green>
+              <blue>128</blue>
+             </color>
+            </brush>
+           </colorrole>
+           <colorrole role="Button">
+            <brush brushstyle="SolidPattern">
+             <color alpha="255">
+              <red>255</red>
+              <green>0</green>
+              <blue>0</blue>
+             </color>
+            </brush>
+           </colorrole>
+           <colorrole role="Light">
+            <brush brushstyle="SolidPattern">
+             <color alpha="255">
+              <red>255</red>
+              <green>127</green>
+              <blue>127</blue>
+             </color>
+            </brush>
+           </colorrole>
+           <colorrole role="Midlight">
+            <brush brushstyle="SolidPattern">
+             <color alpha="255">
+              <red>255</red>
+              <green>38</green>
+              <blue>38</blue>
+             </color>
+            </brush>
+           </colorrole>
+           <colorrole role="Dark">
+            <brush brushstyle="SolidPattern">
+             <color alpha="255">
+              <red>127</red>
+              <green>0</green>
+              <blue>0</blue>
+             </color>
+            </brush>
+           </colorrole>
+           <colorrole role="Mid">
+            <brush brushstyle="SolidPattern">
+             <color alpha="255">
+              <red>170</red>
+              <green>0</green>
+              <blue>0</blue>
+             </color>
+            </brush>
+           </colorrole>
+           <colorrole role="Text">
+            <brush brushstyle="SolidPattern">
+             <color alpha="255">
+              <red>255</red>
+              <green>0</green>
+              <blue>255</blue>
+             </color>
+            </brush>
+           </colorrole>
+           <colorrole role="BrightText">
+            <brush brushstyle="SolidPattern">
+             <color alpha="255">
+              <red>255</red>
+              <green>255</green>
+              <blue>255</blue>
+             </color>
+            </brush>
+           </colorrole>
+           <colorrole role="ButtonText">
+            <brush brushstyle="SolidPattern">
+             <color alpha="255">
+              <red>128</red>
+              <green>128</green>
+              <blue>128</blue>
+             </color>
+            </brush>
+           </colorrole>
+           <colorrole role="Base">
+            <brush brushstyle="SolidPattern">
+             <color alpha="255">
+              <red>255</red>
+              <green>255</green>
+              <blue>255</blue>
+             </color>
+            </brush>
+           </colorrole>
+           <colorrole role="Window">
+            <brush brushstyle="SolidPattern">
+             <color alpha="255">
+              <red>255</red>
+              <green>255</green>
+              <blue>255</blue>
+             </color>
+            </brush>
+           </colorrole>
+           <colorrole role="Shadow">
+            <brush brushstyle="SolidPattern">
+             <color alpha="255">
+              <red>0</red>
+              <green>0</green>
+              <blue>0</blue>
+             </color>
+            </brush>
+           </colorrole>
+           <colorrole role="Highlight">
+            <brush brushstyle="SolidPattern">
+             <color alpha="255">
+              <red>10</red>
+              <green>36</green>
+              <blue>106</blue>
+             </color>
+            </brush>
+           </colorrole>
+           <colorrole role="HighlightedText">
+            <brush brushstyle="SolidPattern">
+             <color alpha="255">
+              <red>255</red>
+              <green>255</green>
+              <blue>255</blue>
+             </color>
+            </brush>
+           </colorrole>
+          </disabled>
+         </palette>
+        </property>
+        <property name="autoFillBackground">
+         <bool>true</bool>
+        </property>
+        <property name="frameShape">
+         <enum>QFrame::Panel</enum>
+        </property>
+        <property name="frameShadow">
+         <enum>QFrame::Sunken</enum>
+        </property>
+        <property name="lineWidth">
+         <number>2</number>
+        </property>
+        <property name="text">
+         <string>TextTextMessage</string>
+        </property>
+        <property name="textFormat">
+         <enum>Qt::RichText</enum>
+        </property>
+        <property name="alignment">
+         <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+        </property>
+        <property name="wordWrap">
+         <bool>true</bool>
+        </property>
+        <property name="openExternalLinks">
+         <bool>true</bool>
+        </property>
+       </widget>
+      </item>
+      <item row="1" column="0">
+       <layout class="QVBoxLayout" name="verticalLayout_2">
+        <item>
+         <widget class="QLabel" name="TextLabelInputLevel">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="palette">
+           <palette>
+            <active>
+             <colorrole role="WindowText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Button">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>169</red>
+                <green>134</green>
+                <blue>107</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Light">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>253</red>
+                <green>200</green>
+                <blue>160</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Midlight">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>211</red>
+                <green>167</green>
+                <blue>133</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Dark">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>84</red>
+                <green>66</green>
+                <blue>53</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Mid">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>112</red>
+                <green>89</green>
+                <blue>71</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Text">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="BrightText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="ButtonText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Base">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Window">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Shadow">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Highlight">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>128</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="HighlightedText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+            </active>
+            <inactive>
+             <colorrole role="WindowText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Button">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>169</red>
+                <green>134</green>
+                <blue>107</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Light">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>253</red>
+                <green>200</green>
+                <blue>160</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Midlight">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>194</red>
+                <green>153</green>
+                <blue>122</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Dark">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>84</red>
+                <green>66</green>
+                <blue>53</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Mid">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>112</red>
+                <green>89</green>
+                <blue>71</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Text">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="BrightText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="ButtonText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Base">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Window">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Shadow">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Highlight">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>128</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="HighlightedText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+            </inactive>
+            <disabled>
+             <colorrole role="WindowText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>128</red>
+                <green>128</green>
+                <blue>128</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Button">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>169</red>
+                <green>134</green>
+                <blue>107</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Light">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>253</red>
+                <green>200</green>
+                <blue>160</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Midlight">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>194</red>
+                <green>153</green>
+                <blue>122</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Dark">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>84</red>
+                <green>66</green>
+                <blue>53</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Mid">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>112</red>
+                <green>89</green>
+                <blue>71</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Text">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="BrightText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="ButtonText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>128</red>
+                <green>128</green>
+                <blue>128</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Base">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Window">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Shadow">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Highlight">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>128</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="HighlightedText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+            </disabled>
+           </palette>
+          </property>
+          <property name="font">
+           <font>
+            <family>Arial</family>
+            <pointsize>7</pointsize>
+            <weight>75</weight>
+            <bold>true</bold>
+           </font>
+          </property>
+          <property name="lineWidth">
+           <number>1</number>
+          </property>
+          <property name="text">
+           <string>Level [dB]</string>
+          </property>
+          <property name="alignment">
+           <set>Qt::AlignCenter</set>
+          </property>
+          <property name="wordWrap">
+           <bool>false</bool>
+          </property>
+          <property name="margin">
+           <number>0</number>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QwtThermo" name="ProgrInputLevel" native="true">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="palette">
+           <palette>
+            <active>
+             <colorrole role="WindowText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Button">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Light">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>127</green>
+                <blue>127</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Midlight">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>63</green>
+                <blue>63</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Dark">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>127</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Mid">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>170</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Text">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="BrightText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="ButtonText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Base">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Window">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Shadow">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Highlight">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>128</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="HighlightedText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+            </active>
+            <inactive>
+             <colorrole role="WindowText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Button">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Light">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>127</green>
+                <blue>127</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Midlight">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>38</green>
+                <blue>38</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Dark">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>127</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Mid">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>170</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Text">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="BrightText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="ButtonText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Base">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Window">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Shadow">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Highlight">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>128</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="HighlightedText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+            </inactive>
+            <disabled>
+             <colorrole role="WindowText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>128</red>
+                <green>128</green>
+                <blue>128</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Button">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Light">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>127</green>
+                <blue>127</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Midlight">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>38</green>
+                <blue>38</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Dark">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>127</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Mid">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>170</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Text">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="BrightText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="ButtonText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>128</red>
+                <green>128</green>
+                <blue>128</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Base">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Window">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Shadow">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Highlight">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>128</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="HighlightedText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+            </disabled>
+           </palette>
+          </property>
+         </widget>
+        </item>
+       </layout>
+      </item>
+      <item row="2" column="0">
+       <layout class="QHBoxLayout" name="_9">
+        <property name="spacing">
+         <number>0</number>
+        </property>
+        <property name="leftMargin">
+         <number>0</number>
+        </property>
+        <property name="topMargin">
+         <number>0</number>
+        </property>
+        <property name="rightMargin">
+         <number>0</number>
+        </property>
+        <property name="bottomMargin">
+         <number>0</number>
+        </property>
+        <item>
+         <widget class="CMultColorLED" name="CLED_FAC" native="true">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="minimumSize">
+           <size>
+            <width>13</width>
+            <height>7</height>
+           </size>
+          </property>
+          <property name="maximumSize">
+           <size>
+            <width>13</width>
+            <height>7</height>
+           </size>
+          </property>
+          <property name="palette">
+           <palette>
+            <active>
+             <colorrole role="WindowText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Button">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Light">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>127</green>
+                <blue>127</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Midlight">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>63</green>
+                <blue>63</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Dark">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>127</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Mid">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>170</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Text">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="BrightText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="ButtonText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Base">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Window">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Shadow">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Highlight">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>128</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="HighlightedText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+            </active>
+            <inactive>
+             <colorrole role="WindowText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Button">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Light">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>127</green>
+                <blue>127</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Midlight">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>38</green>
+                <blue>38</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Dark">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>127</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Mid">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>170</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Text">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="BrightText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="ButtonText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Base">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Window">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Shadow">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Highlight">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>128</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="HighlightedText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+            </inactive>
+            <disabled>
+             <colorrole role="WindowText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>128</red>
+                <green>128</green>
+                <blue>128</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Button">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Light">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>127</green>
+                <blue>127</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Midlight">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>38</green>
+                <blue>38</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Dark">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>127</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Mid">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>170</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Text">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="BrightText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="ButtonText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>128</red>
+                <green>128</green>
+                <blue>128</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Base">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Window">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Shadow">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Highlight">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>128</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="HighlightedText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+            </disabled>
+           </palette>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="CMultColorLED" name="CLED_SDC" native="true">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="minimumSize">
+           <size>
+            <width>13</width>
+            <height>7</height>
+           </size>
+          </property>
+          <property name="maximumSize">
+           <size>
+            <width>13</width>
+            <height>7</height>
+           </size>
+          </property>
+          <property name="palette">
+           <palette>
+            <active>
+             <colorrole role="WindowText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Button">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Light">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>127</green>
+                <blue>127</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Midlight">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>63</green>
+                <blue>63</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Dark">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>127</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Mid">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>170</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Text">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="BrightText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="ButtonText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Base">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Window">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Shadow">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Highlight">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>128</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="HighlightedText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+            </active>
+            <inactive>
+             <colorrole role="WindowText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Button">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Light">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>127</green>
+                <blue>127</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Midlight">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>38</green>
+                <blue>38</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Dark">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>127</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Mid">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>170</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Text">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="BrightText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="ButtonText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Base">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Window">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Shadow">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Highlight">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>128</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="HighlightedText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+            </inactive>
+            <disabled>
+             <colorrole role="WindowText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>128</red>
+                <green>128</green>
+                <blue>128</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Button">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Light">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>127</green>
+                <blue>127</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Midlight">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>38</green>
+                <blue>38</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Dark">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>127</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Mid">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>170</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Text">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="BrightText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="ButtonText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>128</red>
+                <green>128</green>
+                <blue>128</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Base">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Window">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Shadow">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Highlight">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>128</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="HighlightedText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+            </disabled>
+           </palette>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="CMultColorLED" name="CLED_MSC" native="true">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="minimumSize">
+           <size>
+            <width>13</width>
+            <height>7</height>
+           </size>
+          </property>
+          <property name="maximumSize">
+           <size>
+            <width>13</width>
+            <height>7</height>
+           </size>
+          </property>
+          <property name="palette">
+           <palette>
+            <active>
+             <colorrole role="WindowText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Button">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Light">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>127</green>
+                <blue>127</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Midlight">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>63</green>
+                <blue>63</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Dark">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>127</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Mid">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>170</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Text">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="BrightText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="ButtonText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Base">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Window">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Shadow">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Highlight">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>128</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="HighlightedText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+            </active>
+            <inactive>
+             <colorrole role="WindowText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Button">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Light">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>127</green>
+                <blue>127</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Midlight">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>38</green>
+                <blue>38</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Dark">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>127</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Mid">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>170</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Text">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="BrightText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="ButtonText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Base">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Window">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Shadow">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Highlight">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>128</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="HighlightedText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+            </inactive>
+            <disabled>
+             <colorrole role="WindowText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>128</red>
+                <green>128</green>
+                <blue>128</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Button">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Light">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>127</green>
+                <blue>127</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Midlight">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>38</green>
+                <blue>38</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Dark">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>127</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Mid">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>170</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Text">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="BrightText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="ButtonText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>128</red>
+                <green>128</green>
+                <blue>128</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Base">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Window">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Shadow">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Highlight">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>128</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="HighlightedText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+            </disabled>
+           </palette>
+          </property>
+         </widget>
+        </item>
+       </layout>
+      </item>
+      <item row="0" column="0">
+       <layout class="QHBoxLayout" name="horizontalLayout">
+        <item>
+         <widget class="QWidget" name="onebar" native="true">
+          <property name="minimumSize">
+           <size>
+            <width>4</width>
+            <height>5</height>
+           </size>
+          </property>
+          <property name="maximumSize">
+           <size>
+            <width>4</width>
+            <height>4</height>
+           </size>
+          </property>
+          <property name="palette">
+           <palette>
+            <active>
+             <colorrole role="WindowText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Button">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>255</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Light">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>127</red>
+                <green>255</green>
+                <blue>127</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Midlight">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>63</red>
+                <green>255</green>
+                <blue>63</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Dark">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>127</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Mid">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>170</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Text">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="BrightText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="ButtonText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Base">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>255</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Window">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>255</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Shadow">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="AlternateBase">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>127</red>
+                <green>255</green>
+                <blue>127</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="NoRole">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>255</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="ToolTipBase">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>220</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="ToolTipText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+            </active>
+            <inactive>
+             <colorrole role="WindowText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Button">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>255</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Light">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>127</red>
+                <green>255</green>
+                <blue>127</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Midlight">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>63</red>
+                <green>255</green>
+                <blue>63</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Dark">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>127</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Mid">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>170</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Text">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="BrightText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="ButtonText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Base">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>255</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Window">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>255</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Shadow">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="AlternateBase">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>127</red>
+                <green>255</green>
+                <blue>127</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="NoRole">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>255</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="ToolTipBase">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>220</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="ToolTipText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+            </inactive>
+            <disabled>
+             <colorrole role="WindowText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>127</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Button">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>255</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Light">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>127</red>
+                <green>255</green>
+                <blue>127</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Midlight">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>63</red>
+                <green>255</green>
+                <blue>63</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Dark">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>127</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Mid">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>170</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Text">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>127</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="BrightText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="ButtonText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>127</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Base">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>255</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Window">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>255</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Shadow">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="AlternateBase">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>255</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="NoRole">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>255</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="ToolTipBase">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>220</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="ToolTipText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+            </disabled>
+           </palette>
+          </property>
+          <property name="autoFillBackground">
+           <bool>true</bool>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QWidget" name="twobars" native="true">
+          <property name="minimumSize">
+           <size>
+            <width>4</width>
+            <height>5</height>
+           </size>
+          </property>
+          <property name="maximumSize">
+           <size>
+            <width>4</width>
+            <height>8</height>
+           </size>
+          </property>
+          <property name="palette">
+           <palette>
+            <active>
+             <colorrole role="WindowText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Button">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>255</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Light">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>127</red>
+                <green>255</green>
+                <blue>127</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Midlight">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>63</red>
+                <green>255</green>
+                <blue>63</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Dark">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>127</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Mid">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>170</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Text">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="BrightText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="ButtonText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Base">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>255</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Window">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>255</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Shadow">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="AlternateBase">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>127</red>
+                <green>255</green>
+                <blue>127</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="NoRole">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>255</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="ToolTipBase">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>220</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="ToolTipText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+            </active>
+            <inactive>
+             <colorrole role="WindowText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Button">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>255</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Light">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>127</red>
+                <green>255</green>
+                <blue>127</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Midlight">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>63</red>
+                <green>255</green>
+                <blue>63</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Dark">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>127</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Mid">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>170</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Text">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="BrightText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="ButtonText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Base">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>255</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Window">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>255</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Shadow">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="AlternateBase">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>127</red>
+                <green>255</green>
+                <blue>127</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="NoRole">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>255</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="ToolTipBase">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>220</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="ToolTipText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+            </inactive>
+            <disabled>
+             <colorrole role="WindowText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>127</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Button">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>255</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Light">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>127</red>
+                <green>255</green>
+                <blue>127</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Midlight">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>63</red>
+                <green>255</green>
+                <blue>63</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Dark">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>127</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Mid">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>170</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Text">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>127</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="BrightText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="ButtonText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>127</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Base">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>255</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Window">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>255</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Shadow">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="AlternateBase">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>255</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="NoRole">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>255</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="ToolTipBase">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>220</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="ToolTipText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+            </disabled>
+           </palette>
+          </property>
+          <property name="autoFillBackground">
+           <bool>true</bool>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QWidget" name="threebars" native="true">
+          <property name="minimumSize">
+           <size>
+            <width>4</width>
+            <height>5</height>
+           </size>
+          </property>
+          <property name="maximumSize">
+           <size>
+            <width>4</width>
+            <height>12</height>
+           </size>
+          </property>
+          <property name="palette">
+           <palette>
+            <active>
+             <colorrole role="WindowText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Button">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>255</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Light">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>127</red>
+                <green>255</green>
+                <blue>127</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Midlight">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>63</red>
+                <green>255</green>
+                <blue>63</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Dark">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>127</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Mid">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>170</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Text">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="BrightText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="ButtonText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Base">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>255</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Window">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>255</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Shadow">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="AlternateBase">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>127</red>
+                <green>255</green>
+                <blue>127</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="NoRole">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>255</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="ToolTipBase">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>220</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="ToolTipText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+            </active>
+            <inactive>
+             <colorrole role="WindowText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Button">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>255</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Light">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>127</red>
+                <green>255</green>
+                <blue>127</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Midlight">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>63</red>
+                <green>255</green>
+                <blue>63</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Dark">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>127</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Mid">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>170</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Text">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="BrightText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="ButtonText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Base">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>255</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Window">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>255</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Shadow">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="AlternateBase">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>127</red>
+                <green>255</green>
+                <blue>127</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="NoRole">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>255</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="ToolTipBase">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>220</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="ToolTipText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+            </inactive>
+            <disabled>
+             <colorrole role="WindowText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>127</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Button">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>255</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Light">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>127</red>
+                <green>255</green>
+                <blue>127</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Midlight">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>63</red>
+                <green>255</green>
+                <blue>63</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Dark">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>127</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Mid">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>170</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Text">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>127</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="BrightText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="ButtonText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>127</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Base">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>255</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Window">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>255</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Shadow">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="AlternateBase">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>255</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="NoRole">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>255</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="ToolTipBase">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>220</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="ToolTipText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+            </disabled>
+           </palette>
+          </property>
+          <property name="autoFillBackground">
+           <bool>true</bool>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QWidget" name="fourbars" native="true">
+          <property name="minimumSize">
+           <size>
+            <width>4</width>
+            <height>5</height>
+           </size>
+          </property>
+          <property name="maximumSize">
+           <size>
+            <width>4</width>
+            <height>16</height>
+           </size>
+          </property>
+          <property name="palette">
+           <palette>
+            <active>
+             <colorrole role="WindowText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Button">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>255</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Light">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>127</red>
+                <green>255</green>
+                <blue>127</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Midlight">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>63</red>
+                <green>255</green>
+                <blue>63</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Dark">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>127</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Mid">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>170</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Text">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="BrightText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="ButtonText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Base">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>255</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Window">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>255</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Shadow">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="AlternateBase">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>127</red>
+                <green>255</green>
+                <blue>127</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="NoRole">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>255</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="ToolTipBase">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>220</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="ToolTipText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+            </active>
+            <inactive>
+             <colorrole role="WindowText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Button">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>255</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Light">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>127</red>
+                <green>255</green>
+                <blue>127</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Midlight">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>63</red>
+                <green>255</green>
+                <blue>63</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Dark">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>127</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Mid">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>170</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Text">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="BrightText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="ButtonText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Base">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>255</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Window">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>255</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Shadow">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="AlternateBase">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>127</red>
+                <green>255</green>
+                <blue>127</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="NoRole">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>255</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="ToolTipBase">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>220</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="ToolTipText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+            </inactive>
+            <disabled>
+             <colorrole role="WindowText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>127</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Button">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>255</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Light">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>127</red>
+                <green>255</green>
+                <blue>127</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Midlight">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>63</red>
+                <green>255</green>
+                <blue>63</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Dark">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>127</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Mid">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>170</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Text">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>127</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="BrightText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="ButtonText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>127</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Base">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>255</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Window">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>255</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Shadow">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="AlternateBase">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>255</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="NoRole">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>255</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="ToolTipBase">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>220</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="ToolTipText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+            </disabled>
+           </palette>
+          </property>
+          <property name="autoFillBackground">
+           <bool>true</bool>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QWidget" name="fivebars" native="true">
+          <property name="minimumSize">
+           <size>
+            <width>4</width>
+            <height>5</height>
+           </size>
+          </property>
+          <property name="maximumSize">
+           <size>
+            <width>4</width>
+            <height>20</height>
+           </size>
+          </property>
+          <property name="palette">
+           <palette>
+            <active>
+             <colorrole role="WindowText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Button">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>255</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Light">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>127</red>
+                <green>255</green>
+                <blue>127</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Midlight">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>63</red>
+                <green>255</green>
+                <blue>63</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Dark">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>127</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Mid">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>170</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Text">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="BrightText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="ButtonText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Base">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>255</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Window">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>255</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Shadow">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="AlternateBase">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>127</red>
+                <green>255</green>
+                <blue>127</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="NoRole">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>255</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="ToolTipBase">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>220</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="ToolTipText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+            </active>
+            <inactive>
+             <colorrole role="WindowText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Button">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>255</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Light">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>127</red>
+                <green>255</green>
+                <blue>127</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Midlight">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>63</red>
+                <green>255</green>
+                <blue>63</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Dark">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>127</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Mid">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>170</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Text">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="BrightText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="ButtonText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Base">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>255</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Window">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>255</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Shadow">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="AlternateBase">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>127</red>
+                <green>255</green>
+                <blue>127</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="NoRole">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>255</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="ToolTipBase">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>220</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="ToolTipText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+            </inactive>
+            <disabled>
+             <colorrole role="WindowText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>127</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Button">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>255</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Light">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>127</red>
+                <green>255</green>
+                <blue>127</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Midlight">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>63</red>
+                <green>255</green>
+                <blue>63</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Dark">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>127</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Mid">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>170</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Text">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>127</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="BrightText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>255</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="ButtonText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>127</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Base">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>255</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Window">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>255</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="Shadow">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="AlternateBase">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>255</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="NoRole">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>255</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="ToolTipBase">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>255</red>
+                <green>255</green>
+                <blue>220</blue>
+               </color>
+              </brush>
+             </colorrole>
+             <colorrole role="ToolTipText">
+              <brush brushstyle="SolidPattern">
+               <color alpha="255">
+                <red>0</red>
+                <green>0</green>
+                <blue>0</blue>
+               </color>
+              </brush>
+             </colorrole>
+            </disabled>
+           </palette>
+          </property>
+          <property name="autoFillBackground">
+           <bool>true</bool>
+          </property>
+         </widget>
+        </item>
+       </layout>
+      </item>
+     </layout>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>QwtThermo</class>
+   <extends>QWidget</extends>
+   <header>qwt_thermo.h</header>
+  </customwidget>
+  <customwidget>
+   <class>CMultColorLED</class>
+   <extends>QWidget</extends>
+   <header location="global">MultColorLED.h</header>
+  </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/GUI-QT/drmoptions.cpp b/src/GUI-QT/drmoptions.cpp
new file mode 100644
index 0000000..a553370
--- /dev/null
+++ b/src/GUI-QT/drmoptions.cpp
@@ -0,0 +1,258 @@
+#include "drmoptions.h"
+#include "ui_drmoptions.h"
+#include <QButtonGroup>
+
+DRMOptions::DRMOptions(QWidget *parent) :
+    QWidget(parent),
+    ui(new Ui::DRMOptions),rsci_mode(false)
+{
+    ui->setupUi(this);
+    /* Init slider control */
+    ui->SliderNoOfIterations->setRange(0, 4);
+    ui->SliderNoOfIterations->setValue(0);
+    ui->TextNumOfIterations->setText(tr("MLC: Number of Iterations: ") + QString().setNum(0));
+
+    QButtonGroup* ti = new QButtonGroup(this);
+    ti->addButton(ui->RadioButtonTiLinear, CChannelEstimation::TLINEAR);
+    ti->addButton(ui->RadioButtonTiWiener, CChannelEstimation::TWIENER);
+    connect(ti, SIGNAL(buttonClicked(int)), this, SIGNAL(timeIntChanged(int)));
+    QButtonGroup* fr = new QButtonGroup(this);
+    fr->addButton(ui->RadioButtonFreqLinear, CChannelEstimation::FLINEAR);
+    fr->addButton(ui->RadioButtonFreqDFT, CChannelEstimation::FDFTFILTER);
+    fr->addButton(ui->RadioButtonFreqWiener, CChannelEstimation::FWIENER);
+    connect(fr, SIGNAL(buttonClicked(int)), this, SIGNAL(freqIntChanged(int)));
+    QButtonGroup* ts = new QButtonGroup(this);
+    ts->addButton(ui->RadioButtonTiSyncEnergy, CTimeSyncTrack::TSENERGY);
+    ts->addButton(ui->RadioButtonTiSyncFirstPeak, CTimeSyncTrack::TSFIRSTPEAK);
+    connect(ts, SIGNAL(buttonClicked(int)), this, SIGNAL(timeSyncChanged(int)));
+    /* Check boxes */
+    connect(ui->CheckBoxFlipSpec, SIGNAL(clicked(bool)), this, SIGNAL(flipSpectrum(bool)));
+    connect(ui->CheckBoxRecFilter, SIGNAL(clicked(bool)), this, SIGNAL(recFilter(bool)));
+    connect(ui->CheckBoxModiMetric, SIGNAL(clicked(bool)), this, SIGNAL(modiMetric(bool)));
+}
+
+DRMOptions::~DRMOptions()
+{
+    delete ui;
+}
+
+void
+DRMOptions::setRSCIModeEnabled(bool enabled)
+{
+    rsci_mode = enabled;
+    ui->SliderNoOfIterations->setEnabled(!enabled);
+
+    ui->ButtonGroupChanEstFreqInt->setEnabled(!enabled);
+    ui->ButtonGroupChanEstTimeInt->setEnabled(!enabled);
+    ui->ButtonGroupTimeSyncTrack->setEnabled(!enabled);
+    ui->CheckBoxFlipSpec->setEnabled(!enabled);
+    ui->GroupBoxInterfRej->setEnabled(!enabled);
+}
+
+/* Slider for MLC number of iterations */
+void
+DRMOptions::setNumIterations(int iNumIt)
+{
+    if (ui->SliderNoOfIterations->value() != iNumIt)
+    {
+        /* Update slider and label */
+        ui->SliderNoOfIterations->setValue(iNumIt);
+        ui->TextNumOfIterations->setText(tr("MLC: Number of Iterations: ") +
+                                     QString().setNum(iNumIt));
+    }
+}
+
+void DRMOptions::on_SliderNoOfIterations_valueChanged(int value)
+{
+    /* Show the new value in the label control */
+    ui->TextNumOfIterations->setText(tr("MLC: Number of Iterations: ") +
+                                 QString().setNum(value));
+}
+
+void DRMOptions::setTimeInt(CChannelEstimation::ETypeIntTime state)
+{
+    switch (state)
+    {
+    case CChannelEstimation::TLINEAR:
+        if (!ui->RadioButtonTiLinear->isChecked())
+            ui->RadioButtonTiLinear->setChecked(TRUE);
+        break;
+
+    case CChannelEstimation::TWIENER:
+        if (!ui->RadioButtonTiWiener->isChecked())
+            ui->RadioButtonTiWiener->setChecked(TRUE);
+        break;
+    }
+}
+
+void DRMOptions::setFreqInt(CChannelEstimation::ETypeIntFreq state)
+{
+    switch (state)
+    {
+    case CChannelEstimation::FLINEAR:
+        if (!ui->RadioButtonFreqLinear->isChecked())
+            ui->RadioButtonFreqLinear->setChecked(TRUE);
+        break;
+
+    case CChannelEstimation::FDFTFILTER:
+        if (!ui->RadioButtonFreqDFT->isChecked())
+            ui->RadioButtonFreqDFT->setChecked(TRUE);
+        break;
+
+    case CChannelEstimation::FWIENER:
+        if (!ui->RadioButtonFreqWiener->isChecked())
+            ui->RadioButtonFreqWiener->setChecked(TRUE);
+        break;
+    }
+
+}
+
+void DRMOptions::setTiSyncTrac(CTimeSyncTrack::ETypeTiSyncTrac state)
+{
+    switch (state)
+    {
+    case CTimeSyncTrack::TSFIRSTPEAK:
+        if (!ui->RadioButtonTiSyncFirstPeak->isChecked())
+            ui->RadioButtonTiSyncFirstPeak->setChecked(TRUE);
+        break;
+
+    case CTimeSyncTrack::TSENERGY:
+        if (!ui->RadioButtonTiSyncEnergy->isChecked())
+            ui->RadioButtonTiSyncEnergy->setChecked(TRUE);
+        break;
+    }
+
+}
+
+void DRMOptions::setRecFilterEnabled(bool b)
+{
+    ui->CheckBoxRecFilter->setChecked(b);
+}
+
+void DRMOptions::setIntConsEnabled(bool b)
+{
+    ui->CheckBoxModiMetric->setChecked(b);
+}
+
+void DRMOptions::setFlipSpectrumEnabled(bool b)
+{
+    ui->CheckBoxFlipSpec->setChecked(b);
+}
+
+void DRMOptions::AddWhatsThisHelp()
+{
+    /* Flip Input Spectrum */
+    ui->CheckBoxFlipSpec->setWhatsThis(
+                     tr("<b>Flip Input Spectrum:</b> Checking this box "
+                        "will flip or invert the input spectrum. This is necessary if the "
+                        "mixer in the front-end uses the lower side band."));
+
+    /* Wiener */
+    const QString strWienerChanEst =
+        tr("<b>Channel Estimation Settings:</b> With these "
+           "settings, the channel estimation method in time and frequency "
+           "direction can be selected. The default values use the most powerful "
+           "algorithms. For more detailed information about the estimation "
+           "algorithms there are a lot of papers and books available.<br>"
+           "<b>Wiener:</b> Wiener interpolation method "
+           "uses estimation of the statistics of the channel to design an optimal "
+           "filter for noise reduction.");
+
+    ui->RadioButtonFreqWiener->setWhatsThis(strWienerChanEst);
+    ui->RadioButtonTiWiener->setWhatsThis(strWienerChanEst);
+
+    /* Linear */
+    const QString strLinearChanEst =
+        tr("<b>Channel Estimation Settings:</b> With these "
+           "settings, the channel estimation method in time and frequency "
+           "direction can be selected. The default values use the most powerful "
+           "algorithms. For more detailed information about the estimation "
+           "algorithms there are a lot of papers and books available.<br>"
+           "<b>Linear:</b> Simple linear interpolation "
+           "method to get the channel estimate. The real and imaginary parts "
+           "of the estimated channel at the pilot positions are linearly "
+           "interpolated. This algorithm causes the lowest CPU load but "
+           "performs much worse than the Wiener interpolation at low SNRs.");
+
+    ui->RadioButtonFreqLinear->setWhatsThis(strLinearChanEst);
+    ui->RadioButtonTiLinear->setWhatsThis(strLinearChanEst);
+
+    /* DFT Zero Pad */
+    ui->RadioButtonFreqDFT->setWhatsThis(
+                     tr("<b>Channel Estimation Settings:</b> With these "
+                        "settings, the channel estimation method in time and frequency "
+                        "direction can be selected. The default values use the most powerful "
+                        "algorithms. For more detailed information about the estimation "
+                        "algorithms there are a lot of papers and books available.<br>"
+                        "<b>DFT Zero Pad:</b> Channel estimation method "
+                        "for the frequency direction using Discrete Fourier Transformation "
+                        "(DFT) to transform the channel estimation at the pilot positions to "
+                        "the time domain. There, a zero padding is applied to get a higher "
+                        "resolution in the frequency domain -> estimates at the data cells. "
+                        "This algorithm is very speed efficient but has problems at the edges "
+                        "of the OFDM spectrum due to the leakage effect."));
+
+    /* Guard Energy */
+    ui->RadioButtonTiSyncEnergy->setWhatsThis(
+                     tr("<b>Guard Energy:</b> Time synchronization "
+                        "tracking algorithm utilizes the estimation of the impulse response. "
+                        "This method tries to maximize the energy in the guard-interval to set "
+                        "the correct timing."));
+
+    /* First Peak */
+    ui->RadioButtonTiSyncFirstPeak->setWhatsThis(
+                     tr("<b>First Peak:</b> This algorithms searches for "
+                        "the first peak in the estimated impulse response and moves this peak "
+                        "to the beginning of the guard-interval (timing tracking algorithm)."));
+
+    /* Interferer Rejection */
+    const QString strInterfRej =
+        tr("<b>Interferer Rejection:</b> There are two "
+           "algorithms available to reject interferers:<ul>"
+           "<li><b>Bandpass Filter (BP-Filter):</b>"
+           " The bandpass filter is designed to have the same bandwidth as "
+           "the DRM signal. If, e.g., a strong signal is close to the border "
+           "of the actual DRM signal, under some conditions this signal will "
+           "produce interference in the useful bandwidth of the DRM signal "
+           "although it is not on the same frequency as the DRM signal. "
+           "The reason for that behaviour lies in the way the OFDM "
+           "demodulation is done. Since OFDM demodulation is a block-wise "
+           "operation, a windowing has to be applied (which is rectangular "
+           "in case of OFDM). As a result, the spectrum of a signal is "
+           "convoluted with a Sinc function in the frequency domain. If a "
+           "sinusoidal signal close to the border of the DRM signal is "
+           "considered, its spectrum will not be a distinct peak but a "
+           "shifted Sinc function. So its spectrum is broadened caused by "
+           "the windowing. Thus, it will spread in the DRM spectrum and "
+           "act as an in-band interferer.<br>"
+           "There is a special case if the sinusoidal signal is in a "
+           "distance of a multiple of the carrier spacing of the DRM signal. "
+           "Since the Sinc function has zeros at certain positions it happens "
+           "that in this case the zeros are exactly at the sub-carrier "
+           "frequencies of the DRM signal. In this case, no interference takes "
+           "place. If the sinusoidal signal is in a distance of a multiple of "
+           "the carrier spacing plus half of the carrier spacing away from the "
+           "DRM signal, the interference reaches its maximum.<br>"
+           "As a result, if only one DRM signal is present in the 20 kHz "
+           "bandwidth, bandpass filtering has no effect. Also,  if the "
+           "interferer is far away from the DRM signal, filtering will not "
+           "give much improvement since the squared magnitude of the spectrum "
+           "of the Sinc function is approx -15 dB down at 1 1/2 carrier "
+           "spacing (approx 70 Hz with DRM mode B) and goes down to approx "
+           "-30 dB at 10 times the carrier spacing plus 1 / 2 of the carrier "
+           "spacing (approx 525 Hz with DRM mode B). The bandpass filter must "
+           "have very sharp edges otherwise the gain in performance will be "
+           "very small.</li>"
+           "<li><b>Modified Metrics:</b> Based on the "
+           "information from the SNR versus sub-carrier estimation, the metrics "
+           "for the Viterbi decoder can be modified so that sub-carriers with "
+           "high noise are attenuated and do not contribute too much to the "
+           "decoding result. That can improve reception under bad conditions but "
+           "may worsen the reception in situations where a lot of fading happens "
+           "and no interferer are present since the SNR estimation may be "
+           "not correct.</li></ul>");
+
+    ui->GroupBoxInterfRej->setWhatsThis(strInterfRej);
+    ui->CheckBoxRecFilter->setWhatsThis(strInterfRej);
+    ui->CheckBoxModiMetric->setWhatsThis(strInterfRej);
+}
diff --git a/src/GUI-QT/drmoptions.h b/src/GUI-QT/drmoptions.h
new file mode 100644
index 0000000..3c04e11
--- /dev/null
+++ b/src/GUI-QT/drmoptions.h
@@ -0,0 +1,46 @@
+#ifndef DRMOPTIONS_H
+#define DRMOPTIONS_H
+
+#include <QWidget>
+#include <../chanest/ChannelEstimation.h>
+#include <../sync/TimeSyncTrack.h>
+
+namespace Ui {
+class DRMOptions;
+}
+
+class DRMOptions : public QWidget
+{
+    Q_OBJECT
+
+public:
+    explicit DRMOptions(QWidget *parent = 0);
+    ~DRMOptions();
+    void setRSCIModeEnabled(bool enabled);
+    void setNumIterations(int iNumIt);
+    void setTimeInt(CChannelEstimation::ETypeIntTime);
+    void setFreqInt(CChannelEstimation::ETypeIntFreq);
+    void setTiSyncTrac(CTimeSyncTrack::ETypeTiSyncTrac);
+    void setRecFilterEnabled(bool);
+    void setIntConsEnabled(bool);
+    void setFlipSpectrumEnabled(bool);
+
+private:
+    Ui::DRMOptions *ui;
+    bool rsci_mode;
+    void AddWhatsThisHelp();
+
+private slots:
+    void on_SliderNoOfIterations_valueChanged(int);
+
+signals:
+    void noOfIterationsChanged(int);
+    void timeIntChanged(int);
+    void freqIntChanged(int);
+    void timeSyncChanged(int);
+    void flipSpectrum(bool);
+    void recFilter(bool);
+    void modiMetric(bool);
+};
+
+#endif // DRMOPTIONS_H
diff --git a/src/GUI-QT/drmoptions.ui b/src/GUI-QT/drmoptions.ui
new file mode 100644
index 0000000..6178980
--- /dev/null
+++ b/src/GUI-QT/drmoptions.ui
@@ -0,0 +1,364 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>DRMOptions</class>
+ <widget class="QWidget" name="DRMOptions">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>589</width>
+    <height>134</height>
+   </rect>
+  </property>
+  <property name="sizePolicy">
+   <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+    <horstretch>0</horstretch>
+    <verstretch>0</verstretch>
+   </sizepolicy>
+  </property>
+  <property name="windowTitle">
+   <string>Form</string>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout_2">
+   <item>
+    <layout class="QHBoxLayout" name="horizontalLayout_2">
+     <item>
+      <widget class="QGroupBox" name="ButtonGroupChanEstFreqInt">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Fixed" vsizetype="Minimum">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="title">
+        <string>Channel Estimation: Frequency</string>
+       </property>
+       <property name="alignment">
+        <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+       </property>
+       <layout class="QHBoxLayout" name="_19">
+        <property name="spacing">
+         <number>6</number>
+        </property>
+        <property name="leftMargin">
+         <number>9</number>
+        </property>
+        <property name="topMargin">
+         <number>9</number>
+        </property>
+        <property name="rightMargin">
+         <number>9</number>
+        </property>
+        <property name="bottomMargin">
+         <number>9</number>
+        </property>
+        <item>
+         <widget class="QRadioButton" name="RadioButtonFreqWiener">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="text">
+           <string>Wiener</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QRadioButton" name="RadioButtonFreqLinear">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="text">
+           <string>Linear</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QRadioButton" name="RadioButtonFreqDFT">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="text">
+           <string>DFT Zero Pad.</string>
+          </property>
+         </widget>
+        </item>
+       </layout>
+      </widget>
+     </item>
+     <item>
+      <widget class="QGroupBox" name="ButtonGroupChanEstTimeInt">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="title">
+        <string>Channel Estimation: Time</string>
+       </property>
+       <property name="alignment">
+        <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+       </property>
+       <layout class="QHBoxLayout" name="_20">
+        <property name="spacing">
+         <number>6</number>
+        </property>
+        <property name="leftMargin">
+         <number>9</number>
+        </property>
+        <property name="topMargin">
+         <number>9</number>
+        </property>
+        <property name="rightMargin">
+         <number>9</number>
+        </property>
+        <property name="bottomMargin">
+         <number>9</number>
+        </property>
+        <item>
+         <widget class="QRadioButton" name="RadioButtonTiWiener">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="text">
+           <string>Wiener</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QRadioButton" name="RadioButtonTiLinear">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="text">
+           <string>Linear</string>
+          </property>
+         </widget>
+        </item>
+       </layout>
+      </widget>
+     </item>
+     <item>
+      <widget class="QGroupBox" name="ButtonGroupTimeSyncTrack">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="title">
+        <string>Time Sync Tracking</string>
+       </property>
+       <property name="alignment">
+        <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+       </property>
+       <layout class="QHBoxLayout" name="_21">
+        <property name="spacing">
+         <number>6</number>
+        </property>
+        <property name="leftMargin">
+         <number>9</number>
+        </property>
+        <property name="topMargin">
+         <number>9</number>
+        </property>
+        <property name="rightMargin">
+         <number>9</number>
+        </property>
+        <property name="bottomMargin">
+         <number>9</number>
+        </property>
+        <item>
+         <widget class="QRadioButton" name="RadioButtonTiSyncEnergy">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="text">
+           <string>Guard Energy</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QRadioButton" name="RadioButtonTiSyncFirstPeak">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="text">
+           <string>First Peak</string>
+          </property>
+         </widget>
+        </item>
+       </layout>
+      </widget>
+     </item>
+    </layout>
+   </item>
+   <item>
+    <layout class="QHBoxLayout" name="horizontalLayout">
+     <item>
+      <widget class="QGroupBox" name="GroupBoxInterfRej">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="title">
+        <string>Interferer Rejection</string>
+       </property>
+       <property name="alignment">
+        <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+       </property>
+       <layout class="QGridLayout" name="gridLayout">
+        <item row="0" column="0">
+         <widget class="QCheckBox" name="CheckBoxRecFilter">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="text">
+           <string>&Bandpass Filter</string>
+          </property>
+         </widget>
+        </item>
+        <item row="0" column="1">
+         <widget class="QCheckBox" name="CheckBoxModiMetric">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="text">
+           <string>Modified &Metrics</string>
+          </property>
+         </widget>
+        </item>
+       </layout>
+      </widget>
+     </item>
+     <item>
+      <widget class="QGroupBox" name="GroupBoxMiscSettings">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="title">
+        <string>Input</string>
+       </property>
+       <property name="alignment">
+        <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+       </property>
+       <layout class="QGridLayout" name="gridLayout_2">
+        <item row="1" column="0">
+         <widget class="QCheckBox" name="CheckBoxFlipSpec">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="text">
+           <string>&Flip Spectrum</string>
+          </property>
+         </widget>
+        </item>
+       </layout>
+      </widget>
+     </item>
+     <item>
+      <layout class="QVBoxLayout" name="verticalLayout">
+       <item>
+        <widget class="QLabel" name="TextNumOfIterations">
+         <property name="sizePolicy">
+          <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+           <horstretch>0</horstretch>
+           <verstretch>0</verstretch>
+          </sizepolicy>
+         </property>
+         <property name="text">
+          <string>TextNumOfIterations</string>
+         </property>
+         <property name="alignment">
+          <set>Qt::AlignCenter</set>
+         </property>
+         <property name="wordWrap">
+          <bool>false</bool>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="QSlider" name="SliderNoOfIterations">
+         <property name="sizePolicy">
+          <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+           <horstretch>0</horstretch>
+           <verstretch>0</verstretch>
+          </sizepolicy>
+         </property>
+         <property name="minimumSize">
+          <size>
+           <width>100</width>
+           <height>0</height>
+          </size>
+         </property>
+         <property name="maximum">
+          <number>6</number>
+         </property>
+         <property name="pageStep">
+          <number>1</number>
+         </property>
+         <property name="orientation">
+          <enum>Qt::Horizontal</enum>
+         </property>
+         <property name="tickPosition">
+          <enum>QSlider::TicksBothSides</enum>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <spacer name="verticalSpacer">
+         <property name="orientation">
+          <enum>Qt::Vertical</enum>
+         </property>
+         <property name="sizeHint" stdset="0">
+          <size>
+           <width>0</width>
+           <height>0</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
+      </layout>
+     </item>
+    </layout>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/GUI-QT/engineeringtabwidget.cpp b/src/GUI-QT/engineeringtabwidget.cpp
new file mode 100644
index 0000000..f8fe367
--- /dev/null
+++ b/src/GUI-QT/engineeringtabwidget.cpp
@@ -0,0 +1,17 @@
+#include "engineeringtabwidget.h"
+#include "channelwidget.h"
+#include <QLabel>
+
+EngineeringTabWidget::EngineeringTabWidget(ReceiverController* controller, QWidget *parent) :
+    QTabWidget(parent)
+{
+    int iPlotStyle = 0;// TODO set from menu
+    ChannelWidget* pCh = new ChannelWidget(controller);
+    pCh->setPlotStyle(iPlotStyle);
+    controller->setControls(); // new controls so fill their values from the receiver controller
+    //connect(parent, SIGNAL(plotStyleChanged(int)), pCh, SLOT(setPlotStyle(int)));
+    addTab(pCh, "Channel");
+    addTab(new QLabel("Streams"), "Streams");
+    addTab(new QLabel("AFS"), "AFS");
+    addTab(new QLabel("GPS"), "GPS");
+}
diff --git a/src/GUI-QT/engineeringtabwidget.h b/src/GUI-QT/engineeringtabwidget.h
new file mode 100644
index 0000000..9c41121
--- /dev/null
+++ b/src/GUI-QT/engineeringtabwidget.h
@@ -0,0 +1,20 @@
+#ifndef ENGINEERINGTABWIDGET_H
+#define ENGINEERINGTABWIDGET_H
+
+#include <QTabWidget>
+
+class ReceiverController;
+
+class EngineeringTabWidget : public QTabWidget
+{
+    Q_OBJECT
+public:
+    explicit EngineeringTabWidget(ReceiverController*, QWidget *parent = 0);
+
+signals:
+
+public slots:
+
+};
+
+#endif // ENGINEERINGTABWIDGET_H
diff --git a/src/GUI-QT/fdrmdialog.cpp b/src/GUI-QT/fdrmdialog.cpp
new file mode 100644
index 0000000..45160d2
--- /dev/null
+++ b/src/GUI-QT/fdrmdialog.cpp
@@ -0,0 +1,1293 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer, Andrea Russo, David Flamand, Julian Cable
+ *
+ * Description:
+ *
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "fdrmdialog.h"
+#include <iostream>
+#include <QDir>
+#include <QWhatsThis>
+#include <QHideEvent>
+#include <QEvent>
+#include <QShowEvent>
+#include <QCloseEvent>
+#include <QMessageBox>
+#include <QColorDialog>
+#include <QDoubleValidator>
+
+#include "ui_DRMMainWindow.h"
+
+#include "dreamtabwidget.h"
+#include "engineeringtabwidget.h"
+#include "SlideShowViewer.h"
+#include "JLViewer.h"
+#ifdef QT_WEBKIT_LIB
+# include "BWSViewer.h"
+#endif
+#ifdef HAVE_LIBHAMLIB
+# include "../util-QT/Rig.h"
+#endif
+#include "../Scheduler.h"
+#include "../util-QT/Util.h"
+#include "../util-QT/EPG.h"
+#include "EvaluationDlg.h"
+#include "SoundCardSelMenu.h"
+#include "DialogUtil.h"
+#include "StationsDlg.h"
+#include "LiveScheduleDlg.h"
+#include "EPGDlg.h"
+#include "AnalogDemDlg.h"
+#include "MultSettingsDlg.h"
+#include "GeneralSettingsDlg.h"
+#include "MultColorLED.h"
+#include "Logging.h"
+#include "../datadecoding/DataDecoder.h"
+#include "serviceselector.h"
+#include "ThemeCustomizer.h"
+
+// Simone's values
+// static _REAL WMERSteps[] = {8.0, 12.0, 16.0, 20.0, 24.0};
+// David's values
+static _REAL WMERSteps[] = {6.0, 12.0, 18.0, 24.0, 30.0};
+
+static const bool DEFAULT_TO_SINGLE_WINDOW_MODE=true;
+static const int DEFAULT_PLOT_STYLE=0; /* 0 = blue/white, 1 = green/black, 2 = black/grey */
+static const int DEFAULT_MESSAGE_STYLE=0; /* 0 = black on white , 1 = white on black */
+
+/* Implementation *************************************************************/
+#ifdef HAVE_LIBHAMLIB
+FDRMDialog::FDRMDialog(CDRMReceiver& NDRMR, CSettings& Settings, CRig& rig,
+                       QWidget* parent)
+#else
+FDRMDialog::FDRMDialog(CDRMReceiver& NDRMR, CSettings& Settings, 
+                       QWidget* parent)
+#endif
+    :
+    CWindow(parent, Settings, "DRM"),
+    ui(new Ui::DRMMainWindow),
+    DRMReceiver(NDRMR),
+    controller(new ReceiverController(&NDRMR, Settings, this)),
+    pLogging(NULL), pSysEvalDlg(NULL), pBWSDlg(NULL),
+    pGeneralSettingsDlg(NULL), pMultSettingsDlg(NULL),
+    pSysTray(NULL), pAboutDlg(NULL),
+    pScheduler(NULL), pScheduleTimer(NULL), iCurrentFrequency(-1),
+    pServiceSelector(NULL), pServiceTabs(NULL), pEngineeringTabs(NULL),
+    pMultimediaWindow(NULL),
+    baseWindowTitle(tr("Dream DRM Receiver"))
+{
+    ui->setupUi(this);
+    ui->lineEditFrequency->setVisible(false);
+    QDoubleValidator* fvalid = new QDoubleValidator(this);
+    ui->lineEditFrequency->setValidator(fvalid);
+    connect(ui->lineEditFrequency, SIGNAL(returnPressed ()), this, SLOT(tune()));
+
+    /* Set help text for the controls */
+    AddWhatsThisHelp();
+
+    CParameter& Parameters = *DRMReceiver.GetParameters();
+
+    pLogging = new CLogging(Parameters);
+    pLogging->LoadSettings(Settings);
+
+    /* Creation of file and sound card ui->menu */
+    pFileMenu = new CFileMenu(DRMReceiver, this, ui->menu_View);
+    pSoundCardMenu = new CSoundCardSelMenu(DRMReceiver, pFileMenu, this);
+    ui->menu_Settings->addMenu(pSoundCardMenu);
+    connect(pFileMenu, SIGNAL(soundFileChanged(CDRMReceiver::ESFStatus)), this, SLOT(OnSoundFileChanged(CDRMReceiver::ESFStatus)));
+
+    /* Analog demodulation window */
+    pAnalogDemDlg = new AnalogDemDlg(controller, Settings, pFileMenu, pSoundCardMenu);
+
+    /* Parent list for Stations and Live Schedule window */
+	QMap <QWidget*,QString> parents;
+	parents[this] = "drm";
+	parents[pAnalogDemDlg] = "analog";
+
+    /* Stations window */
+#ifdef HAVE_LIBHAMLIB
+    pStationsDlg = new StationsDlg(Settings, rig, parents);
+#else
+    pStationsDlg = new StationsDlg(Settings, parents);
+#endif
+
+    /* Live Schedule window */
+    pLiveScheduleDlg = new LiveScheduleDlg(Settings, parents);
+
+    /* Journaline viewer window */
+    pJLDlg = new JLViewer(Settings, this);
+
+    /* MOT slide show window */
+    pSlideShowDlg = new SlideShowViewer(Settings, this);
+
+    /* Programme Guide Window */
+    string sDataFilesDirectory = Settings.Get(
+                "Receiver", "datafilesdirectory", string(DEFAULT_DATA_FILES_DIRECTORY));
+    pEPGDlg = new EPGDlg(Settings, this);
+    pEPGDlg->setDecoder(new EPG(Parameters, sDataFilesDirectory));
+
+    /* Evaluation window */
+    pSysEvalDlg = new systemevalDlg(controller, Settings, this);
+
+    connect(ui->action_Evaluation_Dialog, SIGNAL(triggered()), pSysEvalDlg, SLOT(show()));
+    connect(ui->action_Stations_Dialog, SIGNAL(triggered()), pStationsDlg, SLOT(show()));
+    connect(ui->action_Live_Schedule_Dialog, SIGNAL(triggered()), pLiveScheduleDlg, SLOT(show()));
+    connect(ui->action_Programme_Guide_Dialog, SIGNAL(triggered()), pEPGDlg, SLOT(show()));
+    connect(ui->actionExit, SIGNAL(triggered()), this, SLOT(close()));
+    ui->action_Multimedia_Dialog->setEnabled(false);
+
+    connect(ui->actionAM, SIGNAL(triggered()), this, SLOT(OnSwitchToAM()));
+    connect(ui->actionDRM, SIGNAL(triggered()), this, SLOT(OnSwitchToDRM()));
+    connect(ui->actionFM, SIGNAL(triggered()), this, SLOT(OnSwitchToFM()));
+
+    connect(ui->actionDisplayColor, SIGNAL(triggered()), this, SLOT(OnMenuSetDisplayColor()));
+
+    /* Message style settings */
+    QSignalMapper* messageStyleMapper = new QSignalMapper(this);
+    QActionGroup* messageStyleGroup = new QActionGroup(this);
+    messageStyleGroup->addAction(ui->actionBlackOnWhite);
+    messageStyleGroup->addAction(ui->actionWhiteOnBlack);
+    messageStyleMapper->setMapping(ui->actionBlackOnWhite, 0);
+    messageStyleMapper->setMapping(ui->actionWhiteOnBlack, 1);
+    connect(ui->actionWhiteOnBlack, SIGNAL(triggered()), messageStyleMapper, SLOT(map()));
+    connect(ui->actionBlackOnWhite, SIGNAL(triggered()), messageStyleMapper, SLOT(map()));
+    connect(messageStyleMapper, SIGNAL(mapped(int)), this, SLOT(OnMenuMessageStyle(int)));
+    int iMessageStyle = getSetting("messagestyle", DEFAULT_MESSAGE_STYLE, true);
+    switch(iMessageStyle) {
+    case 0: ui->actionBlackOnWhite->setChecked(true); break;
+    case 1: ui->actionWhiteOnBlack->setChecked(true); break; }
+    OnMenuMessageStyle(iMessageStyle);
+
+    /* Plot style settings */
+    QSignalMapper* plotStyleMapper = new QSignalMapper(this);
+    QActionGroup* plotStyleGroup = new QActionGroup(this);
+    plotStyleGroup->addAction(ui->actionBlueWhite);
+    plotStyleGroup->addAction(ui->actionGreenBlack);
+    plotStyleGroup->addAction(ui->actionBlackGrey);
+    plotStyleMapper->setMapping(ui->actionBlueWhite, 0);
+    plotStyleMapper->setMapping(ui->actionGreenBlack, 1);
+    plotStyleMapper->setMapping(ui->actionBlackGrey, 2);
+    connect(ui->actionBlueWhite, SIGNAL(triggered()), plotStyleMapper, SLOT(map()));
+    connect(ui->actionGreenBlack, SIGNAL(triggered()), plotStyleMapper, SLOT(map()));
+    connect(ui->actionBlackGrey, SIGNAL(triggered()), plotStyleMapper, SLOT(map()));
+    connect(plotStyleMapper, SIGNAL(mapped(int)), this, SIGNAL(plotStyleChanged(int)));
+    connect(this, SIGNAL(plotStyleChanged(int)), pSysEvalDlg, SLOT(UpdatePlotStyle(int)));
+    connect(this, SIGNAL(plotStyleChanged(int)), pAnalogDemDlg, SLOT(UpdatePlotStyle(int)));
+    connect(this, SIGNAL(plotStyleChanged(int)), this, SLOT(OnMenuPlotStyle(int)));
+    int iPlotStyle = getSetting("plotstyle", DEFAULT_PLOT_STYLE, true);
+    switch(iPlotStyle) {
+    case 0: ui->actionBlueWhite->setChecked(true);  break;
+    case 1: ui->actionGreenBlack->setChecked(true); break;
+    case 2: ui->actionBlackGrey->setChecked(true);  break; }
+    emit plotStyleChanged(iPlotStyle);
+
+    connect(ui->actionAbout_Dream, SIGNAL(triggered()), this, SLOT(OnHelpAbout()));
+    connect(ui->actionWhats_This, SIGNAL(triggered()), this, SLOT(OnWhatsThis()));
+
+    connect(pAnalogDemDlg, SIGNAL(About()), this, SLOT(OnHelpAbout()));
+
+    /* Init progress bar for input signal level */
+#if QWT_VERSION < 0x060100
+    ui->ProgrInputLevel->setRange(-50.0, 0.0);
+    ui->ProgrInputLevel->setOrientation(Qt::Vertical, QwtThermo::LeftScale);
+#else
+    ui->ProgrInputLevel->setScale(-50.0, 0.0);
+    ui->ProgrInputLevel->setOrientation(Qt::Vertical);
+    ui->ProgrInputLevel->setScalePosition(QwtThermo::TrailingScale);
+#endif
+    ui->ProgrInputLevel->setAlarmLevel(-12.5);
+    QColor alarmColor(QColor(255, 0, 0));
+    QColor fillColor(QColor(0, 190, 0));
+#if QWT_VERSION < 0x060000
+    ui->ProgrInputLevel->setAlarmColor(alarmColor);
+    ui->ProgrInputLevel->setFillColor(fillColor);
+#else
+    QPalette newPalette = ui->FrameMainDisplay->palette();
+    newPalette.setColor(QPalette::Base, newPalette.color(QPalette::Window));
+    newPalette.setColor(QPalette::ButtonText, fillColor);
+    newPalette.setColor(QPalette::Highlight, alarmColor);
+    ui->ProgrInputLevel->setPalette(newPalette);
+#endif
+
+#ifdef HAVE_LIBHAMLIB
+    connect(pStationsDlg, SIGNAL(subscribeRig()), &rig, SLOT(subscribe()));
+    connect(pStationsDlg, SIGNAL(unsubscribeRig()), &rig, SLOT(unsubscribe()));
+    connect(&rig, SIGNAL(sigstr(double)), pStationsDlg, SLOT(OnSigStr(double)));
+    connect(pLogging, SIGNAL(subscribeRig()), &rig, SLOT(subscribe()));
+    connect(pLogging, SIGNAL(unsubscribeRig()), &rig, SLOT(unsubscribe()));
+#endif
+    // Evaluation Dialog
+    connect(pSysEvalDlg, SIGNAL(startLogging()), pLogging, SLOT(start()));
+    connect(pSysEvalDlg, SIGNAL(stopLogging()), pLogging, SLOT(stop()));
+    pSysEvalDlg->connectController(controller);
+
+    /* Update times for color LEDs */
+    ui->CLED_FAC->SetUpdateTime(1500);
+    ui->CLED_SDC->SetUpdateTime(1500);
+    ui->CLED_MSC->SetUpdateTime(600);
+
+    connectController();
+
+    connect(pAnalogDemDlg, SIGNAL(ViewStationsDlg()), pStationsDlg, SLOT(show()));
+    connect(pAnalogDemDlg, SIGNAL(ViewLiveScheduleDlg()), pLiveScheduleDlg, SLOT(show()));
+    connect(pAnalogDemDlg, SIGNAL(Closed()), this, SLOT(close()));
+    connect(pAnalogDemDlg, SIGNAL(SwitchMode(int)), pStationsDlg, SLOT(OnSwitchMode(int)));
+
+    connect(&TimerClose, SIGNAL(timeout()), this, SLOT(OnTimerClose()));
+
+    // clear display
+    on_signalLost();
+
+    /* System tray setup */
+    pSysTray = CSysTray::Create(
+        this,
+        SLOT(OnSysTrayActivated(QSystemTrayIcon::ActivationReason)),
+        SLOT(OnSysTrayTimer()),
+        ":/icons/MainIcon.svg");
+    CSysTray::AddAction(pSysTray, tr("&New Acquisition"), controller, SLOT(triggerNewAcquisition()));
+    CSysTray::AddSeparator(pSysTray);
+    CSysTray::AddAction(pSysTray, tr("&Exit"), this, SLOT(close()));
+
+	/* clear signal strenght */
+	setBars(0);
+
+	/* Activate real-time timers */
+    controller->start(GUI_CONTROL_UPDATE_TIME);
+
+    APPLY_CUSTOM_THEME_UI();
+}
+
+FDRMDialog::~FDRMDialog()
+{
+    /* Destroying logger */
+    delete pLogging;
+    /* Destroying top level windows, children are automaticaly destroyed */
+    delete pAnalogDemDlg;
+}
+
+void FDRMDialog::connectController()
+{
+    // ui
+    connect(controller, SIGNAL(setAFS(bool)), ui->labelAFS, SLOT(setEnabled(bool)));
+    connect(controller, SIGNAL(setAFS(bool)), ui->action_Live_Schedule_Dialog, SLOT(setEnabled(bool)));
+    connect(ui->actionReset, SIGNAL(triggered()), controller, SLOT(triggerNewAcquisition()));
+
+    // mainwindow
+    connect(controller, SIGNAL(MSCChanged(ETypeRxStatus)), this, SLOT(on_MSCChanged(ETypeRxStatus)));
+    connect(controller, SIGNAL(SDCChanged(ETypeRxStatus)), this, SLOT(on_SDCChanged(ETypeRxStatus)));
+    connect(controller, SIGNAL(FACChanged(ETypeRxStatus)), this, SLOT(on_FACChanged(ETypeRxStatus)));
+    connect(controller, SIGNAL(channelReceptionChanged(Reception)), this, SLOT(on_channelReceptionChanged(Reception)));
+    connect(controller, SIGNAL(InputSignalLevelChanged(double)), this, SLOT(on_InputSignalLevelChanged(double)));
+    connect(controller, SIGNAL(serviceChanged(int, const CService&)), this, SLOT(on_serviceChanged(int, const CService&)));
+    connect(controller, SIGNAL(signalLost()), this, SLOT(on_signalLost()));
+    connect(controller, SIGNAL(mode(int)), this, SLOT(on_modeChanged(int)));
+    connect(controller, SIGNAL(frequencyChanged(int)), this, SLOT(on_frequencyChanged(int)));
+    connect(this, SIGNAL(frequencyChanged(int)), controller, SLOT(setFrequency(int)));
+
+    // stations
+    connect(pStationsDlg, SIGNAL(frequencyChanged(int)), controller, SLOT(setFrequency(int)));
+    connect(controller, SIGNAL(mode(int)), pStationsDlg, SLOT(OnSwitchMode(int)));
+    connect(controller, SIGNAL(frequencyChanged(int)), pStationsDlg, SLOT(SetFrequency(int)));
+
+    // AFS
+    connect(controller, SIGNAL(frequencyChanged(int)), pLiveScheduleDlg, SLOT(setFrequency(int)));
+    connect(controller, SIGNAL(serviceChanged(int, const CService&)), pLiveScheduleDlg, SLOT(setService(int, const CService&)));
+    connect(controller, SIGNAL(position(double,double)), pLiveScheduleDlg, SLOT(setLocation(double, double)));
+    connect(controller, SIGNAL(position(double,double)), pLiveScheduleDlg, SLOT(setLocation(double, double)));
+    connect(controller, SIGNAL(AFS(const CAltFreqSign&)), pLiveScheduleDlg, SLOT(setAFS(const CAltFreqSign&)));
+    connect(controller, SIGNAL(serviceInformation(const map <uint32_t,CServiceInformation>)),
+            pLiveScheduleDlg, SLOT(setServiceInformation(const map <uint32_t,CServiceInformation>)));
+    connect(pLiveScheduleDlg, SIGNAL(frequencyChanged(int)), controller, SIGNAL(frequencyChanged(int)));
+
+    // AM
+    connect(pAnalogDemDlg, SIGNAL(SwitchMode(int)), controller, SLOT(setMode(int)));
+    connect(pAnalogDemDlg, SIGNAL(NewAMAcquisition()), controller, SLOT(triggerNewAcquisition()));
+}
+
+void FDRMDialog::setBars(int bars)
+{
+    ui->onebar->setAutoFillBackground(bars>0);
+    ui->twobars->setAutoFillBackground(bars>1);
+    ui->threebars->setAutoFillBackground(bars>2);
+    ui->fourbars->setAutoFillBackground(bars>3);
+    ui->fivebars->setAutoFillBackground(bars>4);
+}
+
+void FDRMDialog::on_actionEngineering_Mode_triggered(bool checked)
+{
+    bool bSingle = getSetting("singlewindow", DEFAULT_TO_SINGLE_WINDOW_MODE, true);
+    putSetting(bSingle ? "engineeringsingle" : "engineeringmulti", checked, true);
+    if(ui->actionSingle_Window_Mode->isChecked())
+    {
+        if(pServiceTabs)
+            pServiceTabs->on_engineeringMode(checked);
+    }
+    else
+    {
+        if(checked)
+        {
+            if(pEngineeringTabs==NULL)
+            {
+                pEngineeringTabs = new EngineeringTabWidget(controller);
+                ui->verticalLayout->addWidget(pEngineeringTabs);
+            }
+            pEngineeringTabs->show();
+        }
+        else
+        {
+            if(pEngineeringTabs)
+                pEngineeringTabs->hide();
+        }
+    }
+//    QApplication::processEvents();
+//    resize(0,0); /* not working on linux */
+}
+
+void FDRMDialog::on_actionSingle_Window_Mode_triggered(bool checked)
+{
+    putSetting("singlewindow", checked, true);
+    changeRecMode(controller->getMode(), true);
+}
+
+void FDRMDialog::setupWindowMode()
+{
+    bool bSingleWindowMode = getSetting("singlewindow", DEFAULT_TO_SINGLE_WINDOW_MODE, true);
+    if(bSingleWindowMode)
+    {
+        if(pServiceTabs==NULL)
+        {
+            pServiceTabs = new DreamTabWidget(controller, this);
+            ui->verticalLayout->addWidget(pServiceTabs);
+            connect(pServiceTabs, SIGNAL(audioServiceSelected(int)), controller, SLOT(selectAudioService(int)));
+            connect(pServiceTabs, SIGNAL(dataServiceSelected(int)), this, SLOT(OnSelectDataService(int)));
+            connect(controller, SIGNAL(serviceChanged(int, const CService&)), pServiceTabs, SLOT(onServiceChanged(int, const CService&)));
+            connect(controller, SIGNAL(textMessageChanged(int, QString)), pServiceTabs, SLOT(setText(int, QString)));
+        }
+        ui->action_Multimedia_Dialog->setEnabled(false);
+        //============ try this ========================
+        QWidget* widget = pServiceTabs->currentWidget();
+        if(widget)
+        {
+            widget->parentWidget()->layout()->invalidate();
+            QWidget *parent = widget->parentWidget();
+            while (parent) {
+                parent->adjustSize();
+                parent = parent->parentWidget();
+            }
+        }
+    }
+    else
+    {
+        if(pServiceSelector==NULL)
+        {
+            pServiceSelector = new ServiceSelector(this);
+            ui->verticalLayout->addWidget(pServiceSelector);
+            connect(pServiceSelector, SIGNAL(audioServiceSelected(int)), controller, SLOT(selectAudioService(int)));
+            connect(pServiceSelector, SIGNAL(dataServiceSelected(int)), this, SLOT(OnSelectDataService(int)));
+            connect(controller, SIGNAL(serviceChanged(int,const CService&)), pServiceSelector, SLOT(onServiceChanged(int, const CService&)));
+            connect(controller, SIGNAL(textMessageChanged(int, QString)), this, SLOT(on_textMessageChanged(int, QString)));
+        }
+        // TODO enable multimedia menu option if there is a data service we can decode
+//        ui->action_Multimedia_Dialog->setEnabled(TODO);
+    }
+//    bool bAmMode = ERecMode(controller->getMode()) == RM_AM;
+    bool bFmMode = ERecMode(controller->getMode()) == RM_FM;
+    ui->menu_View->menuAction()->setVisible(!bSingleWindowMode);
+    ui->actionDRM->setVisible(bFmMode);
+    ui->actionFM->setVisible(!bFmMode);
+    ui->lineEditFrequency->setVisible(bFmMode);
+    ui->LabelServiceLabel->setVisible(!bFmMode); // until we have RDS
+    ui->TextTextMessage->setVisible(!bFmMode && !bSingleWindowMode);
+    ui->menuMessage_Style->menuAction()->setVisible(!bFmMode && !bSingleWindowMode);
+//    if (bAmMode)
+//        ((QDoubleValidator*)ui->lineEditFrequency->validator())->setRange(0.1, 26.1, 3); // for later:
+    if (bFmMode)
+        ((QDoubleValidator*)ui->lineEditFrequency->validator())->setRange(65.8, 108.0, 1);
+    if (pServiceSelector)
+        pServiceSelector->setVisible(!bFmMode && !bSingleWindowMode);
+    if (pServiceTabs)
+        pServiceTabs->setVisible(!bFmMode && bSingleWindowMode);
+}
+
+void FDRMDialog::on_actionGeneralSettings_triggered()
+{
+    if (pGeneralSettingsDlg == NULL)
+        pGeneralSettingsDlg = new GeneralSettingsDlg(Settings, this);
+    CParameter& Parameters = *DRMReceiver.GetParameters();
+    Parameters.Lock();
+    pGeneralSettingsDlg->onPosition(Parameters.gps_data.fix.latitude, Parameters.gps_data.fix.longitude);
+    QString gpsd = QString("%1:%2").arg(Parameters.gps_host.c_str()).arg(Parameters.gps_port.c_str());
+    pGeneralSettingsDlg->onGPSd(gpsd, false);
+    Parameters.Unlock();
+    pGeneralSettingsDlg->show();
+}
+
+void FDRMDialog::on_actionMultimediaSettings_triggered()
+{
+    if (pMultSettingsDlg == NULL)
+        pMultSettingsDlg = new MultSettingsDlg(*DRMReceiver.GetParameters(), Settings, this);
+    pMultSettingsDlg->show();
+}
+
+void FDRMDialog::onUserEnteredPosition(double lat, double lng)
+{
+    CParameter& Parameters = *DRMReceiver.GetParameters();
+    Parameters.Lock();
+    Parameters.gps_data.fix.latitude = lat;
+    Parameters.gps_data.fix.longitude = lng;
+    Parameters.Unlock();
+}
+
+void FDRMDialog::onUseGPSd(const QString& s)
+{
+    CParameter& Parameters = *DRMReceiver.GetParameters();
+    Parameters.Lock();
+    QStringList l = s.split(":");
+    string host=l[0].toUtf8().constData();
+    if(Parameters.gps_host != host)
+    {
+        Parameters.restart_gpsd = true;
+        Parameters.gps_host=host;
+    }
+    string port=l[0].toUtf8().constData();
+    if(Parameters.gps_port != port)
+    {
+        Parameters.restart_gpsd = true;
+        Parameters.gps_port=port;
+    }
+    Parameters.Unlock();
+}
+
+void FDRMDialog::OnSysTrayActivated(QSystemTrayIcon::ActivationReason reason)
+{
+    if (reason == QSystemTrayIcon::Trigger
+#if QT_VERSION < 0x050000
+        || reason == QSystemTrayIcon::DoubleClick
+#endif
+    )
+    {
+        const Qt::WindowStates ws = windowState();
+        if (ws & Qt::WindowMinimized)
+            setWindowState((ws & ~Qt::WindowMinimized) | Qt::WindowActive);
+        else
+            toggleVisibility();
+    }
+}
+
+void FDRMDialog::OnSysTrayTimer()
+{
+    QString Title, Message;
+    if (DRMReceiver.GetAcquiState() == AS_WITH_SIGNAL)
+    {
+        CParameter& Parameters = *(DRMReceiver.GetParameters());
+        Parameters.Lock();
+            const int iCurSelAudioServ = Parameters.GetCurSelAudioService();
+            CService audioService = Parameters.Service[iCurSelAudioServ];
+            const bool bServiceIsValid = audioService.IsActive()
+                                   && (audioService.AudioParam.iStreamID != STREAM_ID_NOT_USED)
+                                   && (audioService.eAudDataFlag == CService::SF_AUDIO);
+            if (bServiceIsValid)
+            {
+                /* Service label (UTF-8 encoded string -> convert) */
+                Title = QString::fromUtf8(audioService.strLabel.c_str());
+                // Text message of current selected audio service (UTF-8 decoding)
+                Message = QString::fromUtf8(audioService.AudioParam.strTextMessage.c_str());
+            }
+        Parameters.Unlock();
+    }
+	else {
+        Message = tr("Scanning...");
+	}
+    CSysTray::SetToolTip(pSysTray, Title, Message);
+}
+
+void FDRMDialog::OnWhatsThis()
+{
+    QWhatsThis::enterWhatsThisMode();
+}
+
+// this is just a signal mapper
+void FDRMDialog::OnSwitchToAM()
+{
+    controller->setMode(RM_AM);
+}
+
+// this is just a signal mapper
+void FDRMDialog::OnSwitchToDRM()
+{
+    controller->setMode(RM_DRM);
+}
+
+// this is just a signal mapper
+void FDRMDialog::OnSwitchToFM()
+{
+    controller->setMode(RM_FM);
+}
+
+void FDRMDialog::on_SDCChanged(ETypeRxStatus s)
+{
+    SetStatus(ui->CLED_SDC, s);
+}
+
+void FDRMDialog::on_FACChanged(ETypeRxStatus s)
+{
+    SetStatus(ui->CLED_FAC, s);
+}
+
+void FDRMDialog::on_MSCChanged(ETypeRxStatus s)
+{
+    SetStatus(ui->CLED_MSC, s);
+}
+
+void FDRMDialog::on_channelReceptionChanged(Reception r)
+{
+    if(r.wmer>WMERSteps[4])
+        setBars(5);
+    else if(r.wmer>WMERSteps[3])
+        setBars(4);
+    else if(r.wmer>WMERSteps[2])
+        setBars(3);
+    else if(r.wmer>WMERSteps[1])
+        setBars(2);
+    else if(r.wmer>WMERSteps[0])
+        setBars(1);
+    else
+        setBars(0);
+}
+
+void FDRMDialog::on_InputSignalLevelChanged(double d)
+{
+    ui->ProgrInputLevel->setValue(d);
+}
+
+void FDRMDialog::startLogging()
+{
+    pSysEvalDlg->CheckBoxWriteLog->setChecked(true);
+}
+
+void FDRMDialog::stopLogging()
+{
+    pSysEvalDlg->CheckBoxWriteLog->setChecked(false);
+}
+
+void FDRMDialog::OnScheduleTimer()
+{
+    CScheduler::SEvent e;
+    e = pScheduler->front();
+    if (e.frequency != -1)
+    {
+        controller->setFrequency(e.frequency);
+        if(!pLogging->enabled())
+        {
+            startLogging();
+        }
+    }
+    else
+    {
+        stopLogging();
+    }
+    if(pScheduler->empty())
+    {
+        stopLogging();
+    }
+    else
+    {
+        e = pScheduler->pop();
+        time_t now = time(NULL);
+        pScheduleTimer->start(1000*(e.time-now));
+    }
+}
+
+void FDRMDialog::on_serviceChanged(int short_id, const CService& service)
+{
+    if(short_id==DRMReceiver.GetParameters()->GetCurSelAudioService())
+    {
+        if(service.IsActive())
+        {
+            /* Service label (UTF-8 encoded string -> convert) */
+            QString ServiceLabel(QString::fromUtf8(service.strLabel.c_str()));
+            ui->LabelServiceLabel->setText(ServiceLabel);
+            /* Service ID (plot number in hexadecimal format) */
+            const long iServiceID = (long) service.iServiceID;
+
+            if (iServiceID != 0)
+            {
+                ui->LabelServiceID->setText(QString("ID:%1").arg(iServiceID,4,16).toUpper());
+            }
+            else
+                ui->LabelServiceID->setText("");
+
+            /* Codec label */
+            ui->LabelCodec->setText(GetCodecString(service));
+
+            /* Type (Mono / Stereo) label */
+            ui->LabelStereoMono->setText(GetTypeString(service));
+
+            /* Language and program type labels (only for audio service) */
+            if (service.eAudDataFlag == CService::SF_AUDIO)
+            {
+                /* SDC Language */
+                const string strLangCode = service.strLanguageCode;
+
+                if ((!strLangCode.empty()) && (strLangCode != "---"))
+                {
+                    ui->LabelLanguage->
+                    setText(QString(GetISOLanguageName(strLangCode).c_str()));
+                }
+                else
+                {
+                    /* FAC Language */
+                    const int iLanguageID = service.iLanguage;
+
+                    if ((iLanguageID > 0) &&
+                            (iLanguageID < LEN_TABLE_LANGUAGE_CODE))
+                    {
+                        ui->LabelLanguage->setText(
+                            strTableLanguageCode[iLanguageID].c_str());
+                    }
+                    else
+                        ui->LabelLanguage->setText("");
+                }
+
+                /* Program type */
+                const int iProgrammTypeID = service.iServiceDescr;
+
+                if ((iProgrammTypeID > 0) &&
+                        (iProgrammTypeID < LEN_TABLE_PROG_TYPE_CODE))
+                {
+                    ui->LabelProgrType->setText(
+                        strTableProgTypCod[iProgrammTypeID].c_str());
+                }
+                else
+                    ui->LabelProgrType->setText("");
+            }
+
+            /* Country code */
+            const string strCntryCode = service.strCountryCode;
+
+            if ((!strCntryCode.empty()) && (strCntryCode != "--"))
+            {
+                ui->LabelCountryCode->
+                setText(QString(GetISOCountryName(strCntryCode).c_str()));
+            }
+            else
+                ui->LabelCountryCode->setText("");
+
+            _REAL rPartABLenRat;
+            {
+                CParameter& Parameters = *DRMReceiver.GetParameters();
+                Parameters.Lock();
+                rPartABLenRat = Parameters.PartABLenRatio(short_id);
+                Parameters.Unlock();
+            }
+
+            /* Bit-rate */
+            QString strBitrate = QString().setNum(service.AudioParam.rBitRate, 'f', 2) + tr(" kbps");
+
+            /* Equal or unequal error protection */
+            if (rPartABLenRat != (_REAL) 0.0)
+            {
+                /* Print out the percentage of part A length to total length */
+                strBitrate += " UEP (" +
+                              QString().setNum(rPartABLenRat * 100, 'f', 1) + " %)";
+            }
+            else
+            {
+                /* If part A is zero, equal error protection (EEP) is used */
+                strBitrate += " EEP";
+            }
+            ui->LabelBitrate->setText(strBitrate);
+
+            /* Service selector auto selection */
+            if (pServiceSelector && 
+                service.AudioParam.iStreamID != STREAM_ID_NOT_USED &&
+                service.eAudDataFlag == CService::SF_AUDIO)
+            {
+                pServiceSelector->check(short_id);
+            }
+        }
+        else
+        {
+            ui->LabelServiceLabel->setText(tr("No Service"));
+            ui->LabelBitrate->setText("");
+            ui->LabelCodec->setText("");
+            ui->LabelStereoMono->setText("");
+            ui->LabelProgrType->setText("");
+            ui->LabelLanguage->setText("");
+            ui->LabelCountryCode->setText("");
+            ui->LabelServiceID->setText("");
+        }
+    }
+
+    if (service.DataParam.ePacketModInd == CDataParam::PM_PACKET_MODE)
+    {
+        if (service.DataParam.eAppDomain == CDataParam::AD_DAB_SPEC_APP)
+        {
+            switch (service.DataParam.iUserAppIdent)
+            {
+            case DAB_AT_EPG:
+                ui->action_Multimedia_Dialog->setEnabled(false); // has its own menu
+                break;
+            case DAB_AT_BROADCASTWEBSITE:
+            case DAB_AT_JOURNALINE:
+            case DAB_AT_MOTSLIDESHOW:
+                if(ui->actionSingle_Window_Mode->isChecked()==false)
+                    ui->action_Multimedia_Dialog->setEnabled(true);
+                break;
+            default:
+                ui->action_Multimedia_Dialog->setEnabled(false);
+                ;
+            }
+        }
+    }
+}
+
+void FDRMDialog::on_modeChanged(int value)
+{
+    changeRecMode(value, false);
+}
+
+void FDRMDialog::changeRecMode(int iRecMode, bool bWindowModeChanged)
+{
+    CWindow *pToShow=NULL, *pToHide=NULL;
+    QString settingsTag;
+    bool bSingleWindowMode = getSetting("singlewindow", DEFAULT_TO_SINGLE_WINDOW_MODE, true);
+
+    // Prevent previous layout to interfere with new window size
+    if (bWindowModeChanged)
+    {
+        if (pServiceSelector)
+            pServiceSelector->hide();
+        if (pServiceTabs)
+            pServiceTabs->hide();
+        QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
+    }
+
+    if (pAnalogDemDlg->isVisible())
+        pToHide = pAnalogDemDlg;
+    else if (isVisible() && (bWindowModeChanged || !bSingleWindowMode || ERecMode(iRecMode)==RM_AM))
+        pToHide = this;
+    if (pToHide)
+        pToHide->hide();
+
+    switch(ERecMode(iRecMode))
+    {
+    case RM_DRM:
+        pToShow = this;
+        settingsTag = bSingleWindowMode ? CWINDOW_NOTAG : " DRM";
+        baseWindowTitle = tr("Dream DRM Receiver");
+        CSysTray::Start(pSysTray);
+        break;
+    case RM_AM:
+        pToShow = pAnalogDemDlg;
+        settingsTag = " AM";
+        baseWindowTitle = tr("Analog Demodulation");
+        CSysTray::Stop(pSysTray, baseWindowTitle);
+        break;
+    case RM_FM:
+        pToShow = this;
+        settingsTag = bSingleWindowMode ? CWINDOW_NOTAG : " FM";
+        baseWindowTitle = tr("Dream FM Receiver");
+        CSysTray::Stop(pSysTray, baseWindowTitle);
+        break;
+    case RM_NONE: // wait until working thread starts operating
+        break;
+    }
+
+    setSettingsTag(settingsTag, false);
+    if (pStationsDlg)     pStationsDlg->setSettingsTag(settingsTag, bSingleWindowMode);
+    if (pLiveScheduleDlg) pLiveScheduleDlg->setSettingsTag(settingsTag, true);
+    if (pSysEvalDlg)      pSysEvalDlg->setSettingsTag(CWINDOW_NOTAG, bSingleWindowMode);
+#ifdef QT_WEBKIT_LIB
+    if (pBWSDlg)          pBWSDlg->setSettingsTag(settingsTag, true);
+#endif
+    if (pEPGDlg)          pEPGDlg->setSettingsTag(settingsTag, true);
+    if (pJLDlg)           pJLDlg->setSettingsTag(settingsTag, true);
+    if (pSlideShowDlg)    pSlideShowDlg->setSettingsTag(settingsTag, true);
+
+    if (pToShow)
+    {
+        pToShow->eventUpdate();
+        pToShow->show();
+    }
+
+    // do this once only
+    if(pScheduler==NULL)
+        initialiseSchedule();
+}
+
+void FDRMDialog::initialiseSchedule()
+{
+    string schedfile = Settings.Get("command", "schedule", string());
+    if(schedfile != "")
+    {
+        bool testMode = Settings.Get("command", "test", false);
+        pScheduler = new CScheduler(testMode);
+        if(pScheduler->LoadSchedule(schedfile)) {
+            pScheduleTimer = new QTimer(this);
+            connect(pScheduleTimer, SIGNAL(timeout()), this, SLOT(OnScheduleTimer()));
+            /* Setup the first timeout */
+            CScheduler::SEvent e;
+            if(!pScheduler->empty()) {
+                e = pScheduler->front();
+                time_t now = time(NULL);
+                time_t next = e.time - now;
+                if(next > 0)
+                {
+                    pScheduleTimer->start(1000*next);
+                }
+                else // We are late starting
+                {
+                    startLogging();
+                }
+            }
+        }
+        else {
+            QMessageBox::information(this, "Dream", tr("Schedule file requested but not found"));
+        }
+    }
+    else
+    {
+        if(pLogging->enabled())
+            startLogging();
+    }
+}
+
+void FDRMDialog::OnTimerClose()
+{
+    if (DRMReceiver.GetParameters()->eRunState == CParameter::STOPPED)
+        close();
+}
+
+void FDRMDialog::on_textMessageChanged(int short_id, QString text)
+{
+    if(short_id==DRMReceiver.GetParameters()->GetCurSelAudioService())
+    {
+        ui->TextTextMessage->setEnabled(text!="");
+        ui->TextTextMessage->setText(formatTextMessage(text));
+    }
+}
+
+QString FDRMDialog::formatTextMessage(const QString& textMessage) const
+{
+    /* Activate text window */
+    ui->TextTextMessage->setEnabled(TRUE);
+
+    QString formattedMessage = "";
+    for (int i = 0; i < (int)textMessage.length(); i++)
+    {
+        switch (textMessage.at(i).unicode())
+        {
+        case 0x0A:
+            /* Code 0x0A may be inserted to indicate a preferred
+               line break */
+        case 0x1F:
+            /* Code 0x1F (hex) may be inserted to indicate a
+               preferred word break. This code may be used to
+            	   display long words comprehensibly */
+            formattedMessage += "<br>";
+            break;
+
+        case 0x0B:
+            /* End of a headline */
+            formattedMessage = "<b><u>"
+                               + formattedMessage
+                               + "</u></b></center><br><center>";
+            break;
+
+        case '<':
+            formattedMessage += "<";
+            break;
+
+        case '>':
+            formattedMessage += ">";
+            break;
+
+        default:
+            formattedMessage += textMessage[int(i)];
+        }
+    }
+    Linkify(formattedMessage, ui->actionBlackOnWhite->isChecked() ? "#0000FF" : "#0080FF");
+    return "<center>" + formattedMessage + "</center>";
+}
+
+void FDRMDialog::tune()
+{
+    double f = ui->lineEditFrequency->text().toDouble();
+    emit frequencyChanged(floor(1000.0*f));
+}
+
+void FDRMDialog::on_frequencyChanged(int freq)
+{
+    // TODO - add a MHz suffix without messing up editing
+    QString fs = QString("%1").arg(double(freq)/1000.0, 5, 'f', 1);
+    ui->lineEditFrequency->setText(fs);
+}
+
+void FDRMDialog::on_signalLost()
+{
+    /* No signal is currently received ---------------------------------- */
+    /* Disable service buttons and associated labels */
+    if(pServiceSelector)
+        pServiceSelector->disableAll();
+    if(pServiceTabs)
+        pServiceTabs->removeServices();
+
+    /* Main text labels */
+    ui->LabelBitrate->setText("");
+    ui->LabelCodec->setText("");
+    ui->LabelStereoMono->setText("");
+    ui->LabelProgrType->setText("");
+    ui->LabelLanguage->setText("");
+    ui->LabelCountryCode->setText("");
+    ui->LabelServiceID->setText("");
+
+    /* Hide text message label */
+    ui->TextTextMessage->setEnabled(FALSE);
+    ui->TextTextMessage->setText("");
+
+    ui->LabelServiceLabel->setText(tr("Scanning..."));
+    setBars(0);
+}
+
+void FDRMDialog::UpdateWindowTitle()
+{
+    QString fileName(QString::fromLocal8Bit(DRMReceiver.GetInputFileName().c_str()));
+    const bool bInputFile = fileName != "";
+    fileName = bInputFile ? QDir(fileName).dirName() : "";
+    QString windowName(bInputFile ? fileName + " - " + baseWindowTitle : baseWindowTitle);
+    setWindowTitle(windowName);
+    pAnalogDemDlg->setWindowTitle(windowName);
+}
+
+void FDRMDialog::eventUpdate()
+{
+    /* Put (re)initialization code here for the settings that might have
+       be changed by another top level window. Called on mode switch */
+    UpdateWindowTitle();
+    pFileMenu->UpdateMenu();
+    SetDisplayColor(CRGBConversion::int2RGB(getSetting("colorscheme", 0xff0000, true)));
+    bool bSingle = getSetting("singlewindow", DEFAULT_TO_SINGLE_WINDOW_MODE, true);
+    ui->actionSingle_Window_Mode->setChecked(bSingle); // does not emit trigger signal
+    bool b = getSetting(bSingle ? "engineeringsingle" : "engineeringmulti", false, true);
+    ui->actionEngineering_Mode->setChecked(b); // does not emit trigger signal
+    setupWindowMode();
+    on_actionEngineering_Mode_triggered(b); // depend on setupWindowMode() for pServiceTabs
+}
+
+void FDRMDialog::eventShow(QShowEvent*)
+{
+}
+
+void FDRMDialog::eventHide(QHideEvent*)
+{
+}
+
+void FDRMDialog::OnSelectDataService(int shortId)
+{
+    if(pMultimediaWindow)
+    {
+        disconnect(controller, SIGNAL(dataStatusChanged(int, ETypeRxStatus)), pMultimediaWindow, SLOT(setStatus(int, ETypeRxStatus)));
+        pMultimediaWindow = NULL;
+    }
+    if(ui->action_Multimedia_Dialog->isEnabled()) // must be multi-window
+        on_action_Multimedia_Dialog_triggered();
+    controller->selectDataService(shortId);
+}
+
+void FDRMDialog::on_action_Multimedia_Dialog_triggered()
+{
+    // TODO - run this on startup if the window was already open
+    CParameter& Parameters = *DRMReceiver.GetParameters();
+
+    CDataDecoder* DataDecoder = DRMReceiver.GetDataDecoder();
+
+    Parameters.Lock();
+
+    const int iCurSelAudioServ = Parameters.GetCurSelAudioService();
+    const uint32_t iAudioServiceID = Parameters.Service[iCurSelAudioServ].iServiceID;
+
+    /* Get current data service */
+    int shortID = Parameters.GetCurSelDataService();
+    CService service = Parameters.Service[shortID];
+
+    int iAppIdent = Parameters.Service[shortID].DataParam.iUserAppIdent;
+
+    if(pMultimediaWindow)
+    {
+        disconnect(this, SIGNAL(dataStatusChanged(int, ETypeRxStatus)), pMultimediaWindow, SLOT(setStatus(int, ETypeRxStatus)));
+        pMultimediaWindow = NULL;
+    }
+
+    switch(iAppIdent)
+    {
+    case DAB_AT_EPG:
+        pEPGDlg->setServiceInformation(Parameters.ServiceInformation, iAudioServiceID);
+        break;
+    case DAB_AT_BROADCASTWEBSITE:
+#ifdef QT_WEBKIT_LIB
+        if(pBWSDlg==NULL)
+            pBWSDlg = new BWSViewer(DRMReceiver, Settings, this);
+        //pBWSDlg->setDecoder(DataDecoder);
+        //pBWSDlg->setServiceInformation(service);
+        pMultimediaWindow = pBWSDlg;
+#endif
+        break;
+    case DAB_AT_JOURNALINE:
+        pJLDlg->setServiceInformation(service, iAudioServiceID);
+        pJLDlg->setDecoder(DataDecoder);
+        pMultimediaWindow = pJLDlg;
+        break;
+    case DAB_AT_MOTSLIDESHOW:
+        pSlideShowDlg->setServiceInformation(shortID, service);
+        pMultimediaWindow = pSlideShowDlg;
+        break;
+    }
+
+    Parameters.Unlock();
+
+    if(pMultimediaWindow != NULL)
+    {
+        connect(controller, SIGNAL(dataStatusChanged(int, ETypeRxStatus)), pMultimediaWindow, SLOT(setStatus(int, ETypeRxStatus)));
+        pMultimediaWindow->show();
+    }
+    else
+    {
+        if(iAppIdent!=0) // might not be set yet.
+            QMessageBox::information(this, "Dream", tr("unsupported data application"));
+    }
+}
+
+void FDRMDialog::OnMenuSetDisplayColor()
+{
+    const QColor color = CRGBConversion::int2RGB(getSetting("colorscheme", 0xff0000, true));
+    const QColor newColor = QColorDialog::getColor(color, this);
+    if (newColor.isValid())
+    {
+        /* Store new color and update display */
+        SetDisplayColor(newColor);
+        putSetting("colorscheme", CRGBConversion::RGB2int(newColor), true);
+    }
+}
+
+void FDRMDialog::OnMenuMessageStyle(int index)
+{
+    QPalette palette(ui->TextTextMessage->palette());
+    palette.setColor(QPalette::Window,     QColor(index==0 ? "#FFFFFF" : "#000000"));
+    palette.setColor(QPalette::WindowText, QColor(index==0 ? "#000000" : "#FFFFFF"));
+    ui->TextTextMessage->setPalette(palette);
+    putSetting("messagestyle", index, true);
+}
+
+void FDRMDialog::OnMenuPlotStyle(int index)
+{
+    putSetting("plotstyle", index, true);
+}
+
+void FDRMDialog::eventClose(QCloseEvent* ce)
+{
+    /* The close event has been ui->actioned and we want to shut
+     * down, but the main window should be the last thing to
+     * close so that the user knows the program has completed
+     * when the window closes
+     */
+    if (!TimerClose.isActive())
+    {
+        /* Request that the working thread stops */
+        DRMReceiver.Stop();
+
+        /* Stop real-time timer */
+        //Timer.stop();
+
+        pLogging->SaveSettings(Settings);
+
+        /* Set the timer for polling the working thread state */
+        TimerClose.start(50);
+
+        CSysTray::Destroy(&pSysTray);
+    }
+
+    /* Wait indefinitely until the working thread is stopped,
+     * so if the window never close it mean there is a bug
+     * somewhere, a fix is needed
+     */
+    if (DRMReceiver.GetParameters()->eRunState == CParameter::STOPPED)
+    {
+        TimerClose.stop();
+        if (pAboutDlg)
+            pAboutDlg->close();
+        pAnalogDemDlg->close();
+        ce->accept();
+    }
+    else
+        ce->ignore();
+}
+
+void FDRMDialog::SetDisplayColor(const QColor newColor)
+{
+    /* Collect pointers to the desired controls in a vector */
+    vector<QWidget*> vecpWidgets;
+    vecpWidgets.push_back(ui->TextTextMessage);
+    vecpWidgets.push_back(ui->LabelBitrate);
+    vecpWidgets.push_back(ui->LabelCodec);
+    vecpWidgets.push_back(ui->LabelStereoMono);
+    vecpWidgets.push_back(ui->FrameAudioDataParams);
+    vecpWidgets.push_back(ui->LabelProgrType);
+    vecpWidgets.push_back(ui->LabelLanguage);
+    vecpWidgets.push_back(ui->LabelCountryCode);
+    vecpWidgets.push_back(ui->LabelServiceID);
+    vecpWidgets.push_back(ui->TextLabelInputLevel);
+    vecpWidgets.push_back(ui->ProgrInputLevel);
+    vecpWidgets.push_back(ui->CLED_FAC);
+    vecpWidgets.push_back(ui->CLED_SDC);
+    vecpWidgets.push_back(ui->CLED_MSC);
+    vecpWidgets.push_back(ui->FrameMainDisplay);
+
+    for (size_t i = 0; i < vecpWidgets.size(); i++)
+    {
+        /* Request old palette */
+        QPalette CurPal(vecpWidgets[i]->palette());
+
+        /* Change colors */
+        if (vecpWidgets[i] != ui->TextTextMessage)
+        {
+            CurPal.setColor(QPalette::Active, QPalette::Text, newColor);
+            CurPal.setColor(QPalette::Active, QPalette::Foreground, newColor);
+            CurPal.setColor(QPalette::Inactive, QPalette::Text, newColor);
+            CurPal.setColor(QPalette::Inactive, QPalette::Foreground, newColor);
+        }
+        CurPal.setColor(QPalette::Active, QPalette::Button, newColor);
+        CurPal.setColor(QPalette::Active, QPalette::Light, newColor);
+        CurPal.setColor(QPalette::Active, QPalette::Dark, newColor);
+
+        CurPal.setColor(QPalette::Inactive, QPalette::Button, newColor);
+        CurPal.setColor(QPalette::Inactive, QPalette::Light, newColor);
+        CurPal.setColor(QPalette::Inactive, QPalette::Dark, newColor);
+
+        /* Special treatment for text message window */
+        if (vecpWidgets[i] == ui->TextTextMessage)
+        {
+            /* We need to specify special color for disabled */
+            CurPal.setColor(QPalette::Disabled, QPalette::Light, Qt::black);
+            CurPal.setColor(QPalette::Disabled, QPalette::Dark, Qt::black);
+        }
+
+        /* Set new palette */
+        vecpWidgets[i]->setPalette(CurPal);
+    }
+
+    APPLY_CUSTOM_THEME_UI();
+}
+
+void FDRMDialog::AddWhatsThisHelp()
+{
+    /*
+    	This text was taken from the only documentation of Dream software
+    */
+    /* Text Message */
+    QString strTextMessage =
+        tr("<b>Text Message:</b> On the top right the text "
+           "message label is shown. This label only appears when an actual text "
+           "message is transmitted. If the current service does not transmit a "
+           "text message, the label will be disabled.");
+
+    /* Input Level */
+    const QString strInputLevel =
+        tr("<b>Input Level:</b> The input level meter shows "
+           "the relative input signal peak level in dB. If the level is too high, "
+           "the meter turns from green to red. The red region should be avoided "
+           "since overload causes distortions which degrade the reception "
+           "performance. Too low levels should be avoided too, since in this case "
+           "the Signal-to-Noise Ratio (SNR) degrades.");
+
+
+    /* Status LEDs */
+    const QString strStatusLEDS =
+        tr("<b>Status LEDs:</b> The three status LEDs show "
+           "the current CRC status of the three logical channels of a DRM stream. "
+           "These LEDs are the same as the top LEDs on the Evaluation Dialog.");
+
+
+    /* Station ui->Label and Info Display */
+    const QString strStationLabelOther =
+        tr("<b>Station ui->Label and Info Display:</b> In the "
+           "big label with the black background the station label and some other "
+           "information about the current selected service is displayed. The "
+           "magenta text on the top shows the bit-rate of the current selected "
+           "service (The abbreviations EEP and "
+           "UEP stand for Equal Error Protection and Unequal Error Protection. "
+           "UEP is a feature of DRM for a graceful degradation of the decoded "
+           "audio signal in case of a bad reception situation. UEP means that "
+           "some parts of the audio is higher protected and some parts are lower "
+           "protected (the ratio of higher protected part length to total length "
+           "is shown in the brackets)), the audio compression format "
+           "(e.g. AAC), if SBR is used and what audio mode is used (Mono, Stereo, "
+           "P-Stereo -> low-complexity or parametric stereo). In case SBR is "
+           "used, the actual sample rate is twice the sample rate of the core AAC "
+           "decoder. The next two types of information are the language and the "
+           "program type of the service (e.g. German / News).<br>The big "
+           "turquoise text in the middle is the station label. This label may "
+           "appear later than the magenta text since this information is "
+           "transmitted in a different logical channel of a DRM stream. On the "
+           "right, the ID number connected with this service is shown.");
+
+    ui->TextTextMessage->setWhatsThis(strTextMessage);
+    ui->TextLabelInputLevel->setWhatsThis(strInputLevel);
+    ui->ProgrInputLevel->setWhatsThis(strInputLevel);
+    ui->CLED_MSC->setWhatsThis(strStatusLEDS);
+    ui->CLED_SDC->setWhatsThis(strStatusLEDS);
+    ui->CLED_FAC->setWhatsThis(strStatusLEDS);
+    ui->LabelBitrate->setWhatsThis(strStationLabelOther);
+    ui->LabelCodec->setWhatsThis(strStationLabelOther);
+    ui->LabelStereoMono->setWhatsThis(strStationLabelOther);
+    ui->LabelServiceLabel->setWhatsThis(strStationLabelOther);
+    ui->LabelProgrType->setWhatsThis(strStationLabelOther);
+    ui->LabelServiceID->setWhatsThis(strStationLabelOther);
+    ui->LabelLanguage->setWhatsThis(strStationLabelOther);
+    ui->LabelCountryCode->setWhatsThis(strStationLabelOther);
+    ui->FrameAudioDataParams->setWhatsThis(strStationLabelOther);
+
+    const QString strBars = tr("from 1 to 5 bars indicates WMER in the range %1 to %2 dB")
+            .arg(floor(WMERSteps[0]))
+            .arg(floor(WMERSteps[4]));
+    ui->onebar->setWhatsThis(strBars);
+    ui->twobars->setWhatsThis(strBars);
+    ui->threebars->setWhatsThis(strBars);
+    ui->fourbars->setWhatsThis(strBars);
+    ui->fivebars->setWhatsThis(strBars);
+}
+
+void FDRMDialog::OnHelpAbout()
+{
+    if (!pAboutDlg)
+        pAboutDlg = new CAboutDlg(this);
+    pAboutDlg->show();
+}
+
+void FDRMDialog::OnSoundFileChanged(CDRMReceiver::ESFStatus)
+{
+    UpdateWindowTitle();
+    on_signalLost();
+}
diff --git a/src/GUI-QT/fdrmdialog.h b/src/GUI-QT/fdrmdialog.h
new file mode 100644
index 0000000..07fb86c
--- /dev/null
+++ b/src/GUI-QT/fdrmdialog.h
@@ -0,0 +1,172 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer, Andrea Russo
+ *
+ * Description:
+ *
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#ifndef _FDRMDIALOG_H_
+#define _FDRMDIALOG_H_
+
+
+#include "CWindow.h"
+#include <QTimer>
+#include <QSystemTrayIcon>
+#include <../DrmReceiver.h>
+#include "receivercontroller.h"
+
+/* Classes ********************************************************************/
+class CDRMReceiver;
+class CLogging;
+class EPGDlg;
+class MultSettingsDlg;
+class CMultColorLED;
+class CSoundCardSelMenu;
+class CAboutDlg;
+class ServiceSelector;
+class StationsDlg;
+class LiveScheduleDlg;
+class AnalogDemDlg;
+class systemevalDlg;
+class GeneralSettingsDlg;
+class CSysTray;
+class CFileMenu;
+class BWSViewer;
+class JLViewer;
+class SlideShowViewer;
+class CScheduler;
+class DreamTabWidget;
+class EngineeringTabWidget;
+
+namespace Ui {
+class DRMMainWindow;
+}
+
+class FDRMDialog : public CWindow
+{
+    Q_OBJECT
+
+public:
+#ifdef HAVE_LIBHAMLIB
+    explicit FDRMDialog(CDRMReceiver&, CSettings&, CRig&, QWidget* parent = 0);
+#else
+    explicit FDRMDialog(CDRMReceiver&, CSettings&, QWidget* parent = 0);
+#endif
+    ~FDRMDialog();
+
+private:
+    Ui::DRMMainWindow*  ui;
+    CDRMReceiver&		DRMReceiver;
+    ReceiverController* controller;
+    QTimer				TimerClose;
+
+    CLogging*			pLogging;
+    systemevalDlg*		pSysEvalDlg;
+    BWSViewer*			pBWSDlg;
+    JLViewer*			pJLDlg;
+    SlideShowViewer*	pSlideShowDlg;
+    StationsDlg*		pStationsDlg;
+    LiveScheduleDlg*	pLiveScheduleDlg;
+    EPGDlg*				pEPGDlg;
+    AnalogDemDlg*		pAnalogDemDlg;
+    GeneralSettingsDlg* pGeneralSettingsDlg;
+    MultSettingsDlg*	pMultSettingsDlg;
+    CSysTray*           pSysTray;
+    CFileMenu*			pFileMenu;
+    CSoundCardSelMenu*	pSoundCardMenu;
+    CAboutDlg*		    pAboutDlg;
+    QString             SysTrayTitle;
+    QString             SysTrayMessage;
+    QTimer				TimerSysTray;
+    CScheduler* 	    pScheduler;
+    QTimer*		        pScheduleTimer;
+    int                 iCurrentFrequency;
+    ServiceSelector*    pServiceSelector;
+    DreamTabWidget*     pServiceTabs;
+    EngineeringTabWidget* pEngineeringTabs;
+    QWidget*            pMultimediaWindow;
+    QString             baseWindowTitle;
+
+    virtual void        eventClose(QCloseEvent* ce);
+    virtual void        eventHide(QHideEvent* pEvent);
+    virtual void        eventShow(QShowEvent* pEvent);
+    virtual void        eventUpdate();
+    void		AddWhatsThisHelp();
+    void		UpdateWindowTitle();
+
+    void		SetDisplayColor(const QColor newColor);
+
+    QString formatTextMessage(const QString&) const;
+    void startLogging();
+    void stopLogging();
+    void SysTrayCreate();
+    void SysTrayStart();
+    void SysTrayStop(const QString&);
+    void SysTrayToolTip(const QString&, const QString&);
+    void setBars(int);
+    void connectController();
+    void setupWindowMode();
+    void changeRecMode(int, bool);
+
+private slots:
+    void OnScheduleTimer();
+    void OnSysTrayTimer();
+    void OnTimerClose();
+    void OnSelectDataService(int);
+    void OnMenuSetDisplayColor();
+    void OnMenuMessageStyle(int);
+    void OnMenuPlotStyle(int);
+    void OnSwitchToAM();
+    void OnSwitchToDRM();
+    void OnSwitchToFM();
+    void OnWhatsThis();
+    void OnHelpAbout();
+    void tune();
+    void OnSoundFileChanged(CDRMReceiver::ESFStatus);
+    void OnSysTrayActivated(QSystemTrayIcon::ActivationReason);
+    void initialiseSchedule();
+    void on_actionGeneralSettings_triggered();
+    void on_actionMultimediaSettings_triggered();
+    void onUserEnteredPosition(double, double);
+    void onUseGPSd(const QString&);
+    void on_action_Multimedia_Dialog_triggered();
+    void on_actionSingle_Window_Mode_triggered(bool);
+    void on_actionEngineering_Mode_triggered(bool);
+    void on_textMessageChanged(int, QString);
+    void on_MSCChanged(ETypeRxStatus);
+    void on_SDCChanged(ETypeRxStatus);
+    void on_FACChanged(ETypeRxStatus);
+    void on_InputSignalLevelChanged(double);
+    void on_modeChanged(int);
+    void on_serviceChanged(int, const CService&);
+    void on_signalLost();
+    void on_frequencyChanged(int);
+    void on_channelReceptionChanged(Reception);
+
+signals:
+    void plotStyleChanged(int);
+    void frequencyChanged(int);
+};
+
+#endif // _FDRMDIALOG_H_
diff --git a/src/GUI-QT/gpswidget.cpp b/src/GUI-QT/gpswidget.cpp
new file mode 100644
index 0000000..192e3eb
--- /dev/null
+++ b/src/GUI-QT/gpswidget.cpp
@@ -0,0 +1,59 @@
+#include "gpswidget.h"
+#include "receivercontroller.h"
+#include "ui_gpswidget.h"
+#include <ctime>
+
+GPSWidget::GPSWidget(ReceiverController* rc, QWidget *parent) :
+    QWidget(parent),
+    ui(new Ui::GPSWidget)
+{
+    ui->setupUi(this);
+    connectController(rc);
+}
+
+GPSWidget::~GPSWidget()
+{
+    delete ui;
+}
+
+void GPSWidget::connectController(ReceiverController* controller)
+{
+    connect(controller, SIGNAL(position(double,double)), this, SLOT(setPosition(double,double)));
+}
+
+void GPSWidget::setPosition(double lat, double lng)
+{
+    ui->lat->setText(QString().setNum(lat));
+    ui->lng->setText(QString().setNum(lng));
+}
+
+void GPSWidget::setSpeed(double speed)
+{
+    ui->speed->setText(QString().setNum(speed));
+}
+
+void GPSWidget::setTrack(double track)
+{
+    ui->heading->setText(QString("%1\260").arg(track));
+}
+
+void GPSWidget::setAltitude(double)
+{
+
+}
+
+void GPSWidget::setGPSDatTime(double time)
+{
+    struct tm * p_ts;
+    time_t tt = time_t(time);
+    p_ts = gmtime(&tt);
+    QChar fill('0');
+    ui->time->setText( QString("UTC: %1/%2/%3 %4:%5:%6  ")
+            .arg(1900 + p_ts->tm_year)
+            .arg(1 + p_ts->tm_mon, 2, 10, fill)
+            .arg(p_ts->tm_mday, 2, 10, fill)
+            .arg(p_ts->tm_hour, 2, 10, fill)
+            .arg(p_ts->tm_min, 2, 10, fill)
+            .arg(p_ts->tm_sec,2, 10, fill)
+                       );
+}
diff --git a/src/GUI-QT/gpswidget.h b/src/GUI-QT/gpswidget.h
new file mode 100644
index 0000000..46a8b11
--- /dev/null
+++ b/src/GUI-QT/gpswidget.h
@@ -0,0 +1,33 @@
+#ifndef GPSWIDGET_H
+#define GPSWIDGET_H
+
+#include <QWidget>
+
+namespace Ui {
+class GPSWidget;
+}
+
+class ReceiverController;
+
+class GPSWidget : public QWidget
+{
+    Q_OBJECT
+
+public:
+    explicit GPSWidget(ReceiverController*, QWidget *parent = 0);
+    ~GPSWidget();
+    void connectController(ReceiverController*);
+public slots:
+    void setPosition(double,double);
+    void setSpeed(double);
+    void setTrack(double);
+    void setAltitude(double);
+    void setGPSDatTime(double);
+signals:
+    void position(double,double);
+
+private:
+    Ui::GPSWidget *ui;
+};
+
+#endif // GPSWIDGET_H
diff --git a/src/GUI-QT/gpswidget.ui b/src/GUI-QT/gpswidget.ui
new file mode 100644
index 0000000..aa6b775
--- /dev/null
+++ b/src/GUI-QT/gpswidget.ui
@@ -0,0 +1,609 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>GPSWidget</class>
+ <widget class="QWidget" name="GPSWidget">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>265</width>
+    <height>290</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Form</string>
+  </property>
+  <layout class="QGridLayout" name="gridLayout">
+   <item row="0" column="0">
+    <layout class="QVBoxLayout" name="verticalLayout_4">
+     <item>
+      <layout class="QVBoxLayout" name="verticalLayout_3">
+       <item>
+        <layout class="QHBoxLayout" name="horizontalLayout_2">
+         <item>
+          <widget class="QLabel" name="labelLat">
+           <property name="text">
+            <string>Lat</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QLabel" name="lat">
+           <property name="text">
+            <string>0</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QLabel" name="labelLng">
+           <property name="text">
+            <string>Lng</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QLabel" name="lng">
+           <property name="text">
+            <string>0</string>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </item>
+       <item>
+        <layout class="QHBoxLayout" name="horizontalLayout_3">
+         <item>
+          <widget class="QLabel" name="labelSpeed">
+           <property name="text">
+            <string>Speed</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QLabel" name="speed">
+           <property name="text">
+            <string>10.0 m/s</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QLabel" name="labelHeading">
+           <property name="text">
+            <string>Heading</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QLabel" name="heading">
+           <property name="text">
+            <string>151°</string>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </item>
+       <item>
+        <widget class="QLabel" name="time">
+         <property name="text">
+          <string>24/01/2007 15:14.33 UTC</string>
+         </property>
+         <property name="wordWrap">
+          <bool>false</bool>
+         </property>
+        </widget>
+       </item>
+      </layout>
+     </item>
+     <item>
+      <widget class="QGroupBox" name="GroupReceiverCoord">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="minimumSize">
+        <size>
+         <width>0</width>
+         <height>0</height>
+        </size>
+       </property>
+       <property name="title">
+        <string>Default Receiver coordinates</string>
+       </property>
+       <layout class="QVBoxLayout" name="verticalLayout">
+        <item>
+         <layout class="QHBoxLayout" name="_2">
+          <property name="spacing">
+           <number>6</number>
+          </property>
+          <property name="leftMargin">
+           <number>0</number>
+          </property>
+          <property name="topMargin">
+           <number>0</number>
+          </property>
+          <property name="rightMargin">
+           <number>0</number>
+          </property>
+          <property name="bottomMargin">
+           <number>0</number>
+          </property>
+          <item>
+           <widget class="QLabel" name="TextLatitude">
+            <property name="minimumSize">
+             <size>
+              <width>64</width>
+              <height>0</height>
+             </size>
+            </property>
+            <property name="text">
+             <string>Latitude</string>
+            </property>
+            <property name="wordWrap">
+             <bool>false</bool>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QLineEdit" name="EdtLatitudeDegrees">
+            <property name="sizePolicy">
+             <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+              <horstretch>0</horstretch>
+              <verstretch>0</verstretch>
+             </sizepolicy>
+            </property>
+            <property name="maximumSize">
+             <size>
+              <width>30</width>
+              <height>32767</height>
+             </size>
+            </property>
+            <property name="text">
+             <string/>
+            </property>
+            <property name="maxLength">
+             <number>2</number>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QLabel" name="TextDegLat">
+            <property name="font">
+             <font>
+              <pointsize>12</pointsize>
+             </font>
+            </property>
+            <property name="text">
+             <string>°</string>
+            </property>
+            <property name="wordWrap">
+             <bool>false</bool>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QLineEdit" name="EdtLatitudeMinutes">
+            <property name="sizePolicy">
+             <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+              <horstretch>0</horstretch>
+              <verstretch>0</verstretch>
+             </sizepolicy>
+            </property>
+            <property name="maximumSize">
+             <size>
+              <width>30</width>
+              <height>32767</height>
+             </size>
+            </property>
+            <property name="text">
+             <string/>
+            </property>
+            <property name="maxLength">
+             <number>2</number>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QLabel" name="TextMinutesLat">
+            <property name="font">
+             <font>
+              <pointsize>12</pointsize>
+             </font>
+            </property>
+            <property name="text">
+             <string>'</string>
+            </property>
+            <property name="wordWrap">
+             <bool>false</bool>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QLineEdit" name="EdtLatitudeNS">
+            <property name="sizePolicy">
+             <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+              <horstretch>0</horstretch>
+              <verstretch>0</verstretch>
+             </sizepolicy>
+            </property>
+            <property name="maximumSize">
+             <size>
+              <width>20</width>
+              <height>32767</height>
+             </size>
+            </property>
+            <property name="text">
+             <string/>
+            </property>
+            <property name="maxLength">
+             <number>1</number>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QLabel" name="TextNS">
+            <property name="minimumSize">
+             <size>
+              <width>0</width>
+              <height>0</height>
+             </size>
+            </property>
+            <property name="text">
+             <string>N/S</string>
+            </property>
+            <property name="wordWrap">
+             <bool>false</bool>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <spacer name="Spacer10_2">
+            <property name="orientation">
+             <enum>Qt::Horizontal</enum>
+            </property>
+            <property name="sizeType">
+             <enum>QSizePolicy::Expanding</enum>
+            </property>
+            <property name="sizeHint" stdset="0">
+             <size>
+              <width>20</width>
+              <height>20</height>
+             </size>
+            </property>
+           </spacer>
+          </item>
+         </layout>
+        </item>
+        <item>
+         <layout class="QHBoxLayout" name="_3">
+          <property name="spacing">
+           <number>6</number>
+          </property>
+          <property name="leftMargin">
+           <number>0</number>
+          </property>
+          <property name="topMargin">
+           <number>0</number>
+          </property>
+          <property name="rightMargin">
+           <number>0</number>
+          </property>
+          <property name="bottomMargin">
+           <number>0</number>
+          </property>
+          <item>
+           <widget class="QLabel" name="TextLongitude">
+            <property name="minimumSize">
+             <size>
+              <width>64</width>
+              <height>0</height>
+             </size>
+            </property>
+            <property name="text">
+             <string>Longitude</string>
+            </property>
+            <property name="wordWrap">
+             <bool>false</bool>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QLineEdit" name="EdtLongitudeDegrees">
+            <property name="sizePolicy">
+             <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+              <horstretch>0</horstretch>
+              <verstretch>0</verstretch>
+             </sizepolicy>
+            </property>
+            <property name="maximumSize">
+             <size>
+              <width>30</width>
+              <height>32767</height>
+             </size>
+            </property>
+            <property name="text">
+             <string/>
+            </property>
+            <property name="maxLength">
+             <number>3</number>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QLabel" name="TextDegLong">
+            <property name="font">
+             <font>
+              <pointsize>12</pointsize>
+             </font>
+            </property>
+            <property name="text">
+             <string>°</string>
+            </property>
+            <property name="wordWrap">
+             <bool>false</bool>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QLineEdit" name="EdtLongitudeMinutes">
+            <property name="sizePolicy">
+             <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+              <horstretch>0</horstretch>
+              <verstretch>0</verstretch>
+             </sizepolicy>
+            </property>
+            <property name="maximumSize">
+             <size>
+              <width>30</width>
+              <height>32767</height>
+             </size>
+            </property>
+            <property name="text">
+             <string/>
+            </property>
+            <property name="maxLength">
+             <number>2</number>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QLabel" name="TextMinutesLong">
+            <property name="font">
+             <font>
+              <pointsize>12</pointsize>
+             </font>
+            </property>
+            <property name="text">
+             <string>'</string>
+            </property>
+            <property name="wordWrap">
+             <bool>false</bool>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QLineEdit" name="EdtLongitudeEW">
+            <property name="sizePolicy">
+             <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+              <horstretch>0</horstretch>
+              <verstretch>0</verstretch>
+             </sizepolicy>
+            </property>
+            <property name="maximumSize">
+             <size>
+              <width>20</width>
+              <height>32767</height>
+             </size>
+            </property>
+            <property name="text">
+             <string/>
+            </property>
+            <property name="maxLength">
+             <number>1</number>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QLabel" name="TextEW">
+            <property name="minimumSize">
+             <size>
+              <width>0</width>
+              <height>0</height>
+             </size>
+            </property>
+            <property name="text">
+             <string>E/W</string>
+            </property>
+            <property name="wordWrap">
+             <bool>false</bool>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <spacer name="Spacer10">
+            <property name="orientation">
+             <enum>Qt::Horizontal</enum>
+            </property>
+            <property name="sizeType">
+             <enum>QSizePolicy::Expanding</enum>
+            </property>
+            <property name="sizeHint" stdset="0">
+             <size>
+              <width>20</width>
+              <height>20</height>
+             </size>
+            </property>
+           </spacer>
+          </item>
+         </layout>
+        </item>
+       </layout>
+      </widget>
+     </item>
+     <item>
+      <widget class="QGroupBox" name="GroupGPS">
+       <property name="title">
+        <string>GPSd</string>
+       </property>
+       <layout class="QVBoxLayout" name="verticalLayout_2">
+        <item>
+         <layout class="QGridLayout" name="_4">
+          <property name="leftMargin">
+           <number>0</number>
+          </property>
+          <property name="topMargin">
+           <number>0</number>
+          </property>
+          <property name="rightMargin">
+           <number>0</number>
+          </property>
+          <property name="bottomMargin">
+           <number>0</number>
+          </property>
+          <property name="spacing">
+           <number>6</number>
+          </property>
+          <item row="0" column="1">
+           <widget class="QLabel" name="GPSHost">
+            <property name="text">
+             <string>Host</string>
+            </property>
+            <property name="wordWrap">
+             <bool>false</bool>
+            </property>
+           </widget>
+          </item>
+          <item row="1" column="1">
+           <widget class="QLabel" name="GPSPort">
+            <property name="text">
+             <string>Port</string>
+            </property>
+            <property name="wordWrap">
+             <bool>false</bool>
+            </property>
+           </widget>
+          </item>
+          <item row="1" column="2">
+           <widget class="QLineEdit" name="LineEditGPSPort"/>
+          </item>
+          <item row="0" column="2">
+           <widget class="QLineEdit" name="LineEditGPSHost"/>
+          </item>
+          <item row="0" column="0">
+           <widget class="QCheckBox" name="CheckBoxUseGPS">
+            <property name="text">
+             <string>Use GPS</string>
+            </property>
+           </widget>
+          </item>
+          <item row="1" column="0">
+           <spacer name="Spacer4">
+            <property name="orientation">
+             <enum>Qt::Horizontal</enum>
+            </property>
+            <property name="sizeType">
+             <enum>QSizePolicy::Expanding</enum>
+            </property>
+            <property name="sizeHint" stdset="0">
+             <size>
+              <width>20</width>
+              <height>20</height>
+             </size>
+            </property>
+           </spacer>
+          </item>
+         </layout>
+        </item>
+       </layout>
+      </widget>
+     </item>
+     <item>
+      <layout class="QHBoxLayout" name="horizontalLayout">
+       <item>
+        <widget class="CMultColorLED" name="LEDGPS" native="true">
+         <property name="minimumSize">
+          <size>
+           <width>13</width>
+           <height>13</height>
+          </size>
+         </property>
+         <property name="maximumSize">
+          <size>
+           <width>13</width>
+           <height>13</height>
+          </size>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <spacer name="horizontalSpacer">
+         <property name="orientation">
+          <enum>Qt::Horizontal</enum>
+         </property>
+         <property name="sizeType">
+          <enum>QSizePolicy::Expanding</enum>
+         </property>
+         <property name="sizeHint" stdset="0">
+          <size>
+           <width>40</width>
+           <height>20</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
+       <item>
+        <widget class="QPushButton" name="buttonApply">
+         <property name="text">
+          <string>Apply</string>
+         </property>
+         <property name="autoDefault">
+          <bool>false</bool>
+         </property>
+         <property name="default">
+          <bool>true</bool>
+         </property>
+        </widget>
+       </item>
+      </layout>
+     </item>
+    </layout>
+   </item>
+   <item row="0" column="1">
+    <spacer name="horizontalSpacer_2">
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <property name="sizeHint" stdset="0">
+      <size>
+       <width>0</width>
+       <height>20</height>
+      </size>
+     </property>
+    </spacer>
+   </item>
+   <item row="1" column="0">
+    <spacer name="verticalSpacer">
+     <property name="orientation">
+      <enum>Qt::Vertical</enum>
+     </property>
+     <property name="sizeHint" stdset="0">
+      <size>
+       <width>20</width>
+       <height>0</height>
+      </size>
+     </property>
+    </spacer>
+   </item>
+  </layout>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>CMultColorLED</class>
+   <extends>QWidget</extends>
+   <header>MultColorLED.h</header>
+  </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/GUI-QT/jlbrowser.cpp b/src/GUI-QT/jlbrowser.cpp
new file mode 100644
index 0000000..e5acb63
--- /dev/null
+++ b/src/GUI-QT/jlbrowser.cpp
@@ -0,0 +1,154 @@
+/******************************************************************************\
+ * British Broadcasting Corporation
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	 Julian Cable
+ *
+ * Description: Journaline Specialisation of TextBrowser
+ *
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "jlbrowser.h"
+#include "../datadecoding/DataDecoder.h"
+#include "../datadecoding/Journaline.h"
+#include <iostream>
+
+JLBrowser::JLBrowser(QWidget * parent)
+    : QTextBrowser(parent),decoder(NULL),strFhGIISText(),strJournalineHeadText(),
+      total(0),ready(0)
+{
+
+    /* Set FhG IIS text */
+    strFhGIISText =
+        "<table><tr><td><img src=\":/icons/LogoFhGIIS.png\"></td>"
+        "<td width=\"4\"></td>"
+        "<td><font face=\"Courier\" size=\"-1\">Features NewsService "
+        "Journaline" + QString(QChar(174)) /* (R) */ +
+        " decoder technology by Fraunhofer IIS, Erlangen, "
+        "Germany. For more information visit http://www.iis.fhg.de/dab"
+        "</font></td></tr></table>";
+
+    /* Set Journaline headline text */
+    strJournalineHeadText =
+        "<table><tr><td><img src=\":/icons/LogoJournaline.png\"></td>"
+        "<td width=\"4\"></td>"
+        "<td valign=\"middle\"><h2>NewsService Journaline" + QString(QChar(174)) /* (R) */ +
+        "</h2></td></tr></table>";
+}
+
+bool JLBrowser::changed()
+{
+    if(decoder==NULL)
+    {
+        return false;
+    }
+    int JourID = source().toString().toInt();
+
+    CNews News;
+    decoder->GetNews(JourID, News);
+
+    int new_total=News.vecItem.Size();
+    int new_ready=0;
+    bool dirty = false;
+
+    for (int i = 0; i < new_total; i++)
+    {
+        switch(News.vecItem[i].iLink)
+        {
+        case JOURNALINE_IS_NO_LINK: /* Only text, no link */
+        case JOURNALINE_LINK_NOT_ACTIVE:
+            break;
+        default:
+            new_ready++;
+        }
+    }
+    if(new_total != total)
+    {
+        total = new_total;
+        dirty = true;
+    }
+    if(new_ready != ready)
+    {
+        ready = new_ready;
+        dirty = true;
+    }
+    return dirty;
+}
+
+QVariant JLBrowser::loadResource( int, const QUrl & name )
+{
+    QString strItems, strTitle;
+
+    if(decoder)
+    {
+        /* Get news from actual Journaline decoder */
+        int JourID = name.toString().toInt();
+
+        CNews News;
+        decoder->GetNews(JourID, News);
+
+        /* Decode UTF-8 coding for title */
+        strTitle = QString().fromUtf8(News.sTitle.c_str());
+
+        ready = 0;
+        total = News.vecItem.Size();
+        for (int i = 0; i < total; i++)
+        {
+            QString strCurItem = QString().fromUtf8(News.vecItem[i].sText.c_str());
+
+            /* Replace \n by html command <br> */
+            strCurItem = strCurItem.replace(QRegExp("\n"), "<br>");
+
+            switch(News.vecItem[i].iLink)
+            {
+            case JOURNALINE_IS_NO_LINK: /* Only text, no link */
+                strItems += strCurItem + QString("<br>");
+                break;
+            case JOURNALINE_LINK_NOT_ACTIVE:
+                /* Un-ordered list item without link */
+                strItems += QString("<li>") + strCurItem + QString("</li>");
+                break;
+            default:
+                ready++;
+                QString strLinkStr = QString("%1").arg(News.vecItem[i].iLink);
+                /* Un-ordered list item with link */
+                strItems += QString("<li><a href=\"") + strLinkStr +
+                            QString("\">") + strCurItem + QString("</a></li>");
+            }
+        }
+    }
+
+    return
+        strJournalineHeadText +
+        "<table>"
+        "<tr><td width=\"100%\"><hr></td></tr>" /* horizontial line */
+        "<tr><td><stylebody><b><center>" + strTitle + "</center></b></stylebody></td></tr>"
+        "<tr><td><stylebody><ul type=\"square\">" + strItems +
+        "</ul></stylebody></td></tr>"
+        "<tr><td width=\"100%\"><hr></td></tr>" /* horizontial line */
+        "</table>"
+        + strFhGIISText;
+}
+
+void JLBrowser::setDecoder(CDataDecoder* d)
+{
+    decoder = d;
+}
diff --git a/src/GUI-QT/jlbrowser.h b/src/GUI-QT/jlbrowser.h
new file mode 100644
index 0000000..daeb8a7
--- /dev/null
+++ b/src/GUI-QT/jlbrowser.h
@@ -0,0 +1,55 @@
+/******************************************************************************\
+ * British Broadcasting Corporation
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	 Julian Cable
+ *
+ * Description: Journaline Specialisation of TextBrowser
+ *
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#ifndef _JLBROWSER_H
+#define _JLBROWSER_H
+
+#include <QTextBrowser>
+
+class CDataDecoder;
+
+class JLBrowser : public QTextBrowser
+{
+    Q_OBJECT
+public:
+    JLBrowser(QWidget * parent = 0 );
+    ~JLBrowser() {}
+    QVariant loadResource ( int type, const QUrl & name );
+    bool changed();
+    void setDecoder(CDataDecoder* d);
+
+protected:
+
+    CDataDecoder*   decoder;
+    QString         strFhGIISText;
+    QString         strJournalineHeadText;
+    int             total;
+    int             ready;
+};
+
+#endif
diff --git a/src/GUI-QT/journalineviewer.cpp b/src/GUI-QT/journalineviewer.cpp
new file mode 100644
index 0000000..03e539b
--- /dev/null
+++ b/src/GUI-QT/journalineviewer.cpp
@@ -0,0 +1,88 @@
+#include "journalineviewer.h"
+#include "ui_journalineviewer.h"
+#include <../util-QT/Util.h>
+#include <QFontDialog>
+
+JournalineViewer::JournalineViewer(int s, QWidget *parent) :
+    QWidget(parent),
+    ui(new Ui::JournalineViewer),
+    document(),short_id(s)
+{
+    ui->setupUi(this);
+    ui->textBrowser->setDocument(&document);
+    ui->textBrowser->setSource(QUrl("0"));
+
+    /* Update time for color LED */
+    ui->LEDStatus->SetUpdateTime(1000);
+
+    /* Connect controls */
+    connect(ui->textBrowser, SIGNAL(backwardAvailable(bool)), ui->buttonStepBack, SLOT(setEnabled(bool)));
+    on_buttonClearCache_clicked();
+}
+
+JournalineViewer::~JournalineViewer()
+{
+    delete ui;
+}
+
+void JournalineViewer::on_buttonClearCache_clicked()
+{
+    //actionClear_All->setEnabled(false);
+    ui->buttonStepBack->setEnabled(false);
+    ui->textBrowser->clear();
+    ui->textBrowser->clearHistory();
+    // TODO - clear JL object cache ?
+}
+
+void JournalineViewer::setSavePath(const QString&)
+{
+    //    strCurrentSavePath = s;
+}
+
+void JournalineViewer::setDecoder(CDataDecoder* dec)
+{
+    ui->textBrowser->setDecoder(dec);
+}
+
+void JournalineViewer::setServiceInformation(const CService& service, uint32_t iAudioServiceID)
+{
+    /* Add the service description into the dialog caption */
+    QString strTitle = tr("Journaline");
+
+    if (service.IsActive())
+    {
+        /* Do UTF-8 to QString (UNICODE) conversion with the label strings */
+        QString strLabel = QString().fromUtf8(service.strLabel.c_str()).trimmed();
+
+        /* Service ID (plot number in hexadecimal format) */
+        QString strServiceID = "";
+
+        /* show the ID only if differ from the audio service */
+        if ((service.iServiceID != 0) && (service.iServiceID != iAudioServiceID))
+        {
+            if (strLabel != "")
+                strLabel += " ";
+
+            strServiceID = "- ID:" +
+                           QString().setNum(long(service.iServiceID), 16).toUpper();
+        }
+
+        /* add the description on the title of the dialog */
+        if (strLabel != "" || strServiceID != "")
+            strTitle += " [" + strLabel + strServiceID + "]";
+    }
+    setWindowTitle(strTitle);
+}
+
+void JournalineViewer::setStatus(int s, ETypeRxStatus status)
+{
+    if(s==short_id)
+    {
+        SetStatus(ui->LEDStatus, status);
+
+        if(ui->textBrowser->changed())
+        {
+            ui->textBrowser->reload();
+        }
+    }
+}
diff --git a/src/GUI-QT/journalineviewer.h b/src/GUI-QT/journalineviewer.h
new file mode 100644
index 0000000..40c47a5
--- /dev/null
+++ b/src/GUI-QT/journalineviewer.h
@@ -0,0 +1,38 @@
+#ifndef JOURNALINEVIEWER_H
+#define JOURNALINEVIEWER_H
+
+#include <QWidget>
+#include <QTimer>
+#include <QTextDocument>
+#include <../Parameter.h>
+#include <../datadecoding/Journaline.h>
+
+namespace Ui {
+class JournalineViewer;
+}
+
+class CDataDecoder;
+
+class JournalineViewer : public QWidget
+{
+    Q_OBJECT
+
+public:
+    explicit JournalineViewer(int, QWidget *parent = 0);
+    ~JournalineViewer();
+
+private:
+    Ui::JournalineViewer *ui;
+    QTextDocument   document;
+    int             short_id;
+
+private slots:
+    void on_buttonClearCache_clicked();
+public slots:
+    void setSavePath(const QString&);
+    void setStatus(int, ETypeRxStatus);
+    void setDecoder(CDataDecoder* dec);
+    void setServiceInformation(const CService&, uint32_t);
+};
+
+#endif // JOURNALINEVIEWER_H
diff --git a/src/GUI-QT/journalineviewer.ui b/src/GUI-QT/journalineviewer.ui
new file mode 100644
index 0000000..3f96056
--- /dev/null
+++ b/src/GUI-QT/journalineviewer.ui
@@ -0,0 +1,147 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>JournalineViewer</class>
+ <widget class="QWidget" name="JournalineViewer">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>400</width>
+    <height>300</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Form</string>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <item>
+    <widget class="JLBrowser" name="textBrowser"/>
+   </item>
+   <item>
+    <layout class="QHBoxLayout" name="_2">
+     <property name="spacing">
+      <number>6</number>
+     </property>
+     <property name="leftMargin">
+      <number>0</number>
+     </property>
+     <property name="topMargin">
+      <number>0</number>
+     </property>
+     <property name="rightMargin">
+      <number>0</number>
+     </property>
+     <property name="bottomMargin">
+      <number>0</number>
+     </property>
+     <item>
+      <widget class="QLabel" name="TextLabel1">
+       <property name="text">
+        <string>Receiving Status:</string>
+       </property>
+       <property name="wordWrap">
+        <bool>false</bool>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="CMultColorLED" name="LEDStatus" native="true">
+       <property name="minimumSize">
+        <size>
+         <width>13</width>
+         <height>13</height>
+        </size>
+       </property>
+       <property name="maximumSize">
+        <size>
+         <width>13</width>
+         <height>13</height>
+        </size>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <spacer name="horizontalSpacer">
+       <property name="orientation">
+        <enum>Qt::Horizontal</enum>
+       </property>
+       <property name="sizeHint" stdset="0">
+        <size>
+         <width>40</width>
+         <height>20</height>
+        </size>
+       </property>
+      </spacer>
+     </item>
+     <item>
+      <widget class="QToolButton" name="buttonStepBack">
+       <property name="text">
+        <string/>
+       </property>
+       <property name="icon">
+        <iconset resource="res/icons.qrc">
+         <normaloff>:/icons/StepBack.png</normaloff>:/icons/StepBack.png</iconset>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <spacer name="Spacer5_2">
+       <property name="orientation">
+        <enum>Qt::Horizontal</enum>
+       </property>
+       <property name="sizeType">
+        <enum>QSizePolicy::Expanding</enum>
+       </property>
+       <property name="sizeHint" stdset="0">
+        <size>
+         <width>20</width>
+         <height>20</height>
+        </size>
+       </property>
+      </spacer>
+     </item>
+     <item>
+      <widget class="QPushButton" name="buttonClearCache">
+       <property name="text">
+        <string>Cl&ear Cache</string>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
+  </layout>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>CMultColorLED</class>
+   <extends>QWidget</extends>
+   <header>MultColorLED.h</header>
+  </customwidget>
+  <customwidget>
+   <class>JLBrowser</class>
+   <extends>QTextBrowser</extends>
+   <header>jlbrowser.h</header>
+  </customwidget>
+ </customwidgets>
+ <resources>
+  <include location="res/icons.qrc"/>
+ </resources>
+ <connections>
+  <connection>
+   <sender>buttonStepBack</sender>
+   <signal>clicked()</signal>
+   <receiver>textBrowser</receiver>
+   <slot>backward()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>176</x>
+     <y>277</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>199</x>
+     <y>134</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+</ui>
diff --git a/src/GUI-QT/languages/README.txt b/src/GUI-QT/languages/README.txt
new file mode 100644
index 0000000..dce98ee
--- /dev/null
+++ b/src/GUI-QT/languages/README.txt
@@ -0,0 +1,71 @@
+
+About Translation:
+
+Translation, also called localization (or l10n for short), is a task that can be contributed by anyone. No programming skills are required. Any language that is not English (original messages) can be contributed.
+
+Localization software helps translate the strings that appear inside the application, including menus, buttons, and dialog boxes. All of the user visible strings are extracted from the Dream source code and placed into a "source message file" file called dreamtr.ts. The localization software allows you to translate the strings in this file.
+
+
+Translation instructions:
+
+Before starting a new translation, ask first on the Sourceforge Dream forum if somebody else is doing it for that language. If no, then proceed.
+
+First, you will need to download latest Dream CVS or upcoming version 1.2.
+
+In the following sections, the XX code refers to the code for your language (da=Danish, de=German, en=English, es=Spanish, fi=Finnish, fr=French, it=Italian, nl=Dutch, no=Norwegian, ru=Russian, sv=Swedish, ..). 
+
+Under Linux/Uni*x:
+All the TS files are under common/GUI-QT/languages/dreamtr.XX.ts (in CVS repository). In linux/ subdir, run "make languages/dreamtr.XX.ts" to either create or update/merge the TS file. Edit the linux/languages/dreamtr.XX.ts file and to test it, run "make languages/dreamtr.XX.qm" to create the QM release file. Copy that QM file as dreamtr.qm and restart Dream program to use it. When your are satisfied with the translation, then the TS file has to be copied back into common/GUI-QT/language [...]
+
+
+Under Windows:
+To start a new translation, download the latest file of the language drm/common/GUI-QT/languages/dreamtr.XX.ts. If this is a translation for a new language, download the file drm/linux/dreamtr.ts instead. Rename it dreamtr.XX.ts when you begin translating, where XX is the code explained above. 
+
+When you have begun translating the source message file (a TS file), use your translation program to compile a light-weight binary message file (a QM file) from the TS file, suitable only for end use. This will produce a file called dreamtr.XX.qm. 
+
+
+Providing translations (Linux/Windows):
+Provide translations for the source texts in the TS file. 
+
+The source message file (TS file) is a XML format file. Even though it can be edited by regular text editor, it is recommended to use a specialized tool for ease of use and better support of Unicode charset.
+
+There's a nice Qt GUI named 'linguist'[1] to edit translations. Debian users may simply "apt-get install qt3-linguist". Linguist comes with Qt Phrase Books (QTH files) with translations from common words of many languages. According to Trolltech site[2], it works for Qt2/Windows. I'm curious also if it would handle japanese translation or any non-latin based languages. Anyone from the country of the rising sun?
+KBabel[3], has support for Qt files too.
+To create the QM file from the TS file, you can also use Qt-provided 'lrelease' cmdline tool.
+
+[1] http://www.trolltech.com/company/announce/linguistpre.html
+[2] http://doc.trolltech.com/2.3.9/i18n.html
+[3] http://i18n.kde.org/tools/kbabel/
+
+Notes:
+* Strings like "&File" and "New &Audio Track" are menu items. The letter after the & character is used as a keyboard shortcut on Windows and Unix.
+
+* The HTML tags "<b></b>" etc. have to be reproduced at the appropriate places in the translation.
+
+* Be careful as some texts may have space constraints in the Graphical User Interface.
+
+* You will find some strings like "%1 of %2 files copied.\nCopying: %3". The % signs mark places where additional information will be inserted into the string. You are allowed to change the order of the % markers in the translation if the programmer did his/her work right.
+
+
+
+User Point of view:
+
+Download the QM file for the language of your choice. You may also re-generate it from a TS file.
+In the same folder as the Dream executable, rename your dreamtr.XX.qm file to dreamtr.qm. Restart the Dream program. If dreamtr.qm exists it is loaded, otherwise the internal text (English) is used.
+
+
+
+Programmer point of view:
+
+To the programmer's point of view, to get translation working, just replace all "" literals by tr(""). tr() is based on QString with internal Unicode support. Unlike GNU gettext, the translating library is already included in Qt. A QTranslator is initialized at startup of the program. Then binary translation files (QM file) have to be distributed along for translation to take place. That's all. 
+ 
+The translated text is "plugged" (at runtime) into the code by the tr() function (which tr name is short to not clutter the code). If no translation is available for the argument, the original text is returned, otherwise it is retrieved from a fast access catalog. 
+
+Run "make -C linux/ dreamtr.ts" to extract translatable text from the C++ source code of the Qt application, resulting in a source message file (a TS file).
+
+A Qt tool "lupdate" automatically scans the .cpp/.h/.ui files and extract the string literals within the tr() argument.
+
+
+---
+This text was written by Stephane Fillod
+
diff --git a/src/GUI-QT/languages/dreamtr.es.qm b/src/GUI-QT/languages/dreamtr.es.qm
new file mode 100644
index 0000000..f078656
Binary files /dev/null and b/src/GUI-QT/languages/dreamtr.es.qm differ
diff --git a/src/GUI-QT/languages/dreamtr.es.ts b/src/GUI-QT/languages/dreamtr.es.ts
new file mode 100644
index 0000000..613f637
--- /dev/null
+++ b/src/GUI-QT/languages/dreamtr.es.ts
@@ -0,0 +1,2298 @@
+<!DOCTYPE TS><TS>
+<codec>iso8859-1</codec>
+<context>
+    <name>AnalogDemDlg</name>
+    <message>
+        <source>S&tations Dialog...</source>
+        <translation type='unfinished'>&Estaciones</translation>
+    </message>
+    <message>
+        <source>E&xit</source>
+        <translation type='unfinished'>&Salir</translation>
+    </message>
+    <message>
+        <source>&Sound Card Selection</source>
+        <translation type='unfinished'>&Tarjeta de Sonido...</translation>
+    </message>
+    <message>
+        <source>&DRM (digital)</source>
+        <translation type='unfinished'>&DRM (digital)</translation>
+    </message>
+    <message>
+        <source>New &AM Acquisition</source>
+        <translation type='unfinished'>Nueva Adquisición &AM</translation>
+    </message>
+    <message>
+        <source>&View</source>
+        <translation type='unfinished'>&Ver</translation>
+    </message>
+    <message>
+        <source>&Settings</source>
+        <translation type='unfinished'>&Opciones</translation>
+    </message>
+    <message>
+        <source>&?</source>
+        <translation type='unfinished'>&?</translation>
+    </message>
+    <message>
+        <source>Click on the plot to set the demodulation frequency</source>
+        <translation type='unfinished'>Clickear en el gráfico para ajustar la frecuencia de demodulación</translation>
+    </message>
+    <message>
+        <source> Hz</source>
+        <translation type='unfinished'>Hz</translation>
+    </message>
+    <message>
+        <source>Carrier<br>Frequency:<b><br></source>
+        <translation type='unfinished'>Frecuencia de<br>Portadora:<b><br></translation>
+    </message>
+    <message>
+        <source><b>Noise Reduction:</b> The noise suppression is a frequency domain optimal filter design based algorithm. The noise PSD is estimated utilizing a minimum statistic. A problem of this type of algorithm is that it produces the so called "musical tones". The noise becomes colored and sounds a bit strange. At the same time, the useful signal (which might be speech or music) is also distorted by the algorithm. By selecting the level of noise reduction, a compromise [...]
+        <translation type='unfinished'><b>Reducción de Ruido:</b> La supresión de ruido consiste en un algoritmo basado en el diseño de un filtro óptimo en el dominio de la frecuencia. La DEP del ruido se estima utilizando un estadístico mínimo. Un problema de este tipo de algoritmo es que producen los llamados "tonos musicales". El ruido se colorea y suena un tanto extraño. Al mismo tiempo, la señal útil (que puede tratarse de voz o de música) también se distorsiona por el a [...]
+    </message>
+    <message>
+        <source><b>AGC (Automatic Gain Control):</b> Input signals can have a large variation in power due to channel impairments. To compensate for that, an automatic gain control can be applied. The AGC has four settings: Off, Slow, Medium and Fast.</source>
+        <translation type='unfinished'><b>AGC (Automatic Gain Control - Control Automático de Ganancia):</b> Las señales de entrada presentan una gran variación en potencia debido a las alteraciones del canal. Para compensarlas, se puede aplicar un control automático de la ganancia. Dicho control presenta cuatro posibles configuraciones: Off (Apagado), Slow (Lento), Medium (Medio) y Fast (Alto).</translation>
+    </message>
+    <message>
+        <source><b>Filter Bandwidth:</b> A band-pass filter is applied before the actual demodulation process. With this filter, adjacent signals are attenuated. The bandwidth of this filter can be chosen in steps of 1 Hz by using the slider bar. Clicking on the right or left side of the slider leveler will increase/decrease the bandwidth by 1 kHz. <br>The current filter bandwidth is indicated in the spectrum plot by a selection bar.</source>
+        <translation type='unfinished'><b>Ancho de banda del filtro:</b> Antes del proceso real de demodulación, se aplica un filtro paso banda. Gracias a este filtro, las señales adyacentes se atenúan. El ancho de banda de este filtro se puede escoger en pasos de 1 Hz usando la barra deslizante. Al hacer click a la derecha o a la izquierda del nivelador de deslizamiento, se aumentará/disminuirá el ancho de banda 1 kHz. <br>El ancho de banda actual del filtro se indica  [...]
+    </message>
+    <message>
+        <source><b>Demodulation Type:</b> The following analog demodulation types are available:<ul><li><b>AM:</b> This analog demodulation type is used in most of the hardware radios. The envelope of the complex base-band signal is used followed by a high-pass filter to remove the DC offset. Additionally, a low pass filter with the same bandwidth as the pass-band filter is applied to reduce the noise caused by non-linear distortions.</li><li& [...]
+        <translation type='unfinished'><b>Tipo de demodulación:</b> Están disponibles los siguientes tipos de demodulación analógica:<ul><li><b>AM:</b> Este tipo de demodulación analógica se emplea en la mayoría de las radios hardware. La envolvente de la señal compleja banda base se usa seguida de un filtro paso alto para eliminar el offset de DC. Adicionalmente, se aplica un filtro paso bajo con el mismo ancho de banda que el filtro paso banda para r [...]
+    </message>
+    <message>
+        <source><b>Mute Audio:</b> The audio can be muted by checking this box. The reaction of checking or unchecking this box is delayed by approx. 1 second due to the audio buffers.</source>
+        <translation type='unfinished'><b>Silenciar Audio:</b> Al marcar este cuadro el audio puede silenciarse. Al marcar/desmarcar este cuadro la reacción puede retardarse aproximadamente un segundo, debido a los buffers de audio.</translation>
+    </message>
+    <message>
+        <source><b>Save Audio as WAV:</b> Save the audio signal as stereo, 16-bit, 48 kHz sample rate PCM wave file. Checking this box will let the user choose a file name for the recording.</source>
+        <translation type='unfinished'><b>Guardar Audio como WAV:</b> Guarda la señal de audio como un archivo de onda PCM (Pulse Code Modulation) estéreo de 16 bits y con una tasa de muestreo de 48 kHz. Al marcar este cuadro, el usuario podrá elegir un nombre de archivo para la grabación.</translation>
+    </message>
+    <message>
+        <source><b>Carrier Frequency:</b> The (estimated) carrier frequency of the analog signal is shown. (The estimation of this parameter can be done by the Autom Frequency Acquisition which uses the estimated PSD of the input signal and applies a maximum search.)</source>
+        <translation type='unfinished'><b>Frecuencia de portadora:</b> Muestra la frecuencia de portadora (estimada) de  la señal analógica. La estimación de este parámetro puede hacerse mediante la "Adquisición Automática de Frecuencia", que usa la DEP estimada de la señal de entrada y procede a buscar el máximo.</translation>
+    </message>
+    <message>
+        <source><b>PLL:</b> The Phase-Lock-Loop (PLL) tracks the carrier of the modulated received signal. The resulting phase offset between the reference oscillator and the received carrier is displayed in a dial control. If the pointer is almost steady, the PLL is locked. If the pointer of the dial control turns quickly, the PLL is out of lock. To get the PLL locked, the frequency offset to the true carrier frequency must not exceed a few Hz.</source>
+        <translation type='unfinished'><b>PLL:</b> El PLL (Phase Locked Loop) sigue la portadora de la señal recibida modulada. El "offset" de fase resultante entre el oscilador de referencia y la portadora recibida se muestra en el control del dial. Cuando el puntero está casi parado el PLL está enganchado. En cambio, cuando el puntero del control del dial gira rápidamente significa que el PLL está desenganchado. Para que el PLL se enganche, el "offset" de frecuencia respect [...]
+    </message>
+    <message>
+        <source><b>Auto Frequency Acquisition:</b> Clicking on the input spectrum plot changes the mixing frequency for demodulation. If the Auto Frequency Acquisition is enabled, the largest peak near the curser is selected.</source>
+        <translation type='unfinished'><b>Adquisición Automática de Frecuencia:</b> Al hacer click sobre el gráfico del espectro de entrada se cambia la frecuencia de mezcla para la demodulación. Si esta opción está habilitada, se elige el mayor pico cercano al cursor.</translation>
+    </message>
+    <message>
+        <source>&Live Schedule Dialog...</source>
+        <translation type='unfinished'>&Programación en directo</translation>
+    </message>
+</context>
+<context>
+    <name>AnalogDemDlgBase</name>
+    <message>
+        <source>System Evaluation</source>
+        <translation type='unfinished'>Evaluación del sistema</translation>
+    </message>
+    <message>
+        <source>Indicators</source>
+        <translation type='unfinished'>Indicadores</translation>
+    </message>
+    <message>
+        <source>&Waterfall</source>
+        <translation type='unfinished'>&Cascada</translation>
+    </message>
+    <message>
+        <source>TextFreqOffset</source>
+        <translation type='unfinished'>Offset de frecuencia</translation>
+    </message>
+    <message>
+        <source>PLL
+Phase Offset</source>
+        <translation type='unfinished'>PLL
+Offset de fase</translation>
+    </message>
+    <message>
+        <source>Filter Bandwidth</source>
+        <translation type='unfinished'>Ancho de banda del filtro</translation>
+    </message>
+    <message>
+        <source>TextLabelBandWidth</source>
+        <translation type='unfinished'>Ancho de banda</translation>
+    </message>
+    <message>
+        <source>Demodulation</source>
+        <translation type='unfinished'>Demodulación</translation>
+    </message>
+    <message>
+        <source>AM</source>
+        <translation type='unfinished'>AM</translation>
+    </message>
+    <message>
+        <source>LSB</source>
+        <translation type='unfinished'>LSB</translation>
+    </message>
+    <message>
+        <source>USB</source>
+        <translation type='unfinished'>USB</translation>
+    </message>
+    <message>
+        <source>CW</source>
+        <translation type='unfinished'>CW</translation>
+    </message>
+    <message>
+        <source>FM</source>
+        <translation type='unfinished'>FM</translation>
+    </message>
+    <message>
+        <source>AGC</source>
+        <translation type='unfinished'>AGC</translation>
+    </message>
+    <message>
+        <source>Off</source>
+        <translation type='unfinished'>No</translation>
+    </message>
+    <message>
+        <source>Slow</source>
+        <translation type='unfinished'>Lento</translation>
+    </message>
+    <message>
+        <source>Med</source>
+        <translation type='unfinished'>Medio</translation>
+    </message>
+    <message>
+        <source>Fast</source>
+        <translation type='unfinished'>Rápido</translation>
+    </message>
+    <message>
+        <source>Noise Reduction</source>
+        <translation type='unfinished'>Reducción de ruido</translation>
+    </message>
+    <message>
+        <source>Low</source>
+        <translation type='unfinished'>Baja</translation>
+    </message>
+    <message>
+        <source>High</source>
+        <translation type='unfinished'>Alta</translation>
+    </message>
+    <message>
+        <source>Audio</source>
+        <translation type='unfinished'>Audio</translation>
+    </message>
+    <message>
+        <source>Mute Audio</source>
+        <translation type='unfinished'>Silenciar Audio</translation>
+    </message>
+    <message>
+        <source>Save Audio</source>
+        <translation type='unfinished'>Guardar Audio</translation>
+    </message>
+    <message>
+        <source>PLL</source>
+        <translation type='unfinished'>PLL</translation>
+    </message>
+    <message>
+        <source>Enable</source>
+        <translation type='unfinished'>Habilitar</translation>
+    </message>
+    <message>
+        <source>Auto Frequency Acquisition</source>
+        <translation type='unfinished'>Adquisición Automática de Frecuencia</translation>
+    </message>
+    <message>
+        <source>&AMSS</source>
+        <translation type='unfinished'>&AMSS</translation>
+    </message>
+    <message>
+        <source>&DRM</source>
+        <translation type='unfinished'>&DRM</translation>
+    </message>
+</context>
+<context>
+    <name>CAMSSDlg</name>
+    <message>
+        <source>No AMSS detected</source>
+        <translation type='unfinished'>AMSS no detectada</translation>
+    </message>
+    <message>
+        <source>Awaiting AMSS data...</source>
+        <translation type='unfinished'>Esperando datos AMSS...</translation>
+    </message>
+</context>
+<context>
+    <name>CAMSSDlgBase</name>
+    <message>
+        <source>AMSS</source>
+        <translation type='unfinished'>AMSS</translation>
+    </message>
+    <message>
+        <source>AMSS Decoding</source>
+        <translation type='unfinished'>Decodificación AMSS</translation>
+    </message>
+    <message>
+        <source>ServiceLabelAMSS</source>
+        <translation type='unfinished'>Etiqueta de servicio AMSS</translation>
+    </message>
+    <message>
+        <source>AMSSInfo</source>
+        <translation type='unfinished'>Información AMSS</translation>
+    </message>
+    <message>
+        <source>Block:</source>
+        <translation type='unfinished'>Bloque:</translation>
+    </message>
+    <message>
+        <source>Bits:</source>
+        <translation type='unfinished'>Bits:</translation>
+    </message>
+    <message>
+        <source>SDC:  </source>
+        <translation type='unfinished'>SDC:</translation>
+    </message>
+    <message>
+        <source>................</source>
+        <translation type='unfinished'>................</translation>
+    </message>
+    <message>
+        <source>AFS:  </source>
+        <translation type='unfinished'>AFS:</translation>
+    </message>
+    <message>
+        <source>AMSS Offset</source>
+        <translation type='unfinished'>Offset AMSS</translation>
+    </message>
+    <message>
+        <source>AMSSContryCode</source>
+        <translation type='unfinished'>Código de país AMSS</translation>
+    </message>
+</context>
+<context>
+    <name>CAboutDlg</name>
+    <message>
+        <source>is a software implementation of a Digital Radio Mondiale (DRM) receiver. With Dream, DRM broadcasts can be received with a modified analog receiver (SW, MW, LW) and a PC with a sound card.</source>
+        <translation type='unfinished'>es una implementación software de un receptor DRM (Digital Radio Mondiale). Con Dream, se pueden recibir difusiones DRM con un receptor analógico (SW, MW, LW) modificado y un PC con una tarjeta de sonido. Esta traducción a castellano ha sido realizada por / Translation to Spanish by: gonzalosuardiaz at gmail.com.</translation>
+    </message>
+    <message>
+        <source>Although this software is going to be distributed as free software under the terms of the GPL this does not mean that its use is free of rights of others. The use may infringe third party IP and thus may not be legal in some countries.</source>
+        <translation type='unfinished'>Aunque este software se distribuya como software gratuito bajo los términos de la GPL, no significa que su uso esté exento de derechos de terceros. El uso podría infringir la propiedad intelectual de terceros, lo cual podría no ser legal en algunos países.</translation>
+    </message>
+    <message>
+        <source>This compilation of Dream uses the following libraries:</source>
+        <translation type='unfinished'>Esta compilación de Dream usa las siguientes bibliotecas:</translation>
+    </message>
+    <message>
+        <source>Dream, Version </source>
+        <translation type='unfinished'>Dream, Versión</translation>
+    </message>
+    <message>
+        <source>Open-Source Software Implementation of a DRM-Receiver</source>
+        <translation type='unfinished'>Implementación Software de código fuente abierto de un Receptor DRM</translation>
+    </message>
+    <message>
+        <source>Under the GNU General Public License (GPL)</source>
+        <translation type='unfinished'>Bajo la Licencia Pública General (GPL) de GNU</translation>
+    </message>
+</context>
+<context>
+    <name>CAboutDlgBase</name>
+    <message>
+        <source>About Dream</source>
+        <translation type='unfinished'>Sobre Dream</translation>
+    </message>
+    <message>
+        <source>TextLabelVersion</source>
+        <translation type='unfinished'>Versión</translation>
+    </message>
+    <message>
+        <source>Volker Fischer, Alexander Kurpiers</source>
+        <translation type='unfinished'>Volker Fischer, Alexander Kurpiers</translation>
+    </message>
+    <message>
+        <source>Darmstadt University of Technology
+Institute for Communication Technology</source>
+        <translation type='unfinished'>Darmstadt University of Technology
+Institute for Communication Technology</translation>
+    </message>
+    <message>
+        <source>Copyright (C) 2001 - 2005</source>
+        <translation type='unfinished'>Copyright (C) 2001 - 2005</translation>
+    </message>
+    <message>
+        <source>TextViewCredits</source>
+        <translation type='unfinished'>Créditos</translation>
+    </message>
+    <message>
+        <source>&OK</source>
+        <translation type='unfinished'>&OK</translation>
+    </message>
+</context>
+<context>
+    <name>CDRMPlot</name>
+    <message>
+        <source>Channel Impulse Response</source>
+        <translation type='unfinished'>Respuesta impulsional del canal</translation>
+    </message>
+    <message>
+        <source>Time [ms]</source>
+        <translation type='unfinished'>Tiempo [ms]</translation>
+    </message>
+    <message>
+        <source>IR [dB]</source>
+        <translation type='unfinished'>IR [dB]</translation>
+    </message>
+    <message>
+        <source>Guard-interval beginning</source>
+        <translation type='unfinished'>Comienzo del Intervalo de Guarda</translation>
+    </message>
+    <message>
+        <source>Guard-interval end</source>
+        <translation type='unfinished'>Final del Intervalo de Guarda</translation>
+    </message>
+    <message>
+        <source>Estimated begin of impulse response</source>
+        <translation type='unfinished'>Comienzo estimado de la respuesta impulsional</translation>
+    </message>
+    <message>
+        <source>Estimated end of impulse response</source>
+        <translation type='unfinished'>Final estimado de la respuesta impulsional</translation>
+    </message>
+    <message>
+        <source>Higher Bound</source>
+        <translation type='unfinished'>Limite superior</translation>
+    </message>
+    <message>
+        <source>Lower bound</source>
+        <translation type='unfinished'>Límite inferior</translation>
+    </message>
+    <message>
+        <source>Channel Transfer Function / Group Delay</source>
+        <translation type='unfinished'>Función de transferencia del canal / Retardo de grupo</translation>
+    </message>
+    <message>
+        <source>Carrier Index</source>
+        <translation type='unfinished'>Índice de portadora</translation>
+    </message>
+    <message>
+        <source>TF [dB]</source>
+        <translation type='unfinished'>TF [dB]</translation>
+    </message>
+    <message>
+        <source>Group Delay [ms]</source>
+        <translation type='unfinished'>Retardo de grupo [ms]</translation>
+    </message>
+    <message>
+        <source>Transf. Fct.</source>
+        <translation type='unfinished'>Func. Transferencia</translation>
+    </message>
+    <message>
+        <source>Group Del.</source>
+        <translation type='unfinished'>Ret. Grupo</translation>
+    </message>
+    <message>
+        <source>Audio Spectrum</source>
+        <translation type='unfinished'>Espectro de Audio</translation>
+    </message>
+    <message>
+        <source>Frequency [kHz]</source>
+        <translation type='unfinished'>Frecuencia [kHz]</translation>
+    </message>
+    <message>
+        <source>Rel. Frequency Offset / Sample Rate Offset History</source>
+        <translation type='unfinished'>Offset de frec. relativa/ Historial de offset de tasa de muestreo</translation>
+    </message>
+    <message>
+        <source>Time [s]</source>
+        <translation type='unfinished'>Tiempo [s]</translation>
+    </message>
+    <message>
+        <source>Sample Rate Offset [Hz]</source>
+        <translation type='unfinished'>Offset de tasa de muestreo [Hz]</translation>
+    </message>
+    <message>
+        <source>Freq.</source>
+        <translation type='unfinished'>Frec.</translation>
+    </message>
+    <message>
+        <source>Samp.</source>
+        <translation type='unfinished'>Muestra</translation>
+    </message>
+    <message>
+        <source>Freq. Offset [Hz] rel. to </source>
+        <translation type='unfinished'>Offset de Frec. [Hz] rel. a</translation>
+    </message>
+    <message>
+        <source>Delay / Doppler History</source>
+        <translation type='unfinished'>Historial de Retardo / Doppler</translation>
+    </message>
+    <message>
+        <source>Time [min]</source>
+        <translation type='unfinished'>Tiempo [min]</translation>
+    </message>
+    <message>
+        <source>Delay [ms]</source>
+        <translation type='unfinished'>Retardo [ms]</translation>
+    </message>
+    <message>
+        <source>Doppler [Hz]</source>
+        <translation type='unfinished'>Doppler [Hz]</translation>
+    </message>
+    <message>
+        <source>Delay</source>
+        <translation type='unfinished'>Retardo</translation>
+    </message>
+    <message>
+        <source>Doppler</source>
+        <translation type='unfinished'>Doppler</translation>
+    </message>
+    <message>
+        <source>SNR / Correctly Decoded Audio History</source>
+        <translation type='unfinished'>Historial de Audio decodificado correctamente / SNR</translation>
+    </message>
+    <message>
+        <source>SNR [dB]</source>
+        <translation type='unfinished'>SNR [dB]</translation>
+    </message>
+    <message>
+        <source>Corr. Dec. Audio / DRM-Frame</source>
+        <translation type='unfinished'>Audio Corr. Decodificado / Trama DRM</translation>
+    </message>
+    <message>
+        <source>Shifted Power Spectral Density of Input Signal</source>
+        <translation type='unfinished'>DEP desplazada de señal de entrada</translation>
+    </message>
+    <message>
+        <source>PSD [dB]</source>
+        <translation type='unfinished'>DEP [dB]</translation>
+    </message>
+    <message>
+        <source>DC carrier</source>
+        <translation type='unfinished'>Portadora DC</translation>
+    </message>
+    <message>
+        <source>Shifted PSD</source>
+        <translation type='unfinished'>DEP Desplazada</translation>
+    </message>
+    <message>
+        <source>SNR Spectrum (Weighted MER on MSC Cells)</source>
+        <translation type='unfinished'>Espectro SNR (MER ponderada en celdas MSC)</translation>
+    </message>
+    <message>
+        <source>WMER [dB]</source>
+        <translation type='unfinished'>WMER [dB]</translation>
+    </message>
+    <message>
+        <source>SNR Spectrum</source>
+        <translation type='unfinished'>Espectro SNR</translation>
+    </message>
+    <message>
+        <source>Input Spectrum</source>
+        <translation type='unfinished'>Espectro de entrada</translation>
+    </message>
+    <message>
+        <source>Input Spectrum [dB]</source>
+        <translation type='unfinished'>Espectro de entrada [dB]</translation>
+    </message>
+    <message>
+        <source>Input spectrum</source>
+        <translation type='unfinished'>Espectro de entrada</translation>
+    </message>
+    <message>
+        <source>Input PSD</source>
+        <translation type='unfinished'>DEP de entrada</translation>
+    </message>
+    <message>
+        <source>Input PSD [dB]</source>
+        <translation type='unfinished'>DEP de entrada [dB]</translation>
+    </message>
+    <message>
+        <source>Filter bandwidth</source>
+        <translation type='unfinished'>Ancho de banda del filtro</translation>
+    </message>
+    <message>
+        <source>My Grid</source>
+        <translation type='unfinished'>Mi cuadrícula</translation>
+    </message>
+    <message>
+        <source>Waterfall Input Spectrum</source>
+        <translation type='unfinished'>Espectro de entrada en Cascada</translation>
+    </message>
+    <message>
+        <source>FAC Constellation</source>
+        <translation type='unfinished'>Constelación FAC</translation>
+    </message>
+    <message>
+        <source>Real</source>
+        <translation type='unfinished'>Real</translation>
+    </message>
+    <message>
+        <source>Imaginary</source>
+        <translation type='unfinished'>Imaginaria</translation>
+    </message>
+    <message>
+        <source>SDC Constellation</source>
+        <translation type='unfinished'>Constelación SDC</translation>
+    </message>
+    <message>
+        <source>MSC Constellation</source>
+        <translation type='unfinished'>Constelación MSC</translation>
+    </message>
+    <message>
+        <source>MSC / SDC / FAC Constellation</source>
+        <translation type='unfinished'>Constelación MSC / SDC / FAC</translation>
+    </message>
+    <message>
+        <source><b>Impulse Response:</b> This plot shows the estimated Impulse Response (IR) of the channel based on the channel estimation. It is the averaged, Hamming Window weighted Fourier back transformation of the transfer function. The length of PDS estimation and time synchronization tracking is based on this function. The two red dashed vertical lines show the beginning and the end of the guard-interval. The two black dashed vertical lines show the estimated beginnin [...]
+        <translation type='unfinished'><b>Respuesta Impulsional:</b> Este gráfico muestra la respuesta impulsional (IR) estimada del canal basada en la estimación del canal. Es el promedio de la ventana de Hamming de la Transformada de Fourier inversa ponderada de la función de transferencia. La longitud de la estimación de la PDS y el seguimiento de la sincronización temporal están basados en esta función. Las dos líneas rojas verticales discontinuas muestran el comienzo y e [...]
+    </message>
+    <message>
+        <source><b>Transfer Function / Group Delay:</b> This plot shows the squared magnitude and the group delay of the estimated channel at each sub-carrier.</source>
+        <translation type='unfinished'><b>Función de Transferencia / Retardo de Grupo:</b> Este gráfico muestra la el módulo al cuadrado y el retardo al cuadrado del canal estimado en cada subportadora.</translation>
+    </message>
+    <message>
+        <source><b>FAC, SDC, MSC:</b> The plots show the constellations of the FAC, SDC and MSC logical channel of the DRM stream. Depending on the current transmitter settings, the SDC and MSC can have 4-QAM, 16-QAM or 64-QAM modulation.</source>
+        <translation type='unfinished'><b>FAC, SDC, MSC:</b> Los gráficos muestran las constelaciones de los canales lógicos FAC, SDC y MSC del flujo DRM. Dependiendo de la configuración del transmisor actual, el SDC y el MSC pueden tener modulaciones 4-QAM, 16-QAM y 64-QAM.</translation>
+    </message>
+    <message>
+        <source><b>Shifted PSD:</b> This plot shows the estimated Power Spectrum Density (PSD) of the input signal. The DC frequency (red dashed vertical line) is fixed at 6 kHz. If the frequency offset acquisition was successful, the rectangular DRM spectrum should show up with a center frequency of 6 kHz. This plot represents the frequency synchronized OFDM spectrum. If the frequency synchronization was successful, the useful signal really shows up only inside the actual DR [...]
+        <translation type='unfinished'><b>DEP Desplazada:</b> Este gráfico muestra la Densidad Espectral de Potencia (DEP) de la señal de entrada. La frecuencia DC (línea roja vertical discontinua) se fija a 6 kHz. Si la adquisición del offset de frecuencia fue satisfactoria, el espectro rectangular DRM debería aparecer con una frecuencia central de 6 kHz. Este gráfico representa el espectro OFDM sincronizado en frecuencia. Si la sincronización en frecuencia fue satisfactoria [...]
+    </message>
+    <message>
+        <source><b>SNR Spectrum (Weighted MER on MSC Cells):</b> This plot shows the Weighted MER on MSC cells for each carrier separately.</source>
+        <translation type='unfinished'><b>Espectro SNR (MER ponderada en Celdas MSC):</b> Este gráfico muestra la MER ponderada en celdas MSC para cada portadora de forma separada.</translation>
+    </message>
+    <message>
+        <source><b>Input Spectrum:</b> This plot shows the Fast Fourier Transformation (FFT) of the input signal. This plot is active in both modes, analog and digital. There is no averaging applied. The screen shot of the Evaluation Dialog shows the significant shape of a DRM signal (almost rectangular). The dashed vertical line shows the estimated DC frequency. This line is very important for the analog AM demodulation. Each time a new carrier frequency is acquired, the red [...]
+        <translation type='unfinished'><b>Espectro de entrada:</b> Este gráfico muestra la FFT (Transformada Rápida de Fourier) de la señal de entrada. Esta representación está activa en ambos modos, tanto digital como analógico. No se aplica promediado. La captura de pantalla de la ventana de Evaluación muestra la forma significativa de una señal DRM (casi rectangular). La línea vertical discontinua muestra la frecuencia DC estimada. Esta línea es muy importante para la demo [...]
+    </message>
+    <message>
+        <source><b>Input PSD:</b> This plot shows the estimated power spectral density (PSD) of the input signal. The PSD is estimated by averaging some Hamming Window weighted Fourier transformed blocks of the input signal samples. The dashed vertical line shows the estimated DC frequency.</source>
+        <translation type='unfinished'><b>DEP de Entrada:</b> Este gráfico muestra la densidad espectral de potencia (DEP) de la señal de entrada. La DEP se estima promediando algunos bloques de las muestras de la señal de entrada a los que se le ha aplicado la ventana de Hamming de la Transformada de Fourier. La línea vertical discontinua muestra la frecuencia DC estimada.</translation>
+    </message>
+    <message>
+        <source><b>Audio Spectrum:</b> This plot shows the averaged audio spectrum of the currently played audio. With this plot the actual audio bandwidth can easily determined. Since a linear scale is used for the frequency axis, most of the energy of the signal is usually concentrated on the far left side of the spectrum.</source>
+        <translation type='unfinished'><b>Espectro de Audio:</b> Este gráfico muestra el espectro de audio promediado del audio que se reproduce actualmente. Mediante esta representación, se puede determinar fácilmente el ancho de banda de audio real. Dado que para el eje de frecuencia se emplea una escala lineal, la mayor parte de la energía de la señal se concentra normalmente en el extremo izquierdo del espectro.</translation>
+    </message>
+    <message>
+        <source><b>Frequency Offset / Sample Rate Offset History:</b> The history of the values for frequency offset and sample rate offset estimation is shown. If the frequency offset drift is very small, this is an indication that the analog front end is of high quality.</source>
+        <translation type='unfinished'><b>Espectro de Audio:</b> Este gráfico muestra el espectro de audio promediado del audio que se reproduce actualmente. Mediante esta representación, se puede determinar fácilmente el ancho de banda de audio real. Dado que para el eje de frecuencia se emplea una escala lineal, la mayor parte de la energía de la señal se concentra normalmente en el extremo izquierdo del espectro.</translation>
+    </message>
+    <message>
+        <source><b>Doppler / Delay History:</b> The history of the values for the Doppler and Impulse response length is shown. Large Doppler values might be responsable for audio drop-outs.</source>
+        <translation type='unfinished'><b>Historial de Retardo / Doppler:</b> Muestra el historial de valores para la longitud Doppler y de la respuesta impulsional. Valores de Doppler muy grandes podrían ser los causantes de caídas del audio.</translation>
+    </message>
+    <message>
+        <source><b>SNR History:</b> The history of the values for the SNR and correctly decoded audio blocks is shown. The maximum achievable number of correctly decoded audio blocks per DRM frame is 10 or 5 depending on the audio sample rate (24 kHz or 12 kHz AAC core bandwidth).</source>
+        <translation type='unfinished'><b>Historial de SNR:</b> Muestra el historial de valores para la relación señal a ruido (SNR) y bloques de audio correctamente decodificados. El número máximo que se puede conseguir de bloques de audio correctamente decodificados es de 10 ó de 5 dependiendo de si la tasa de muestreo del audio es de 24 kHz o de 12 kHz (ancho de banda esencial AAC).</translation>
+    </message>
+    <message>
+        <source><b>Waterfall Display of Input Spectrum:</b> The input spectrum is displayed as a waterfall type. The different colors represent different levels.</source>
+        <translation type='unfinished'><b>Representación en Cascada del espectro de entrada:</b> El espectro de entrada se muestra en modo cascada. Los diferentes colores representan diferentes niveles.</translation>
+    </message>
+</context>
+<context>
+    <name>CDreamHelpMenu</name>
+    <message>
+        <source>What's &This</source>
+        <translation type='unfinished'>Qué es es&to</translation>
+    </message>
+    <message>
+        <source>&About...</source>
+        <translation type='unfinished'>&Sobre...</translation>
+    </message>
+</context>
+<context>
+    <name>CEPGDlgbase</name>
+    <message>
+        <source>Programme Guide</source>
+        <translation type='unfinished'>Guía de Programa</translation>
+    </message>
+    <message>
+        <source>Guide</source>
+        <translation type='unfinished'>Guía</translation>
+    </message>
+    <message>
+        <source>Name</source>
+        <translation type='unfinished'>Nombre</translation>
+    </message>
+    <message>
+        <source>Description</source>
+        <translation type='unfinished'>Descripción</translation>
+    </message>
+    <message>
+        <source>Genre</source>
+        <translation type='unfinished'>Género</translation>
+    </message>
+    <message>
+        <source>New Item</source>
+        <translation type='unfinished'>Nuevo objeto</translation>
+    </message>
+    <message>
+        <source>Basic Profile Data</source>
+        <translation type='unfinished'>Datos de perfil básico</translation>
+    </message>
+    <message>
+        <source>Advanced Profile Data</source>
+        <translation type='unfinished'>Datos de perfil avanzado</translation>
+    </message>
+    <message>
+        <source>EPG decoding is disabled</source>
+        <translation type='unfinished'>Decodifiación EPG deshabilitada</translation>
+    </message>
+    <message>
+        <source>Time [UTC]</source>
+        <translation type='unfinished'>Hora [UTC]</translation>
+    </message>
+    <message>
+        <source>&Close</source>
+        <translation type='unfinished'>&Cerrar</translation>
+    </message>
+</context>
+<context>
+    <name>CGeneralSettingsDlgBase</name>
+    <message>
+        <source>General settings</source>
+        <translation type='unfinished'>Opciones Generales</translation>
+    </message>
+    <message>
+        <source>&OK</source>
+        <translation type='unfinished'>&OK</translation>
+    </message>
+    <message>
+        <source>Receiver coordinates</source>
+        <translation type='unfinished'>Coordenadas del receptor</translation>
+    </message>
+    <message>
+        <source>Latitude   </source>
+        <translation type='unfinished'>Latitud</translation>
+    </message>
+    <message>
+        <source>'</source>
+        <translation type='unfinished'>'</translation>
+    </message>
+    <message>
+        <source>N/S</source>
+        <translation type='unfinished'>N/S</translation>
+    </message>
+    <message>
+        <source>Longitude</source>
+        <translation type='unfinished'>Longitud</translation>
+    </message>
+    <message>
+        <source>E/W</source>
+        <translation type='unfinished'>E/W</translation>
+    </message>
+</context>
+<context>
+    <name>CLiveScheduleDlgBase</name>
+    <message>
+        <source>Live Schedule</source>
+        <translation type='unfinished'>Programación en Directo</translation>
+    </message>
+    <message>
+        <source>Column 1</source>
+        <translation type='unfinished'>Columna 1</translation>
+    </message>
+    <message>
+        <source>New Item</source>
+        <translation type='unfinished'>Nuevo objeto</translation>
+    </message>
+    <message>
+        <source>TextLabelUTCTime</source>
+        <translation type='unfinished'>Hora UTC</translation>
+    </message>
+    <message>
+        <source>&Close</source>
+        <translation type='unfinished'>&Cerrar</translation>
+    </message>
+    <message>
+        <source>F&reeze</source>
+        <translation type='unfinished'>Pa&rar</translation>
+    </message>
+</context>
+<context>
+    <name>CMultSettingsDlgBase</name>
+    <message>
+        <source>Multimedia settings</source>
+        <translation type='unfinished'>Opciones Multimedia</translation>
+    </message>
+    <message>
+        <source>MOT Broadcast Web Site</source>
+        <translation type='unfinished'>Página Web de Difusión MOT</translation>
+    </message>
+    <message>
+        <source>Add refresh header of seconds</source>
+        <translation type='unfinished'>Añadir cabecera de segundos de refresco</translation>
+    </message>
+    <message>
+        <source>Clear cache</source>
+        <translation type='unfinished'>Borrar caché</translation>
+    </message>
+    <message>
+        <source>EPG - Electronic Programme Guide</source>
+        <translation type='unfinished'>EPG - Guía Electrónica de Programa</translation>
+    </message>
+    <message>
+        <source>&Close</source>
+        <translation type='unfinished'>&Cerrar</translation>
+    </message>
+</context>
+<context>
+    <name>CSoundCardSelMenu</name>
+    <message>
+        <source>Sound &In</source>
+        <translation type='unfinished'>&Entrada de Sonido</translation>
+    </message>
+    <message>
+        <source>Sound &Out</source>
+        <translation type='unfinished'>&Salida de Sonido</translation>
+    </message>
+</context>
+<context>
+    <name>CStationsDlgBase</name>
+    <message>
+        <source>Stations</source>
+        <translation type='unfinished'>Estaciones</translation>
+    </message>
+    <message>
+        <source>Column 1</source>
+        <translation type='unfinished'>Columna 1</translation>
+    </message>
+    <message>
+        <source>New Item</source>
+        <translation type='unfinished'>Nuevo objeto</translation>
+    </message>
+    <message>
+        <source>TextLabelUTCTime</source>
+        <translation type='unfinished'>Hora UTC</translation>
+    </message>
+    <message>
+        <source>kHz</source>
+        <translation type='unfinished'>kHz</translation>
+    </message>
+    <message>
+        <source>S-Meter [dB]
+(relative to S9):</source>
+        <translation type='unfinished'>Parámetros S [dB]
+(relativos a S9):</translation>
+    </message>
+    <message>
+        <source>&Close</source>
+        <translation type='unfinished'>&Cerrar</translation>
+    </message>
+</context>
+<context>
+    <name>EPGDlg</name>
+    <message>
+        <source>no basic profile data</source>
+        <translation type='unfinished'>Sin datos de perfil básico</translation>
+    </message>
+    <message>
+        <source>no advanced profile data</source>
+        <translation type='unfinished'>Sin datos de perfil avanzado</translation>
+    </message>
+    <message>
+        <source>no data</source>
+        <translation type='unfinished'>Sin datos</translation>
+    </message>
+</context>
+<context>
+    <name>FDRMDialog</name>
+    <message>
+        <source>&Evaluation Dialog...</source>
+        <translation type='unfinished'>Ventana de &Evaluación...</translation>
+    </message>
+    <message>
+        <source>M&ultimedia Dialog...</source>
+        <translation type='unfinished'>Ventana M&ultimedia...</translation>
+    </message>
+    <message>
+        <source>S&tations Dialog...</source>
+        <translation type='unfinished'>Ventana de Es&taciones...</translation>
+    </message>
+    <message>
+        <source>&Live Schedule Dialog...</source>
+        <translation type='unfinished'>Programación en &Directo...</translation>
+    </message>
+    <message>
+        <source>&Programme Guide...</source>
+        <translation type='unfinished'>Guía de &Programas...</translation>
+    </message>
+    <message>
+        <source>E&xit</source>
+        <translation type='unfinished'>&Salir</translation>
+    </message>
+    <message>
+        <source>&Sound Card Selection</source>
+        <translation type='unfinished'>Elegir Tarjeta de &Sonido</translation>
+    </message>
+    <message>
+        <source>&AM (analog)</source>
+        <translation type='unfinished'>&AM (analógico)</translation>
+    </message>
+    <message>
+        <source>New &DRM Acquisition</source>
+        <translation type='unfinished'>Nueva Adquisición &DRM</translation>
+    </message>
+    <message>
+        <source>Set D&isplay Color...</source>
+        <translation type='unfinished'>Ajustar Color de V&isualización...</translation>
+    </message>
+    <message>
+        <source>&Blue / White</source>
+        <translation type='unfinished'>&Azul / Blanco</translation>
+    </message>
+    <message>
+        <source>&Green / Black</source>
+        <translation type='unfinished'>&Verde / Blanco</translation>
+    </message>
+    <message>
+        <source>B&lack / Grey</source>
+        <translation type='unfinished'>&Negro / Gris</translation>
+    </message>
+    <message>
+        <source>&Plot Style</source>
+        <translation type='unfinished'>Ti&po de Gráfico</translation>
+    </message>
+    <message>
+        <source>&View</source>
+        <translation type='unfinished'>&Ver</translation>
+    </message>
+    <message>
+        <source>&Settings</source>
+        <translation type='unfinished'>&Opciones</translation>
+    </message>
+    <message>
+        <source>&?</source>
+        <translation type='unfinished'>&?</translation>
+    </message>
+    <message>
+        <source>Stations</source>
+        <translation type='unfinished'>Estaciones</translation>
+    </message>
+    <message>
+        <source>Live Schedule</source>
+        <translation type='unfinished'>Programación en Directo</translation>
+    </message>
+    <message>
+        <source>Programme Guide</source>
+        <translation type='unfinished'>Guía de Programas</translation>
+    </message>
+    <message>
+        <source>System Evaluation</source>
+        <translation type='unfinished'>Evaluación del Sistema</translation>
+    </message>
+    <message>
+        <source>Multimedia</source>
+        <translation type='unfinished'>Multimedia</translation>
+    </message>
+    <message>
+        <source> kbps</source>
+        <translation type='unfinished'>kbps</translation>
+    </message>
+    <message>
+        <source>No Service</source>
+        <translation type='unfinished'>Sin Servicio</translation>
+    </message>
+    <message>
+        <source> + EPG</source>
+        <translation type='unfinished'>+ EPG</translation>
+    </message>
+    <message>
+        <source> + MM</source>
+        <translation type='unfinished'>+ MM</translation>
+    </message>
+    <message>
+        <source> + AFS</source>
+        <translation type='unfinished'>+ AFS</translation>
+    </message>
+    <message>
+        <source>Scanning...</source>
+        <translation type='unfinished'>Rastreando...</translation>
+    </message>
+    <message>
+        <source><b>Text Message:</b> On the top right the text message label is shown. This label only appears when an actual text message is transmitted. If the current service does not transmit a text message, the label will be disabled.</source>
+        <translation type='unfinished'><b>Mensaje de Texto:</b> En la parte superior derecha se muestra la etiqueta del mensaje de texto. Esta etiqueta aparece sólo cuando se transmite un mensaje de texto real. Si el servicio actual no transmite un mensaje de texto, la etiqueta quedará deshabilitada.</translation>
+    </message>
+    <message>
+        <source><b>Input Level:</b> The input level meter shows the relative input signal peak level in dB. If the level is too high, the meter turns from green to red. The red region should be avoided since overload causes distortions which degrade the reception performance. Too low levels should be avoided too, since in this case the Signal-to-Noise Ratio (SNR) degrades.</source>
+        <translation type='unfinished'><b>Nivel de Entrada:</b> El medidor del nivel de entrada muestra el valor de pico relativo (en dB) de la señal de entrada. Si el nivel es demasiado elevado, el medidor pasa de verde a rojo. La región roja debería evitarse, ya que la sobrecarga causa distorsiones que degradan el rendimiento de la recepción. Igualmente, deberían evitarse los niveles de entrada demasiado bajos, ya que en este caso la SNR (Relación Señal a Ruido) es la que s [...]
+    </message>
+    <message>
+        <source><b>Status LEDs:</b> The three status LEDs show the current CRC status of the three logical channels of a DRM stream. These LEDs are the same as the top LEDs on the Evaluation Dialog.</source>
+        <translation type='unfinished'><b>LEDs indicadores de estado:</b> Los tres LEDs indicadores de estado muestran el estado CRC (Cyclic Redundancy Check) de los tres canales lógicos de una trama DRM. Estos LEDs son los mismos que los LEDs de la parte superior de la ventana de Evaluación.</translation>
+    </message>
+    <message>
+        <source><b>Station Label and Info Display:</b> In the big label with the black background the station label and some other information about the current selected service is displayed. The magenta text on the top shows the bit-rate of the current selected service (The abbreviations EEP and UEP stand for Equal Error Protection and Unequal Error Protection. UEP is a feature of DRM for a graceful degradation of the decoded audio signal in case of a bad reception situation [...]
+        <translation type='unfinished'><b>Etiqueta de Estación y Visualización de Info:</b> En el recuadro grande de fondo negro se puede visualizar la etiqueta de la estación recibida y otro tipo de información sobre el servicio actualmente seleccionado. El texto de color magenta de la parte superior muestra la tasa binaria del servicio elegido en se momento (EEP es un acrónimo para "Equal Error Protection", mientras que UEP lo es para "Unequal Error Protection". UEP es una  [...]
+    </message>
+    <message>
+        <source><b>Service Selectors:</b> In a DRM stream up to four services can be carried. The service can be an audio service, a data service or an audio service with data. Audio services can have associated text messages, in addition to any data component. If a Multimedia data service is selected, the Multimedia Dialog will automatically show up. On the right of each service selection button a short description of the service is shown. If an audio service has associated  [...]
+        <translation type='unfinished'><b>Selectores de Servicio:</b> Una trama DRM puede transportar hasta cuatro servicios. Puede tratarse de un servicio de audio, un servicio de datos o un servicio de audio con datos. Los servicios de audio pueden llevar asociados mensajes de texto, además de algún componente de datos. Si se elige un servicio de datos Multimedia, se mostrará automáticamente la ventana Multimedia. A la derecha de cada botón de selección de servicio se muest [...]
+    </message>
+    <message>
+        <source>&Multimedia settings...</source>
+        <translation type='unfinished'>Opciones &Multimedia...</translation>
+    </message>
+    <message>
+        <source>Multimedia settings</source>
+        <translation type='unfinished'>Opciones Multimedia</translation>
+    </message>
+    <message>
+        <source>&General settings...</source>
+        <translation type='unfinished'>Opciones &Generales...</translation>
+    </message>
+    <message>
+        <source>General settings</source>
+        <translation type='unfinished'>Opciones Generales</translation>
+    </message>
+</context>
+<context>
+    <name>FDRMDialogBase</name>
+    <message>
+        <source>Dream</source>
+        <translation type='unfinished'>Dream</translation>
+    </message>
+    <message>
+        <source>Level [dB]</source>
+        <translation type='unfinished'>Nivel [dB]</translation>
+    </message>
+    <message>
+        <source>15 kbps</source>
+        <translation type='unfinished'>15 kbps</translation>
+    </message>
+    <message>
+        <source>AAC+</source>
+        <translation type='unfinished'>AAC+</translation>
+    </message>
+    <message>
+        <source>Stereo</source>
+        <translation type='unfinished'>Estéreo</translation>
+    </message>
+    <message>
+        <source>Deutsche Welle</source>
+        <translation type='unfinished'>Deutsche Welle</translation>
+    </message>
+    <message>
+        <source>German</source>
+        <translation type='unfinished'>Alemán</translation>
+    </message>
+    <message>
+        <source>DE</source>
+        <translation type='unfinished'>DE</translation>
+    </message>
+    <message>
+        <source>Information</source>
+        <translation type='unfinished'>Información</translation>
+    </message>
+    <message>
+        <source>1001</source>
+        <translation type='unfinished'>1001</translation>
+    </message>
+    <message>
+        <source>TextTextMessage</source>
+        <translation type='unfinished'>Mensaje_Texto</translation>
+    </message>
+    <message>
+        <source>1</source>
+        <comment>Selects the first service</comment>
+        <translation type='unfinished'>1
+Escoge el primer servicio</translation>
+    </message>
+    <message>
+        <source>TextMiniService1</source>
+        <translation type='unfinished'>MiniServicio1</translation>
+    </message>
+    <message>
+        <source>2</source>
+        <comment>Selects the second service</comment>
+        <translation type='unfinished'>2
+Escoge el segundo servicio</translation>
+    </message>
+    <message>
+        <source>TextMiniService2</source>
+        <translation type='unfinished'>MiniServicio2</translation>
+    </message>
+    <message>
+        <source>3</source>
+        <comment>Selects the third service</comment>
+        <translation type='unfinished'>3
+Escoge el tercer servicio</translation>
+    </message>
+    <message>
+        <source>TextMiniService3</source>
+        <translation type='unfinished'>MiniServicio3</translation>
+    </message>
+    <message>
+        <source>4</source>
+        <comment>Selects the fourth service</comment>
+        <translation type='unfinished'>4
+Escoge el cuarto servicio</translation>
+    </message>
+    <message>
+        <source>TextMiniService4</source>
+        <translation type='unfinished'>MiniServicio4</translation>
+    </message>
+</context>
+<context>
+    <name>GeneralSettingsDlg</name>
+    <message>
+        <source>Latitude value must be in the range 0 to 90</source>
+        <translation type='unfinished'>El valor de latitud ha de estar en un rango de 0 a 90</translation>
+    </message>
+    <message>
+        <source>Longitude value must be in the range 0 to 180</source>
+        <translation type='unfinished'>El valor de longitud ha de estar en un rango de 0 a 90</translation>
+    </message>
+    <message>
+        <source>Minutes value must be in the range 0 to 59</source>
+        <translation type='unfinished'>El valor de los minutos debe estar en un rango de 0 a 59</translation>
+    </message>
+    <message>
+        <source>Compile all fields on receiver coordinates</source>
+        <translation type='unfinished'>Recopilar todos los datos en las coordenadas del receptor</translation>
+    </message>
+    <message>
+        <source><b>Receiver coordinates:</b> Are used on Live Schedule Dialog for show a little green cube on the left of the target column if the receiver coordinates (latitude and longitude) are inside the target area of this transmission.<br>Receiver coordinates are also saved into the Log file.</source>
+        <translation type='unfinished'><b>Coordenadas del Receptor:</b> Se usan en la ventana de Programación en Directo para mostrar un cubo verde pequeño a la izquierda de la columna de la columna del blanco si éstas (latitud y longitud) están dentro del área de blanco de esta transmisión.<br>Las coordenadas del receptor también se guardan en el archivo de registro.</translation>
+    </message>
+</context>
+<context>
+    <name>LiveScheduleDlg</name>
+    <message>
+        <source>System</source>
+        <translation type='unfinished'>Sistema</translation>
+    </message>
+    <message>
+        <source>Time [UTC]</source>
+        <translation type='unfinished'>Hora [UTC]</translation>
+    </message>
+    <message>
+        <source>Target</source>
+        <translation type='unfinished'>Blanco</translation>
+    </message>
+    <message>
+        <source>Show &only active stations</source>
+        <translation type='unfinished'>M&ostrar sólo estaciones activas</translation>
+    </message>
+    <message>
+        <source>Show &all stations</source>
+        <translation type='unfinished'>Mostrar tod&as las estaciones</translation>
+    </message>
+    <message>
+        <source>&Disabled</source>
+        <translation type='unfinished'>&Deshabilitado</translation>
+    </message>
+    <message>
+        <source>&5 minutes</source>
+        <translation type='unfinished'>&5 minutos</translation>
+    </message>
+    <message>
+        <source>&15 minutes</source>
+        <translation type='unfinished'>&15 minutos</translation>
+    </message>
+    <message>
+        <source>&30 minutes</source>
+        <translation type='unfinished'>&30 minutos</translation>
+    </message>
+    <message>
+        <source>Stations &preview</source>
+        <translation type='unfinished'>&Previsualización de Estaciones</translation>
+    </message>
+    <message>
+        <source>&Save...</source>
+        <translation type='unfinished'>&Guardar...</translation>
+    </message>
+    <message>
+        <source>&File</source>
+        <translation type='unfinished'>&Archivo</translation>
+    </message>
+    <message>
+        <source>&View</source>
+        <translation type='unfinished'>&Ver</translation>
+    </message>
+    <message>
+        <source>AFS Live Schedule</source>
+        <translation type='unfinished'>Programación en Directo AFS</translation>
+    </message>
+    <message>
+        <source><b>UTC Time:</b> Shows the current Coordinated Universal Time (UTC) which is also known as Greenwich Mean Time (GMT).</source>
+        <translation type='unfinished'><b>Hora UTC:</b> Muestra la hora UTC (Coordinated Universal Time) actual, también conocida como GMT (Greenwich Mean Time).</translation>
+    </message>
+    <message>
+        <source>Frequency [kHz/MHz]</source>
+        <translation type='unfinished'>Frecuencia [kHz/MHz]</translation>
+    </message>
+    <message>
+        <source>Start day</source>
+        <translation type='unfinished'>Día de comienzo</translation>
+    </message>
+    <message>
+        <source>Live Schedule</source>
+        <translation type='unfinished'>Programación en Directo</translation>
+    </message>
+    <message>
+        <source><b>Freeze:</b> If this check box is selected the live schedule is frozen.</source>
+        <translation type='unfinished'><b>Parar:</b> Al seleccionar esta opción, la programación en directo se detiene.</translation>
+    </message>
+    <message>
+        <source><b>Live Schedule List:</b> In the live schedule list it's possible to view AFS (Alternative Frequency Signalling) informations trasmitted with the current DRM or AMSS signal.</b>It is possible to show only active stations by changing a setting in the 'view' menu.<br>The color of the cube on the left of the frequency shows the current status of the transmission.<br>A green box shows that the transmission takes place right now a  [...]
+        <translation type='unfinished'><b>Lista de Programación en Directo:</b> En esta lista es posible ver informaciones AFS (Señalización de Frecuencia Alternativa) transmitidas en la señal DRM o AMSS actual. Es posible mostrar únicamente las estaciones activas cambiando una opción en el menú 'ver'.<br>El color del cubo a la izquierda de la frecuencia muestra el estado actual de la transmisión.<br>Una caja verde significa que la transmisión tiene luga [...]
+    </message>
+</context>
+<context>
+    <name>MultimediaDlg</name>
+    <message>
+        <source>C&lear all</source>
+        <translation type='unfinished'>&Borrar todo</translation>
+    </message>
+    <message>
+        <source>&Save...</source>
+        <translation type='unfinished'>&Guardar...</translation>
+    </message>
+    <message>
+        <source>Save &all...</source>
+        <translation type='unfinished'>Guardar &todo...</translation>
+    </message>
+    <message>
+        <source>&Close</source>
+        <translation type='unfinished'>&Cerrar</translation>
+    </message>
+    <message>
+        <source>Set &Font...</source>
+        <translation type='unfinished'>Ajustar &Fuente...</translation>
+    </message>
+    <message>
+        <source>&File</source>
+        <translation type='unfinished'>&Archivo</translation>
+    </message>
+    <message>
+        <source>&Settings</source>
+        <translation type='unfinished'>&Opciones</translation>
+    </message>
+    <message>
+        <source>MOT Broadcast Web Site</source>
+        <translation type='unfinished'>Página Web de Difusión MOT</translation>
+    </message>
+    <message>
+        <source>The home page is available</source>
+        <translation type='unfinished'>La página Web está disponible</translation>
+    </message>
+    <message>
+        <source>Image could not be loaded, </source>
+        <translation type='unfinished'>No se pudo cargar la imagen,</translation>
+    </message>
+    <message>
+        <source>-format not supported by this version of QT!</source>
+        <translation type='unfinished'>-formato no soportado por esta versión de QT!</translation>
+    </message>
+    <message>
+        <source>If you want to view the image, save it to file and use an external viewer</source>
+        <translation type='unfinished'>Si desea visualizar esta imagen, guarde el fichero y utilice un visualizador externo</translation>
+    </message>
+    <message>
+        <source>MOT Slideshow Viewer</source>
+        <translation type='unfinished'>Exposición de Diapositivas MOT</translation>
+    </message>
+    <message>
+        <source>No data service or data service not supported.</source>
+        <translation type='unfinished'>Sin servicio de datos (o servicio de datos no soportado).</translation>
+    </message>
+    <message>
+        <source>The homepage is available.</source>
+        <translation type='unfinished'>La página Web está disponible.</translation>
+    </message>
+    <message>
+        <source>Press the button to open it in the default browser.</source>
+        <translation type='unfinished'>Presione el botón para abrirlo en el buscador por defecto.</translation>
+    </message>
+    <message>
+        <source>Multimedia</source>
+        <translation type='unfinished'>Multimedia</translation>
+    </message>
+</context>
+<context>
+    <name>MultimediaDlgBase</name>
+    <message>
+        <source>Dream Multimedia</source>
+        <translation type='unfinished'>Dream Multimedia</translation>
+    </message>
+    <message>
+        <source>Receiving Status:</source>
+        <translation type='unfinished'>Estado de la Recepción:</translation>
+    </message>
+    <message>
+        <source>0/0</source>
+        <translation type='unfinished'>0/0</translation>
+    </message>
+    <message>
+        <source>&Close</source>
+        <translation type='unfinished'>&Cerrar</translation>
+    </message>
+</context>
+<context>
+    <name>QObject</name>
+    <message>
+        <source>Sun</source>
+        <translation type='unfinished'>Dom</translation>
+    </message>
+    <message>
+        <source>Mon</source>
+        <translation type='unfinished'>Lun</translation>
+    </message>
+    <message>
+        <source>Tue</source>
+        <translation type='unfinished'>Mar</translation>
+    </message>
+    <message>
+        <source>Wed</source>
+        <translation type='unfinished'>Mié</translation>
+    </message>
+    <message>
+        <source>Thu</source>
+        <translation type='unfinished'>Jue</translation>
+    </message>
+    <message>
+        <source>Fri</source>
+        <translation type='unfinished'>Vie</translation>
+    </message>
+    <message>
+        <source>Sat</source>
+        <translation type='unfinished'>Sáb</translation>
+    </message>
+    <message>
+        <source>irregular</source>
+        <translation type='unfinished'>irregular</translation>
+    </message>
+    <message>
+        <source>daily</source>
+        <translation type='unfinished'>diario</translation>
+    </message>
+    <message>
+        <source>from Sun to Thu</source>
+        <translation type='unfinished'>de Dom a Jue</translation>
+    </message>
+    <message>
+        <source>from Sun to Fri</source>
+        <translation type='unfinished'>de Dom a Vie</translation>
+    </message>
+    <message>
+        <source>from Mon to Fri</source>
+        <translation type='unfinished'>de Lun a Vie</translation>
+    </message>
+    <message>
+        <source>from Mon to Sat</source>
+        <translation type='unfinished'>de Lun a Sáb</translation>
+    </message>
+</context>
+<context>
+    <name>StationsDlg</name>
+    <message>
+        <source>Station Name</source>
+        <translation type='unfinished'>Nombre de Estación</translation>
+    </message>
+    <message>
+        <source>Time [UTC]</source>
+        <translation type='unfinished'>Hora [UTC]</translation>
+    </message>
+    <message>
+        <source>Frequency [kHz]</source>
+        <translation type='unfinished'>Frecuencia [kHz]</translation>
+    </message>
+    <message>
+        <source>Target</source>
+        <translation type='unfinished'>Blanco</translation>
+    </message>
+    <message>
+        <source>Power [kW]</source>
+        <translation type='unfinished'>Potencia [kW]</translation>
+    </message>
+    <message>
+        <source>Country</source>
+        <translation type='unfinished'>País</translation>
+    </message>
+    <message>
+        <source>Site</source>
+        <translation type='unfinished'>Emplazamiento</translation>
+    </message>
+    <message>
+        <source>Language</source>
+        <translation type='unfinished'>Idioma</translation>
+    </message>
+    <message>
+        <source>Days</source>
+        <translation type='unfinished'>Días</translation>
+    </message>
+    <message>
+        <source>Show &only active stations</source>
+        <translation type='unfinished'>Mostrar sól&o estaciones activas</translation>
+    </message>
+    <message>
+        <source>Show &all stations</source>
+        <translation type='unfinished'>Mostrar tod&as las estaciones</translation>
+    </message>
+    <message>
+        <source>&Disabled</source>
+        <translation type='unfinished'>&Deshabilitado</translation>
+    </message>
+    <message>
+        <source>&5 minutes</source>
+        <translation type='unfinished'>&5 minutos</translation>
+    </message>
+    <message>
+        <source>&15 minutes</source>
+        <translation type='unfinished'>&15 minutos</translation>
+    </message>
+    <message>
+        <source>&30 minutes</source>
+        <translation type='unfinished'>&30 minutos</translation>
+    </message>
+    <message>
+        <source>Stations &preview</source>
+        <translation type='unfinished'>&Previsualización de Estaciones</translation>
+    </message>
+    <message>
+        <source>None</source>
+        <translation type='unfinished'>Ninguna</translation>
+    </message>
+    <message>
+        <source>Other</source>
+        <translation type='unfinished'>Otra</translation>
+    </message>
+    <message>
+        <source>Enable S-Meter</source>
+        <translation type='unfinished'>Habilitar Parámetros S</translation>
+    </message>
+    <message>
+        <source>With DRM Modification</source>
+        <translation type='unfinished'>Con Modificación DRM</translation>
+    </message>
+    <message>
+        <source>&Get Update...</source>
+        <translation type='unfinished'>Actuali&zar...</translation>
+    </message>
+    <message>
+        <source>&View</source>
+        <translation type='unfinished'>&Ver</translation>
+    </message>
+    <message>
+        <source>&Remote</source>
+        <translation type='unfinished'>&Remoto</translation>
+    </message>
+    <message>
+        <source>&Update</source>
+        <translation type='unfinished'>&Actualización</translation>
+    </message>
+    <message>
+        <source>Dream Schedule Update</source>
+        <translation type='unfinished'>Actualización de Programación</translation>
+    </message>
+    <message>
+        <source>Dream tries to download the newest DRM schedule
+from www.drm-dx.de (powered by Klaus Schneider).
+Your computer must be connected to the internet.
+
+The current file DRMSchedule.ini will be overwritten.
+Do you want to continue?</source>
+        <translation type='unfinished'>Dream intentará descargar la programación DRM más reciente
+del sitio web www.drm-dx.de (impulsada por Klaus Schneider).
+Su ordenador ha de estar conectado a Internet.
+
+La versión actual de DRMSchedule.ini se sobrescribirá.
+Desea continuar?</translation>
+    </message>
+    <message>
+        <source>- the file 'DRMSchedule.ini' could not be written</source>
+        <translation type='unfinished'>- no se pudo escribir el archivo 'DRMSchedule.ini'</translation>
+    </message>
+    <message>
+        <source>Update successful.
+Due to network problems with the Windows version of QT, the Dream software must be restarted after a DRMSchedule update.
+Please exit Dream now.</source>
+        <translation type='unfinished'>Actualización llevada a cabo con éxito.
+Debido a problemas de red con la versión Windows de QT, Dream ha de reiniciarse después de una actualización de la programación.
+Por favor, salga de Dream ahora.</translation>
+    </message>
+    <message>
+        <source>Ok</source>
+        <translation type='unfinished'>Ok</translation>
+    </message>
+    <message>
+        <source>Update successful.</source>
+        <translation type='unfinished'>Actualización llevada a cabo con éxito.</translation>
+    </message>
+    <message>
+        <source><b>Frequency Counter:</b> The current frequency value can be changed by using this counter. The tuning steps are 100 kHz for the  buttons with three arrows, 10 kHz for the buttons with two arrows and 1 kHz for the buttons having only one arrow. By keeping the button pressed, the values are increased / decreased automatically.</source>
+        <translation type='unfinished'><b>Contador de Frecuencia:</b> El valor de la frecuencia actual se puede cambiar usando este contador. Los botones con tres flechas producen un incremento/decremento de 100 kHz; los de dos flechas, de 10 kHz y los de una flecha, de 1 kHz. Al mantener pulsado un botón, los valores se incrementan/decrementan de forma automática.</translation>
+    </message>
+    <message>
+        <source><b>UTC Time:</b> Shows the current Coordinated Universal Time (UTC) which is also known as Greenwich Mean Time (GMT).</source>
+        <translation type='unfinished'><b>Hora UTC:</b> Muestra la hora UTC (Coordinated Universal Time) actual, también conocida como GMT (Greenwich Mean Time).</translation>
+    </message>
+    <message>
+        <source><b>Signal-Meter:</b> Shows the signal strength level in dB relative to S9.<br>Note that not all front-ends controlled by hamlib support this feature. If the s-meter is not available, the controls are disabled.</source>
+        <translation type='unfinished'><b>Medidor de señal:</b> Muestra en dB el nivel de fuerza de la señal relativo a S9.<br>Obsérvese que no todos los receptores controlados por Hamlib soportan esta opción. Si el medidor de parámetros S no está disponible, se deshabilitan los controles.</translation>
+    </message>
+    <message>
+        <source> (last update: </source>
+        <translation type='unfinished'>(última actualización:</translation>
+    </message>
+    <message>
+        <source>&Get Update</source>
+        <translation type='unfinished'>Actuali&zar</translation>
+    </message>
+    <message>
+        <source><b>Stations List:</b> In the stations list view all DRM stations which are stored in the DRMSchedule.ini file are shown. It is possible to show only active stations by changing a setting in the 'view' menu. The color of the cube on the left of a menu item shows the current status of the DRM transmission. A green box shows that the transmission takes place right now, a yellow cube shows that this is a test transmission and with a red cube it is shown  [...]
+        <translation type='unfinished'><b>Lista de Estaciones:</b> En la lista de estaciones se muestran todas las estaciones guardadas en el archivo DRMSchedule.ini. Es posible mostrar únicamente las estaciones activas cambiando una opción en el menú 'ver'. El color del cubo a la izquierda de la frecuencia muestra el estado actual de la transmisión. Una caja verde significa que la transmisión tiene lugar ahora; una de color roja significa que la transmisión está fu [...]
+    </message>
+</context>
+<context>
+    <name>TransmDialog</name>
+    <message>
+        <source>new</source>
+        <translation type='unfinished'>nuevo</translation>
+    </message>
+    <message>
+        <source>&Start</source>
+        <translation type='unfinished'>&Comenzar</translation>
+    </message>
+    <message>
+        <source>2 s (Long Interleaving)</source>
+        <translation type='unfinished'>2 s (Intercalado largo)</translation>
+    </message>
+    <message>
+        <source>400 ms (Short Interleaving)</source>
+        <translation type='unfinished'>400 ms (Intercalado corto)</translation>
+    </message>
+    <message>
+        <source>SM 16-QAM</source>
+        <translation type='unfinished'>SM 16-QAM</translation>
+    </message>
+    <message>
+        <source>SM 64-QAM</source>
+        <translation type='unfinished'>SM 64-QAM</translation>
+    </message>
+    <message>
+        <source>4-QAM</source>
+        <translation type='unfinished'>4-QAM</translation>
+    </message>
+    <message>
+        <source>16-QAM</source>
+        <translation type='unfinished'>16-QAM</translation>
+    </message>
+    <message>
+        <source>
+This is a test transmission</source>
+        <translation type='unfinished'>Esto es una transmisión de prueba</translation>
+    </message>
+    <message>
+        <source>&Sound Card Selection</source>
+        <translation type='unfinished'>Elegir Tarjeta de &Sonido</translation>
+    </message>
+    <message>
+        <source>&Settings</source>
+        <translation type='unfinished'>&Opciones</translation>
+    </message>
+    <message>
+        <source>&?</source>
+        <translation type='unfinished'>&?</translation>
+    </message>
+    <message>
+        <source>&Stop</source>
+        <translation type='unfinished'>&Parar</translation>
+    </message>
+    <message>
+        <source>Image Files (*.png *.jpg *.jpeg *.jfif)</source>
+        <translation type='unfinished'>Archivos de imagen (*.png *.jpg *.jpeg *.jfif)</translation>
+    </message>
+    <message>
+        <source><b>Dream Logo:</b> This is the official logo of the Dream software.</source>
+        <translation type='unfinished'><b> Logotipo de Dream</b>: Este es el logotipo oficial del SW Dream</translation>
+    </message>
+    <message>
+        <source><b>Input Level:</b> The input level meter shows the relative input signal peak level in dB. If the level is too high, the meter turns from green to red.</source>
+        <translation type='unfinished'><b>Nivel de Entrada:</b> El medidor del nivel de entrada muestra el valor de pico relativo (en dB) de la señal de entrada. Si el nivel es demasiado elevado, el medidor pasa de verde a rojo.</translation>
+    </message>
+    <message>
+        <source><b>DRM Robustness Mode:</b> In a DRM system, four possible robustness modes are defined to adapt the system to different channel conditions. According to the DRM standard:<ul><li><i>Mode A:</i> Gaussian channels, with minor fading</li><li><i>Mode B:</i> Time and frequency selective channels, with longer delay spread</li><li><i>Mode C:</i> As robustness mode B, but with higher Doppler sprea [...]
+        <translation type='unfinished'><b>Modo de Robustez DRM:</b> En un sistema DRM, se definen cuatro modos de robustez posibles para adaptar el sistema a las diferentes condiciones del canal. Según el estándar de DRM:<ul><li><i>Modo A:</i> Canales Gaussianos, con escaso desvanecimiento</li><li><i>Modo B:</i> Canales Selectivos en Tempo y en Frecuencia, con mayor propagación de retardo</li><li><i>Modo C:< [...]
+    </message>
+    <message>
+        <source><b>DRM Bandwidth:</b> The bandwith is the gross bandwidth of the generated DRM signal. Not all DRM robustness mode / bandwidth constellations are possible, e.g., DRM robustness mode D and C are only defined for the bandwidths 10 kHz and 20 kHz.</source>
+        <translation type='unfinished'><b>Ancho de Banda DRM:</b> Es el ancho de banda bruto de la señal DRM generada. No todas las conjugaciones modo de robustez/ancho de banda son posibles. Por ejemplo, los modos de robustez C y D sólo están definidos para anchos de banda de 10 kHz y 20 kHz.</translation>
+    </message>
+    <message>
+        <source><b>Output intermediate frequency of DRM signal:</b> Set the output intermediate frequency (IF) of generated DRM signal in the 'sound-card pass-band'. In some DRM modes, the IF is located at the edge of the DRM signal, in other modes it is centered. The IF should be chosen that the DRM signal lies entirely inside the sound-card bandwidth.</source>
+        <translation type='unfinished'><b>Frecuencia Intermedia de salida de la señal DRM:</b> Ajusta la frecuencia intermedia (IF) de salida de la señal DRM generada en el filtro paso banda de la tarjeta de sonido. En algunos modos DRM, la IF está en un extremo de la señal DRM, mientras que en otros está centrada. La IF se ha de escoger de modo tal que la señal DRM entre íntegramente en el ancho de banda de la tarjeta de sonido.</translation>
+    </message>
+    <message>
+        <source><b>Output format:</b> Since the sound-card outputs signals in stereo format, it is possible to output the DRM signal in three formats:<ul><li><b>real valued</b> output on both, left and right, sound-card channels</li><li><b>I / Q</b> output which is the in-phase and quadrature component of the complex base-band signal at the desired IF. In-phase is output on the left channel and quadrature on the right channel.&l [...]
+        <translation type='unfinished'><b>Formato de salida:</b> Dado que la tarjeta de sonido saca las señales en formato estéreo, es posible sacar la señal DRM en tres formatos:<ul><li><b>Valor real</b> Salida en ambos canales de la tarjeta de sonido, izquierdo y derecho</li><li><b>I / Q</b> Saca las componentes en fase y en cuadratura de la señal compleja en banda base a la frecuencia intermedia deseada. La componente en fase [...]
+    </message>
+    <message>
+        <source><b>MSC interleaver mode:</b> The symbol interleaver depth can be either short (approx. 400 ms) or long (approx. 2 s). The longer the interleaver the better the channel decoder can correct errors from slow fading signals. But the longer the interleaver length the longer the delay until (after a re-synchronization) audio can be heard.</source>
+        <translation type='unfinished'><b>Modo de Intercalado MSC:</b> La profundidad del intercalado de símbolos puede ser bien corta (aproximadamente 400 ms) o bien larga (aproximadamente 2 s). Mientras mayor sea la longitud de intercalado, mejor podrá el decodificador de canal corregir errores en señales con escaso desvanecimiento, aunque también será mayor el retardo (después de una resincronización) hasta que pueda oirse el audio.</translation>
+    </message>
+    <message>
+        <source>Dream DRM Transmitter</source>
+        <translation type='unfinished'>Transmisor DRM Dream</translation>
+    </message>
+</context>
+<context>
+    <name>TransmDlgBase</name>
+    <message>
+        <source>Dream DRM Transmitter</source>
+        <translation type='unfinished'>Transmisor DRM Dream</translation>
+    </message>
+    <message>
+        <source>Volker Fischer, Alexander Kurpiers</source>
+        <translation type='unfinished'>Volker Fischer, Alexander Kurpiers</translation>
+    </message>
+    <message>
+        <source>Darmstadt University of Technology
+Institute for Communication Technology</source>
+        <translation type='unfinished'>Darmstadt University of Technology
+Institute for Communication Technology</translation>
+    </message>
+    <message>
+        <source>Indicators</source>
+        <translation type='unfinished'>Indicadores</translation>
+    </message>
+    <message>
+        <source>Audio Level [dB]:</source>
+        <translation type='unfinished'>Nivel de Audio [dB]:</translation>
+    </message>
+    <message>
+        <source>TextLabelCurPict</source>
+        <translation type='unfinished'>EtiquetaFoto</translation>
+    </message>
+    <message>
+        <source>Channel Parameters</source>
+        <translation type='unfinished'>Parámetros del Canal</translation>
+    </message>
+    <message>
+        <source>Robustness Mode</source>
+        <translation type='unfinished'>Modo de Robustez</translation>
+    </message>
+    <message>
+        <source>A</source>
+        <translation type='unfinished'>A</translation>
+    </message>
+    <message>
+        <source>B</source>
+        <translation type='unfinished'>B</translation>
+    </message>
+    <message>
+        <source>C</source>
+        <translation type='unfinished'>C</translation>
+    </message>
+    <message>
+        <source>D</source>
+        <translation type='unfinished'>D</translation>
+    </message>
+    <message>
+        <source>Bandwidth</source>
+        <translation type='unfinished'>Ancho de Banda</translation>
+    </message>
+    <message>
+        <source>4,5 kHz</source>
+        <translation type='unfinished'>4,5 kHz</translation>
+    </message>
+    <message>
+        <source>9 kHz</source>
+        <translation type='unfinished'>9 kHz</translation>
+    </message>
+    <message>
+        <source>18 kHz</source>
+        <translation type='unfinished'>18 kHz</translation>
+    </message>
+    <message>
+        <source>5 kHz</source>
+        <translation type='unfinished'>5 kHz</translation>
+    </message>
+    <message>
+        <source>10 kHz</source>
+        <translation type='unfinished'>10 kHz</translation>
+    </message>
+    <message>
+        <source>20 kHz</source>
+        <translation type='unfinished'>20 kHz</translation>
+    </message>
+    <message>
+        <source>MSC Constellation Scheme:</source>
+        <translation type='unfinished'>Esquema de Constelación MSC:</translation>
+    </message>
+    <message>
+        <source>MSC Protection Level:</source>
+        <translation type='unfinished'>Nivel de Protección MSC:</translation>
+    </message>
+    <message>
+        <source>SDC Constellation Scheme:</source>
+        <translation type='unfinished'>Esquema de Constelación SDC:</translation>
+    </message>
+    <message>
+        <source>MSC Interleaver Mode:</source>
+        <translation type='unfinished'>Modo de Intercalado MSC:</translation>
+    </message>
+    <message>
+        <source>Output</source>
+        <translation type='unfinished'>Salida</translation>
+    </message>
+    <message>
+        <source>IF:</source>
+        <translation type='unfinished'>Freq. Interm:</translation>
+    </message>
+    <message>
+        <source> Hz</source>
+        <translation type='unfinished'>Hz</translation>
+    </message>
+    <message>
+        <source>Real val.</source>
+        <translation type='unfinished'>Val. Real</translation>
+    </message>
+    <message>
+        <source>I / Q (pos)</source>
+        <translation type='unfinished'>I / Q (pos)</translation>
+    </message>
+    <message>
+        <source>I / Q (neg)</source>
+        <translation type='unfinished'>I / Q (neg)</translation>
+    </message>
+    <message>
+        <source>E / P</source>
+        <translation type='unfinished'>E / P</translation>
+    </message>
+    <message>
+        <source>Service 1</source>
+        <translation type='unfinished'>Servicio 1</translation>
+    </message>
+    <message>
+        <source>Enable</source>
+        <translation type='unfinished'>Habilitar</translation>
+    </message>
+    <message>
+        <source>Label:</source>
+        <translation type='unfinished'>Etiqueta:</translation>
+    </message>
+    <message>
+        <source>Service ID:</source>
+        <translation type='unfinished'>Id. de Servicio:</translation>
+    </message>
+    <message>
+        <source>Language:</source>
+        <translation type='unfinished'>Idioma:</translation>
+    </message>
+    <message>
+        <source>Audio</source>
+        <translation type='unfinished'>Audio</translation>
+    </message>
+    <message>
+        <source>Program Type:</source>
+        <translation type='unfinished'>Tipo de programa:</translation>
+    </message>
+    <message>
+        <source>Text Message</source>
+        <translation type='unfinished'>Mensaje de texto:</translation>
+    </message>
+    <message>
+        <source>&Clear All</source>
+        <translation type='unfinished'>&Borrar todo</translation>
+    </message>
+    <message>
+        <source>&Add / Modify</source>
+        <translation type='unfinished'>&Añadir / Modificar</translation>
+    </message>
+    <message>
+        <source>Data (SlideShow Application)</source>
+        <translation type='unfinished'>Datos (Aplicación Diapositivas)</translation>
+    </message>
+    <message>
+        <source>Column 1</source>
+        <translation type='unfinished'>Columna 1</translation>
+    </message>
+    <message>
+        <source>New Item</source>
+        <translation type='unfinished'>Nuevo objeto</translation>
+    </message>
+    <message>
+        <source>&Add</source>
+        <translation type='unfinished'>&Añadir</translation>
+    </message>
+    <message>
+        <source>Service 2</source>
+        <translation type='unfinished'>Servicio 2</translation>
+    </message>
+    <message>
+        <source>Service 3</source>
+        <translation type='unfinished'>Servicio 3</translation>
+    </message>
+    <message>
+        <source>Service 4</source>
+        <translation type='unfinished'>Servicio 4</translation>
+    </message>
+    <message>
+        <source>&Start</source>
+        <translation type='unfinished'>Co&menzar</translation>
+    </message>
+    <message>
+        <source>&Close</source>
+        <translation type='unfinished'>&Cerrar</translation>
+    </message>
+</context>
+<context>
+    <name>systemevalDlg</name>
+    <message>
+        <source>MLC: Number of Iterations: </source>
+        <translation type='unfinished'>MLC: Nº de Iteraciones:</translation>
+    </message>
+    <message>
+        <source>History</source>
+        <translation type='unfinished'>Historial</translation>
+    </message>
+    <message>
+        <source>Constellation</source>
+        <translation type='unfinished'>Constelación</translation>
+    </message>
+    <message>
+        <source>Channel</source>
+        <translation type='unfinished'>Canal</translation>
+    </message>
+    <message>
+        <source>Spectrum</source>
+        <translation type='unfinished'>Espectro</translation>
+    </message>
+    <message>
+        <source>SNR Spectrum</source>
+        <translation type='unfinished'>Espectro SNR</translation>
+    </message>
+    <message>
+        <source>Audio Spectrum</source>
+        <translation type='unfinished'>Espectro Audio</translation>
+    </message>
+    <message>
+        <source>Shifted PSD</source>
+        <translation type='unfinished'>DEP Desplazada</translation>
+    </message>
+    <message>
+        <source>Waterfall Input Spectrum</source>
+        <translation type='unfinished'>Espectro de Entrada en Cascada</translation>
+    </message>
+    <message>
+        <source>Input Spectrum</source>
+        <translation type='unfinished'>Espectro de Entrada</translation>
+    </message>
+    <message>
+        <source>Input PSD</source>
+        <translation type='unfinished'>DEP de Entrada</translation>
+    </message>
+    <message>
+        <source>MSC</source>
+        <translation type='unfinished'>MSC</translation>
+    </message>
+    <message>
+        <source>SDC</source>
+        <translation type='unfinished'>SDC</translation>
+    </message>
+    <message>
+        <source>FAC</source>
+        <translation type='unfinished'>FAC</translation>
+    </message>
+    <message>
+        <source>FAC / SDC / MSC</source>
+        <translation type='unfinished'>FAC / SDC / MSC</translation>
+    </message>
+    <message>
+        <source>Frequency / Sample Rate</source>
+        <translation type='unfinished'>Frecuencia / Tasa de Muestreo</translation>
+    </message>
+    <message>
+        <source>Delay / Doppler</source>
+        <translation type='unfinished'>Retardo / Doppler</translation>
+    </message>
+    <message>
+        <source>SNR / Audio</source>
+        <translation type='unfinished'>SNR / Audio</translation>
+    </message>
+    <message>
+        <source>Transfer Function</source>
+        <translation type='unfinished'>Función de Transferencia</translation>
+    </message>
+    <message>
+        <source>Impulse Response</source>
+        <translation type='unfinished'>Respuesta Impulsional</translation>
+    </message>
+    <message>
+        <source>ListView context menu</source>
+        <translation type='unfinished'>Menú Contextual ListView</translation>
+    </message>
+    <message>
+        <source>&Open in separate window</source>
+        <translation type='unfinished'>&Abrir en una ventana nueva</translation>
+    </message>
+    <message>
+        <source>Chart Window</source>
+        <translation type='unfinished'>Gráfico</translation>
+    </message>
+    <message>
+        <source>Metrics [dB]: MSC: </source>
+        <translation type='unfinished'>Medidas [dB]: MSC:</translation>
+    </message>
+    <message>
+        <source>2 s (Long Interleaving)</source>
+        <translation type='unfinished'>2 s (Intercalado largo)</translation>
+    </message>
+    <message>
+        <source>400 ms (Short Interleaving)</source>
+        <translation type='unfinished'>400 ms (Intercalado corto)</translation>
+    </message>
+    <message>
+        <source>Interleaver Depth:</source>
+        <translation type='unfinished'>Profundidad de Intercalado:</translation>
+    </message>
+    <message>
+        <source>SDC / MSC Mode:</source>
+        <translation type='unfinished'>Modo SDC / MSC:</translation>
+    </message>
+    <message>
+        <source>Prot. Level (B / A):</source>
+        <translation type='unfinished'>Nivel de Protección (B / A):</translation>
+    </message>
+    <message>
+        <source>Audio: </source>
+        <translation type='unfinished'>Audio:</translation>
+    </message>
+    <message>
+        <source> / Data: </source>
+        <translation type='unfinished'>/ Datos:</translation>
+    </message>
+    <message>
+        <source>Number of Services:</source>
+        <translation type='unfinished'>Nº de Servicios:</translation>
+    </message>
+    <message>
+        <source>Service not available</source>
+        <translation type='unfinished'>Servicio no disponible</translation>
+    </message>
+    <message>
+        <source>Received time - date:</source>
+        <translation type='unfinished'>Hora / Fecha Recibidas:</translation>
+    </message>
+    <message>
+        <source>DreamOut.wav</source>
+        <translation type='unfinished'>DreamOut.wav</translation>
+    </message>
+    <message>
+        <source>Label            </source>
+        <translation type='unfinished'>Etiqueta</translation>
+    </message>
+    <message>
+        <source>
+Bitrate          </source>
+        <translation type='unfinished'>Tasa de Bit</translation>
+    </message>
+    <message>
+        <source>
+Mode             </source>
+        <translation type='unfinished'>Modo</translation>
+    </message>
+    <message>
+        <source>
+Bandwidth        </source>
+        <translation type='unfinished'>Ancho de Banda</translation>
+    </message>
+    <message>
+        <source><b>DC Frequency Offset:</b> This is the estimation of the DC frequency offset. This offset corresponds to the resulting sound card intermedia frequency of the front-end. This frequency is not restricted to a certain value. The only restriction is that the DRM spectrum must be completely inside the bandwidth of the sound card.</source>
+        <translation type='unfinished'><b>Offset de Frecuencia DC:</b> Es una estimación del offset de la frecuencia continua (DC). Este offset corresponde a la frecuencia intermedia de la tarjeta de sonido resultante en el receptor. Esta frecuencia no está restringida a un valor determinado. La única restricción es que el espectro DRM ha de estar completamente dentro del ancho de banda de la tarjeta de sonido.</translation>
+    </message>
+    <message>
+        <source><b>Sample Frequency Offset:</b> This is the estimation of the sample rate offset between the sound card sample rate of the local computer and the sample rate of the D / A (digital to analog) converter in the transmitter. Usually the sample rate offset is very constant for a given sound card. Therefore it is useful to inform the Dream software about this value at application startup to increase the acquisition speed and reliability.</source>
+        <translation type='unfinished'><b>Offset de Frecuencia de Muestreo:</b> Se trata de una estimación del offset de la tasa de muestreo entre la tasa de muestreo de la tarjeta de sonido del ordenador local y la tasa de muestreo de conversor digital / analógico (DAC) del transmisor. Normalmente, este offset es constante para una cierta tarjeta de sonido. Por tanto, resulta útil informar con este valor a Dream en el arranque de la aplicación para aumentar la velocidad de a [...]
+    </message>
+    <message>
+        <source><b>Doppler / Delay:</b> The Doppler frequency of the channel is estimated for the Wiener filter design of channel estimation in time direction. If linear interpolation is set for channel estimation in time direction, this estimation is not updated. The Doppler frequency is an indication of how fast the channel varies with time. The higher the frequency, the faster the channel changes are.<br>The total delay of the Power Delay Spectrum (PDS) is estimated  [...]
+        <translation type='unfinished'><b>Doppler / Retardo:</b> La frecuencia Doppler del canal se estima con objeto de diseñar el filtro de Wiener para la estimación del canal en el dominio del tiempo. Si se configura la interpolación lineal para la estimación del canal en el dominio del tiempo, esta estimación no se actualiza. La frecuencia Doppler indica cómo de rápido varía el canal con el tiempo. Mientras mayor sea la frecuencia, más rápidamente se producen los cambios  [...]
+    </message>
+    <message>
+        <source><b>I / O Interface LED:</b> This LED shows the current status of the sound card interface. The yellow light shows that the audio output was corrected. Since the sample rate of the transmitter and local computer are different, from time to time the audio buffers will overflow or under run and a correction is necessary. When a correction occurs, a "click" sound can be heard. The red light shows that a buffer was lost in the sound card input stream. This can happ [...]
+        <translation type='unfinished'><b>LED Interfaz E / S:</b> Este LED muestra el estado actual del interfaz de la tarjeta de sonido. La luz amarilla indica que la salida de audio fue corregida. Dado que las tasas de muestreo del transmisor y del ordenador local son diferentes, de vez en cuando los buffers de audio se saturarán o estarán infrautilizados, por lo que será necesaria una corrección. Cuando se produce una corrección, puede oírse un "click". La luz roja indica  [...]
+    </message>
+    <message>
+        <source><b>Time Sync Acq LED:</b> This LED shows the state of the timing acquisition (search for the beginning of an OFDM symbol). If the acquisition is done, this LED will stay green.</source>
+        <translation type='unfinished'><b>LED de Adquisición de Sincronización Temporal:</b> Este LED muestra el estado de la sincronización temporal (busca el principio de un símbolo OFDM). Una vez hecha la adquisición, la luz se muestra de color verde.</translation>
+    </message>
+    <message>
+        <source><b>Frame Sync LED:</b> The DRM frame synchronization status is shown with this LED. This LED is also only active during acquisition state of the Dream receiver. In tracking mode, this LED is always green.</source>
+        <translation type='unfinished'><b>LED de Sincronización en Frecuencia:</b> El estado de sincronización de la trama DRM se muestra mediante este LED, que únicamente está activo durante el estado de adquisición del receptor Dream. En modo seguimiento, este LED está siempre verde.</translation>
+    </message>
+    <message>
+        <source><b>FAC CRC LED:</b> This LED shows the Cyclic Redundancy Check (CRC) of the Fast Access Channel (FAC) of DRM. FAC is one of the three logical channels and is always modulated with a 4-QAM. If the FAC CRC check was successful, the receiver changes to tracking mode. The FAC LED is the indication whether the receiver is synchronized to a DRM transmission or not.<br>The bandwidth of the DRM signal, the constellation scheme of MSC and SDC channels and the int [...]
+        <translation type='unfinished'><b>LED de CRC de canal FAC:</b> Este LED indica el CRC (Cyclic Redundancy Check) del canal FAC (Fast Access Channel) de DRM. FAC es uno de los tres canales lógicos y siempre va modulado con una 4-QAM. Si el CRC de este canal es correcto, el receptor cambia a modo seguimiento. El LED del canal FAC indica si el receptor está sincronizado a una transmisión DRM o no.<br>El ancho de banda de la señal DRM, el esquema de constelación para [...]
+    </message>
+    <message>
+        <source><b>SDC CRC LED:</b> This LED shows the CRC check result of the Service Description Channel (SDC) which is one logical channel of the DRM stream. This data is transmitted in approx. 1 second intervals and contains information about station label, audio and data format, etc. The error protection is normally lower than the protection of the FAC. Therefore this LED will turn to red earlier than the FAC LED in general.<br>If the CRC check is ok but errors in  [...]
+        <translation type='unfinished'><b>LED de CRC de canal SDC:</b> Este LED indica el CRC (Cyclic Redundancy Check) del canal SDC (Service Description Channel). SDC es uno de los tres canales lógicos de DRM. Estos datos se transmiten en intervalos de aproximadamente un segundo y contienen información sobre el nombre de la estación, formatos de audio y datos, etc. El nivel de protección frente a errores es normalmente más bajo que el del FAC. Por tanto, este LED se pondrá  [...]
+    </message>
+    <message>
+        <source><b>MSC CRC LED:</b> This LED shows the status of the Main Service Channel (MSC). This channel contains the actual audio and data bits. The LED shows the CRC check of the AAC core decoder. The SBR has a separate CRC, but this status is not shown with this LED. If SBR CRC is wrong but the AAC CRC is ok one can still hear something (of course, the high frequencies are not there in this case). If this LED turns red, interruptions of the audio are heard. The yellow [...]
+        <translation type='unfinished'><b>LED de CRC de canal MSC:</b> Este LED indica el CRC (Cyclic Redundancy Check) del canal MSC (Main Service Channel). Este canal contiene el audio y los bits de datos reales. El LED indica la comprobación del CRC del decodificador principal AAC. SBR (Spectral Band Replication) tiene un CRC separado, pero su estado no se muestra con este LED. Si el CRC de la parte SBR es erróneo y el de la parte AAC es correcto, se puede oír algo (aunque [...]
+    </message>
+    <message>
+        <source><b>MLC, Number of Iterations:</b> In DRM, a multilevel channel coder is used. With this code it is possible to iterate the decoding process in the decoder to improve the decoding result. The more iterations are used the better the result will be. But switching to more iterations will increase the CPU load. Simulations showed that the first iteration (number of iterations = 1) gives the most improvement (approx. 1.5 dB at a BER of 10-4 on a Gaussian channel, Mo [...]
+        <translation type='unfinished'><b>MLC, Número de Iteraciones:</b> En DRM se utiliza un codificador de canal multinivel. Con este código, es posible iterar en el proceso de decodificación para mejorar el resultado de la misma. Cuantas más iteraciones se empleen, mejores resultados se obtendrán. Pero cambiar a un mayor número de iteraciones aumentará la carga de la CPU. Mediante simulaciones se ha probado que la primera iteración (número de iteraciones = 1) proporciona  [...]
+    </message>
+    <message>
+        <source><b>Flip Input Spectrum:</b> Checking this box will flip or invert the input spectrum. This is necessary if the mixer in the front-end uses the lower side band.</source>
+        <translation type='unfinished'><b>Invertir Espectro de Entrada:</b> Marcar esta opción invertirá o volteará el espectro de entrada. Esto es necesario si el mezclador del receptor utiliza la banda lateral inferior.</translation>
+    </message>
+    <message>
+        <source><b>Mute Audio:</b> The audio can be muted by checking this box. The reaction of checking or unchecking this box is delayed by approx. 1 second due to the audio buffers.</source>
+        <translation type='unfinished'><b>Silenciar Audio:</b> Al marcar este cuadro el audio puede silenciarse. Al marcar/desmarcar este cuadro la reacción puede retardarse aproximadamente un segundo, debido a los buffers de audio.</translation>
+    </message>
+    <message>
+        <source><b>Reverberation Effect:</b> If this check box is checked, a reverberation effect is applied each time an audio drop-out occurs. With this effect it is possible to mask short drop-outs.</source>
+        <translation type='unfinished'><b>Efecto de resonancia:</b> Al marcar esta opción, se aplica un efecto de resonancia cada vez que hay una pérdida de información de audio. Con este efecto es posible enmascarar breves pérdidas de información.</translation>
+    </message>
+    <message>
+        <source><b>Freq:</b> In this edit control, the current selected frequency on the front-end can be specified. This frequency will be written into the log file.</source>
+        <translation type='unfinished'><b>Frec:</b> En este cuadro de control se puede especificar la frecuencia a la que está sintonizado el receptor. Esta frecuencia se escribirá en el fichero de registro.</translation>
+    </message>
+    <message>
+        <source><b>Channel Estimation Settings:</b> With these settings, the channel estimation method in time and frequency direction can be selected. The default values use the most powerful algorithms. For more detailed information about the estimation algorithms there are a lot of papers and books available.<br><b>Wiener:</b> Wiener interpolation method uses estimation of the statistics of the channel to design an optimal filter for noise reduction.</source>
+        <translation type='unfinished'><b>Opciones de Estimación del Canal:</b> Con estas opciones, se puede elegir el método de estimación del canal tanto en tiempo como en frecuencia. Los valores por defecto usan los algoritmos más potentes. Para información más detallada sobre los algoritmos de estimación, existen multitud de artículos y libros disponibles.<br><b>Wiener:</b> El método de interpolación de Wiener usa una estimación de los estadísticos del c [...]
+    </message>
+    <message>
+        <source><b>Channel Estimation Settings:</b> With these settings, the channel estimation method in time and frequency direction can be selected. The default values use the most powerful algorithms. For more detailed information about the estimation algorithms there are a lot of papers and books available.<br><b>Linear:</b> Simple linear interpolation method to get the channel estimate. The real and imaginary parts of the estimated channel at the pilot [...]
+        <translation type='unfinished'><b>Opciones de Estimación del Canal:</b> Con estas opciones, se puede elegir el método de estimación del canal tanto en tiempo como en frecuencia. Los valores por defecto usan los algoritmos más potentes. Para información más detallada sobre los algoritmos de estimación, existen multitud de artículos y libros disponibles.<br><b>Lineal:</b> Método simple de interpolación lineal para conseguir una estimación del canal. Se [...]
+    </message>
+    <message>
+        <source><b>Channel Estimation Settings:</b> With these settings, the channel estimation method in time and frequency direction can be selected. The default values use the most powerful algorithms. For more detailed information about the estimation algorithms there are a lot of papers and books available.<br><b>DFT Zero Pad:</b> Channel estimation method for the frequency direction using Discrete Fourier Transformation (DFT) to transform the channel e [...]
+        <translation type='unfinished'><b>Opciones de Estimación del Canal:</b> Con estas opciones, se puede elegir el método de estimación del canal tanto en tiempo como en frecuencia. Los valores por defecto usan los algoritmos más potentes. Para información más detallada sobre los algoritmos de estimación, existen multitud de artículos y libros disponibles.<br><b>Relleno de ceros en la DFT:</b> Método de estimación del canal en el dominio de la frecuencia [...]
+    </message>
+    <message>
+        <source><b>Guard Energy:</b> Time synchronization tracking algorithm utilizes the estimation of the impulse response. This method tries to maximize the energy in the guard-interval to set the correct timing.</source>
+        <translation type='unfinished'><b>Energía de Guarda:</b> El algoritmo de seguimiento de sincronización temporal utiliza la estimación de la respuesta impulsional. Este método intenta maximizar la energía en el intervalo de guarda para ajustar la coordinación adecuada.</translation>
+    </message>
+    <message>
+        <source><b>First Peak:</b> This algorithms searches for the first peak in the estimated impulse response and moves this peak to the beginning of the guard-interval (timing tracking algorithm).</source>
+        <translation type='unfinished'><b>Primer pico:</b> Este algoritmo busca el primer pico en la respuesta impulsional estimada y mueve este pico al comienzo del intervalo de guarda (algoritmo de seguimiento temporal).</translation>
+    </message>
+    <message>
+        <source><b>SNR:</b> Signal to Noise Ratio (SNR) estimation based on FAC cells. Since the FAC cells are only located approximately in the region 0-5 kHz relative to the DRM DC frequency, it may happen that the SNR value is very high although the DRM spectrum on the left side of the DRM DC frequency is heavily distorted or disturbed by an interferer so that the true overall SNR is lower as indicated by the SNR value. Similarly, the SNR value might show a very low value  [...]
+        <translation type='unfinished'><b>Relación Señal a Ruido (SNR):</b> Se trata de una estimación de la SNR (Signal to Noise Ratio) basada en celdas del canal FAC. Dado que las celdas FAC están únicamente situadas aproximadamente en la región 0 - 5 kHz relativa a la frecuencia DC de la señal DRM, puede ocurrir que el valor de la SNR estimada sea muy alto aunque el espectro DRM de la parte derecha de la frecuencia DC esté gravemente distorsionado o interrumpido por una se [...]
+    </message>
+    <message>
+        <source><b>MSC WMER / MSC MER:</b> Modulation Error Ratio (MER) and weighted MER (WMER) calculated on the MSC cells is shown. The MER is calculated as follows: For each equalized MSC cell (only MSC cells, no FAC cells, no SDC cells, no pilot cells), the error vector from the nearest ideal point of the constellation diagram is measured. The squared magnitude of this error is found, and a mean of the squared errors is calculated (over one frame). The MER is the ratio in [...]
+        <translation type='unfinished'><b>WMER del canal MSC / MER del canal MSC:</b> Se muestra la MER (Tasa de Error de Modulación) y la WMER (MER Ponderada). La MER se calcula de la siguiente manera: Por cada celda MSC ecualizada (sólo celdas MSC; no celdas FAC, ni celdas SDC, ni celdas piloto), se mide el vector de error desde el punto ideal más cercano del diagrama de la constelación. Se halla el cuadrado del módulo de este error y se calcula el promedio (sobre una trama [...]
+    </message>
+    <message>
+        <source><b>DRM Mode / Bandwidth:</b> In a DRM system, four possible robustness modes are defined to adapt the system to different channel conditions. According to the DRM standard:<ul><li><i>Mode A:</i> Gaussian channels, with minor fading</li><li><i>Mode B:</i> Time and frequency selective channels, with longer delay spread</li><li><i>Mode C:</i> As robustness mode B, but with higher Doppler spre [...]
+        <translation type='unfinished'><b>Modo DRM / Ancho de Banda:</b> En un sistema DRM, se definen cuatro modos de robustez posibles para adaptar el sistema a las diferentes condiciones del canal. Según el estándar de DRM:<ul><li><i>Modo A:</i> Canales Gaussianos, con escaso desvanecimiento</li><li><i>Modo B:</i> Canales Selectivos en Tempo y en Frecuencia, con mayor propagación de retardo</li><li><i>Modo C [...]
+    </message>
+    <message>
+        <source><b>Interleaver Depth:</b> The symbol interleaver depth can be either short (approx. 400 ms) or long (approx. 2 s). The longer the interleaver the better the channel decoder can correct errors from slow fading signals. But the longer the interleaver length the longer the delay until (after a re-synchronization) audio can be heard.</source>
+        <translation type='unfinished'><b>Modo de Intercalado MSC:</b> La profundidad del intercalado de símbolos puede ser bien corta (aproximadamente 400 ms) o bien larga (aproximadamente 2 s). Mientras mayor sea la longitud de intercalado, mejor podrá el decodificador de canal corregir errores en señales con escaso desvanecimiento, aunque también será mayor el retardo (después de una resincronización) hasta que pueda oírse el audio.</translation>
+    </message>
+    <message>
+        <source><b>SDC / MSC Mode:</b> Shows the modulation type of the SDC and MSC channel. For the MSC channel, some hierarchical modes are defined which can provide a very strong protected service channel.</source>
+        <translation type='unfinished'><b>Modo SDC / MSC:</b> Muestra el tipo de modulación de los canales SDC y MSC. Para el canal MSC, se definen algunos modos jerárquicos que pueden proveer un canal de servicio fuertemente protegido.</translation>
+    </message>
+    <message>
+        <source><b>Prot. Level (B/A):</b> The error protection level of the channel coder. For 64-QAM, there are four protection levels defined in the DRM standard. Protection level 0 has the highest protection whereas level 3 has the lowest protection. The letters A and B are the names of the higher and lower protected parts of a DRM block when Unequal Error Protection (UEP) is used. If Equal Error Protection (EEP) is used, only the protection level of part B is valid.</source>
+        <translation type='unfinished'><b>Nivel de Protección (B/A):</b> Es el nivel de protección de error del codificador de canal. Para una 64-QAM se definen cuatro niveles de protección en el estándar de DRM. En nivel de protección 0 tienen la máxima protección, mientras que el nivel de protección 3 tiene la mínima. Las letras A y B son los nombres de las partes más y menos protegidas de un bloque DRM cuando se emplea UEP (Unequal Error Protection). Si se usa EEP (Equal E [...]
+    </message>
+    <message>
+        <source><b>Number of Services:</b> This shows the number of audio and data services transmitted in the DRM stream. The maximum number of streams is four.</source>
+        <translation type='unfinished'><b>Número de Servicios:</b> Muestra el número de servicios de audio y de datos transmitidos en el flujo DRM. El máximo número de tramas es cuatro.</translation>
+    </message>
+    <message>
+        <source><b>Received time - date:</b> This label shows the received time and date in UTC. This information is carried in the SDC channel.</source>
+        <translation type='unfinished'><b>Hora / Fecha Recibidas:</b> Esta etiqueta muestra la hora y fecha recibidas en UTC. Esta información se transmite en el canal SDC (Service Description Channel).</translation>
+    </message>
+    <message>
+        <source><b>Save Audio as WAV:</b> Save the audio signal as stereo, 16-bit, 48 kHz sample rate PCM wave file. Checking this box will let the user choose a file name for the recording.</source>
+        <translation type='unfinished'><b>Guardar Audio como WAV:</b> Guarda la señal de audio como un archivo de onda PCM (Pulse Code Modulation) estéreo de 16 bits y con una tasa de muestreo de 48 kHz. Al marcar este cuadro, el usuario podrá elegir un nombre de archivo para la grabación.</translation>
+    </message>
+    <message>
+        <source><b>Chart Selector:</b> With the chart selector different types of graphical display of parameters and receiver states can be chosen. The different plot types are sorted in different groups. To open a group just double-click on the group or click on the plus left of the group name. After clicking on an item it is possible to choose other items by using the up / down arrow keys. With these keys it is also possible to open and close the groups by using the left / [...]
+        <translation type='unfinished'><b>Selector de Gráfico:</b> Mediante esta opción se pueden seleccionar diferentes tipos de visualización gráfica de parámetros y de estados del receptor. Los diferentes tipos de representación están agrupados en diversos grupos. Para abrir un grupo simplemente ha de hacer doble click sobre el grupo o hacer click en el símbolo 'más' a la izquierda del nombre del grupo. Después de clickear sobre un objeto es posible escoger otros [...]
+    </message>
+    <message>
+        <source><b>Interferer Rejection:</b> There are two algorithms available to reject interferers:<ul><li><b>Bandpass Filter (BP-Filter):</b> The bandpass filter is designed to have the same bandwidth as the DRM signal. If, e.g., a strong signal is close to the border of the actual DRM signal, under some conditions this signal will produce interference in the useful bandwidth of the DRM signal although it is not on the same frequency as the DRM sig [...]
+        <translation type='unfinished'><b>Rechazo a Interferencias:</b> Hay dos algoritmos disponibles para el rechazo contra interferentes:<ul><li><b>Filtro Paso Banda (BP-Filter):</b> El filtro paso banda se diseña para que tenga el mismo ancho de banda que la señal DRM. Si, por ejemplo, una señal fuerte está próxima al borde de la señal DRM real, bajo algunas condiciones esta señal producirá interferencia en el ancho de banda útil de la señal DRM au [...]
+    </message>
+</context>
+<context>
+    <name>systemevalDlgBase</name>
+    <message>
+        <source>System Evaluation</source>
+        <translation type='unfinished'>Evaluación del Sistema</translation>
+    </message>
+    <message>
+        <source>SNR:</source>
+        <translation type='unfinished'>SNR:</translation>
+    </message>
+    <message>
+        <source>MSC WMER / MSC MER:</source>
+        <translation type='unfinished'>WMER / MER en canal MSC:</translation>
+    </message>
+    <message>
+        <source>DC Frequency of DRM Signal:</source>
+        <translation type='unfinished'>Frecuencia DC de Señal DRM:</translation>
+    </message>
+    <message>
+        <source>Sample Frequency Offset:</source>
+        <translation type='unfinished'>Offset de Frecuencia de Muestreo:</translation>
+    </message>
+    <message>
+        <source>Doppler / Delay:</source>
+        <translation type='unfinished'>Doppler / Retardo:</translation>
+    </message>
+    <message>
+        <source>SNR</source>
+        <translation type='unfinished'>SNR</translation>
+    </message>
+    <message>
+        <source>MER</source>
+        <translation type='unfinished'>MER</translation>
+    </message>
+    <message>
+        <source>FreqOffset</source>
+        <translation type='unfinished'>OffsetFrec</translation>
+    </message>
+    <message>
+        <source>SampFreqOffset</source>
+        <translation type='unfinished'>OffsetFrecMuestreo</translation>
+    </message>
+    <message>
+        <source>Wiener</source>
+        <translation type='unfinished'>Wiener</translation>
+    </message>
+    <message>
+        <source>MSC CRC:</source>
+        <translation type='unfinished'>CRC de MSC:</translation>
+    </message>
+    <message>
+        <source>SDC CRC:</source>
+        <translation type='unfinished'>CRC de MSC:</translation>
+    </message>
+    <message>
+        <source>FAC CRC:</source>
+        <translation type='unfinished'>CRC  de FAC:</translation>
+    </message>
+    <message>
+        <source>Frame Sync:</source>
+        <translation type='unfinished'>Sinc. de Trama:</translation>
+    </message>
+    <message>
+        <source>Time Sync Acq:</source>
+        <translation type='unfinished'>Adq. Sinc. Temporal:</translation>
+    </message>
+    <message>
+        <source>I/O Interface:</source>
+        <translation type='unfinished'>Interfaz E/S:</translation>
+    </message>
+    <message>
+        <source>FACDRMModeBWL</source>
+        <translation type='unfinished'>FACDRMModoBWL</translation>
+    </message>
+    <message>
+        <source>FACInterleaverDepthL</source>
+        <translation type='unfinished'>ProfundidadIntercaladoFACL</translation>
+    </message>
+    <message>
+        <source>FACSDCMSCModeL</source>
+        <translation type='unfinished'>FACSDCMSCModoL</translation>
+    </message>
+    <message>
+        <source>FACCodeRateL</source>
+        <translation type='unfinished'>TasaCodigoFACL</translation>
+    </message>
+    <message>
+        <source>FACNumServicesL</source>
+        <translation type='unfinished'>NumServiciosFACL</translation>
+    </message>
+    <message>
+        <source>FACTimeDateL</source>
+        <translation type='unfinished'>HoraFechaFACL</translation>
+    </message>
+    <message>
+        <source>FACDRMModeBWV</source>
+        <translation type='unfinished'>FACDRMModoBWV</translation>
+    </message>
+    <message>
+        <source>FACInterleaverDepthV</source>
+        <translation type='unfinished'>ProfundidadIntercaladoFACV</translation>
+    </message>
+    <message>
+        <source>FACSDCMSCModeV</source>
+        <translation type='unfinished'>FACSDCMSCModoV</translation>
+    </message>
+    <message>
+        <source>FACCodeRateV</source>
+        <translation type='unfinished'>TasaCodigoFACV</translation>
+    </message>
+    <message>
+        <source>FACNumServicesV</source>
+        <translation type='unfinished'>NumServiciosFACV</translation>
+    </message>
+    <message>
+        <source>FACTimeDateV</source>
+        <translation type='unfinished'>HoraFechaFACV</translation>
+    </message>
+    <message>
+        <source>Chart Selector</source>
+        <translation type='unfinished'>Selector de Gráfico</translation>
+    </message>
+    <message>
+        <source>D-Spectrum</source>
+        <translation type='unfinished'>Espectro-D</translation>
+    </message>
+    <message>
+        <source>D-InpPSD</source>
+        <translation type='unfinished'>DEPEntrada-D</translation>
+    </message>
+    <message>
+        <source>D-InpSpectr</source>
+        <translation type='unfinished'>EspectroEnt-D</translation>
+    </message>
+    <message>
+        <source>D-Waterfall</source>
+        <translation type='unfinished'>Cascada-D</translation>
+    </message>
+    <message>
+        <source>D-ShiftedPSD</source>
+        <translation type='unfinished'>DEPDespl-D</translation>
+    </message>
+    <message>
+        <source>D-AudSpectr</source>
+        <translation type='unfinished'>EspectroAudio-D</translation>
+    </message>
+    <message>
+        <source>D-SNRSpectr</source>
+        <translation type='unfinished'>EspectroSNR-D</translation>
+    </message>
+    <message>
+        <source>D-Channel</source>
+        <translation type='unfinished'>Canal-D</translation>
+    </message>
+    <message>
+        <source>D-IR</source>
+        <translation type='unfinished'>IR-D</translation>
+    </message>
+    <message>
+        <source>D-TF</source>
+        <translation type='unfinished'>TF-D</translation>
+    </message>
+    <message>
+        <source>D-Constellation</source>
+        <translation type='unfinished'>Constelación-D</translation>
+    </message>
+    <message>
+        <source>D-FAC</source>
+        <translation type='unfinished'>FAC-D</translation>
+    </message>
+    <message>
+        <source>D-SDC</source>
+        <translation type='unfinished'>SDC-D</translation>
+    </message>
+    <message>
+        <source>D-MSC</source>
+        <translation type='unfinished'>MSC-D</translation>
+    </message>
+    <message>
+        <source>D-History</source>
+        <translation type='unfinished'>Historial-D</translation>
+    </message>
+    <message>
+        <source>D-SNRAudiHist</source>
+        <translation type='unfinished'>SNRAudioHIst-D</translation>
+    </message>
+    <message>
+        <source>D-DelDopp</source>
+        <translation type='unfinished'>RetardoDoppler-D</translation>
+    </message>
+    <message>
+        <source>D-FreqSam</source>
+        <translation type='unfinished'>TasaMuestr-D</translation>
+    </message>
+    <message>
+        <source>Channel Estimation: Frequency Interpolation</source>
+        <translation type='unfinished'>Estimación de Canal: Interpolación en Dom. Frecuencia</translation>
+    </message>
+    <message>
+        <source>Linear</source>
+        <translation type='unfinished'>Lineal</translation>
+    </message>
+    <message>
+        <source>DFT Zero Pad.</source>
+        <translation type='unfinished'>Relleno de ceros en DFT</translation>
+    </message>
+    <message>
+        <source>Channel Estimation: Time Interpolation</source>
+        <translation type='unfinished'>Estimación de Canal: Interpolación en Dom. Tiempo</translation>
+    </message>
+    <message>
+        <source>Time Sync Tracking</source>
+        <translation type='unfinished'>Seguimiento de Sincronización Temporal</translation>
+    </message>
+    <message>
+        <source>Guard Energy</source>
+        <translation type='unfinished'>Energía de Guarda</translation>
+    </message>
+    <message>
+        <source>First Peak</source>
+        <translation type='unfinished'>Primer Pico</translation>
+    </message>
+    <message>
+        <source>Misc Settings</source>
+        <translation type='unfinished'>Opciones Varias</translation>
+    </message>
+    <message>
+        <source>TextNumOfIterations</source>
+        <translation type='unfinished'>TextoNumeroIteraciones</translation>
+    </message>
+    <message>
+        <source>Log File, Audio</source>
+        <translation type='unfinished'>Archivo de Registro, Audio</translation>
+    </message>
+    <message>
+        <source>kHz</source>
+        <translation type='unfinished'>kHz</translation>
+    </message>
+    <message>
+        <source>Interferer Rejection</source>
+        <translation type='unfinished'>Rechazo a Interferencias</translation>
+    </message>
+    <message>
+        <source>&Close</source>
+        <translation type='unfinished'>&Cerrar</translation>
+    </message>
+    <message>
+        <source>&Flip Input Spectrum</source>
+        <translation type='unfinished'>&Voltear Espectro de Entrada</translation>
+    </message>
+    <message>
+        <source>Mute &Audio</source>
+        <translation type='unfinished'>Silenciar &Audio</translation>
+    </message>
+    <message>
+        <source>&Log File, Freq:</source>
+        <translation type='unfinished'>&Archivo de Registro, Frec:</translation>
+    </message>
+    <message>
+        <source>&Save Audio as WAV</source>
+        <translation type='unfinished'>&Guardar Audio como WAV</translation>
+    </message>
+    <message>
+        <source>&Reverberation</source>
+        <translation type='unfinished'>&Resonancia</translation>
+    </message>
+    <message>
+        <source>&Bandpass Filter</source>
+        <translation type='unfinished'>Filtro Paso &Banda</translation>
+    </message>
+    <message>
+        <source>Modified &Metrics</source>
+        <translation type='unfinished'>Medidas &Modificadas</translation>
+    </message>
+</context>
+</TS>
diff --git a/src/GUI-QT/languages/drm.fr.ts b/src/GUI-QT/languages/drm.fr.ts
new file mode 100644
index 0000000..f385be7
--- /dev/null
+++ b/src/GUI-QT/languages/drm.fr.ts
@@ -0,0 +1,2391 @@
+<!DOCTYPE TS><TS>
+<context>
+    <name>AnalogDemDlg</name>
+    <message>
+        <source>S&tations Dialog...</source>
+        <translation>Dialogue des S&tations...</translation>
+    </message>
+    <message>
+        <source>&Live Schedule Dialog...</source>
+        <translation>Dialogue Programmation &En cours...</translation>
+    </message>
+    <message>
+        <source>E&xit</source>
+        <translation>&Quitter</translation>
+    </message>
+    <message>
+        <source>&Sound Card Selection</source>
+        <translation>&Sélection de la Carte Son</translation>
+    </message>
+    <message>
+        <source>&DRM (digital)</source>
+        <translation>&DRM (digital)</translation>
+    </message>
+    <message>
+        <source>New &AM Acquisition</source>
+        <translation>Nouvelle Acquisition &AM</translation>
+    </message>
+    <message>
+        <source>&View</source>
+        <translation>A&ffichage</translation>
+    </message>
+    <message>
+        <source>&Settings</source>
+        <translation>&Paramètres</translation>
+    </message>
+    <message>
+        <source>&?</source>
+        <translation>&?</translation>
+    </message>
+    <message>
+        <source>Click on the plot to set the demodulation frequency</source>
+        <translation>Cliquer sur le graphe pour sélectionner la fréquence de démodulation</translation>
+    </message>
+    <message>
+        <source> Hz</source>
+        <translation> Hz</translation>
+    </message>
+    <message>
+        <source>Carrier<br>Frequency:<br><b></source>
+        <translation>Fréquence<br>Porteuse:<br><b></translation>
+    </message>
+    <message>
+        <source><b>Noise Reduction:</b> The noise suppression is a frequency domain optimal filter design based algorithm. The noise PSD is estimated utilizing a minimum statistic. A problem of this type of algorithm is that it produces the so called "musical tones". The noise becomes colored and sounds a bit strange. At the same time, the useful signal (which might be speech or music) is also distorted by the algorithm. By selecting the level of noise reduction, a  [...]
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>AGC (Automatic Gain Control):</b> Input signals can have a large variation in power due to channel impairments. To compensate for that, an automatic gain control can be applied. The AGC has four settings: Off, Slow, Medium and Fast.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Filter Bandwidth:</b> A band-pass filter is applied before the actual demodulation process. With this filter, adjacent signals are attenuated. The bandwidth of this filter can be chosen in steps of 1 Hz by using the slider bar. Clicking on the right or left side of the slider leveler will increase/decrease the bandwidth by 1 kHz. <br>The current filter bandwidth is indicated in the spectrum plot by a selection bar.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Demodulation Type:</b> The following analog demodulation types are available:<ul><li><b>AM:</b> This analog demodulation type is used in most of the hardware radios. The envelope of the complex base-band signal is used followed by a high-pass filter to remove the DC offset. Additionally, a low pass filter with the same bandwidth as the pass-band filter is applied to reduce the noise caused by non-linear distortions.</li><li& [...]
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Mute Audio:</b> The audio can be muted by checking this box. The reaction of checking or unchecking this box is delayed by approx. 1 second due to the audio buffers.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Save Audio as WAV:</b> Save the audio signal as stereo, 16-bit, 48 kHz sample rate PCM wave file. Checking this box will let the user choose a file name for the recording.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Carrier Frequency:</b> The (estimated) carrier frequency of the analog signal is shown. (The estimation of this parameter can be done by the Autom Frequency Acquisition which uses the estimated PSD of the input signal and applies a maximum search.)</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>PLL:</b> The Phase-Lock-Loop (PLL) tracks the carrier of the modulated received signal. The resulting phase offset between the reference oscillator and the received carrier is displayed in a dial control. If the pointer is almost steady, the PLL is locked. If the pointer of the dial control turns quickly, the PLL is out of lock. To get the PLL locked, the frequency offset to the true carrier frequency must not exceed a few Hz.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Auto Frequency Acquisition:</b> Clicking on the input spectrum plot changes the mixing frequency for demodulation. If the Auto Frequency Acquisition is enabled, the largest peak near the curser is selected.</source>
+        <translation type="unfinished"></translation>
+    </message>
+</context>
+<context>
+    <name>AnalogDemDlgBase</name>
+    <message>
+        <source>System Evaluation</source>
+        <translation>Evaluation Système</translation>
+    </message>
+    <message>
+        <source>Indicators</source>
+        <translation>Indicateurs</translation>
+    </message>
+    <message>
+        <source>&Waterfall</source>
+        <translation>&Spectrogramme</translation>
+    </message>
+    <message>
+        <source>TextFreqOffset</source>
+        <translation>TextFreqOffset</translation>
+    </message>
+    <message>
+        <source>PLL
+Phase Offset</source>
+        <translation>PLL
+Correction de Phase</translation>
+    </message>
+    <message>
+        <source>Filter Bandwidth</source>
+        <translation>Bande passante du filtre</translation>
+    </message>
+    <message>
+        <source>TextLabelBandWidth</source>
+        <translation>TextLabelBandWidth</translation>
+    </message>
+    <message>
+        <source>Demodulation</source>
+        <translation>Démodulation</translation>
+    </message>
+    <message>
+        <source>AM</source>
+        <translation>AM</translation>
+    </message>
+    <message>
+        <source>LSB</source>
+        <translation>LSB</translation>
+    </message>
+    <message>
+        <source>USB</source>
+        <translation>USB</translation>
+    </message>
+    <message>
+        <source>CW</source>
+        <translation>CW</translation>
+    </message>
+    <message>
+        <source>FM</source>
+        <translation>FM</translation>
+    </message>
+    <message>
+        <source>AGC</source>
+        <translation>CAG</translation>
+    </message>
+    <message>
+        <source>Off</source>
+        <translation>Sans</translation>
+    </message>
+    <message>
+        <source>Slow</source>
+        <translation>Lent</translation>
+    </message>
+    <message>
+        <source>Med</source>
+        <translation>Moyen</translation>
+    </message>
+    <message>
+        <source>Fast</source>
+        <translation>Rapide</translation>
+    </message>
+    <message>
+        <source>Noise Reduction</source>
+        <translation>Réduction de Bruit</translation>
+    </message>
+    <message>
+        <source>Low</source>
+        <translation>Bas</translation>
+    </message>
+    <message>
+        <source>High</source>
+        <translation>Haut</translation>
+    </message>
+    <message>
+        <source>Audio</source>
+        <translation>Audio</translation>
+    </message>
+    <message>
+        <source>Mute Audio</source>
+        <translation>Audio Muet</translation>
+    </message>
+    <message>
+        <source>Save Audio</source>
+        <translation>Enregistrer l'Audio</translation>
+    </message>
+    <message>
+        <source>PLL</source>
+        <translation>PLL</translation>
+    </message>
+    <message>
+        <source>Enable</source>
+        <translation>Activé</translation>
+    </message>
+    <message>
+        <source>Auto Frequency Acquisition</source>
+        <translation>Acquisition de Fréquence Automatique</translation>
+    </message>
+    <message>
+        <source>&AMSS</source>
+        <translation>&AMSS</translation>
+    </message>
+    <message>
+        <source>&DRM</source>
+        <translation>&DRM</translation>
+    </message>
+</context>
+<context>
+    <name>CAMSSDlg</name>
+    <message>
+        <source></source>
+        <translation></translation>
+    </message>
+    <message>
+        <source>No AMSS detected</source>
+        <translation>Pas d'AMSS détecté</translation>
+    </message>
+    <message>
+        <source>Awaiting AMSS data...</source>
+        <translation>En attente de donnée AMSS...</translation>
+    </message>
+</context>
+<context>
+    <name>CAMSSDlgBase</name>
+    <message>
+        <source>AMSS</source>
+        <translation>AMSS</translation>
+    </message>
+    <message>
+        <source>AMSS Decoding</source>
+        <translation>Décodage AMSS</translation>
+    </message>
+    <message>
+        <source>AMSSAMCarrierMode</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>AMSSInfo</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>AMSSServiceID</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>AMSSLanguage</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>AMSSCountryCode</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>AMSSTimeDate</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>ServiceLabelAMSS</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Block:</source>
+        <translation>Bloc:</translation>
+    </message>
+    <message>
+        <source>Bits:</source>
+        <translation>Bits:</translation>
+    </message>
+    <message>
+        <source>SDC:  </source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>................</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>AFS:  </source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>AMSS Offset</source>
+        <translation type="unfinished"></translation>
+    </message>
+</context>
+<context>
+    <name>CAboutDlg</name>
+    <message>
+        <source>is a software implementation of a Digital Radio Mondiale (DRM) receiver. With Dream, DRM broadcasts can be received with a modified analog receiver (SW, MW, LW) and a PC with a sound card.</source>
+        <translation>est une implémentation logicielle d'un récepteur de Digital Radio Mondiale (DRM). Avec Dream, les diffusions DRM peuvent être reçues avec un récepteur analogique modifié (SW, MW, LW) et un PC avec une carte son.</translation>
+    </message>
+    <message>
+        <source>Although this software is going to be distributed as free software under the terms of the GPL this does not mean that its use is free of rights of others. The use may infringe third party IP and thus may not be legal in some countries.</source>
+        <translation>Bien que ce logiciel soit distribué comme logiciel libre sous les termes de la GPL, cela ne signifie pas que son usage est libre de droits pour d'autres. L'utilisation peut enfreindre des IP tierces et ainsi être illégal dans certains pays.</translation>
+    </message>
+    <message>
+        <source>This compilation of Dream uses the following libraries:</source>
+        <translation>Cette compilation de Dream utilise les librairies suivantes:</translation>
+    </message>
+    <message>
+        <source>Dream, Version </source>
+        <translation>Dream, Version</translation>
+    </message>
+    <message>
+        <source>Open-Source Software Implementation of a DRM-Receiver</source>
+        <translation>Implémentation en Logiciel Libre d'un Récepteur DRM</translation>
+    </message>
+    <message>
+        <source>Under the GNU General Public License (GPL)</source>
+        <translation>Sous la GNU General Public License (GPL)</translation>
+    </message>
+    <message>
+        <source>We want to thank all the contributors to the Dream software (in alphabetical order):</source>
+        <translation>Nous voudrions remercier tous les contributeurs du logiciel Dream (par ordre alphabétique):</translation>
+    </message>
+</context>
+<context>
+    <name>CAboutDlgBase</name>
+    <message>
+        <source>About Dream</source>
+        <translation>A propos de Dream</translation>
+    </message>
+    <message>
+        <source>TextLabelVersion</source>
+        <translation>TextLabelVersion</translation>
+    </message>
+    <message>
+        <source>Volker Fischer, Alexander Kurpiers, Andrea Russo
+Julian Cable, Andrew Murphy, Oliver Haffenden</source>
+        <translation>Volker Fischer, Alexander Kurpiers, Andrea Russo
+Julian Cable, Andrew Murphy, Oliver Haffenden</translation>
+    </message>
+    <message>
+        <source>Copyright (C) 2001 - 2001-2014</source>
+        <translation>Copyright (C) 2001 - 2001-2014</translation>
+    </message>
+    <message>
+        <source>TextViewCredits</source>
+        <translation>TextViewCredits</translation>
+    </message>
+    <message>
+        <source>&OK</source>
+        <translation>&OK</translation>
+    </message>
+</context>
+<context>
+    <name>CDRMPlot</name>
+    <message>
+        <source>Channel Impulse Response</source>
+        <translation>Réponse Impulsionelle du Canal</translation>
+    </message>
+    <message>
+        <source>Time [ms]</source>
+        <translation>Temps [ms]</translation>
+    </message>
+    <message>
+        <source>IR [dB]</source>
+        <translation>IR [dB]</translation>
+    </message>
+    <message>
+        <source>Guard-interval beginning</source>
+        <translation>Début de l'Interval de Garde</translation>
+    </message>
+    <message>
+        <source>Guard-interval end</source>
+        <translation>Find de l'Interval de Garde</translation>
+    </message>
+    <message>
+        <source>Estimated begin of impulse response</source>
+        <translation>Estimation du début de réponse impulsionelle</translation>
+    </message>
+    <message>
+        <source>Estimated end of impulse response</source>
+        <translation>Estimation de fin de réponse impulsionelle</translation>
+    </message>
+    <message>
+        <source>Higher Bound</source>
+        <translation>Limite Haute</translation>
+    </message>
+    <message>
+        <source>Lower bound</source>
+        <translation>Limite basse</translation>
+    </message>
+    <message>
+        <source>Channel Transfer Function / Group Delay</source>
+        <translation>Fonction de Transfert Canal / Délai Groupe</translation>
+    </message>
+    <message>
+        <source>Carrier Index</source>
+        <translation>Index Porteuse</translation>
+    </message>
+    <message>
+        <source>TF [dB]</source>
+        <translation>TF [dB]</translation>
+    </message>
+    <message>
+        <source>Group Delay [ms]</source>
+        <translation>Délai Group [ms]</translation>
+    </message>
+    <message>
+        <source>Transf. Fct.</source>
+        <translation>Fct. Transf.</translation>
+    </message>
+    <message>
+        <source>Group Del.</source>
+        <translation>Del. Group</translation>
+    </message>
+    <message>
+        <source>Audio Spectrum</source>
+        <translation>Spectre Audio</translation>
+    </message>
+    <message>
+        <source>Frequency [kHz]</source>
+        <translation>Fréquence [kHz]</translation>
+    </message>
+    <message>
+        <source>Rel. Frequency Offset / Sample Rate Offset History</source>
+        <translation>Offset Fréquence Rel. / Historique Corr. Echantiollonnage</translation>
+    </message>
+    <message>
+        <source>Time [s]</source>
+        <translation>Temps [s]</translation>
+    </message>
+    <message>
+        <source>Sample Rate Offset [Hz]</source>
+        <translation>Corr. Echantiollonnage [Hz]</translation>
+    </message>
+    <message>
+        <source>Freq.</source>
+        <translation>Fréq.</translation>
+    </message>
+    <message>
+        <source>Samp.</source>
+        <translation>Ech.</translation>
+    </message>
+    <message>
+        <source>Freq. Offset [Hz] rel. to </source>
+        <translation>Corr. Fréq. [Hz] rel. à </translation>
+    </message>
+    <message>
+        <source>Delay / Doppler History</source>
+        <translation>Délai / Historique Doppler</translation>
+    </message>
+    <message>
+        <source>Time [min]</source>
+        <translation>Temps [min]</translation>
+    </message>
+    <message>
+        <source>Delay [ms]</source>
+        <translation>Délai [ms]</translation>
+    </message>
+    <message>
+        <source>Doppler [Hz]</source>
+        <translation>Doppler [Hz]</translation>
+    </message>
+    <message>
+        <source>Delay</source>
+        <translation>Délai</translation>
+    </message>
+    <message>
+        <source>Doppler</source>
+        <translation>Doppler</translation>
+    </message>
+    <message>
+        <source>SNR / Correctly Decoded Audio History</source>
+        <translation>SNR / Historique Audio Décodée Correctement</translation>
+    </message>
+    <message>
+        <source>SNR [dB]</source>
+        <translation>SNR [dB]</translation>
+    </message>
+    <message>
+        <source>Corr. Dec. Audio / DRM-Frame</source>
+        <translation>Audio Déc. Ok / Trame DRM</translation>
+    </message>
+    <message>
+        <source>Shifted Power Spectral Density of Input Signal</source>
+        <translation>Densité Spectrale de Puissance Shiftée du Signal d'Entrée</translation>
+    </message>
+    <message>
+        <source>PSD [dB]</source>
+        <translation>PSD [dB]</translation>
+    </message>
+    <message>
+        <source>DC carrier</source>
+        <translation>Porteuse DC</translation>
+    </message>
+    <message>
+        <source>Shifted PSD</source>
+        <translation>PSD Shifté</translation>
+    </message>
+    <message>
+        <source>SNR Spectrum (Weighted MER on MSC Cells)</source>
+        <translation>Spectre SNR (MER pondéré sur cellulles MSC)</translation>
+    </message>
+    <message>
+        <source>WMER [dB]</source>
+        <translation>WMER [dB]</translation>
+    </message>
+    <message>
+        <source>SNR Spectrum</source>
+        <translation>Spectre SNR</translation>
+    </message>
+    <message>
+        <source>Input Spectrum</source>
+        <translation>Spectre d'Entrée</translation>
+    </message>
+    <message>
+        <source>Input Spectrum [dB]</source>
+        <translation>Spectre d'Entrée [dB]</translation>
+    </message>
+    <message>
+        <source>Input spectrum</source>
+        <translation>Spectre d'Entrée</translation>
+    </message>
+    <message>
+        <source>Input PSD</source>
+        <translation>PSD Entrée</translation>
+    </message>
+    <message>
+        <source>Input PSD [dB]</source>
+        <translation>PSD Entrée [dB]</translation>
+    </message>
+    <message>
+        <source>Filter bandwidth</source>
+        <translation>Bande passante du filtre</translation>
+    </message>
+    <message>
+        <source>My Grid</source>
+        <translation>Ma Grille</translation>
+    </message>
+    <message>
+        <source>Waterfall Input Spectrum</source>
+        <translation>Spectrogramme de l'Entrée</translation>
+    </message>
+    <message>
+        <source>FAC Constellation</source>
+        <translation>Constellation FAC</translation>
+    </message>
+    <message>
+        <source>Real</source>
+        <translation>Réel</translation>
+    </message>
+    <message>
+        <source>Imaginary</source>
+        <translation>Imaginaire</translation>
+    </message>
+    <message>
+        <source>SDC Constellation</source>
+        <translation>Constellation SDC</translation>
+    </message>
+    <message>
+        <source>MSC Constellation</source>
+        <translation>Constellation MSC</translation>
+    </message>
+    <message>
+        <source>MSC / SDC / FAC Constellation</source>
+        <translation>Constellation MSC / SDC / FAC</translation>
+    </message>
+    <message>
+        <source><b>Impulse Response:</b> This plot shows the estimated Impulse Response (IR) of the channel based on the channel estimation. It is the averaged, Hamming Window weighted Fourier back transformation of the transfer function. The length of PDS estimation and time synchronization tracking is based on this function. The two red dashed vertical lines show the beginning and the end of the guard-interval. The two black dashed vertical lines show the estimated beginnin [...]
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Transfer Function / Group Delay:</b> This plot shows the squared magnitude and the group delay of the estimated channel at each sub-carrier.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>FAC, SDC, MSC:</b> The plots show the constellations of the FAC, SDC and MSC logical channel of the DRM stream. Depending on the current transmitter settings, the SDC and MSC can have 4-QAM, 16-QAM or 64-QAM modulation.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Shifted PSD:</b> This plot shows the estimated Power Spectrum Density (PSD) of the input signal. The DC frequency (red dashed vertical line) is fixed at 6 kHz. If the frequency offset acquisition was successful, the rectangular DRM spectrum should show up with a center frequency of 6 kHz. This plot represents the frequency synchronized OFDM spectrum. If the frequency synchronization was successful, the useful signal really shows up only inside the actual DR [...]
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>SNR Spectrum (Weighted MER on MSC Cells):</b> This plot shows the Weighted MER on MSC cells for each carrier separately.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Input Spectrum:</b> This plot shows the Fast Fourier Transformation (FFT) of the input signal. This plot is active in both modes, analog and digital. There is no averaging applied. The screen shot of the Evaluation Dialog shows the significant shape of a DRM signal (almost rectangular). The dashed vertical line shows the estimated DC frequency. This line is very important for the analog AM demodulation. Each time a new carrier frequency is acquired, the red [...]
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Input PSD:</b> This plot shows the estimated power spectral density (PSD) of the input signal. The PSD is estimated by averaging some Hamming Window weighted Fourier transformed blocks of the input signal samples. The dashed vertical line shows the estimated DC frequency.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Audio Spectrum:</b> This plot shows the averaged audio spectrum of the currently played audio. With this plot the actual audio bandwidth can easily determined. Since a linear scale is used for the frequency axis, most of the energy of the signal is usually concentrated on the far left side of the spectrum.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Frequency Offset / Sample Rate Offset History:</b> The history of the values for frequency offset and sample rate offset estimation is shown. If the frequency offset drift is very small, this is an indication that the analog front end is of high quality.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Doppler / Delay History:</b> The history of the values for the Doppler and Impulse response length is shown. Large Doppler values might be responsable for audio drop-outs.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>SNR History:</b> The history of the values for the SNR and correctly decoded audio blocks is shown. The maximum achievable number of correctly decoded audio blocks per DRM frame is 10 or 5 depending on the audio sample rate (24 kHz or 12 kHz AAC core bandwidth).</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Waterfall Display of Input Spectrum:</b> The input spectrum is displayed as a waterfall type. The different colors represent different levels.</source>
+        <translation type="unfinished"></translation>
+    </message>
+</context>
+<context>
+    <name>CDreamHelpMenu</name>
+    <message>
+        <source>What's &This</source>
+        <translation>&Qu'est-ce que c'est</translation>
+    </message>
+    <message>
+        <source>&About...</source>
+        <translation>&A propos...</translation>
+    </message>
+</context>
+<context>
+    <name>CEPGDlgbase</name>
+    <message>
+        <source>Programme Guide</source>
+        <translation>Guide de Programmes</translation>
+    </message>
+    <message>
+        <source>Guide</source>
+        <translation>Guide</translation>
+    </message>
+    <message>
+        <source>Time [UTC]</source>
+        <translation>Heure [UTC]</translation>
+    </message>
+    <message>
+        <source>Name</source>
+        <translation>Nom</translation>
+    </message>
+    <message>
+        <source>Genre</source>
+        <translation>Genre</translation>
+    </message>
+    <message>
+        <source>Description</source>
+        <translation>Description</translation>
+    </message>
+    <message>
+        <source>New Item</source>
+        <translation>Nouvel Elément</translation>
+    </message>
+    <message>
+        <source>Basic Profile Data</source>
+        <translation>Donnée Profil Basique</translation>
+    </message>
+    <message>
+        <source>Advanced Profile Data</source>
+        <translation>Donnée Profil Avancé</translation>
+    </message>
+    <message>
+        <source>&Close</source>
+        <translation>&Fermer</translation>
+    </message>
+    <message>
+        <source>EPG decoding is disabled</source>
+        <translation>Décodage EPG désactivé</translation>
+    </message>
+</context>
+<context>
+    <name>CGeneralSettingsDlgBase</name>
+    <message>
+        <source>General settings</source>
+        <translation>Paramètres Généraux</translation>
+    </message>
+    <message>
+        <source>Default Receiver coordinates</source>
+        <translation>Coordonnées du Récepteur par Défaut</translation>
+    </message>
+    <message>
+        <source>Latitude   </source>
+        <translation>Latitude</translation>
+    </message>
+    <message encoding="UTF-8">
+        <source>°</source>
+        <translation>°</translation>
+    </message>
+    <message>
+        <source>'</source>
+        <translation>'</translation>
+    </message>
+    <message>
+        <source>N/S</source>
+        <translation>N/S</translation>
+    </message>
+    <message>
+        <source>Longitude</source>
+        <translation>Longitude</translation>
+    </message>
+    <message>
+        <source>E/W</source>
+        <translation>E/W</translation>
+    </message>
+    <message>
+        <source>GPS</source>
+        <translation>GPS</translation>
+    </message>
+    <message>
+        <source>Use GPS</source>
+        <translation>Utiliser le GPS</translation>
+    </message>
+    <message>
+        <source>Host</source>
+        <translation>Hôte</translation>
+    </message>
+    <message>
+        <source>Port</source>
+        <translation>Port</translation>
+    </message>
+    <message>
+        <source>&OK</source>
+        <translation>&OK</translation>
+    </message>
+</context>
+<context>
+    <name>CLiveScheduleDlgBase</name>
+    <message>
+        <source>Live Schedule</source>
+        <translation>Programmation En cours</translation>
+    </message>
+    <message>
+        <source>Column 1</source>
+        <translation>Colonne 1</translation>
+    </message>
+    <message>
+        <source>New Item</source>
+        <translation>Nouvel Elément</translation>
+    </message>
+    <message>
+        <source>TextLabelUTCTime</source>
+        <translation>TextLavelUTCTime</translation>
+    </message>
+    <message>
+        <source>F&reeze</source>
+        <translation>F&iger</translation>
+    </message>
+    <message>
+        <source>&Close</source>
+        <translation>&Fermer</translation>
+    </message>
+</context>
+<context>
+    <name>CMultSettingsDlgBase</name>
+    <message>
+        <source>Multimedia settings</source>
+        <translation>Paramètres Multimédia</translation>
+    </message>
+    <message>
+        <source>MOT Broadcast Web Site</source>
+        <translation>Site Web de la Diffusion MOT</translation>
+    </message>
+    <message>
+        <source>Add refresh header of seconds</source>
+        <translation>Ajouter une entête de rafraîchissement en secondes</translation>
+    </message>
+    <message>
+        <source>Clear cache</source>
+        <translation>Effacer le cache</translation>
+    </message>
+    <message>
+        <source>EPG - Electronic Programme Guide</source>
+        <translation>EPG - Guide Electronique de Programme</translation>
+    </message>
+    <message>
+        <source>&Close</source>
+        <translation>&Fermer</translation>
+    </message>
+</context>
+<context>
+    <name>CSoundCardSelMenu</name>
+    <message>
+        <source>Sound &In</source>
+        <translation>&Entrée Son</translation>
+    </message>
+    <message>
+        <source>Sound &Out</source>
+        <translation>&Sortie Son</translation>
+    </message>
+</context>
+<context>
+    <name>CStationsDlgBase</name>
+    <message>
+        <source>Stations</source>
+        <translation>Stations</translation>
+    </message>
+    <message>
+        <source>Column 1</source>
+        <translation>Colonne 1</translation>
+    </message>
+    <message>
+        <source>New Item</source>
+        <translation>Nouvel Elément</translation>
+    </message>
+    <message>
+        <source>TextLabelUTCTime</source>
+        <translation>TextLavelUTCTime</translation>
+    </message>
+    <message>
+        <source>kHz</source>
+        <translation>kHz</translation>
+    </message>
+    <message>
+        <source>S-Meter [dB]
+(relative to S9):</source>
+        <translation>S-Mètre [dB]
+(relatif à S9):</translation>
+    </message>
+    <message>
+        <source>&Close</source>
+        <translation>&Fermer</translation>
+    </message>
+    <message>
+        <source>Filters</source>
+        <translation>Filtres</translation>
+    </message>
+    <message>
+        <source>Target</source>
+        <translation>Cible</translation>
+    </message>
+    <message>
+        <source>Country</source>
+        <translation>Pays</translation>
+    </message>
+    <message>
+        <source>Language</source>
+        <translation>Langue</translation>
+    </message>
+</context>
+<context>
+    <name>EPGDlg</name>
+    <message>
+        <source>no basic profile data</source>
+        <translation>aucune donnée de profil basique</translation>
+    </message>
+    <message>
+        <source>no advanced profile data</source>
+        <translation>aucune donnée de profil avancé</translation>
+    </message>
+    <message>
+        <source>no data</source>
+        <translation>aucune donnée</translation>
+    </message>
+</context>
+<context>
+    <name>FDRMDialog</name>
+    <message>
+        <source>&Evaluation Dialog...</source>
+        <translation>Dialogue &Evaluation...</translation>
+    </message>
+    <message>
+        <source>M&ultimedia Dialog...</source>
+        <translation>Dialogue M&ultimedia...</translation>
+    </message>
+    <message>
+        <source>S&tations Dialog...</source>
+        <translation>Dialogue des S&tations...</translation>
+    </message>
+    <message>
+        <source>&Live Schedule Dialog...</source>
+        <translation>Dialogue Programmation &En cours...</translation>
+    </message>
+    <message>
+        <source>&Programme Guide...</source>
+        <translation>Guide de &Programmes...</translation>
+    </message>
+    <message>
+        <source>E&xit</source>
+        <translation>&Quitter</translation>
+    </message>
+    <message>
+        <source>&Sound Card Selection</source>
+        <translation>&Sélection de la Carte Son</translation>
+    </message>
+    <message>
+        <source>&AM (analog)</source>
+        <translation>&AM (analogique)</translation>
+    </message>
+    <message>
+        <source>New &DRM Acquisition</source>
+        <translation>Nouvelle Acquisition &DRM</translation>
+    </message>
+    <message>
+        <source>Set D&isplay Color...</source>
+        <translation>Déf&inir la Couleur d'Affichage...</translation>
+    </message>
+    <message>
+        <source>&Blue / White</source>
+        <translation>&Bleu / Blanc</translation>
+    </message>
+    <message>
+        <source>&Green / Black</source>
+        <translation>&Vert / Noir</translation>
+    </message>
+    <message>
+        <source>B&lack / Grey</source>
+        <translation>&Noir / Gris</translation>
+    </message>
+    <message>
+        <source>&Plot Style</source>
+        <translation>&Style de Graphe</translation>
+    </message>
+    <message>
+        <source>&Multimedia settings...</source>
+        <translation>Paramètres &Multimédia...</translation>
+    </message>
+    <message>
+        <source>&General settings...</source>
+        <translation>Paramètres &Généraux...</translation>
+    </message>
+    <message>
+        <source>&View</source>
+        <translation>A&ffichage</translation>
+    </message>
+    <message>
+        <source>&Settings</source>
+        <translation>&Paramètres</translation>
+    </message>
+    <message>
+        <source>&?</source>
+        <translation>&?</translation>
+    </message>
+    <message>
+        <source>Stations</source>
+        <translation>Stations</translation>
+    </message>
+    <message>
+        <source>Live Schedule</source>
+        <translation>Programmation En cours</translation>
+    </message>
+    <message>
+        <source>Programme Guide</source>
+        <translation>Guide de Programmes</translation>
+    </message>
+    <message>
+        <source>System Evaluation</source>
+        <translation>Evaluation Système</translation>
+    </message>
+    <message>
+        <source>Multimedia</source>
+        <translation>Multimédia</translation>
+    </message>
+    <message>
+        <source>General settings</source>
+        <translation>Paramètres Généraux</translation>
+    </message>
+    <message>
+        <source> kbps</source>
+        <translation> kbps</translation>
+    </message>
+    <message>
+        <source>No Service</source>
+        <translation>Aucun Service</translation>
+    </message>
+    <message>
+        <source> + EPG</source>
+        <translation> + EPG</translation>
+    </message>
+    <message>
+        <source> + MM</source>
+        <translation> + MM</translation>
+    </message>
+    <message>
+        <source> + AFS</source>
+        <translation> + AFS</translation>
+    </message>
+    <message>
+        <source>Scanning...</source>
+        <translation>Recherche...</translation>
+    </message>
+    <message>
+        <source>Multimedia settings</source>
+        <translation>Paramètres Multimédia</translation>
+    </message>
+    <message>
+        <source><b>Text Message:</b> On the top right the text message label is shown. This label only appears when an actual text message is transmitted. If the current service does not transmit a text message, the label will be disabled.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Input Level:</b> The input level meter shows the relative input signal peak level in dB. If the level is too high, the meter turns from green to red. The red region should be avoided since overload causes distortions which degrade the reception performance. Too low levels should be avoided too, since in this case the Signal-to-Noise Ratio (SNR) degrades.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Status LEDs:</b> The three status LEDs show the current CRC status of the three logical channels of a DRM stream. These LEDs are the same as the top LEDs on the Evaluation Dialog.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Station Label and Info Display:</b> In the big label with the black background the station label and some other information about the current selected service is displayed. The magenta text on the top shows the bit-rate of the current selected service (The abbreviations EEP and UEP stand for Equal Error Protection and Unequal Error Protection. UEP is a feature of DRM for a graceful degradation of the decoded audio signal in case of a bad reception situation [...]
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Service Selectors:</b> In a DRM stream up to four services can be carried. The service can be an audio service, a data service or an audio service with data. Audio services can have associated text messages, in addition to any data component. If a Multimedia data service is selected, the Multimedia Dialog will automatically show up. On the right of each service selection button a short description of the service is shown. If an audio service has associated  [...]
+        <translation type="unfinished"></translation>
+    </message>
+</context>
+<context>
+    <name>FDRMDialogBase</name>
+    <message>
+        <source>Dream</source>
+        <translation>Dream</translation>
+    </message>
+    <message>
+        <source>Level [dB]</source>
+        <translation>Niveau [dB]</translation>
+    </message>
+    <message>
+        <source>15 kbps</source>
+        <translation>15 kbps</translation>
+    </message>
+    <message>
+        <source>AAC+</source>
+        <translation>AAC+</translation>
+    </message>
+    <message>
+        <source>Stereo</source>
+        <translation>Stéréo</translation>
+    </message>
+    <message>
+        <source>Deutsche Welle</source>
+        <translation>Deutsche Welle</translation>
+    </message>
+    <message>
+        <source>German</source>
+        <translation>Allemand</translation>
+    </message>
+    <message>
+        <source>DE</source>
+        <translation>DE</translation>
+    </message>
+    <message>
+        <source>Information</source>
+        <translation>Information</translation>
+    </message>
+    <message>
+        <source>1001</source>
+        <translation>1001</translation>
+    </message>
+    <message>
+        <source>TextTextMessage</source>
+        <translation>TextTextMessage</translation>
+    </message>
+    <message>
+        <source>1</source>
+        <comment>Selects the first service</comment>
+        <translation>1</translation>
+    </message>
+    <message>
+        <source>TextMiniService1</source>
+        <translation>TextMiniService1</translation>
+    </message>
+    <message>
+        <source>2</source>
+        <comment>Selects the second service</comment>
+        <translation>2</translation>
+    </message>
+    <message>
+        <source>TextMiniService2</source>
+        <translation>TextMiniService2</translation>
+    </message>
+    <message>
+        <source>3</source>
+        <comment>Selects the third service</comment>
+        <translation>3</translation>
+    </message>
+    <message>
+        <source>TextMiniService3</source>
+        <translation>TextMiniService3</translation>
+    </message>
+    <message>
+        <source>4</source>
+        <comment>Selects the fourth service</comment>
+        <translation>4</translation>
+    </message>
+    <message>
+        <source>TextMiniService4</source>
+        <translation>TextMiniService4</translation>
+    </message>
+</context>
+<context>
+    <name>GeneralSettingsDlg</name>
+    <message>
+        <source>Latitude value must be in the range 0 to 90</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Longitude value must be in the range 0 to 180</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Minutes value must be in the range 0 to 59</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Compile all fields on receiver coordinates</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Receiver coordinates:</b> Are used on Live Schedule Dialog to show a little green cube on the left of the target column if the receiver coordinates (latitude and longitude) are inside the target area of this transmission.<br>Receiver coordinates are also saved into the Log file.</source>
+        <translation type="unfinished"></translation>
+    </message>
+</context>
+<context>
+    <name>LiveScheduleDlg</name>
+    <message>
+        <source>Frequency [kHz/MHz]</source>
+        <translation>Fréquence [kHz/MHz]</translation>
+    </message>
+    <message>
+        <source></source>
+        <translation></translation>
+    </message>
+    <message>
+        <source>Station Name/Id</source>
+        <translation>Nom/Id de Station</translation>
+    </message>
+    <message>
+        <source>System</source>
+        <translation>Système</translation>
+    </message>
+    <message>
+        <source>Time [UTC]</source>
+        <translation>Heure [UTC]</translation>
+    </message>
+    <message>
+        <source>Target</source>
+        <translation>Cible</translation>
+    </message>
+    <message>
+        <source>Start day</source>
+        <translation>Jour de départ</translation>
+    </message>
+    <message>
+        <source>Show &only active stations</source>
+        <translation>Montre &que les stations actives</translation>
+    </message>
+    <message>
+        <source>Show &all stations</source>
+        <translation>Montre &toutes les stations</translation>
+    </message>
+    <message>
+        <source>&Disabled</source>
+        <translation>&Désactivé</translation>
+    </message>
+    <message>
+        <source>&5 minutes</source>
+        <translation>&5 minutes</translation>
+    </message>
+    <message>
+        <source>&15 minutes</source>
+        <translation>&15 minuites</translation>
+    </message>
+    <message>
+        <source>&30 minutes</source>
+        <translation>&30 minutes</translation>
+    </message>
+    <message>
+        <source>Stations &preview</source>
+        <translation>&Prévisualisation des Stations</translation>
+    </message>
+    <message>
+        <source>&Save...</source>
+        <translation>&Enregistrer...</translation>
+    </message>
+    <message>
+        <source>&File</source>
+        <translation>&Fichier</translation>
+    </message>
+    <message>
+        <source>&View</source>
+        <translation>A&ffichage</translation>
+    </message>
+    <message>
+        <source>Live Schedule</source>
+        <translation>Programmation En cours</translation>
+    </message>
+    <message>
+        <source>AFS Live Schedule</source>
+        <translation>AFS Programmation En cours</translation>
+    </message>
+    <message>
+        <source><b>Live Schedule List:</b> In the live schedule list it's possible to view AFS (Alternative Frequency Signalling) information transmitted with the current DRM or AMSS signal.</b>It is possible to limit the view to active stations by changing a setting in the 'view' menu.<br>The color of the cube on the left of the frequency shows the current status of the transmission.<br>A green box shows that the transmission takes place righ [...]
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>UTC Time:</b> Shows the current Coordinated Universal Time (UTC) which is also known as Greenwich Mean Time (GMT).</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Freeze:</b> If this check box is selected the live schedule is frozen.</source>
+        <translation type="unfinished"></translation>
+    </message>
+</context>
+<context>
+    <name>MultimediaDlg</name>
+    <message>
+        <source>C&lear all</source>
+        <translation>T&out effacer</translation>
+    </message>
+    <message>
+        <source>&Save...</source>
+        <translation>&Enregistrer...</translation>
+    </message>
+    <message>
+        <source>Save &all...</source>
+        <translation>&Tout enregistrer...</translation>
+    </message>
+    <message>
+        <source>&Close</source>
+        <translation>&Fermer</translation>
+    </message>
+    <message>
+        <source>Set &Font...</source>
+        <translation>Sélectionne la &Police...</translation>
+    </message>
+    <message>
+        <source>&File</source>
+        <translation>&Fichier</translation>
+    </message>
+    <message>
+        <source>&Settings</source>
+        <translation>&Paramètres</translation>
+    </message>
+    <message>
+        <source>MOT Broadcast Web Site</source>
+        <translation>Site Web de la Diffusion MOT</translation>
+    </message>
+    <message>
+        <source>The home page is available</source>
+        <translation>La portail est disponible</translation>
+    </message>
+    <message>
+        <source>Multimedia</source>
+        <translation>MMultimédia</translation>
+    </message>
+    <message>
+        <source>Image could not be loaded, </source>
+        <translation>L'image n'a pas pu être chargée, </translation>
+    </message>
+    <message>
+        <source>-format not supported by this version of QT!</source>
+        <translation>-format non supporté par cette version de QT!</translation>
+    </message>
+    <message>
+        <source>If you want to view the image, save it to file and use an external viewer</source>
+        <translation>Si vous voulez voir cette image, enregistrez le fichier et utilisez un visualiseur externe</translation>
+    </message>
+    <message>
+        <source>MOT Slideshow Viewer</source>
+        <translation>Visualiseur de Diaporama MOT</translation>
+    </message>
+    <message>
+        <source>No data service or data service not supported.</source>
+        <translation>Pas de service de donnée ou service de donnée non supporté.</translation>
+    </message>
+    <message>
+        <source>The homepage is available.</source>
+        <translation>Le portail est disponible.</translation>
+    </message>
+    <message>
+        <source>Press the button to open it in the default browser.</source>
+        <translation>Appuyez sur le bouton pour l'ouvrir dans le navigateur par défaut.</translation>
+    </message>
+</context>
+<context>
+    <name>MultimediaDlgBase</name>
+    <message>
+        <source>Dream Multimedia</source>
+        <translation>Dream Multimédia</translation>
+    </message>
+    <message>
+        <source>Receiving Status:</source>
+        <translation>Satus de Réception:</translation>
+    </message>
+    <message>
+        <source>0/0</source>
+        <translation>0/0</translation>
+    </message>
+    <message>
+        <source>&Close</source>
+        <translation>&Fermer</translation>
+    </message>
+</context>
+<context>
+    <name>QObject</name>
+    <message>
+        <source>Sun</source>
+        <translation>Dim</translation>
+    </message>
+    <message>
+        <source>Mon</source>
+        <translation>Lun</translation>
+    </message>
+    <message>
+        <source>Tue</source>
+        <translation>Mar</translation>
+    </message>
+    <message>
+        <source>Wed</source>
+        <translation>Mer</translation>
+    </message>
+    <message>
+        <source>Thu</source>
+        <translation>Jeu</translation>
+    </message>
+    <message>
+        <source>Fri</source>
+        <translation>Ven</translation>
+    </message>
+    <message>
+        <source>Sat</source>
+        <translation>Sam</translation>
+    </message>
+    <message>
+        <source>irregular</source>
+        <translation>irrégulier</translation>
+    </message>
+    <message>
+        <source>daily</source>
+        <translation>journalier</translation>
+    </message>
+    <message>
+        <source>from Sun to Thu</source>
+        <translation>de Dim à Jeu</translation>
+    </message>
+    <message>
+        <source>from Sun to Fri</source>
+        <translation>de Dim à Ven</translation>
+    </message>
+    <message>
+        <source>from Mon to Fri</source>
+        <translation>de Lun à Ven</translation>
+    </message>
+    <message>
+        <source>from Mon to Sat</source>
+        <translation>de Lun à Sam</translation>
+    </message>
+</context>
+<context>
+    <name>StationsDlg</name>
+    <message>
+        <source>Station Name</source>
+        <translation>Nom de Station</translation>
+    </message>
+    <message>
+        <source>Time [UTC]</source>
+        <translation>Heure [UTC]</translation>
+    </message>
+    <message>
+        <source>Frequency [kHz]</source>
+        <translation>Fréquence [kHz]</translation>
+    </message>
+    <message>
+        <source>Target</source>
+        <translation>Cible</translation>
+    </message>
+    <message>
+        <source>Power [kW]</source>
+        <translation>Puissance [kW]</translation>
+    </message>
+    <message>
+        <source>Country</source>
+        <translation>Pays</translation>
+    </message>
+    <message>
+        <source>Site</source>
+        <translation>Site</translation>
+    </message>
+    <message>
+        <source>Language</source>
+        <translation>Langue</translation>
+    </message>
+    <message>
+        <source>Days</source>
+        <translation>Jours</translation>
+    </message>
+    <message>
+        <source>Show &only active stations</source>
+        <translation>Montre &que les stations actives</translation>
+    </message>
+    <message>
+        <source>Show &all stations</source>
+        <translation>Montre &toutes les stations</translation>
+    </message>
+    <message>
+        <source>&Disabled</source>
+        <translation>&Désactivé</translation>
+    </message>
+    <message>
+        <source>&5 minutes</source>
+        <translation>&5 minutes</translation>
+    </message>
+    <message>
+        <source>&15 minutes</source>
+        <translation>&15 minuites</translation>
+    </message>
+    <message>
+        <source>&30 minutes</source>
+        <translation>&30 minutes</translation>
+    </message>
+    <message>
+        <source>Stations &preview</source>
+        <translation>&Prévisualisation des Stations</translation>
+    </message>
+    <message>
+        <source>None</source>
+        <translation>Aucun</translation>
+    </message>
+    <message>
+        <source>Other</source>
+        <translation>Autre</translation>
+    </message>
+    <message>
+        <source>Enable S-Meter</source>
+        <translation>Active le S-Mètre</translation>
+    </message>
+    <message>
+        <source>With DRM Modification</source>
+        <translation>Avec Modification DRM</translation>
+    </message>
+    <message>
+        <source>&Get Update...</source>
+        <translation>&Récupère la Mise-à-Jour...</translation>
+    </message>
+    <message>
+        <source>&View</source>
+        <translation>A&ffichage</translation>
+    </message>
+    <message>
+        <source>&Remote</source>
+        <translation>&Télécommande</translation>
+    </message>
+    <message>
+        <source>&Update</source>
+        <translation>&Mise-à-Jour</translation>
+    </message>
+    <message>
+        <source> (last update: </source>
+        <translation> (dernière mise à jour: </translation>
+    </message>
+    <message>
+        <source>&Get Update</source>
+        <translation>&Récupère la Mise-à-Jour</translation>
+    </message>
+    <message>
+        <source>Dream Schedule Update</source>
+        <translation>Mise à Jour de la Programmation Dream</translation>
+    </message>
+    <message>
+        <source>Dream tries to download the newest DRM schedule
+from www.drm-dx.de (powered by Klaus Schneider).
+Your computer must be connected to the internet.
+
+The current file DRMSchedule.ini will be overwritten.
+Do you want to continue?</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Update failed. The following things may caused the failure:
+<byte value="x9"/>- the internet connection was not set up properly
+<byte value="x9"/>- the server www.drm-dx.de is currently not available
+<byte value="x9"/>- the file 'DRMSchedule.ini' could not be written</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Update successful.
+Due to network problems with the Windows version of QT, the Dream software must be restarted after a DRMSchedule update.
+Please exit Dream now.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Ok</source>
+        <translation>Ok</translation>
+    </message>
+    <message>
+        <source>Update successful.</source>
+        <translation>Mise à jour réussie.</translation>
+    </message>
+    <message>
+        <source><b>Stations List:</b> In the stations list view all DRM stations which are stored in the DRMSchedule.ini file are shown. It is possible to show only active stations by changing a setting in the 'view' menu. The color of the cube on the left of a menu item shows the current status of the DRM transmission. A green box shows that the transmission takes place right now, a yellow cube shows that this is a test transmission and with a red cube it is shown  [...]
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Frequency Counter:</b> The current frequency value can be changed by using this counter. The tuning steps are 100 kHz for the  buttons with three arrows, 10 kHz for the buttons with two arrows and 1 kHz for the buttons having only one arrow. By keeping the button pressed, the values are increased / decreased automatically.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>UTC Time:</b> Shows the current Coordinated Universal Time (UTC) which is also known as Greenwich Mean Time (GMT).</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Signal-Meter:</b> Shows the signal strength level in dB relative to S9.<br>Note that not all front-ends controlled by hamlib support this feature. If the s-meter is not available, the controls are disabled.</source>
+        <translation type="unfinished"></translation>
+    </message>
+</context>
+<context>
+    <name>TransmDialog</name>
+    <message>
+        <source>Dream DRM Transmitter</source>
+        <translation>Transmetteur Dream DRM</translation>
+    </message>
+    <message>
+        <source>new</source>
+        <translation>nouveau</translation>
+    </message>
+    <message>
+        <source>&Start</source>
+        <translation>&Commencer</translation>
+    </message>
+    <message>
+        <source>2 s (Long Interleaving)</source>
+        <translation>2 s (Entrelacement Long)</translation>
+    </message>
+    <message>
+        <source>400 ms (Short Interleaving)</source>
+        <translation>400 ms (Entrelacement Court)</translation>
+    </message>
+    <message>
+        <source>SM 16-QAM</source>
+        <translation>SM 16-QAM</translation>
+    </message>
+    <message>
+        <source>SM 64-QAM</source>
+        <translation>SM 64-QAM</translation>
+    </message>
+    <message>
+        <source>4-QAM</source>
+        <translation>4-QAM</translation>
+    </message>
+    <message>
+        <source>16-QAM</source>
+        <translation>16-QAM</translation>
+    </message>
+    <message>
+        <source>Dream DRM Transmitter<byte value="xb"/>
+This is a test transmission</source>
+        <translation>Transmetteur Dream DRM 
+Ceci est un test de transmission</translation>
+    </message>
+    <message>
+        <source>&Sound Card Selection</source>
+        <translation>&Sélection de la Carte Son</translation>
+    </message>
+    <message>
+        <source>&Settings</source>
+        <translation>&Paramètres</translation>
+    </message>
+    <message>
+        <source>&?</source>
+        <translation>&?</translation>
+    </message>
+    <message>
+        <source>&Stop</source>
+        <translation>&Arrêter</translation>
+    </message>
+    <message>
+        <source>Image Files (*.png *.jpg *.jpeg *.jfif)</source>
+        <translation>Fichiers Image (*.png *.jpg *.jpeg *.jfif)</translation>
+    </message>
+    <message>
+        <source><b>Dream Logo:</b> This is the official logo of the Dream software.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Input Level:</b> The input level meter shows the relative input signal peak level in dB. If the level is too high, the meter turns from green to red.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>DRM Robustness Mode:</b> In a DRM system, four possible robustness modes are defined to adapt the system to different channel conditions. According to the DRM standard:<ul><li><i>Mode A:</i> Gaussian channels, with minor fading</li><li><i>Mode B:</i> Time and frequency selective channels, with longer delay spread</li><li><i>Mode C:</i> As robustness mode B, but with higher Doppler sprea [...]
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>DRM Bandwidth:</b> The bandwith is the gross bandwidth of the generated DRM signal. Not all DRM robustness mode / bandwidth constellations are possible, e.g., DRM robustness mode D and C are only defined for the bandwidths 10 kHz and 20 kHz.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Output intermediate frequency of DRM signal:</b> Set the output intermediate frequency (IF) of generated DRM signal in the 'sound-card pass-band'. In some DRM modes, the IF is located at the edge of the DRM signal, in other modes it is centered. The IF should be chosen that the DRM signal lies entirely inside the sound-card bandwidth.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Output format:</b> Since the sound-card outputs signals in stereo format, it is possible to output the DRM signal in three formats:<ul><li><b>real valued</b> output on both, left and right, sound-card channels</li><li><b>I / Q</b> output which is the in-phase and quadrature component of the complex base-band signal at the desired IF. In-phase is output on the left channel and quadrature on the right channel.&l [...]
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>MSC interleaver mode:</b> The symbol interleaver depth can be either short (approx. 400 ms) or long (approx. 2 s). The longer the interleaver the better the channel decoder can correct errors from slow fading signals. But the longer the interleaver length the longer the delay until (after a re-synchronization) audio can be heard.</source>
+        <translation type="unfinished"></translation>
+    </message>
+</context>
+<context>
+    <name>TransmDlgBase</name>
+    <message>
+        <source>Dream DRM Transmitter</source>
+        <translation>Transmetteur Dream DRM</translation>
+    </message>
+    <message>
+        <source>Volker Fischer, Alexander Kurpiers</source>
+        <translation>Volker Fischer, Alexander Kurpiers</translation>
+    </message>
+    <message>
+        <source>Darmstadt University of Technology
+Institute for Communication Technology</source>
+        <translation>Darmstadt University of Technology
+Institute for Communication Technology</translation>
+    </message>
+    <message>
+        <source>Indicators</source>
+        <translation>Indicateurs</translation>
+    </message>
+    <message>
+        <source>Audio Level [dB]:</source>
+        <translation>Niveau Audio [dB]:</translation>
+    </message>
+    <message>
+        <source>TextLabelCurPict</source>
+        <translation>TextLabelCurPict</translation>
+    </message>
+    <message>
+        <source>Channel Parameters</source>
+        <translation>Paramètres Canal</translation>
+    </message>
+    <message>
+        <source>Robustness Mode</source>
+        <translation>Mode Robustesse</translation>
+    </message>
+    <message>
+        <source>A</source>
+        <translation>A</translation>
+    </message>
+    <message>
+        <source>B</source>
+        <translation>B</translation>
+    </message>
+    <message>
+        <source>C</source>
+        <translation>C</translation>
+    </message>
+    <message>
+        <source>D</source>
+        <translation>D</translation>
+    </message>
+    <message>
+        <source>Bandwidth</source>
+        <translation>Bande Passante</translation>
+    </message>
+    <message>
+        <source>4,5 kHz</source>
+        <translation>4,5 kHz</translation>
+    </message>
+    <message>
+        <source>9 kHz</source>
+        <translation>9 kHz</translation>
+    </message>
+    <message>
+        <source>18 kHz</source>
+        <translation>18 kHz</translation>
+    </message>
+    <message>
+        <source>5 kHz</source>
+        <translation>5 kHz</translation>
+    </message>
+    <message>
+        <source>10 kHz</source>
+        <translation>10 kHz</translation>
+    </message>
+    <message>
+        <source>20 kHz</source>
+        <translation>20 kHz</translation>
+    </message>
+    <message>
+        <source>MSC Constellation Scheme:</source>
+        <translation>Schéma de Constellation MSC:</translation>
+    </message>
+    <message>
+        <source>MSC Protection Level:</source>
+        <translation>Niveau de Protection MSC:</translation>
+    </message>
+    <message>
+        <source>SDC Constellation Scheme:</source>
+        <translation>Schéma de Constellation SDC:</translation>
+    </message>
+    <message>
+        <source>MSC Interleaver Mode:</source>
+        <translation>Mode d'Entrelacement MSC:</translation>
+    </message>
+    <message>
+        <source>Output</source>
+        <translation>Sortie</translation>
+    </message>
+    <message>
+        <source>IF:</source>
+        <translation>FI:</translation>
+    </message>
+    <message>
+        <source> Hz</source>
+        <translation>Hz</translation>
+    </message>
+    <message>
+        <source>Real val.</source>
+        <translation>Val. Réel</translation>
+    </message>
+    <message>
+        <source>I / Q (pos)</source>
+        <translation>I / Q (pos)</translation>
+    </message>
+    <message>
+        <source>I / Q (neg)</source>
+        <translation>I / Q (nég)</translation>
+    </message>
+    <message>
+        <source>E / P</source>
+        <translation>E / P</translation>
+    </message>
+    <message>
+        <source>Service 1</source>
+        <translation>Service 1</translation>
+    </message>
+    <message>
+        <source>Enable</source>
+        <translation>Activé</translation>
+    </message>
+    <message>
+        <source>Label:</source>
+        <translation>Label:</translation>
+    </message>
+    <message>
+        <source>Service ID:</source>
+        <translation>Service ID:</translation>
+    </message>
+    <message>
+        <source>Language:</source>
+        <translation>Langue:</translation>
+    </message>
+    <message>
+        <source>Audio</source>
+        <translation>Audio</translation>
+    </message>
+    <message>
+        <source>Program Type:</source>
+        <translation>Type Programme:</translation>
+    </message>
+    <message>
+        <source>Text Message</source>
+        <translation>Message Texte</translation>
+    </message>
+    <message>
+        <source>&Clear All</source>
+        <translation>T&out effacer</translation>
+    </message>
+    <message>
+        <source>&Add / Modify</source>
+        <translation>&Ajouter / Modifier</translation>
+    </message>
+    <message>
+        <source>Data (SlideShow Application)</source>
+        <translation>Donnée (Application Diaporama)</translation>
+    </message>
+    <message>
+        <source>Column 1</source>
+        <translation>Colonne 1</translation>
+    </message>
+    <message>
+        <source>New Item</source>
+        <translation>Nouvel Elément</translation>
+    </message>
+    <message>
+        <source>&Add</source>
+        <translation>&Ajouter</translation>
+    </message>
+    <message>
+        <source>Service 2</source>
+        <translation>Service 2</translation>
+    </message>
+    <message>
+        <source>Service 3</source>
+        <translation>Service 3</translation>
+    </message>
+    <message>
+        <source>Service 4</source>
+        <translation>Service 4</translation>
+    </message>
+    <message>
+        <source>&Start</source>
+        <translation>&Commencer</translation>
+    </message>
+    <message>
+        <source>&Close</source>
+        <translation>&Fermer</translation>
+    </message>
+</context>
+<context>
+    <name>systemevalDlg</name>
+    <message>
+        <source>MLC: Number of Iterations: </source>
+        <translation>MLC: Nombre d'Itérations: </translation>
+    </message>
+    <message>
+        <source>History</source>
+        <translation>Historique</translation>
+    </message>
+    <message>
+        <source>Constellation</source>
+        <translation>Constellation</translation>
+    </message>
+    <message>
+        <source>Channel</source>
+        <translation>Canal</translation>
+    </message>
+    <message>
+        <source>Spectrum</source>
+        <translation>Spectre</translation>
+    </message>
+    <message>
+        <source>SNR Spectrum</source>
+        <translation>Spectre SNR</translation>
+    </message>
+    <message>
+        <source>Audio Spectrum</source>
+        <translation>Spectre Audio</translation>
+    </message>
+    <message>
+        <source>Shifted PSD</source>
+        <translation>PSD Décalé</translation>
+    </message>
+    <message>
+        <source>Waterfall Input Spectrum</source>
+        <translation>Spectrogramme de l'Entrée</translation>
+    </message>
+    <message>
+        <source>Input Spectrum</source>
+        <translation>Spectre d'Entrée</translation>
+    </message>
+    <message>
+        <source>Input PSD</source>
+        <translation>PSD Entrée</translation>
+    </message>
+    <message>
+        <source>MSC</source>
+        <translation>MSC</translation>
+    </message>
+    <message>
+        <source>SDC</source>
+        <translation>SDC</translation>
+    </message>
+    <message>
+        <source>FAC</source>
+        <translation>FAC</translation>
+    </message>
+    <message>
+        <source>FAC / SDC / MSC</source>
+        <translation>FAC / SDC / MSC</translation>
+    </message>
+    <message>
+        <source>Frequency / Sample Rate</source>
+        <translation>Fréquence / Débit d'Echantiollonnage</translation>
+    </message>
+    <message>
+        <source>Delay / Doppler</source>
+        <translation>Délai / Doppler</translation>
+    </message>
+    <message>
+        <source>SNR / Audio</source>
+        <translation>SNR / Audio</translation>
+    </message>
+    <message>
+        <source>Transfer Function</source>
+        <translation>Fonction de Transfert</translation>
+    </message>
+    <message>
+        <source>Impulse Response</source>
+        <translation>Réponse Impulsionelle</translation>
+    </message>
+    <message>
+        <source>ListView context menu</source>
+        <translation>ListView context menu</translation>
+    </message>
+    <message>
+        <source>&Open in separate window</source>
+        <translation>&Ouvrir dans une fenêtre séparée</translation>
+    </message>
+    <message>
+        <source>Chart Window</source>
+        <translation type="unfinished">Fenêtre Chart</translation>
+    </message>
+    <message>
+        <source>Metrics [dB]: MSC: </source>
+        <translation>Métriques [dB]: MSC: </translation>
+    </message>
+    <message>
+        <source>2 s (Long Interleaving)</source>
+        <translation>2 s (Entrelacement Long)</translation>
+    </message>
+    <message>
+        <source>400 ms (Short Interleaving)</source>
+        <translation>400 ms (Entrelacement Court)</translation>
+    </message>
+    <message>
+        <source>Interleaver Depth:</source>
+        <translation>Profondeur d'Entrelacement:</translation>
+    </message>
+    <message>
+        <source>SDC / MSC Mode:</source>
+        <translation>Mode SDC / MSC:</translation>
+    </message>
+    <message>
+        <source>Prot. Level (B / A):</source>
+        <translation>Niveau Prot (B / A):</translation>
+    </message>
+    <message>
+        <source>Audio: </source>
+        <translation>Audio: </translation>
+    </message>
+    <message>
+        <source> / Data: </source>
+        <translation> / Donnée: </translation>
+    </message>
+    <message>
+        <source>Number of Services:</source>
+        <translation>Nombre de Services:</translation>
+    </message>
+    <message>
+        <source>Service not available</source>
+        <translation>Service non disponible</translation>
+    </message>
+    <message>
+        <source>Received time - date:</source>
+        <translation>Heure - date Récepetion:</translation>
+    </message>
+    <message>
+        <source>DreamOut.wav</source>
+        <translation>DreamOut.wav</translation>
+    </message>
+    <message>
+        <source><b>DC Frequency Offset:</b> This is the estimation of the DC frequency offset. This offset corresponds to the resulting sound card intermedia frequency of the front-end. This frequency is not restricted to a certain value. The only restriction is that the DRM spectrum must be completely inside the bandwidth of the sound card.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Sample Frequency Offset:</b> This is the estimation of the sample rate offset between the sound card sample rate of the local computer and the sample rate of the D / A (digital to analog) converter in the transmitter. Usually the sample rate offset is very constant for a given sound card. Therefore it is useful to inform the Dream software about this value at application startup to increase the acquisition speed and reliability.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Doppler / Delay:</b> The Doppler frequency of the channel is estimated for the Wiener filter design of channel estimation in time direction. If linear interpolation is set for channel estimation in time direction, this estimation is not updated. The Doppler frequency is an indication of how fast the channel varies with time. The higher the frequency, the faster the channel changes are.<br>The total delay of the Power Delay Spectrum (PDS) is estimated  [...]
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>I / O Interface LED:</b> This LED shows the current status of the sound card interface. The yellow light shows that the audio output was corrected. Since the sample rate of the transmitter and local computer are different, from time to time the audio buffers will overflow or under run and a correction is necessary. When a correction occurs, a "click" sound can be heard. The red light shows that a buffer was lost in the sound card input stream. Thi [...]
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Time Sync Acq LED:</b> This LED shows the state of the timing acquisition (search for the beginning of an OFDM symbol). If the acquisition is done, this LED will stay green.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Frame Sync LED:</b> The DRM frame synchronization status is shown with this LED. This LED is also only active during acquisition state of the Dream receiver. In tracking mode, this LED is always green.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>FAC CRC LED:</b> This LED shows the Cyclic Redundancy Check (CRC) of the Fast Access Channel (FAC) of DRM. FAC is one of the three logical channels and is always modulated with a 4-QAM. If the FAC CRC check was successful, the receiver changes to tracking mode. The FAC LED is the indication whether the receiver is synchronized to a DRM transmission or not.<br>The bandwidth of the DRM signal, the constellation scheme of MSC and SDC channels and the int [...]
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>SDC CRC LED:</b> This LED shows the CRC check result of the Service Description Channel (SDC) which is one logical channel of the DRM stream. This data is transmitted in approx. 1 second intervals and contains information about station label, audio and data format, etc. The error protection is normally lower than the protection of the FAC. Therefore this LED will turn to red earlier than the FAC LED in general.<br>If the CRC check is ok but errors in  [...]
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>MSC CRC LED:</b> This LED shows the status of the Main Service Channel (MSC). This channel contains the actual audio and data bits. The LED shows the CRC check of the AAC core decoder. The SBR has a separate CRC, but this status is not shown with this LED. If SBR CRC is wrong but the AAC CRC is ok one can still hear something (of course, the high frequencies are not there in this case). If this LED turns red, interruptions of the audio are heard. The yellow [...]
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>MLC, Number of Iterations:</b> In DRM, a multilevel channel coder is used. With this code it is possible to iterate the decoding process in the decoder to improve the decoding result. The more iterations are used the better the result will be. But switching to more iterations will increase the CPU load. Simulations showed that the first iteration (number of iterations = 1) gives the most improvement (approx. 1.5 dB at a BER of 10-4 on a Gaussian channel, Mo [...]
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Flip Input Spectrum:</b> Checking this box will flip or invert the input spectrum. This is necessary if the mixer in the front-end uses the lower side band.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Mute Audio:</b> The audio can be muted by checking this box. The reaction of checking or unchecking this box is delayed by approx. 1 second due to the audio buffers.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Reverberation Effect:</b> If this check box is checked, a reverberation effect is applied each time an audio drop-out occurs. With this effect it is possible to mask short drop-outs.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Freq:</b> In this edit control, the current selected frequency on the front-end can be specified. This frequency will be written into the log file.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Channel Estimation Settings:</b> With these settings, the channel estimation method in time and frequency direction can be selected. The default values use the most powerful algorithms. For more detailed information about the estimation algorithms there are a lot of papers and books available.<br><b>Wiener:</b> Wiener interpolation method uses estimation of the statistics of the channel to design an optimal filter for noise reduction.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Channel Estimation Settings:</b> With these settings, the channel estimation method in time and frequency direction can be selected. The default values use the most powerful algorithms. For more detailed information about the estimation algorithms there are a lot of papers and books available.<br><b>Linear:</b> Simple linear interpolation method to get the channel estimate. The real and imaginary parts of the estimated channel at the pilot [...]
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Channel Estimation Settings:</b> With these settings, the channel estimation method in time and frequency direction can be selected. The default values use the most powerful algorithms. For more detailed information about the estimation algorithms there are a lot of papers and books available.<br><b>DFT Zero Pad:</b> Channel estimation method for the frequency direction using Discrete Fourier Transformation (DFT) to transform the channel e [...]
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Guard Energy:</b> Time synchronization tracking algorithm utilizes the estimation of the impulse response. This method tries to maximize the energy in the guard-interval to set the correct timing.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>First Peak:</b> This algorithms searches for the first peak in the estimated impulse response and moves this peak to the beginning of the guard-interval (timing tracking algorithm).</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>SNR:</b> Signal to Noise Ratio (SNR) estimation based on FAC cells. Since the FAC cells are only located approximately in the region 0-5 kHz relative to the DRM DC frequency, it may happen that the SNR value is very high although the DRM spectrum on the left side of the DRM DC frequency is heavily distorted or disturbed by an interferer so that the true overall SNR is lower as indicated by the SNR value. Similarly, the SNR value might show a very low value  [...]
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>MSC WMER / MSC MER:</b> Modulation Error Ratio (MER) and weighted MER (WMER) calculated on the MSC cells is shown. The MER is calculated as follows: For each equalized MSC cell (only MSC cells, no FAC cells, no SDC cells, no pilot cells), the error vector from the nearest ideal point of the constellation diagram is measured. The squared magnitude of this error is found, and a mean of the squared errors is calculated (over one frame). The MER is the ratio in [...]
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>DRM Mode / Bandwidth:</b> In a DRM system, four possible robustness modes are defined to adapt the system to different channel conditions. According to the DRM standard:<ul><li><i>Mode A:</i> Gaussian channels, with minor fading</li><li><i>Mode B:</i> Time and frequency selective channels, with longer delay spread</li><li><i>Mode C:</i> As robustness mode B, but with higher Doppler spre [...]
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Interleaver Depth:</b> The symbol interleaver depth can be either short (approx. 400 ms) or long (approx. 2 s). The longer the interleaver the better the channel decoder can correct errors from slow fading signals. But the longer the interleaver length the longer the delay until (after a re-synchronization) audio can be heard.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>SDC / MSC Mode:</b> Shows the modulation type of the SDC and MSC channel. For the MSC channel, some hierarchical modes are defined which can provide a very strong protected service channel.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Prot. Level (B/A):</b> The error protection level of the channel coder. For 64-QAM, there are four protection levels defined in the DRM standard. Protection level 0 has the highest protection whereas level 3 has the lowest protection. The letters A and B are the names of the higher and lower protected parts of a DRM block when Unequal Error Protection (UEP) is used. If Equal Error Protection (EEP) is used, only the protection level of part B is valid.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Number of Services:</b> This shows the number of audio and data services transmitted in the DRM stream. The maximum number of streams is four.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Received time - date:</b> This label shows the received time and date in UTC. This information is carried in the SDC channel.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Save Audio as WAV:</b> Save the audio signal as stereo, 16-bit, 48 kHz sample rate PCM wave file. Checking this box will let the user choose a file name for the recording.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Chart Selector:</b> With the chart selector different types of graphical display of parameters and receiver states can be chosen. The different plot types are sorted in different groups. To open a group just double-click on the group or click on the plus left of the group name. After clicking on an item it is possible to choose other items by using the up / down arrow keys. With these keys it is also possible to open and close the groups by using the left / [...]
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source><b>Interferer Rejection:</b> There are two algorithms available to reject interferers:<ul><li><b>Bandpass Filter (BP-Filter):</b> The bandpass filter is designed to have the same bandwidth as the DRM signal. If, e.g., a strong signal is close to the border of the actual DRM signal, under some conditions this signal will produce interference in the useful bandwidth of the DRM signal although it is not on the same frequency as the DRM sig [...]
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>DRM Mode / Bandwidth:</source>
+        <translation>Mode DRM / Bande passante:</translation>
+    </message>
+    <message>
+        <source>Lat: %1&#xb0;  Long: %2&#xb0;</source>
+        <translation>Lat: %1&#xb0;  Long: %2&#xb0;</translation>
+    </message>
+    <message>
+        <source>Lat: ?  Long: ?</source>
+        <translation>Lat: ?  Long: ?</translation>
+    </message>
+    <message>
+        <source>  Alt: %1 m</source>
+        <translation>  Alt: %1 m</translation>
+    </message>
+    <message>
+        <source>  Alt: ?</source>
+        <translation>  Alt: ?</translation>
+    </message>
+    <message>
+        <source>Speed: </source>
+        <translation>Vitesse: </translation>
+    </message>
+    <message>
+        <source>%1 m/s</source>
+        <translation>%1 m/s</translation>
+    </message>
+    <message>
+        <source>  Heading: </source>
+        <translation>  Direction: </translation>
+    </message>
+    <message>
+        <source>Satellites: </source>
+        <translation>Satellites: </translation>
+    </message>
+    <message>
+        <source>Satellites: ?</source>
+        <translation>Satellites: ?</translation>
+    </message>
+</context>
+<context>
+    <name>systemevalDlgBase</name>
+    <message>
+        <source>System Evaluation</source>
+        <translation>Evaluation Système</translation>
+    </message>
+    <message>
+        <source>SNR:</source>
+        <translation>SNR:</translation>
+    </message>
+    <message>
+        <source>MSC WMER / MSC MER:</source>
+        <translation>MSC WMER / MSC MER:</translation>
+    </message>
+    <message>
+        <source>DC Frequency of DRM Signal:</source>
+        <translation>Fréquence DC du Signal DRM:</translation>
+    </message>
+    <message>
+        <source>Sample Frequency Offset:</source>
+        <translation>Corr. Fréq. Echantillonnage:</translation>
+    </message>
+    <message>
+        <source>Doppler / Delay:</source>
+        <translation>Doppler / Délai:</translation>
+    </message>
+    <message>
+        <source>SNR</source>
+        <translation>SNR</translation>
+    </message>
+    <message>
+        <source>MER</source>
+        <translation>MER</translation>
+    </message>
+    <message>
+        <source>FreqOffset</source>
+        <translation>FreqOffset</translation>
+    </message>
+    <message>
+        <source>SampFreqOffset</source>
+        <translation>SampFreqOffset</translation>
+    </message>
+    <message>
+        <source>Wiener</source>
+        <translation>Wiener</translation>
+    </message>
+    <message>
+        <source>MSC CRC:</source>
+        <translation>MSC CRC:</translation>
+    </message>
+    <message>
+        <source>SDC CRC:</source>
+        <translation>SDC CRC:</translation>
+    </message>
+    <message>
+        <source>FAC CRC:</source>
+        <translation>FAC CRC:</translation>
+    </message>
+    <message>
+        <source>Frame Sync:</source>
+        <translation>Sync Trame:</translation>
+    </message>
+    <message>
+        <source>Time Sync Acq:</source>
+        <translation>Acq Sync Temps:</translation>
+    </message>
+    <message>
+        <source>I/O Interface:</source>
+        <translation>Interface E/S:</translation>
+    </message>
+    <message>
+        <source>FACDRMModeBWL</source>
+        <translation>FACDRMModeBWL</translation>
+    </message>
+    <message>
+        <source>FACInterleaverDepthL</source>
+        <translation>FACInterleaverDepthL</translation>
+    </message>
+    <message>
+        <source>FACSDCMSCModeL</source>
+        <translation>FACSDCMSCModeL</translation>
+    </message>
+    <message>
+        <source>FACCodeRateL</source>
+        <translation>FACCodeRateL</translation>
+    </message>
+    <message>
+        <source>FACNumServicesL</source>
+        <translation>FACNumServicesL</translation>
+    </message>
+    <message>
+        <source>FACTimeDateL</source>
+        <translation>FACTimeDateL</translation>
+    </message>
+    <message>
+        <source>FACDRMModeBWV</source>
+        <translation>FACDRMModeBWV</translation>
+    </message>
+    <message>
+        <source>FACInterleaverDepthV</source>
+        <translation>FACInterleaverDepthV</translation>
+    </message>
+    <message>
+        <source>FACSDCMSCModeV</source>
+        <translation>FACSDCMSCModeV</translation>
+    </message>
+    <message>
+        <source>FACCodeRateV</source>
+        <translation>FACCodeRateV</translation>
+    </message>
+    <message>
+        <source>FACNumServicesV</source>
+        <translation>FACNumServicesV</translation>
+    </message>
+    <message>
+        <source>FACTimeDateV</source>
+        <translation>FACTimeDateV</translation>
+    </message>
+    <message>
+        <source>Chart Selector</source>
+        <translation>Sélecteur de Graph</translation>
+    </message>
+    <message>
+        <source>D-Spectrum</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>D-InpPSD</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>D-InpSpectr</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>D-Waterfall</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>D-ShiftedPSD</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>D-AudSpectr</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>D-SNRSpectr</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>D-Channel</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>D-IR</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>D-TF</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>D-Constellation</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>D-FAC</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>D-SDC</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>D-MSC</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>D-History</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>D-SNRAudiHist</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>D-DelDopp</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>D-FreqSam</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Channel Estimation: Frequency Interpolation</source>
+        <translation>Estimation Canal: Interpolation Fréquence</translation>
+    </message>
+    <message>
+        <source>Linear</source>
+        <translation>Linéaire</translation>
+    </message>
+    <message>
+        <source>DFT Zero Pad.</source>
+        <translation>DFT Zéro Pad.</translation>
+    </message>
+    <message>
+        <source>Channel Estimation: Time Interpolation</source>
+        <translation>Estimation Canal: Interpolation Temps</translation>
+    </message>
+    <message>
+        <source>Time Sync Tracking</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Guard Energy</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>First Peak</source>
+        <translation>Première Crête</translation>
+    </message>
+    <message>
+        <source>Misc Settings</source>
+        <translation>Paramètres Divers</translation>
+    </message>
+    <message>
+        <source>&Flip Input Spectrum</source>
+        <translation>&Inverse Spectre d'Entrée</translation>
+    </message>
+    <message>
+        <source>Mute &Audio</source>
+        <translation>Audio Muet</translation>
+    </message>
+    <message>
+        <source>TextNumOfIterations</source>
+        <translation>TextNumOfIterations</translation>
+    </message>
+    <message>
+        <source>Log File, Audio</source>
+        <translation>Log Fichier, Audio</translation>
+    </message>
+    <message>
+        <source>&Log File, Freq:</source>
+        <translation>Fichier &Log, Freq:</translation>
+    </message>
+    <message>
+        <source>kHz</source>
+        <translation>kHz</translation>
+    </message>
+    <message>
+        <source>&Save Audio as WAV</source>
+        <translation>&Enregistre l'Audio en WAV</translation>
+    </message>
+    <message>
+        <source>&Reverberation</source>
+        <translation>&Réverbération</translation>
+    </message>
+    <message>
+        <source>Interferer Rejection</source>
+        <translation>Réjection d'Interférence</translation>
+    </message>
+    <message>
+        <source>&Bandpass Filter</source>
+        <translation>Filtre Passe-&Bande</translation>
+    </message>
+    <message>
+        <source>Modified &Metrics</source>
+        <translation>&Métriques Modifiées</translation>
+    </message>
+    <message>
+        <source>GPS</source>
+        <translation>GPS</translation>
+    </message>
+    <message encoding="UTF-8">
+        <source>Lat: 53.123°   Long: 00.456°</source>
+        <translation>Lat: 53.123°   Long: 00.456°</translation>
+    </message>
+    <message>
+        <source>24/01/2001-2014 15:14.33 UTC</source>
+        <translation>24/01/2001-2014 15:14.33 UTC</translation>
+    </message>
+    <message encoding="UTF-8">
+        <source>10.0 m/s  151°</source>
+        <translation>10.0 m/s  151°</translation>
+    </message>
+    <message>
+        <source>&Close</source>
+        <translation>&Fermer</translation>
+    </message>
+</context>
+</TS>
diff --git a/src/GUI-QT/liveschedulewidget.ui b/src/GUI-QT/liveschedulewidget.ui
new file mode 100644
index 0000000..d8c3dd0
--- /dev/null
+++ b/src/GUI-QT/liveschedulewidget.ui
@@ -0,0 +1,252 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>LiveScheduleWidget</class>
+ <widget class="QDialog" name="LiveScheduleWidget">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>526</width>
+    <height>179</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Dialog</string>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <item>
+    <widget class="QTreeWidget" name="ListViewStations">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
+     </property>
+     <property name="rootIsDecorated">
+      <bool>false</bool>
+     </property>
+     <property name="uniformRowHeights">
+      <bool>true</bool>
+     </property>
+     <column>
+      <property name="text">
+       <string>Frequency [kHz/MHz]</string>
+      </property>
+     </column>
+     <column>
+      <property name="text">
+       <string>Station Name/Id</string>
+      </property>
+     </column>
+     <column>
+      <property name="text">
+       <string>System</string>
+      </property>
+     </column>
+     <column>
+      <property name="text">
+       <string>Time [UTC]</string>
+      </property>
+     </column>
+     <column>
+      <property name="text">
+       <string>Target</string>
+      </property>
+     </column>
+     <column>
+      <property name="text">
+       <string>Start Day</string>
+      </property>
+     </column>
+    </widget>
+   </item>
+   <item>
+    <widget class="QGroupBox" name="groupBox">
+     <property name="title">
+      <string>Filters</string>
+     </property>
+     <layout class="QHBoxLayout" name="horizontalLayout_2">
+      <item>
+       <widget class="QLabel" name="label">
+        <property name="text">
+         <string>Time</string>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QComboBox" name="comboBoxFilterTime">
+        <item>
+         <property name="text">
+          <string>Any</string>
+         </property>
+        </item>
+        <item>
+         <property name="text">
+          <string>Active</string>
+         </property>
+        </item>
+        <item>
+         <property name="text">
+          <string>Coming (5min)</string>
+         </property>
+        </item>
+        <item>
+         <property name="text">
+          <string>Coming (15min)</string>
+         </property>
+        </item>
+        <item>
+         <property name="text">
+          <string>Coming (30min)</string>
+         </property>
+        </item>
+       </widget>
+      </item>
+      <item>
+       <widget class="QLabel" name="TextLabelTarget">
+        <property name="text">
+         <string>Target</string>
+        </property>
+        <property name="wordWrap">
+         <bool>false</bool>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QComboBox" name="comboBoxFilterTarget">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QLabel" name="TextLabelCountry">
+        <property name="text">
+         <string>Country</string>
+        </property>
+        <property name="wordWrap">
+         <bool>false</bool>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QComboBox" name="comboBoxFilterCountry">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QLabel" name="TextLabelLanguage">
+        <property name="text">
+         <string>Language</string>
+        </property>
+        <property name="wordWrap">
+         <bool>false</bool>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QComboBox" name="comboBoxFilterLanguage">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item>
+    <layout class="QHBoxLayout" name="horizontalLayout">
+     <item>
+      <widget class="QLabel" name="TextLabelUTCTime">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Minimum" vsizetype="Maximum">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="minimumSize">
+        <size>
+         <width>0</width>
+         <height>23</height>
+        </size>
+       </property>
+       <property name="frameShape">
+        <enum>QFrame::Panel</enum>
+       </property>
+       <property name="frameShadow">
+        <enum>QFrame::Sunken</enum>
+       </property>
+       <property name="text">
+        <string>UTC</string>
+       </property>
+       <property name="wordWrap">
+        <bool>false</bool>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QCheckBox" name="freeze">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="text">
+        <string>F&reeze</string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <spacer name="Spacer4">
+       <property name="orientation">
+        <enum>Qt::Horizontal</enum>
+       </property>
+       <property name="sizeType">
+        <enum>QSizePolicy::Expanding</enum>
+       </property>
+       <property name="sizeHint" stdset="0">
+        <size>
+         <width>20</width>
+         <height>20</height>
+        </size>
+       </property>
+      </spacer>
+     </item>
+     <item>
+      <widget class="QPushButton" name="buttonSave">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Minimum" vsizetype="Maximum">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="text">
+        <string>Save</string>
+       </property>
+       <property name="autoDefault">
+        <bool>true</bool>
+       </property>
+       <property name="default">
+        <bool>true</bool>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/GUI-QT/main.cpp b/src/GUI-QT/main.cpp
new file mode 100644
index 0000000..3f5143d
--- /dev/null
+++ b/src/GUI-QT/main.cpp
@@ -0,0 +1,339 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer, Stephane Fillod
+ *
+ * Description:
+ *
+ * 11/10/2001-2014 Stephane Fillod
+ *	- QT translation
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#ifdef _WIN32
+# include <windows.h>
+#endif
+#if defined(__unix__) && !defined(__APPLE__)
+# include <csignal>
+#endif
+
+#include "../GlobalDefinitions.h"
+#include "../DrmReceiver.h"
+#include "../DrmTransmitter.h"
+#include "../DrmSimulation.h"
+#include "../util/Settings.h"
+#include <iostream>
+
+#ifdef QT_CORE_LIB
+# ifdef QT_GUI_LIB
+#  include "fdrmdialog.h"
+#  include "TransmDlg.h"
+#  include "DialogUtil.h"
+#  ifdef HAVE_LIBHAMLIB
+#   include "../util-QT/Rig.h"
+#  endif
+#  include <QApplication>
+#  include <QMessageBox>
+# endif
+# include <QCoreApplication>
+# include <QTranslator>
+# include <QThread>
+
+class CRx: public QThread
+{
+public:
+	CRx(CDRMReceiver& nRx):rx(nRx)
+	{}
+	void run();
+private:
+	CDRMReceiver& rx;
+};
+
+void
+CRx::run()
+{
+    qDebug("Working thread started");
+    try
+    {
+        /* Call receiver main routine */
+        rx.Start();
+    }
+    catch (CGenErr GenErr)
+    {
+        ErrorMessage(GenErr.strError);
+    }
+    catch (string strError)
+    {
+        ErrorMessage(strError);
+    }
+    qDebug("Working thread complete");
+}
+#endif
+
+#ifdef USE_OPENSL
+# include <SLES/OpenSLES.h>
+SLObjectItf engineObject = NULL;
+#endif
+
+#ifdef QT_GUI_LIB
+/******************************************************************************\
+* Using GUI with QT                                                            *
+\******************************************************************************/
+int
+main(int argc, char **argv)
+{
+#ifdef USE_OPENSL
+    (void)slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL);
+    (void)(*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
+#endif
+#if defined(__unix__) && !defined(__APPLE__)
+	/* Prevent signal interaction with popen */
+	sigset_t sigset;
+	sigemptyset(&sigset);
+	sigaddset(&sigset, SIGPIPE);
+	sigaddset(&sigset, SIGCHLD);
+	pthread_sigmask(SIG_BLOCK, &sigset, NULL);
+#endif
+
+	/* create app before running Settings.Load to consume platform/QT parameters */
+	QApplication app(argc, argv);
+
+#if defined(__APPLE__)
+	/* find plugins on MacOs when deployed in a bundle */
+	app.addLibraryPath(app.applicationDirPath()+"../PlugIns");
+#endif
+#ifdef _WIN32
+	WSADATA wsaData;
+	(void)WSAStartup(MAKEWORD(2,2), &wsaData);
+#endif
+
+	/* Load and install multi-language support (if available) */
+	QTranslator translator(0);
+	if (translator.load("dreamtr"))
+		app.installTranslator(&translator);
+
+	CDRMSimulation DRMSimulation;
+
+	/* Call simulation script. If simulation is activated, application is
+	   automatically exit in that routine. If in the script no simulation is
+	   activated, this function will immediately return */
+	DRMSimulation.SimScript();
+
+	CSettings Settings;
+	/* Parse arguments and load settings from init-file */
+	Settings.Load(argc, argv);
+
+	try
+	{
+		string mode = Settings.Get("command", "mode", string());
+		if (mode == "receive")
+		{
+			CDRMReceiver DRMReceiver(&Settings);
+
+			/* First, initialize the working thread. This should be done in an extra
+			   routine since we cannot 100% assume that the working thread is
+			   ready before the GUI thread */
+
+#ifdef HAVE_LIBHAMLIB
+			CRig rig(&Settings, DRMReceiver.GetParameters()); // must be before DRMReceiver.LoadSettings() for G313
+
+			DRMReceiver.LoadSettings();
+
+			DRMReceiver.SetSFCallback(&CRig::SetFrequencyCallback, &rig);
+
+			if (DRMReceiver.GetDownstreamRSCIOutEnabled())
+				rig.subscribe();
+
+			FDRMDialog *pMainDlg = new FDRMDialog(DRMReceiver, Settings, rig);
+#else
+			DRMReceiver.LoadSettings();
+
+			FDRMDialog *pMainDlg = new FDRMDialog(DRMReceiver, Settings);
+#endif
+
+			/* Start working thread */
+			CRx rx(DRMReceiver);
+			rx.start();
+
+			/* Set main window */
+			app.exec();
+
+            delete pMainDlg;
+
+#ifdef HAVE_LIBHAMLIB
+			if(DRMReceiver.GetDownstreamRSCIOutEnabled())
+				rig.unsubscribe();
+#endif
+			DRMReceiver.SaveSettings();
+		}
+		else if(mode == "transmit")
+		{
+			TransmDialog* pMainDlg = new TransmDialog(Settings);
+
+			/* Show dialog */
+			pMainDlg->show();
+			app.exec();
+		}
+		else
+		{
+			CHelpUsage HelpUsage(Settings.UsageArguments(), argv[0]);
+			app.exec();
+			exit(0);
+		}
+	}
+
+	catch(CGenErr GenErr)
+	{
+		ErrorMessage(GenErr.strError);
+	}
+	catch(string strError)
+	{
+		ErrorMessage(strError);
+	}
+	catch(char *Error)
+	{
+		ErrorMessage(Error);
+	}
+
+	/* Save settings to init-file */
+	Settings.Save();
+
+	return 0;
+}
+
+/* Implementation of global functions *****************************************/
+
+void
+ErrorMessage(string strErrorString)
+{
+	/* Workaround for the QT problem */
+	string strError = "The following error occured:\n";
+	strError += strErrorString.c_str();
+	strError += "\n\nThe application will exit now.";
+
+#ifdef _WIN32
+	MessageBoxA(NULL, strError.c_str(), "Dream",
+			   MB_SYSTEMMODAL | MB_OK | MB_ICONEXCLAMATION);
+#else
+	perror(strError.c_str());
+#endif
+
+/*
+// Does not work correctly. If it is called by a different thread, the
+// application hangs! FIXME
+	QMessageBox::critical(0, "Dream",
+		QString("The following error occured:<br><b>") +
+		QString(strErrorString.c_str()) +
+		"</b><br><br>The application will exit now.");
+*/
+	exit(1);
+}
+#else /* QT_GUI_LIB */
+/******************************************************************************\
+* No GUI                                                                       *
+\******************************************************************************/
+
+int
+main(int argc, char **argv)
+{
+#ifdef USE_OPENSL
+    (void)slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL);
+    (void)(*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
+#endif
+    try
+	{
+		CSettings Settings;
+		Settings.Load(argc, argv);
+
+		string mode = Settings.Get("command", "mode", string());
+		if (mode == "receive")
+		{
+			CDRMSimulation DRMSimulation;
+			CDRMReceiver DRMReceiver(&Settings);
+
+			DRMSimulation.SimScript();
+			DRMReceiver.LoadSettings();
+
+#ifdef _WIN32
+			WSADATA wsaData;
+			(void)WSAStartup(MAKEWORD(2,2), &wsaData);
+#endif
+#ifdef QT_CORE_LIB
+			QCoreApplication app(argc, argv);
+			/* Start working thread */
+			CRx rx(DRMReceiver);
+			rx.start();
+			return app.exec();
+#else
+			DRMReceiver.Start();
+#endif
+		}
+		else if (mode == "transmit")
+		{
+			CDRMTransmitter DRMTransmitter(&Settings);
+			DRMTransmitter.LoadSettings();
+			DRMTransmitter.Start();
+		}
+		else
+		{
+			string usage(Settings.UsageArguments());
+			for (;;)
+			{
+				size_t pos = usage.find("$EXECNAME");
+				if (pos == string::npos) break;
+				usage.replace(pos, sizeof("$EXECNAME")-1, argv[0]);
+			}
+			cerr << usage << endl << endl;
+			exit(0);
+		}
+	}
+	catch(CGenErr GenErr)
+	{
+		ErrorMessage(GenErr.strError);
+	}
+
+	return 0;
+}
+
+void
+ErrorMessage(string strErrorString)
+{
+	perror(strErrorString.c_str());
+}
+#endif /* QT_GUI_LIB */
+
+void
+DebugError(const char *pchErDescr, const char *pchPar1Descr,
+		   const double dPar1, const char *pchPar2Descr, const double dPar2)
+{
+	FILE *pFile = fopen("test/DebugError.dat", "a");
+	fprintf(pFile, "%s", pchErDescr);
+	fprintf(pFile, " ### ");
+	fprintf(pFile, "%s", pchPar1Descr);
+	fprintf(pFile, ": ");
+	fprintf(pFile, "%e ### ", dPar1);
+	fprintf(pFile, "%s", pchPar2Descr);
+	fprintf(pFile, ": ");
+	fprintf(pFile, "%e\n", dPar2);
+	fclose(pFile);
+	fprintf(stderr, "\nDebug error! For more information see test/DebugError.dat\n");
+	exit(1);
+}
diff --git a/src/GUI-QT/receivercontroller.cpp b/src/GUI-QT/receivercontroller.cpp
new file mode 100644
index 0000000..ea3cdfa
--- /dev/null
+++ b/src/GUI-QT/receivercontroller.cpp
@@ -0,0 +1,315 @@
+#include "receivercontroller.h"
+
+ReceiverController::ReceiverController(CDRMReceiver* p, CSettings& s, QObject *parent) :
+    QObject(parent),
+    timer(),
+    receiver(p),
+    iCurrentFrequency(-1),
+    currentMode(RM_NONE),
+    settings(s)
+{
+    setObjectName("controller");
+    connect(&timer, SIGNAL(timeout()), SLOT(on_timer()));
+}
+
+void ReceiverController::setControls()
+{
+    // initialise from settings here so multiple panels are synced
+    emit numMSCMLCIterationsChanged(settings.Get("Receiver", "mlciter", 1));
+    emit timeIntChanged(settings.Get("Receiver", "timeint", 1));
+    emit freqIntChanged(settings.Get("Receiver", "freqint", 1));
+    emit tiSyncTracTypeChanged(settings.Get("Receiver", "timesync", 1));
+
+    emit recFilterChanged(settings.Get("Receiver", "filter", FALSE));
+    emit intConsChanged(settings.Get("Receiver", "modemetric", FALSE));
+    emit flippedSpectrumChanged(settings.Get("Receiver", "flipspectrum", FALSE));
+}
+
+void ReceiverController::on_timer()
+{
+    CParameter& Parameters = *receiver->GetParameters();
+    Parameters.Lock();
+
+    /* Input level meter */
+    double sigstr = Parameters.GetIFSignalLevel();
+
+    /* LEDs */
+    ETypeRxStatus msc,sdc,fac,fsync,tsync,inp,outp;
+    fac = Parameters.ReceiveStatus.FAC.GetStatus();
+    sdc = Parameters.ReceiveStatus.SDC.GetStatus();
+    int iShortID = Parameters.GetCurSelAudioService();
+    if(Parameters.Service[iShortID].eAudDataFlag == CService::SF_AUDIO)
+        msc = Parameters.AudioComponentStatus[iShortID].GetStatus();
+    else
+        msc = Parameters.DataComponentStatus[iShortID].GetStatus();
+    fsync = Parameters.ReceiveStatus.FSync.GetStatus();
+    tsync = Parameters.ReceiveStatus.TSync.GetStatus();
+    inp = Parameters.ReceiveStatus.InterfaceI.GetStatus();
+    outp = Parameters.ReceiveStatus.InterfaceO.GetStatus();
+
+    /* detect if AFS mux information is available */
+    bool bAFS = (Parameters.AltFreqSign.vecMultiplexes.size() > 0)
+             || (Parameters.AltFreqSign.vecOtherServices.size() > 0);
+    gps_data_t gps_data = Parameters.gps_data;
+
+    map<uint32_t,CServiceInformation> si = Parameters.ServiceInformation;
+
+    Reception reception;
+
+    reception.snr = Parameters.GetSNR();
+    reception.mer = Parameters.rMER;
+    reception.wmer = Parameters.rWMERMSC;
+    reception.sigmaEstimate = Parameters.rSigmaEstimate;
+    reception.minDelay = Parameters.rMinDelay;
+    reception.sampleOffset = Parameters.rResampleOffset;
+    reception.sampleRate = Parameters.GetSigSampleRate();
+    reception.dcOffset = receiver->GetReceiveData()->ConvertFrequency(Parameters.GetDCFrequency());
+    reception.rdop = Parameters.rRdop;
+
+    ChannelConfiguration channel;
+
+    channel.robm = Parameters.GetWaveMode();
+    channel.mode = Parameters.GetSpectrumOccup();
+    channel.interl = Parameters.eSymbolInterlMode;
+    channel.sdcConst = Parameters.eSDCCodingScheme;
+    channel.mscConst = Parameters.eMSCCodingScheme;
+    channel.protLev = Parameters.MSCPrLe;
+    channel.nAudio = Parameters.iNumAudioService;
+    channel.nData = Parameters.iNumDataService;
+
+    Parameters.Unlock();
+
+    emit InputSignalLevelChanged(sigstr);
+    emit FACChanged(fac);
+    emit SDCChanged(sdc);
+    emit MSCChanged(msc);
+    emit FSyncChanged(fsync);
+    emit TSyncChanged(tsync);
+    emit InputStatusChanged(inp);
+    emit OutputStatusChanged(outp);
+
+    emit setAFS(bAFS);
+    // NB following is not efficient - TODO - have a better idea
+    if(bAFS)
+        emit AFS(Parameters.AltFreqSign);
+
+    if(gps_data.status&LATLON_SET)
+        emit position(gps_data.fix.latitude, gps_data.fix.longitude);
+
+    emit serviceInformation(si);
+
+    ERecMode newMode = receiver->GetReceiverMode();
+    if(newMode!=currentMode)
+    {
+        currentMode = newMode;
+        emit mode(currentMode);
+    }
+
+    /* Check if receiver does receive a signal */
+    if(receiver->GetAcquiState() == AS_WITH_SIGNAL)
+    {
+        switch(Parameters.GetReceiverMode())
+        {
+        case RM_DRM:
+            updateDRM(Parameters);
+        default:
+            ;
+        }
+
+        emit channelReceptionChanged(reception);
+        emit channelConfigurationChanged(channel);
+
+        int iFreq = receiver->GetFrequency();
+        if(iFreq != iCurrentFrequency)
+        {
+            emit frequencyChanged(iFreq);
+            iCurrentFrequency = iFreq;
+        }
+    }
+    else
+    {
+        emit signalLost();
+    }
+
+    /* Time, date ####################
+    if ((Parameters.iUTCHour == 0) &&
+            (Parameters.iUTCMin == 0) &&
+            (Parameters.iDay == 0) &&
+            (Parameters.iMonth == 0) &&
+            (Parameters.iYear == 0))
+            */
+}
+
+
+
+void ReceiverController::updateDRM(CParameter& Parameters)
+{
+    for(int i=0; i < MAX_NUM_SERVICES; i++)
+    {
+        Parameters.Lock();
+        CService& service = Parameters.Service[i];
+        service.AudioParam.rBitRate = Parameters.GetBitRateKbps(i, false);
+        service.AudioParam.bCanDecode = receiver->GetAudSorceDec()->CanDecode(service.AudioParam.eAudioCoding);
+        service.DataParam.rBitRate = Parameters.GetBitRateKbps(i, true);
+        service.DataParam.pDecoder = receiver->GetDataDecoder();
+        ETypeRxStatus e = Parameters.DataComponentStatus[i].GetStatus();
+        Parameters.Unlock();
+
+        emit serviceChanged(i, service); // TODO emit only when changed
+
+        /* If we have text messages */
+        QString textMessage = "";
+        if (service.AudioParam.bTextflag)
+        {
+            // Text message of current selected audio service (UTF-8 decoding)
+            textMessage = QString::fromUtf8(service.AudioParam.strTextMessage.c_str());
+        }
+        emit textMessageChanged(i, textMessage);
+
+        if(service.DataParam.iStreamID != STREAM_ID_NOT_USED)
+            emit dataStatusChanged(i, e);
+    }
+}
+
+void ReceiverController::setFrequency(int f)
+{
+    receiver->SetFrequency(f);
+}
+
+void ReceiverController::triggerNewAcquisition()
+{
+    receiver->RequestNewAcquisition();
+}
+
+void ReceiverController::setMode(int newMode)
+{
+    receiver->SetReceiverMode(ERecMode(newMode));
+}
+
+int ReceiverController::getMode() const
+{
+    return currentMode;
+}
+
+void ReceiverController::selectAudioService(int shortId)
+{
+    CParameter& Parameters = *receiver->GetParameters();
+    Parameters.Lock();
+    Parameters.SetCurSelAudioService(shortId);
+    Parameters.Unlock();
+}
+
+void ReceiverController::selectDataService(int shortId)
+{
+    CParameter& Parameters = *receiver->GetParameters();
+    Parameters.Lock();
+    Parameters.SetCurSelDataService(shortId);
+    Parameters.Unlock();
+}
+void ReceiverController::setSaveAudio(const string& s)
+{
+    if(s!="")
+        receiver->GetWriteData()->StartWriteWaveFile(s);
+    else
+        receiver->GetWriteData()->StopWriteWaveFile();
+}
+
+void ReceiverController::muteAudio(bool b)
+{
+    receiver->GetWriteData()->MuteAudio(b);
+}
+
+void ReceiverController::setTimeInt(int v)
+{
+    CChannelEstimation::ETypeIntTime e = CChannelEstimation::ETypeIntTime(v);
+    if (receiver->GetTimeInt() != e)
+        receiver->SetTimeInt(e);
+}
+
+void ReceiverController::setFreqInt(int v)
+{
+    CChannelEstimation::ETypeIntFreq e = CChannelEstimation::ETypeIntFreq(v);
+    if (receiver->GetFreqInt() != e)
+        receiver->SetFreqInt(e);
+}
+
+void ReceiverController::setTiSyncTracType(int v)
+{
+    CTimeSyncTrack::ETypeTiSyncTrac e = CTimeSyncTrack::ETypeTiSyncTrac(v);
+    if (receiver->GetTiSyncTracType() != e)
+        receiver->SetTiSyncTracType(e);
+}
+
+void ReceiverController::setNumMSCMLCIterations(int value)
+{
+    receiver->GetMSCMLC()->SetNumIterations(value);
+}
+
+void ReceiverController::setFlippedSpectrum(bool b)
+{
+    receiver->GetReceiveData()->SetFlippedSpectrum(b);
+}
+
+void ReceiverController::setReverbEffect(bool b)
+{
+    receiver->GetAudSorceDec()->SetReverbEffect(b);
+}
+
+void ReceiverController::setRecFilter(bool b)
+{
+    /* Set parameter in working thread module */
+    receiver->GetFreqSyncAcq()->SetRecFilter(b);
+
+    /* If filter status is changed, a new aquisition is necessary */
+    receiver->RequestNewAcquisition();
+}
+
+void ReceiverController::setIntCons(bool b)
+{
+    /* Set parameter in working thread module */
+    receiver->SetIntCons(b);
+}
+
+// AM
+
+void ReceiverController::setAnalogModulation(int i)
+{
+    receiver->GetAMDemod()->SetDemodType(CAMDemodulation::EDemodType(i));
+}
+
+void ReceiverController::setAnalogAGC(int i)
+{
+    receiver->GetAMDemod()->SetAGCType(CAGC::EType(i));
+}
+
+void ReceiverController::setAnalogNoiseReduction(int i)
+{
+    receiver->GetAMDemod()->SetNoiRedType(CAMDemodulation::ENoiRedType(i));
+}
+
+void ReceiverController::setAMFilterBW(int value)
+{
+    receiver->SetAMFilterBW(value);
+}
+
+void ReceiverController::setEnableAutoFreqAcq(bool b)
+{
+    /* Set parameter in working thread module */
+    receiver->GetAMDemod()->EnableAutoFreqAcq(b);
+}
+
+void ReceiverController::setEnablePLL(bool b)
+{
+    /* Set parameter in working thread module */
+    receiver->GetAMDemod()->EnablePLL(b);
+}
+
+void ReceiverController::setAMDemodAcq(double dVal)
+{
+    receiver->SetAMDemodAcq(dVal);
+}
+
+void ReceiverController::setNoiRedLevel(int value)
+{
+    receiver->GetAMDemod()->SetNoiRedLevel(value);
+}
diff --git a/src/GUI-QT/receivercontroller.h b/src/GUI-QT/receivercontroller.h
new file mode 100644
index 0000000..13fc489
--- /dev/null
+++ b/src/GUI-QT/receivercontroller.h
@@ -0,0 +1,106 @@
+#ifndef RECEIVERCONTROLLER_H
+#define RECEIVERCONTROLLER_H
+
+#include <QObject>
+#include <QTimer>
+#include <../DrmReceiver.h>
+#include <../util/Settings.h>
+
+struct Reception {
+    double snr, mer, wmer;
+    double sigmaEstimate;
+    double minDelay;
+    double sampleOffset;
+    int sampleRate;
+    double dcOffset;
+    double rdop;
+};
+
+struct ChannelConfiguration {
+    int robm;
+    int mode;
+    int interl;
+    int sdcConst, mscConst;
+    CMSCProtLev protLev;
+    int nData, nAudio;
+};
+
+class ReceiverController : public QObject
+{
+    Q_OBJECT
+public:
+    explicit ReceiverController(CDRMReceiver*, CSettings&, QObject *parent = 0);
+    // TODO - remove this:
+    CDRMReceiver* getReceiver() { return receiver; }
+    int getMode() const;
+
+signals:
+    void serviceChanged(int, const CService&);
+    void dataStatusChanged(int, ETypeRxStatus);
+    void frequencyChanged(int);
+    void mode(int);
+    void position(double,double);
+    void AFS(const CAltFreqSign&);
+    void setAFS(bool);
+    void serviceInformation(const map <uint32_t,CServiceInformation>);
+    void textMessageChanged(int, const QString&);
+    void MSCChanged(ETypeRxStatus);
+    void SDCChanged(ETypeRxStatus);
+    void FACChanged(ETypeRxStatus);
+    void FSyncChanged(ETypeRxStatus);
+    void TSyncChanged(ETypeRxStatus);
+    void InputStatusChanged(ETypeRxStatus);
+    void OutputStatusChanged(ETypeRxStatus);
+    void InputSignalLevelChanged(double);
+    void signalLost();
+    void channelReceptionChanged(Reception);
+    void channelConfigurationChanged(ChannelConfiguration);
+    void timeIntChanged(int);
+    void freqIntChanged(int);
+    void tiSyncTracTypeChanged(int);
+    void numMSCMLCIterationsChanged(int);
+    void flippedSpectrumChanged(bool);
+    void recFilterChanged(bool);
+    void intConsChanged(bool);
+
+public slots:
+    void start(int ms) { timer.start(ms); }
+    void stop() { timer.stop(); }
+    void setControls();
+    void selectDataService(int);
+    void selectAudioService(int);
+    void triggerNewAcquisition();
+    void setMode(int);
+    void setFrequency(int);
+    void muteAudio(bool);
+    void setSaveAudio(const string&);
+    void setTimeInt(int);
+    void setFreqInt(int);
+    void setTiSyncTracType(int);
+    void setNumMSCMLCIterations(int);
+    void setFlippedSpectrum(bool);
+    void setReverbEffect(bool);
+    void setRecFilter(bool);
+    void setIntCons(bool);
+    void setAnalogModulation(int i);
+    void setAnalogAGC(int i);
+    void setAnalogNoiseReduction(int i);
+    void setAMFilterBW(int value);
+    void setEnableAutoFreqAcq(bool b);
+    void setEnablePLL(bool b);
+    void setAMDemodAcq(double dVal);
+    void setNoiRedLevel(int value);
+
+private:
+    QTimer        timer;
+    CDRMReceiver* receiver;
+    int           iCurrentFrequency;
+    ERecMode      currentMode;
+    CSettings&    settings;
+
+private slots:
+    void on_timer();
+    void updateDRM(CParameter&);
+};
+
+#endif // RECEIVERCONTROLLER_H
diff --git a/src/GUI-QT/res/CSAudSNRHist.png b/src/GUI-QT/res/CSAudSNRHist.png
new file mode 100644
index 0000000..17b221b
Binary files /dev/null and b/src/GUI-QT/res/CSAudSNRHist.png differ
diff --git a/src/GUI-QT/res/CSChannel.png b/src/GUI-QT/res/CSChannel.png
new file mode 100644
index 0000000..03686ec
Binary files /dev/null and b/src/GUI-QT/res/CSChannel.png differ
diff --git a/src/GUI-QT/res/CSConstellation.png b/src/GUI-QT/res/CSConstellation.png
new file mode 100644
index 0000000..d9f8618
Binary files /dev/null and b/src/GUI-QT/res/CSConstellation.png differ
diff --git a/src/GUI-QT/res/CSFAC.png b/src/GUI-QT/res/CSFAC.png
new file mode 100644
index 0000000..72021ec
Binary files /dev/null and b/src/GUI-QT/res/CSFAC.png differ
diff --git a/src/GUI-QT/res/CSHistory.png b/src/GUI-QT/res/CSHistory.png
new file mode 100644
index 0000000..3818566
Binary files /dev/null and b/src/GUI-QT/res/CSHistory.png differ
diff --git a/src/GUI-QT/res/CSHistoryDelDopp.png b/src/GUI-QT/res/CSHistoryDelDopp.png
new file mode 100644
index 0000000..524e609
Binary files /dev/null and b/src/GUI-QT/res/CSHistoryDelDopp.png differ
diff --git a/src/GUI-QT/res/CSHistoryFreqSam.png b/src/GUI-QT/res/CSHistoryFreqSam.png
new file mode 100644
index 0000000..d070334
Binary files /dev/null and b/src/GUI-QT/res/CSHistoryFreqSam.png differ
diff --git a/src/GUI-QT/res/CSIR.png b/src/GUI-QT/res/CSIR.png
new file mode 100644
index 0000000..4823248
Binary files /dev/null and b/src/GUI-QT/res/CSIR.png differ
diff --git a/src/GUI-QT/res/CSMSC.png b/src/GUI-QT/res/CSMSC.png
new file mode 100644
index 0000000..b95477c
Binary files /dev/null and b/src/GUI-QT/res/CSMSC.png differ
diff --git a/src/GUI-QT/res/CSSDC.png b/src/GUI-QT/res/CSSDC.png
new file mode 100644
index 0000000..431c354
Binary files /dev/null and b/src/GUI-QT/res/CSSDC.png differ
diff --git a/src/GUI-QT/res/CSSpectrum.png b/src/GUI-QT/res/CSSpectrum.png
new file mode 100644
index 0000000..9a7b832
Binary files /dev/null and b/src/GUI-QT/res/CSSpectrum.png differ
diff --git a/src/GUI-QT/res/CSSpectrumAudio.png b/src/GUI-QT/res/CSSpectrumAudio.png
new file mode 100644
index 0000000..2ba6f87
Binary files /dev/null and b/src/GUI-QT/res/CSSpectrumAudio.png differ
diff --git a/src/GUI-QT/res/CSSpectrumInpPSD.png b/src/GUI-QT/res/CSSpectrumInpPSD.png
new file mode 100644
index 0000000..bc0caf2
Binary files /dev/null and b/src/GUI-QT/res/CSSpectrumInpPSD.png differ
diff --git a/src/GUI-QT/res/CSSpectrumInpSpectr.png b/src/GUI-QT/res/CSSpectrumInpSpectr.png
new file mode 100644
index 0000000..d70e721
Binary files /dev/null and b/src/GUI-QT/res/CSSpectrumInpSpectr.png differ
diff --git a/src/GUI-QT/res/CSSpectrumSNR.png b/src/GUI-QT/res/CSSpectrumSNR.png
new file mode 100644
index 0000000..83465bf
Binary files /dev/null and b/src/GUI-QT/res/CSSpectrumSNR.png differ
diff --git a/src/GUI-QT/res/CSSpectrumShiftedPSD.png b/src/GUI-QT/res/CSSpectrumShiftedPSD.png
new file mode 100644
index 0000000..fb808dd
Binary files /dev/null and b/src/GUI-QT/res/CSSpectrumShiftedPSD.png differ
diff --git a/src/GUI-QT/res/CSSpectrumWaterf.png b/src/GUI-QT/res/CSSpectrumWaterf.png
new file mode 100644
index 0000000..13b150e
Binary files /dev/null and b/src/GUI-QT/res/CSSpectrumWaterf.png differ
diff --git a/src/GUI-QT/res/CSTF.png b/src/GUI-QT/res/CSTF.png
new file mode 100644
index 0000000..281b0a0
Binary files /dev/null and b/src/GUI-QT/res/CSTF.png differ
diff --git a/src/GUI-QT/res/Home.png b/src/GUI-QT/res/Home.png
new file mode 100644
index 0000000..b1aface
Binary files /dev/null and b/src/GUI-QT/res/Home.png differ
diff --git a/src/GUI-QT/res/JumpBegin.png b/src/GUI-QT/res/JumpBegin.png
new file mode 100644
index 0000000..d46c084
Binary files /dev/null and b/src/GUI-QT/res/JumpBegin.png differ
diff --git a/src/GUI-QT/res/JumpEnd.png b/src/GUI-QT/res/JumpEnd.png
new file mode 100644
index 0000000..ce00505
Binary files /dev/null and b/src/GUI-QT/res/JumpEnd.png differ
diff --git a/src/GUI-QT/res/LogoFhGIIS.png b/src/GUI-QT/res/LogoFhGIIS.png
new file mode 100644
index 0000000..c174b56
Binary files /dev/null and b/src/GUI-QT/res/LogoFhGIIS.png differ
diff --git a/src/GUI-QT/res/LogoJournaline.png b/src/GUI-QT/res/LogoJournaline.png
new file mode 100644
index 0000000..2d968b8
Binary files /dev/null and b/src/GUI-QT/res/LogoJournaline.png differ
diff --git a/src/GUI-QT/res/LogoOpus.png b/src/GUI-QT/res/LogoOpus.png
new file mode 100644
index 0000000..43f66dd
Binary files /dev/null and b/src/GUI-QT/res/LogoOpus.png differ
diff --git a/src/GUI-QT/res/LogoSmall.png b/src/GUI-QT/res/LogoSmall.png
new file mode 100644
index 0000000..b725b27
Binary files /dev/null and b/src/GUI-QT/res/LogoSmall.png differ
diff --git a/src/GUI-QT/res/LogoSmallOrig.png b/src/GUI-QT/res/LogoSmallOrig.png
new file mode 100644
index 0000000..95afa8d
Binary files /dev/null and b/src/GUI-QT/res/LogoSmallOrig.png differ
diff --git a/src/GUI-QT/res/MainIcon.ico b/src/GUI-QT/res/MainIcon.ico
new file mode 100644
index 0000000..eeb392d
Binary files /dev/null and b/src/GUI-QT/res/MainIcon.ico differ
diff --git a/src/GUI-QT/res/MainIcon.png b/src/GUI-QT/res/MainIcon.png
new file mode 100644
index 0000000..a6cba48
Binary files /dev/null and b/src/GUI-QT/res/MainIcon.png differ
diff --git a/src/GUI-QT/res/MainIcon.svg b/src/GUI-QT/res/MainIcon.svg
new file mode 100644
index 0000000..cc9552f
--- /dev/null
+++ b/src/GUI-QT/res/MainIcon.svg
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   version="1.1"
+   width="64"
+   height="64"
+   id="svg2985">
+  <title
+     id="title2987">Dream Icon</title>
+  <metadata
+     id="metadata10">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title>Dream Receiver Icon</dc:title>
+        <dc:creator>
+          <cc:Agent>
+            <dc:title>David Flamand</dc:title>
+          </cc:Agent>
+        </dc:creator>
+        <cc:license
+           rdf:resource="http://creativecommons.org/licenses/by/3.0/" />
+        <dc:date>2013-01-09</dc:date>
+      </cc:Work>
+      <cc:License
+         rdf:about="http://creativecommons.org/licenses/by/3.0/">
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Reproduction" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Distribution" />
+        <cc:requires
+           rdf:resource="http://creativecommons.org/ns#Notice" />
+        <cc:requires
+           rdf:resource="http://creativecommons.org/ns#Attribution" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
+      </cc:License>
+    </rdf:RDF>
+  </metadata>
+  <defs
+     id="defs2987" />
+  <g
+     id="layer1"
+     style="display:inline">
+    <path
+       d="m 59.636364,34.18182 a 21.363636,22.90909 0 1 1 -42.727272,0 21.363636,22.90909 0 1 1 42.727272,0 z"
+       transform="matrix(1.2217815,0,0,1.1393597,-14.76091,-6.9453891)"
+       id="path5207"
+       style="opacity:0.98000004;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#45528e;stroke-width:4.02593184;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+    <g
+       transform="matrix(0.96426357,0,0,1.0370609,1.0516663e-6,-2.8950616e-6)"
+       id="text5241"
+       style="fill:#45528e;fill-opacity:1;stroke:none">
+      <path
+         d="m 28.698168,21.442433 0,18.828005 2.852102,0 c 3.251653,6e-6 5.731739,-0.806022 7.440265,-2.418086 1.72226,-1.612048 2.583401,-3.954351 2.583425,-7.026917 -2.4e-5,-3.058758 -0.854276,-5.387283 -2.562758,-6.985583 -1.708526,-1.598255 -4.195501,-2.397394 -7.460932,-2.397419 l -2.852102,0 m -7.956951,-6.014214 8.390966,0 c 4.684595,3e-5 8.170493,0.337598 10.457707,1.012702 2.300946,0.661387 4.271236,1.791203 5.910877,3.389455 1.446688,1.39163 2.521392,2.996797 3.224115,4.815505  [...]
+         id="path5293"
+         style="fill:#45528e;fill-opacity:1" />
+    </g>
+  </g>
+</svg>
diff --git a/src/GUI-QT/res/MainIconOrig.png b/src/GUI-QT/res/MainIconOrig.png
new file mode 100644
index 0000000..c5271ea
Binary files /dev/null and b/src/GUI-QT/res/MainIconOrig.png differ
diff --git a/src/GUI-QT/res/MainIconTx.svg b/src/GUI-QT/res/MainIconTx.svg
new file mode 100644
index 0000000..71f5f44
--- /dev/null
+++ b/src/GUI-QT/res/MainIconTx.svg
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   version="1.1"
+   width="64"
+   height="64"
+   id="svg2985">
+  <title
+     id="title2987">Dream Transmitter Icon</title>
+  <metadata
+     id="metadata10">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title>Dream Transmitter Icon</dc:title>
+        <dc:creator>
+          <cc:Agent>
+            <dc:title>David Flamand</dc:title>
+          </cc:Agent>
+        </dc:creator>
+        <cc:license
+           rdf:resource="http://creativecommons.org/licenses/by/3.0/" />
+        <dc:date>2013-01-09</dc:date>
+      </cc:Work>
+      <cc:License
+         rdf:about="http://creativecommons.org/licenses/by/3.0/">
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Reproduction" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Distribution" />
+        <cc:requires
+           rdf:resource="http://creativecommons.org/ns#Notice" />
+        <cc:requires
+           rdf:resource="http://creativecommons.org/ns#Attribution" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
+      </cc:License>
+    </rdf:RDF>
+  </metadata>
+  <defs
+     id="defs2987" />
+  <g
+     id="layer1"
+     style="display:inline">
+    <path
+       d="m 59.636364,34.18182 a 21.363636,22.90909 0 1 1 -42.727272,0 21.363636,22.90909 0 1 1 42.727272,0 z"
+       transform="matrix(1.2217815,0,0,1.1393597,-14.76091,-6.9453891)"
+       id="path5207"
+       style="opacity:0.98000004;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#45528e;stroke-width:4.02593184;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+    <g
+       transform="matrix(0.96426357,0,0,1.0370609,1.0516663e-6,-2.8950616e-6)"
+       id="text5241"
+       style="fill:#f31d2a;fill-opacity:1;stroke:none">
+      <path
+         d="m 28.698168,21.442433 0,18.828005 2.852102,0 c 3.251653,6e-6 5.731739,-0.806022 7.440265,-2.418086 1.72226,-1.612048 2.583401,-3.954351 2.583425,-7.026917 -2.4e-5,-3.058758 -0.854276,-5.387283 -2.562758,-6.985583 -1.708526,-1.598255 -4.195501,-2.397394 -7.460932,-2.397419 l -2.852102,0 m -7.956951,-6.014214 8.390966,0 c 4.684595,3e-5 8.170493,0.337598 10.457707,1.012702 2.300946,0.661387 4.271236,1.791203 5.910877,3.389455 1.446688,1.39163 2.521392,2.996797 3.224115,4.815505  [...]
+         id="path5293"
+         style="fill:#f31d2a;fill-opacity:1" />
+    </g>
+  </g>
+</svg>
diff --git a/src/GUI-QT/res/Refresh.png b/src/GUI-QT/res/Refresh.png
new file mode 100644
index 0000000..043a2a3
Binary files /dev/null and b/src/GUI-QT/res/Refresh.png differ
diff --git a/src/GUI-QT/res/StepBack.png b/src/GUI-QT/res/StepBack.png
new file mode 100644
index 0000000..5bf99c4
Binary files /dev/null and b/src/GUI-QT/res/StepBack.png differ
diff --git a/src/GUI-QT/res/StepForw.png b/src/GUI-QT/res/StepForw.png
new file mode 100644
index 0000000..9a7fe9f
Binary files /dev/null and b/src/GUI-QT/res/StepForw.png differ
diff --git a/src/GUI-QT/res/Stop.png b/src/GUI-QT/res/Stop.png
new file mode 100644
index 0000000..749f53b
Binary files /dev/null and b/src/GUI-QT/res/Stop.png differ
diff --git a/src/GUI-QT/res/greenCube.png b/src/GUI-QT/res/greenCube.png
new file mode 100644
index 0000000..54f72e2
Binary files /dev/null and b/src/GUI-QT/res/greenCube.png differ
diff --git a/src/GUI-QT/res/icons.qrc b/src/GUI-QT/res/icons.qrc
new file mode 100644
index 0000000..559fa6d
--- /dev/null
+++ b/src/GUI-QT/res/icons.qrc
@@ -0,0 +1,40 @@
+<RCC>
+  <qresource prefix="/icons">
+    <file>greenCube.png</file>
+    <file>smallGreenCube.png</file>
+    <file>redCube.png</file>
+    <file>pinkCube.png</file>
+    <file>orangeCube.png</file>
+    <file>CSAudSNRHist.png</file>
+    <file>CSChannel.png</file>
+    <file>CSConstellation.png</file>
+    <file>CSFAC.png</file>
+    <file>CSHistory.png</file>
+    <file>CSHistoryDelDopp.png</file>
+    <file>CSHistoryFreqSam.png</file>
+    <file>CSIR.png</file>
+    <file>CSMSC.png</file>
+    <file>CSSDC.png</file>
+    <file>CSSpectrum.png</file>
+    <file>CSSpectrumAudio.png</file>
+    <file>CSSpectrumInpPSD.png</file>
+    <file>CSSpectrumInpSpectr.png</file>
+    <file>CSSpectrumSNR.png</file>
+    <file>CSSpectrumShiftedPSD.png</file>
+    <file>CSSpectrumWaterf.png</file>
+    <file>CSTF.png</file>
+    <file>Home.png</file>
+    <file>JumpBegin.png</file>
+    <file>JumpEnd.png</file>
+    <file>LogoFhGIIS.png</file>
+    <file>LogoJournaline.png</file>
+    <file>LogoOpus.png</file>
+    <file>LogoSmall.png</file>
+    <file>MainIcon.svg</file>
+    <file>MainIconTx.svg</file>
+    <file>Refresh.png</file>
+    <file>StepBack.png</file>
+    <file>StepForw.png</file>
+    <file>Stop.png</file>
+  </qresource>
+</RCC>
diff --git a/src/GUI-QT/res/macicons.icns b/src/GUI-QT/res/macicons.icns
new file mode 100644
index 0000000..2ef4f4c
Binary files /dev/null and b/src/GUI-QT/res/macicons.icns differ
diff --git a/src/GUI-QT/res/orangeCube.png b/src/GUI-QT/res/orangeCube.png
new file mode 100644
index 0000000..2d57d50
Binary files /dev/null and b/src/GUI-QT/res/orangeCube.png differ
diff --git a/src/GUI-QT/res/pinkCube.png b/src/GUI-QT/res/pinkCube.png
new file mode 100644
index 0000000..8e2c6df
Binary files /dev/null and b/src/GUI-QT/res/pinkCube.png differ
diff --git a/src/GUI-QT/res/redCube.png b/src/GUI-QT/res/redCube.png
new file mode 100644
index 0000000..59742d9
Binary files /dev/null and b/src/GUI-QT/res/redCube.png differ
diff --git a/src/GUI-QT/res/smallGreenCube.png b/src/GUI-QT/res/smallGreenCube.png
new file mode 100644
index 0000000..1184fb0
Binary files /dev/null and b/src/GUI-QT/res/smallGreenCube.png differ
diff --git a/src/GUI-QT/serviceselector.cpp b/src/GUI-QT/serviceselector.cpp
new file mode 100644
index 0000000..dc73ec0
--- /dev/null
+++ b/src/GUI-QT/serviceselector.cpp
@@ -0,0 +1,145 @@
+#include "serviceselector.h"
+#include "ui_serviceselector.h"
+#include "../Parameter.h"
+#include "../util-QT/Util.h"
+#include <../datadecoding/DataDecoder.h>
+#include "ThemeCustomizer.h"
+
+ServiceSelector::ServiceSelector(QWidget *parent) :
+    QWidget(parent),
+    ui(new Ui::ServiceSelector),
+    pButtonGroup(NULL),serviceLabels(4)
+{
+    ui->setupUi(this);
+    pButtonGroup = new QButtonGroup(this);
+    pButtonGroup->setExclusive(true);
+    pButtonGroup->addButton(ui->PushButtonService1, 0);
+    pButtonGroup->addButton(ui->PushButtonService2, 1);
+    pButtonGroup->addButton(ui->PushButtonService3, 2);
+    pButtonGroup->addButton(ui->PushButtonService4, 3);
+    connect(pButtonGroup, SIGNAL(buttonClicked(int)), this, SIGNAL(audioServiceSelected(int)));
+    connect(pButtonGroup, SIGNAL(buttonClicked(int)), this, SIGNAL(dataServiceSelected(int)));
+
+    serviceLabels[0] = ui->TextMiniService1;
+    serviceLabels[1] = ui->TextMiniService2;
+    serviceLabels[2] = ui->TextMiniService3;
+    serviceLabels[3] = ui->TextMiniService4;
+
+    /* Service Selectors */
+    const QString strServiceSel =
+        tr("<b>Service Selectors:</b> In a DRM stream up to "
+           "four services can be carried. The service can be an audio service, "
+           "a data service or an audio service with data. "
+           "Audio services can have associated text messages, in addition to any data component. "
+           "If a Multimedia data service is selected, the Multimedia Dialog will automatically show up. "
+           "On the right of each service selection button a short description of the service is shown. "
+           "If an audio service has associated Multimedia data, \"+ MM\" is added to this text. "
+           "If such a service is selected, opening the Multimedia Dialog will allow the data to be viewed "
+           "while the audio is still playing. If the data component of a service is not Multimedia, "
+           "but an EPG (Electronic Programme Guide) \"+ EPG\" is added to the description. "
+           "The accumulated Programme Guides for all stations can be viewed by opening the Programme Guide Dialog. "
+           "The selected channel in the Programme Guide Dialog defaults to the station being received. "
+           "If Alternative Frequency Signalling is available, \"+ AFS\" is added to the description. "
+           "In this case the alternative frequencies can be viewed by opening the Live Schedule Dialog."
+          );
+    ui->PushButtonService1->setWhatsThis(strServiceSel);
+    ui->PushButtonService2->setWhatsThis(strServiceSel);
+    ui->PushButtonService3->setWhatsThis(strServiceSel);
+    ui->PushButtonService4->setWhatsThis(strServiceSel);
+    ui->TextMiniService1->setWhatsThis(strServiceSel);
+    ui->TextMiniService2->setWhatsThis(strServiceSel);
+    ui->TextMiniService3->setWhatsThis(strServiceSel);
+    ui->TextMiniService4->setWhatsThis(strServiceSel);
+
+    APPLY_CUSTOM_THEME_UI();
+}
+
+ServiceSelector::~ServiceSelector()
+{
+    delete ui;
+}
+
+void ServiceSelector::onServiceChanged(int short_id, const CService& service)
+{
+    QString text;
+
+    /* Check, if service is used */
+    if (service.IsActive())
+    {
+        /* Do UTF-8 to string conversion with the label strings */
+        QString strLabel = QString().fromUtf8(service.strLabel.c_str());
+
+        /* Label for service selection button (service label, codec
+           and Mono / Stereo information) */
+        QString strCodec = GetCodecString(service);
+        QString strType = GetTypeString(service);
+        text = strLabel;
+        if (!strCodec.isEmpty() || !strType.isEmpty())
+            text += "  |   " + strCodec + " " + strType;
+
+        /* Bit-rate (only show if greater than 0) */
+        if (service.AudioParam.rBitRate > (_REAL) 0.0)
+        {
+            text += " (" + QString().setNum(service.AudioParam.rBitRate, 'f', 2) + " kbps)";
+        }
+
+        /* Audio service */
+        if ((service.eAudDataFlag == CService::SF_AUDIO))
+        {
+            /* Report missing codec */
+            if (!service.AudioParam.bCanDecode)
+                text += tr(" [no codec available]");
+
+            /* Show, if a multimedia stream is connected to this service */
+            if (service.DataParam.iStreamID != STREAM_ID_NOT_USED)
+            {
+                if (service.DataParam.iUserAppIdent == DAB_AT_EPG)
+                    text += tr(" + EPG"); /* EPG service */
+                else
+                {
+                    text += tr(" + MM"); /* other multimedia service */
+                }
+
+                /* Bit-rate of connected data stream */
+                text += " (" + QString().setNum(service.DataParam.rBitRate, 'f', 2) + " kbps)";
+            }
+        }
+        /* Data service */
+        else
+        {
+            if (service.DataParam.ePacketModInd == CDataParam::PM_PACKET_MODE)
+            {
+                if (service.DataParam.eAppDomain == CDataParam::AD_DAB_SPEC_APP)
+                {
+                    switch (service.DataParam.iUserAppIdent)
+                    {
+                    case DAB_AT_BROADCASTWEBSITE:
+                    case DAB_AT_JOURNALINE:
+                    case DAB_AT_MOTSLIDESHOW:
+                        break;
+                    }
+                }
+            }
+        }
+    }
+    serviceLabels[short_id]->setText(text);
+    pButtonGroup->button(short_id)->setEnabled(text != "");
+}
+
+void ServiceSelector::check(int i)
+{
+    pButtonGroup->button(i)->setChecked(true);
+}
+
+void ServiceSelector::disableAll()
+{
+    pButtonGroup->setExclusive(false);
+    for(size_t i=0; i<serviceLabels.size(); i++)
+    {
+        QPushButton* button = (QPushButton*)pButtonGroup->button(i);
+        if (button && button->isEnabled()) button->setEnabled(false);
+        if (button && button->isChecked()) button->setChecked(false);
+        serviceLabels[i]->setText("");
+    }
+    pButtonGroup->setExclusive(true);
+}
diff --git a/src/GUI-QT/serviceselector.h b/src/GUI-QT/serviceselector.h
new file mode 100644
index 0000000..f007dde
--- /dev/null
+++ b/src/GUI-QT/serviceselector.h
@@ -0,0 +1,35 @@
+#ifndef SERVICESELECTOR_H
+#define SERVICESELECTOR_H
+
+#include <QWidget>
+#include <QButtonGroup>
+#include <QLabel>
+#include <vector>
+
+namespace Ui {
+class ServiceSelector;
+}
+
+class CService;
+
+class ServiceSelector : public QWidget
+{
+    Q_OBJECT
+
+public:
+    explicit ServiceSelector(QWidget *parent = 0);
+    ~ServiceSelector();
+    void check(int i);
+    void disableAll();
+public slots:
+    void onServiceChanged(int, const CService&);
+private:
+    Ui::ServiceSelector* ui;
+    QButtonGroup*		 pButtonGroup;
+    std::vector<QLabel*> serviceLabels;
+signals:
+    void audioServiceSelected(int);
+    void dataServiceSelected(int);
+};
+
+#endif // SERVICESELECTOR_H
diff --git a/src/GUI-QT/serviceselector.ui b/src/GUI-QT/serviceselector.ui
new file mode 100644
index 0000000..d27c565
--- /dev/null
+++ b/src/GUI-QT/serviceselector.ui
@@ -0,0 +1,351 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>ServiceSelector</class>
+ <widget class="QWidget" name="ServiceSelector">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>401</width>
+    <height>148</height>
+   </rect>
+  </property>
+  <property name="sizePolicy">
+   <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+    <horstretch>0</horstretch>
+    <verstretch>0</verstretch>
+   </sizepolicy>
+  </property>
+  <property name="windowTitle">
+   <string>Form</string>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <property name="leftMargin">
+    <number>0</number>
+   </property>
+   <property name="topMargin">
+    <number>0</number>
+   </property>
+   <property name="rightMargin">
+    <number>0</number>
+   </property>
+   <property name="bottomMargin">
+    <number>0</number>
+   </property>
+   <item>
+    <layout class="QHBoxLayout" name="_2">
+     <property name="spacing">
+      <number>6</number>
+     </property>
+     <property name="leftMargin">
+      <number>0</number>
+     </property>
+     <property name="topMargin">
+      <number>0</number>
+     </property>
+     <property name="rightMargin">
+      <number>0</number>
+     </property>
+     <property name="bottomMargin">
+      <number>0</number>
+     </property>
+     <item>
+      <widget class="QPushButton" name="PushButtonService1">
+       <property name="enabled">
+        <bool>false</bool>
+       </property>
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="minimumSize">
+        <size>
+         <width>45</width>
+         <height>26</height>
+        </size>
+       </property>
+       <property name="maximumSize">
+        <size>
+         <width>45</width>
+         <height>32767</height>
+        </size>
+       </property>
+       <property name="text">
+        <string comment="Selects the first service">1</string>
+       </property>
+       <property name="checkable">
+        <bool>true</bool>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QLabel" name="TextMiniService1">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Expanding" vsizetype="Minimum">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="acceptDrops">
+        <bool>false</bool>
+       </property>
+       <property name="frameShape">
+        <enum>QFrame::Panel</enum>
+       </property>
+       <property name="frameShadow">
+        <enum>QFrame::Sunken</enum>
+       </property>
+       <property name="text">
+        <string/>
+       </property>
+       <property name="textFormat">
+        <enum>Qt::PlainText</enum>
+       </property>
+       <property name="wordWrap">
+        <bool>true</bool>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
+   <item>
+    <layout class="QHBoxLayout" name="_3">
+     <property name="spacing">
+      <number>6</number>
+     </property>
+     <property name="leftMargin">
+      <number>0</number>
+     </property>
+     <property name="topMargin">
+      <number>0</number>
+     </property>
+     <property name="rightMargin">
+      <number>0</number>
+     </property>
+     <property name="bottomMargin">
+      <number>0</number>
+     </property>
+     <item>
+      <widget class="QPushButton" name="PushButtonService2">
+       <property name="enabled">
+        <bool>false</bool>
+       </property>
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="minimumSize">
+        <size>
+         <width>45</width>
+         <height>26</height>
+        </size>
+       </property>
+       <property name="maximumSize">
+        <size>
+         <width>45</width>
+         <height>32767</height>
+        </size>
+       </property>
+       <property name="text">
+        <string comment="Selects the second service">2</string>
+       </property>
+       <property name="checkable">
+        <bool>true</bool>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QLabel" name="TextMiniService2">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Expanding" vsizetype="Minimum">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="acceptDrops">
+        <bool>false</bool>
+       </property>
+       <property name="frameShape">
+        <enum>QFrame::Panel</enum>
+       </property>
+       <property name="frameShadow">
+        <enum>QFrame::Sunken</enum>
+       </property>
+       <property name="text">
+        <string/>
+       </property>
+       <property name="textFormat">
+        <enum>Qt::PlainText</enum>
+       </property>
+       <property name="wordWrap">
+        <bool>true</bool>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
+   <item>
+    <layout class="QHBoxLayout" name="_4">
+     <property name="spacing">
+      <number>6</number>
+     </property>
+     <property name="leftMargin">
+      <number>0</number>
+     </property>
+     <property name="topMargin">
+      <number>0</number>
+     </property>
+     <property name="rightMargin">
+      <number>0</number>
+     </property>
+     <property name="bottomMargin">
+      <number>0</number>
+     </property>
+     <item>
+      <widget class="QPushButton" name="PushButtonService3">
+       <property name="enabled">
+        <bool>false</bool>
+       </property>
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="minimumSize">
+        <size>
+         <width>45</width>
+         <height>26</height>
+        </size>
+       </property>
+       <property name="maximumSize">
+        <size>
+         <width>45</width>
+         <height>32767</height>
+        </size>
+       </property>
+       <property name="text">
+        <string comment="Selects the third service">3</string>
+       </property>
+       <property name="checkable">
+        <bool>true</bool>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QLabel" name="TextMiniService3">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Expanding" vsizetype="Minimum">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="acceptDrops">
+        <bool>false</bool>
+       </property>
+       <property name="frameShape">
+        <enum>QFrame::Panel</enum>
+       </property>
+       <property name="frameShadow">
+        <enum>QFrame::Sunken</enum>
+       </property>
+       <property name="text">
+        <string/>
+       </property>
+       <property name="textFormat">
+        <enum>Qt::PlainText</enum>
+       </property>
+       <property name="wordWrap">
+        <bool>true</bool>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
+   <item>
+    <layout class="QHBoxLayout" name="_5">
+     <property name="spacing">
+      <number>6</number>
+     </property>
+     <property name="leftMargin">
+      <number>0</number>
+     </property>
+     <property name="topMargin">
+      <number>0</number>
+     </property>
+     <property name="rightMargin">
+      <number>0</number>
+     </property>
+     <property name="bottomMargin">
+      <number>0</number>
+     </property>
+     <item>
+      <widget class="QPushButton" name="PushButtonService4">
+       <property name="enabled">
+        <bool>false</bool>
+       </property>
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="minimumSize">
+        <size>
+         <width>45</width>
+         <height>26</height>
+        </size>
+       </property>
+       <property name="maximumSize">
+        <size>
+         <width>45</width>
+         <height>32767</height>
+        </size>
+       </property>
+       <property name="text">
+        <string comment="Selects the fourth service">4</string>
+       </property>
+       <property name="checkable">
+        <bool>true</bool>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QLabel" name="TextMiniService4">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Expanding" vsizetype="Minimum">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="acceptDrops">
+        <bool>false</bool>
+       </property>
+       <property name="frameShape">
+        <enum>QFrame::Panel</enum>
+       </property>
+       <property name="frameShadow">
+        <enum>QFrame::Sunken</enum>
+       </property>
+       <property name="text">
+        <string/>
+       </property>
+       <property name="textFormat">
+        <enum>Qt::PlainText</enum>
+       </property>
+       <property name="wordWrap">
+        <bool>true</bool>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/GUI-QT/slideshowwidget.cpp b/src/GUI-QT/slideshowwidget.cpp
new file mode 100644
index 0000000..dad21e0
--- /dev/null
+++ b/src/GUI-QT/slideshowwidget.cpp
@@ -0,0 +1,261 @@
+/******************************************************************************\
+ * British Broadcasting Corporation
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	 Julian Cable, David Flamand
+ *
+ * Description: SlideShow Viewer
+ *
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "slideshowwidget.h"
+#include "ui_slideshowwidget.h"
+#include "../util-QT/Util.h"
+#include <../datadecoding/DataDecoder.h>
+#include "../datadecoding/DABMOT.h"
+#include <QFileDialog>
+
+SlideShowWidget::SlideShowWidget(QWidget *parent) :
+    QWidget(parent),
+    ui(new Ui::SlideShowWidget),
+    pics(), iCurImagePos(-1),
+    bClearMOTCache(false),
+    motdec(NULL)
+{
+    ui->setupUi(this);
+    ui->LEDStatus->SetUpdateTime(1000);
+}
+
+SlideShowWidget::~SlideShowWidget()
+{
+    delete ui;
+}
+
+void SlideShowWidget::setSavePath(const QString& s)
+{
+    strCurrentSavePath = s;
+}
+
+void SlideShowWidget::setServiceInformation(int s, CService service)
+{
+    short_id = s;
+    if(service.DataParam.pDecoder)
+        motdec = service.DataParam.pDecoder->getApplication(service.DataParam.iPacketID);
+    QString strLabel = QString().fromUtf8(service.strLabel.c_str()).trimmed();
+    QString strTitle("MOT Slide Show");
+    QString strServiceID;
+
+    if (service.iServiceID != 0)
+    {
+        if (strLabel != "")
+            strLabel += " - ";
+
+        /* Service ID (plot number in hexadecimal format) */
+        strServiceID = "ID:" +
+                       QString().setNum(service.iServiceID, 16).toUpper();
+    }
+
+    /* Add the description on the title of the dialog */
+    if (strLabel != "" || strServiceID != "")
+        strTitle += " [" + strLabel + strServiceID + "]";
+    setWindowTitle(strTitle);
+}
+
+void SlideShowWidget::setStatus(int i, ETypeRxStatus eStatus)
+{
+    if(short_id == i)
+        SetStatus(ui->LEDStatus, eStatus);
+
+    if (motdec == NULL)
+    {
+        return;
+    }
+    if (bClearMOTCache)
+    {
+        bClearMOTCache = false;
+        /* Remove all object from cache */
+        while (motdec->NewObjectAvailable())
+        {
+            CMOTObject	NewObj;
+            motdec->GetNextObject(NewObj);
+        }
+    }
+    else
+    {
+        /* Poll the data decoder module for one new picture */
+        if(motdec->NewObjectAvailable())
+        {
+            CMOTObject	NewObj;
+            motdec->GetNextObject(NewObj);
+
+            /* Store received picture */
+            int iCurNumPict = pics.size();
+            CVector<_BYTE>& imagedata = NewObj.Body.vecData;
+
+            /* Load picture in QT format */
+            QPixmap pic;
+            if (pic.loadFromData(&imagedata[0], imagedata.size()))
+            {
+                /* Set new picture in source factory */
+                Img p;
+                p.pic = pic;
+                p.name = QString::fromUtf8(NewObj.strName.c_str());
+                pics.push_back(p);
+            }
+
+            /* If the last received picture was selected, automatically show
+               new picture */
+            if (iCurImagePos == iCurNumPict - 1)
+                SetImage(iCurNumPict);
+            else
+                UpdateButtons();
+        }
+    }
+}
+
+void SlideShowWidget::on_ButtonStepBack_clicked()
+{
+    SetImage(iCurImagePos-1);
+}
+
+void SlideShowWidget::on_ButtonStepForward_clicked()
+{
+    SetImage(iCurImagePos+1);
+}
+
+void SlideShowWidget::on_ButtonJumpBegin_clicked()
+{
+    SetImage(0);
+}
+
+void SlideShowWidget::on_ButtonJumpEnd_clicked()
+{
+    SetImage(pics.size()-1);
+}
+
+void SlideShowWidget::OnSave()
+{
+    /* Create directory for storing the file (if not exists) */
+    CreateDirectories(strCurrentSavePath);
+
+    QString strFilename = strCurrentSavePath + VerifyFilename(pics[iCurImagePos].name);
+    strFilename = QFileDialog::getSaveFileName(this,
+        tr("Save File"), strFilename, tr("Images (*.png *.jpg)"));
+
+    /* Check if user not hit the cancel button */
+    if (!strFilename.isEmpty())
+    {
+        pics[iCurImagePos].pic.save(strFilename);
+
+        strCurrentSavePath = QFileInfo(strFilename).path() + PATH_SEPARATOR;
+    }
+}
+
+void SlideShowWidget::OnSaveAll()
+{
+    /* Create directory for storing the files (if not exists) */
+    CreateDirectories(strCurrentSavePath);
+
+    QString strDirectory = QFileDialog::getExistingDirectory(this,
+        tr("Open Directory"), strCurrentSavePath);
+
+    /* Check if user not hit the cancel button */
+    if (!strDirectory.isEmpty())
+    {
+        strCurrentSavePath = strDirectory + PATH_SEPARATOR;
+
+        for(size_t i=0; i<pics.size(); i++)
+            pics[i].pic.save(strCurrentSavePath + VerifyFilename(pics[i].name));
+    }
+}
+
+void SlideShowWidget::OnClearAll()
+{
+    pics.clear();
+    iCurImagePos = -1;
+    UpdateButtons();
+    ui->LabelTitle->setText("");
+    bClearMOTCache = true;
+}
+
+void SlideShowWidget::SetImage(int pos)
+{
+    if(pics.size()==0)
+        return;
+    if(pos<0)
+        pos = 0;
+    if(pos>int(pics.size()-1))
+        pos = pics.size()-1;
+    iCurImagePos = pos;
+    ui->Image->setPixmap(pics[pos].pic);
+    QString imagename = pics[pos].name;
+    ui->Image->setToolTip(imagename);
+    imagename =  "<b>" + imagename + "</b>";
+    Linkify(imagename);
+    ui->LabelTitle->setText(imagename);
+    UpdateButtons();
+}
+
+void SlideShowWidget::UpdateButtons()
+{
+
+    if (iCurImagePos <= 0)
+    {
+        /* We are already at the beginning */
+        ui->ButtonStepBack->setEnabled(false);
+        ui->ButtonJumpBegin->setEnabled(false);
+    }
+    else
+    {
+        ui->ButtonStepBack->setEnabled(true);
+        ui->ButtonJumpBegin->setEnabled(true);
+    }
+
+    if (iCurImagePos == int(pics.size()-1))
+    {
+        /* We are already at the end */
+        ui->ButtonStepForward->setEnabled(false);
+        ui->ButtonJumpEnd->setEnabled(false);
+    }
+    else
+    {
+        ui->ButtonStepForward->setEnabled(true);
+        ui->ButtonJumpEnd->setEnabled(true);
+    }
+
+    QString strTotImages = QString().setNum(pics.size());
+    QString strNumImage = QString().setNum(iCurImagePos + 1);
+
+    QString strSep("");
+
+    for (int i = 0; i < (strTotImages.length() - strNumImage.length()); i++)
+        strSep += " ";
+
+    ui->LabelCurPicNum->setText(strSep + strNumImage + PATH_SEPARATOR + strTotImages);
+
+    /* If no picture was received, show the following text */
+    if (iCurImagePos < 0)
+    {
+        /* Init text browser window */
+        ui->Image->setText("<center>" + tr("MOT Slideshow Viewer") + "</center>");
+        ui->Image->setToolTip("");
+    }
+}
diff --git a/src/GUI-QT/slideshowwidget.h b/src/GUI-QT/slideshowwidget.h
new file mode 100644
index 0000000..1dd8ded
--- /dev/null
+++ b/src/GUI-QT/slideshowwidget.h
@@ -0,0 +1,53 @@
+#ifndef SLIDESHOWWIDGET_H
+#define SLIDESHOWWIDGET_H
+
+#include <../Parameter.h>
+#include <QWidget>
+
+namespace Ui {
+class SlideShowWidget;
+}
+
+class CMOTDABDec;
+
+class SlideShowWidget : public QWidget
+{
+    Q_OBJECT
+
+public:
+    explicit SlideShowWidget(QWidget *parent = 0);
+    ~SlideShowWidget();
+public slots:
+    void setSavePath(const QString&);
+    void setStatus(int, ETypeRxStatus);
+    void setServiceInformation(int, CService);
+
+private:
+
+    struct Img {
+        QPixmap pic;
+        QString name;
+    };
+
+    Ui::SlideShowWidget *ui;
+    QString                 strCurrentSavePath;
+    vector<Img>             pics;
+    int                     iCurImagePos;
+    bool                    bClearMOTCache;
+    CMOTDABDec*             motdec;
+    int                     short_id;
+
+    void                    SetImage(int);
+    void                    UpdateButtons();
+
+private slots:
+    void on_ButtonStepBack_clicked();
+    void on_ButtonStepForward_clicked();
+    void on_ButtonJumpBegin_clicked();
+    void on_ButtonJumpEnd_clicked();
+    void OnSave();
+    void OnSaveAll();
+    void OnClearAll();
+};
+
+#endif // SLIDESHOWWIDGET_H
diff --git a/src/GUI-QT/slideshowwidget.ui b/src/GUI-QT/slideshowwidget.ui
new file mode 100644
index 0000000..3a19d9b
--- /dev/null
+++ b/src/GUI-QT/slideshowwidget.ui
@@ -0,0 +1,312 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>SlideShowWidget</class>
+ <widget class="QWidget" name="SlideShowWidget">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>340</width>
+    <height>314</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Form</string>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <item>
+    <widget class="QLabel" name="LabelTitle">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
+     </property>
+     <property name="lineWidth">
+      <number>0</number>
+     </property>
+     <property name="text">
+      <string><b>Title</b></string>
+     </property>
+     <property name="textFormat">
+      <enum>Qt::RichText</enum>
+     </property>
+     <property name="alignment">
+      <set>Qt::AlignCenter</set>
+     </property>
+     <property name="wordWrap">
+      <bool>true</bool>
+     </property>
+     <property name="openExternalLinks">
+      <bool>true</bool>
+     </property>
+     <property name="textInteractionFlags">
+      <set>Qt::LinksAccessibleByMouse</set>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QFrame" name="frame">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
+     </property>
+     <property name="frameShape">
+      <enum>QFrame::StyledPanel</enum>
+     </property>
+     <property name="frameShadow">
+      <enum>QFrame::Sunken</enum>
+     </property>
+     <layout class="QVBoxLayout" name="verticalLayout_2">
+      <property name="spacing">
+       <number>0</number>
+      </property>
+      <property name="leftMargin">
+       <number>0</number>
+      </property>
+      <property name="topMargin">
+       <number>0</number>
+      </property>
+      <property name="rightMargin">
+       <number>0</number>
+      </property>
+      <property name="bottomMargin">
+       <number>0</number>
+      </property>
+      <item>
+       <widget class="QLabel" name="Image">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Ignored" vsizetype="Ignored">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="minimumSize">
+         <size>
+          <width>320</width>
+          <height>240</height>
+         </size>
+        </property>
+        <property name="baseSize">
+         <size>
+          <width>320</width>
+          <height>240</height>
+         </size>
+        </property>
+        <property name="autoFillBackground">
+         <bool>false</bool>
+        </property>
+        <property name="styleSheet">
+         <string notr="true">background: white</string>
+        </property>
+        <property name="frameShadow">
+         <enum>QFrame::Plain</enum>
+        </property>
+        <property name="lineWidth">
+         <number>0</number>
+        </property>
+        <property name="text">
+         <string>MOT Slideshow Viewer</string>
+        </property>
+        <property name="textFormat">
+         <enum>Qt::RichText</enum>
+        </property>
+        <property name="alignment">
+         <set>Qt::AlignCenter</set>
+        </property>
+        <property name="textInteractionFlags">
+         <set>Qt::NoTextInteraction</set>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item>
+    <layout class="QHBoxLayout" name="horizontalLayout">
+     <item>
+      <widget class="QLabel" name="TextLabel1">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="text">
+        <string>Receiving Status:</string>
+       </property>
+       <property name="wordWrap">
+        <bool>false</bool>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="CMultColorLED" name="LEDStatus" native="true">
+       <property name="minimumSize">
+        <size>
+         <width>13</width>
+         <height>13</height>
+        </size>
+       </property>
+       <property name="maximumSize">
+        <size>
+         <width>13</width>
+         <height>13</height>
+        </size>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QToolButton" name="ButtonJumpBegin">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="text">
+        <string/>
+       </property>
+       <property name="icon">
+        <iconset resource="res/icons.qrc">
+         <normaloff>:/icons/JumpBegin.png</normaloff>:/icons/JumpBegin.png</iconset>
+       </property>
+       <property name="iconSize">
+        <size>
+         <width>16</width>
+         <height>16</height>
+        </size>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QToolButton" name="ButtonStepBack">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="text">
+        <string/>
+       </property>
+       <property name="icon">
+        <iconset resource="res/icons.qrc">
+         <normaloff>:/icons/StepBack.png</normaloff>:/icons/StepBack.png</iconset>
+       </property>
+       <property name="iconSize">
+        <size>
+         <width>16</width>
+         <height>16</height>
+        </size>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QLabel" name="LabelCurPicNum">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="font">
+        <font>
+         <family>Arial Black</family>
+         <pointsize>14</pointsize>
+        </font>
+       </property>
+       <property name="frameShadow">
+        <enum>QFrame::Sunken</enum>
+       </property>
+       <property name="text">
+        <string>0/0</string>
+       </property>
+       <property name="alignment">
+        <set>Qt::AlignCenter</set>
+       </property>
+       <property name="wordWrap">
+        <bool>false</bool>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QToolButton" name="ButtonStepForward">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="text">
+        <string/>
+       </property>
+       <property name="icon">
+        <iconset resource="res/icons.qrc">
+         <normaloff>:/icons/StepForw.png</normaloff>:/icons/StepForw.png</iconset>
+       </property>
+       <property name="iconSize">
+        <size>
+         <width>16</width>
+         <height>16</height>
+        </size>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QToolButton" name="ButtonJumpEnd">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="text">
+        <string/>
+       </property>
+       <property name="icon">
+        <iconset resource="res/icons.qrc">
+         <normaloff>:/icons/JumpEnd.png</normaloff>:/icons/JumpEnd.png</iconset>
+       </property>
+       <property name="iconSize">
+        <size>
+         <width>16</width>
+         <height>16</height>
+        </size>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <spacer name="Spacer5_2">
+       <property name="orientation">
+        <enum>Qt::Horizontal</enum>
+       </property>
+       <property name="sizeType">
+        <enum>QSizePolicy::Expanding</enum>
+       </property>
+       <property name="sizeHint" stdset="0">
+        <size>
+         <width>40</width>
+         <height>20</height>
+        </size>
+       </property>
+      </spacer>
+     </item>
+    </layout>
+   </item>
+  </layout>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>CMultColorLED</class>
+   <extends>QWidget</extends>
+   <header>MultColorLED.h</header>
+  </customwidget>
+ </customwidgets>
+ <resources>
+  <include location="res/icons.qrc"/>
+ </resources>
+ <connections/>
+</ui>
diff --git a/src/GUI-QT/stationswidget.cpp b/src/GUI-QT/stationswidget.cpp
new file mode 100644
index 0000000..025655c
--- /dev/null
+++ b/src/GUI-QT/stationswidget.cpp
@@ -0,0 +1,350 @@
+#include "stationswidget.h"
+#include <ui_stationswidget.h>
+#include "../util/Settings.h"
+#include "../util-QT/Util.h" /* TODO for ColumnParamToStr and ColumnParamFromStr */
+#include "receivercontroller.h"
+#include <QNetworkAccessManager>
+#include <QNetworkRequest>
+#include <QNetworkReply>
+#include <QDateTime>
+#include <QMessageBox>
+#include <QFileInfo>
+#include <cmath>
+
+
+StationsWidget::StationsWidget(ReceiverController* rc, QWidget *parent) :
+    QWidget(parent),
+    ui(new Ui::StationsWidget),
+    schedule(),scheduleLoader(),
+    greenCube(), redCube(":/icons/redCube.png"),
+    orangeCube(":/icons/orangeCube.png"), pinkCube(":/icons/pinkCube.png")
+{
+    ui->setupUi(this);
+    for(int i=0; i<ui->comboBoxFilterTime->count(); i++)
+    {
+        QString l = ui->comboBoxFilterTime->itemText(i);
+        if(l == tr("Any"))
+            ui->comboBoxFilterTime->setItemData(i, -1);
+        if(l == tr("Active"))
+            ui->comboBoxFilterTime->setItemData(i, 0);
+        if(l.contains("(5"))
+            ui->comboBoxFilterTime->setItemData(i, NUM_SECONDS_PREV_5MIN);
+        if(l.contains("(15"))
+            ui->comboBoxFilterTime->setItemData(i, NUM_SECONDS_PREV_15MIN);
+        if(l.contains("(30"))
+            ui->comboBoxFilterTime->setItemData(i, NUM_SECONDS_PREV_30MIN);
+    }
+
+    QStringList headers;
+    headers
+        << QString() /* icon, enable sorting by online/offline */
+        << tr("Station Name")
+        << tr("Time [UTC]")
+        << tr("Frequency [kHz]")
+        << tr("Power [kW]")
+        << tr("Target")
+        << tr("Country")
+        << tr("Site")
+        << tr("Language")
+        << tr("Days");
+
+    ui->stations->setHeaderLabels(headers);
+    ui->stations->headerItem()->setTextAlignment(2, Qt::AlignRight | Qt::AlignVCenter);
+    ui->stations->headerItem()->setTextAlignment(3, Qt::AlignRight | Qt::AlignVCenter);
+    ui->stations->headerItem()->setTextAlignment(4, Qt::AlignRight | Qt::AlignVCenter);
+
+    connect(this, SIGNAL(frequencyChanged(int)), rc, SLOT(setFrequency(int)));
+    //connect(rc, SIGNAL(mode(int)), this, SLOT(OnSwitchMode(int)));
+    connect(rc, SIGNAL(frequencyChanged(int)), this, SLOT(SetFrequency(int)));
+
+    QTreeWidgetItem* drm = new QTreeWidgetItem(QStringList("DRM"));
+    QTreeWidgetItem* am = new QTreeWidgetItem(QStringList("AM"));
+    ui->stations->addTopLevelItem(drm);
+    ui->stations->addTopLevelItem(am);
+    QStringList x; x << "" << "-";
+    QTreeWidgetItem* drm_manual = new QTreeWidgetItem(x);
+    drm->addChild(drm_manual);
+    QTreeWidgetItem* am_manual = new QTreeWidgetItem(x);
+    am->addChild(am_manual);
+    drm_manual->setFlags(drm_manual->flags() | Qt::ItemIsEditable);
+    am_manual->setFlags(am_manual->flags() | Qt::ItemIsEditable);
+}
+
+StationsWidget::~StationsWidget()
+{
+    delete ui;
+}
+
+void StationsWidget::SetFrequency(int f)
+{
+//    ui->frequency->setValue(f);
+}
+
+void StationsWidget::on_comboBoxFilterTarget_activated(const QString& s)
+{
+    schedule.setTargetFilter(s);
+    updateTransmissionStatus();
+}
+
+void StationsWidget::on_comboBoxFilterCountry_activated(const QString& s)
+{
+    schedule.setCountryFilter(s);
+    updateTransmissionStatus();
+}
+
+void StationsWidget::on_comboBoxFilterLanguage_activated(const QString& s)
+{
+    schedule.setLanguageFilter(s);
+    updateTransmissionStatus();
+}
+
+void StationsWidget::on_comboBoxFilterTime_activated(int n)
+{
+    int secs = ui->comboBoxFilterTime->itemData(n).toInt();
+    schedule.SetSecondsPreview(secs);
+    updateTransmissionStatus();
+}
+
+void StationsWidget::loadSchedule()
+{
+    schedule.LoadSchedule(DRMSCHEDULE_INI_FILE_NAME);
+}
+
+void StationsWidget::OnTimer()
+{
+    /* Get current UTC time */
+    time_t ltime;
+    time(&ltime);
+
+    /* reload schedule on minute boundaries */
+    if (ltime % 60 == 0)
+        updateTransmissionStatus();
+}
+
+void StationsWidget::OnUpdate()
+{
+    if (!isVisible())
+        return;
+
+    if (schedule.GetNumberOfStations()==0)
+    {
+        if(QFile::exists(DRMSCHEDULE_INI_FILE_NAME))
+        {
+            loadSchedule();
+        }
+        else
+        {
+            QMessageBox::information(this, "Dream", tr("The schedule file "
+            " could not be found or contains no data.\n"
+            "No stations can be displayed.\n"
+            "Try to download this file by using the 'Update' menu."),
+            QMessageBox::Ok);
+        }
+    }
+    loadScheduleView();
+    updateTransmissionStatus();
+}
+
+void StationsWidget::loadSettings(const CSettings& settings)
+{
+    bool showAll = settings.Get("Stations", "showall", false);
+    int iPrevSecs = settings.Get("Stations", "preview", NUM_SECONDS_PREV_5MIN);
+    schedule.SetSecondsPreview(iPrevSecs);
+    if(showAll)
+        ui->comboBoxFilterTime->setCurrentIndex(0);
+    else
+        ui->comboBoxFilterTime->setCurrentIndex(ui->comboBoxFilterTime->findData(iPrevSecs));
+
+    ui->stations->sortItems(iSortColumn, sortOrder);
+
+    schedule.SetSecondsPreview(settings.Get("Stations","preview", NUM_SECONDS_PREV_5MIN));
+    iSortColumn = settings.Get("Stations","sortcolumn", 0);
+    sortOrder = Qt::SortOrder(settings.Get("Stations","sortascending", 0));
+    strColumnParam = settings.Get("Stations","columnparam", string()).c_str();
+
+    drm_url = settings.Get("Stations","DRM URL", string(DRM_SCHEDULE_URL)).c_str();
+    schedule.setTargetFilter(settings.Get("Stations","targetfilter", string()).c_str());
+    schedule.setLanguageFilter(settings.Get("Stations","languagefilter", string()).c_str());
+    schedule.setCountryFilter(settings.Get("Stations","countryfilter", string()).c_str());
+}
+
+void StationsWidget::saveSettings(CSettings& settings)
+{
+    settings.Put("Stations","targetfilter", schedule.getTargetFilter().toStdString());
+    settings.Put("Stations","countryfilter", schedule.getCountryFilter().toStdString());
+    settings.Put("Stations","languagefilter", schedule.getLanguageFilter().toStdString());
+
+    /* Store preview settings */
+    settings.Put("Stations","preview", schedule.GetSecondsPreview());
+
+    settings.Put("Stations","sortcolumn", iSortColumn);
+    settings.Get("Stations","sortascending", sortOrder==Qt::AscendingOrder);
+    settings.Put("Stations","columnparam", strColumnParam.toStdString());
+}
+
+void StationsWidget::loadScheduleView(QTreeWidgetItem* parent)
+{
+    if(parent==NULL)
+        ui->stations->clear();
+    for (int i = 0; i < schedule.GetNumberOfStations(); i++)
+    {
+        const CStationsItem& station = schedule.GetItem(i);
+
+        /* Get power of the station. We have to do a special treatment
+        * here, because we want to avoid having a "0" in the list when
+        * a "?" was in the schedule-ini-file */
+        const _REAL rPower = station.rPower;
+
+        QString strPower;
+        if (rPower == (_REAL) 0.0)
+            strPower = "?";
+        else
+            strPower.setNum(rPower);
+
+        QString strTimes = QString().sprintf("%04d-%04d", station.StartTime(), station.StopTime());
+
+        /* Generate new list station with all necessary column entries */
+        QTreeWidgetItem* item = new CaseInsensitiveTreeWidgetItem();
+        item->setText(1, station.strName);
+        item->setText(2, strTimes /* time */);
+        item->setText(3, QString().setNum(station.iFreq) /* freq. */);
+        item->setText(4, strPower            /* power */);
+        item->setText(5, station.strTarget   /* target */);
+        item->setText(6, station.strCountry  /* country */);
+        item->setText(7, station.strSite     /* site */);
+        item->setText(8, station.strLanguage /* language */);
+        item->setText(9, station.strDaysShow);
+        item->setData(1, Qt::UserRole, i);
+        item->setTextAlignment(2, Qt::AlignRight | Qt::AlignVCenter);
+        item->setTextAlignment(3, Qt::AlignRight | Qt::AlignVCenter);
+        item->setTextAlignment(4, Qt::AlignRight | Qt::AlignVCenter);
+        if(parent)
+            parent->addChild(item);
+        else
+            ui->stations->addTopLevelItem(item);
+    }
+    ui->comboBoxFilterTarget->clear();
+    ui->comboBoxFilterCountry->clear();
+    ui->comboBoxFilterLanguage->clear();
+    ui->comboBoxFilterTarget->addItems(schedule.ListTargets);
+    ui->comboBoxFilterCountry->addItems(schedule.ListCountries);
+    ui->comboBoxFilterLanguage->addItems(schedule.ListLanguages);
+
+    ui->comboBoxFilterTarget->setCurrentIndex(ui->comboBoxFilterTarget->findText(schedule.getTargetFilter()));
+    ui->comboBoxFilterCountry->setCurrentIndex(ui->comboBoxFilterCountry->findText(schedule.getCountryFilter()));
+    ui->comboBoxFilterLanguage->setCurrentIndex(ui->comboBoxFilterLanguage->findText(schedule.getLanguageFilter()));
+}
+
+void StationsWidget::updateTransmissionStatus()
+{
+    return; // until rewritten for heirarchy of items.
+    Timer.stop();
+    mutex.lock();
+    bool bShowAll = showAll();
+    ui->stations->setSortingEnabled(false);
+    for (int i = 0; i < ui->stations->topLevelItemCount(); i++)
+    {
+        QTreeWidgetItem* item = ui->stations->topLevelItem(i);
+        int scheduleItem = item->data(1, Qt::UserRole).toInt();
+
+        Station::EState iState = schedule.GetState(scheduleItem);
+
+        switch (iState)
+        {
+        case Station::IS_ACTIVE:
+            item->setData(0, Qt::UserRole, 1);
+            item->setIcon(0, greenCube);
+            break;
+        case Station::IS_PREVIEW:
+            item->setData(0, Qt::UserRole, 2);
+            item->setIcon(0, orangeCube);
+            break;
+        case Station::IS_SOON_INACTIVE:
+            item->setData(0, Qt::UserRole, 0);
+            item->setIcon(0, pinkCube);
+            break;
+        case Station::IS_INACTIVE:
+            item->setData(0, Qt::UserRole, 3);
+            item->setIcon(0, redCube);
+            break;
+        default:
+            item->setData(0, Qt::UserRole, 4);
+            item->setIcon(0, redCube);
+            break;
+        }
+        if(schedule.CheckFilter(scheduleItem) && (bShowAll || (iState != Station::IS_INACTIVE)))
+        {
+            item->setHidden(false);
+        }
+        else
+        {
+            item->setHidden(true);
+        }
+    }
+    ui->stations->setSortingEnabled(true);
+    ui->stations->sortItems(iSortColumn, sortOrder);
+    ui->stations->setFocus();
+    mutex.unlock();
+    Timer.start();
+}
+
+void StationsWidget::on_stations_itemSelectionChanged()
+{
+    QList<QTreeWidgetItem *> items =  ui->stations->selectedItems();
+
+    if(items.size()==1)
+    {
+        QTreeWidgetItem* w = items.first();
+        if(w->parent()==NULL)
+        {
+            QString col1 = w->text(0);
+            if(col1 == "DRM")
+            {
+                schedule.LoadSchedule(DRMSCHEDULE_INI_FILE_NAME);
+                loadScheduleView(w);
+                updateTransmissionStatus();
+            }
+            if(col1 == "AM")
+            {
+                schedule.LoadSchedule(AMSCHEDULE_CSV_FILE_NAME);
+                loadScheduleView(w);
+                updateTransmissionStatus();
+            }
+        }
+        else
+        {
+            int iFreq = QString(items.first()->text(3)).toInt();
+            emit frequencyChanged(iFreq);
+        }
+    }
+}
+
+void StationsWidget::AddWhatsThisHelp()
+{
+    /* Stations List */
+    QString strList =
+        tr("<b>Stations List:</b> In the stations list "
+        "view all DRM stations which are stored in the schedule.ini file "
+        "are shown. It is possible to show only active stations by changing a "
+        "setting in the 'view' menu. The color of the cube on the left of a "
+        "menu item shows the current status of the DRM transmission. A green "
+        "box shows that the transmission takes place right now, a "
+        //           "yellow cube shows that this is a test transmission and with a "
+        "red cube it is shown that the transmission is offline, "
+        "a pink cube shown that the transmission soon will be offline.<br>"
+        "If the stations preview is active an orange box shows the stations "
+        "that will be active.<br>"
+        "The list can be sorted by clicking on the headline of the "
+        "column.<br>By clicking on a menu item, a remote front-end can "
+        "be automatically switched to the current frequency and the "
+        "Dream software is reset to a new acquisition (to speed up the "
+        "synchronization process). Also, the log-file frequency edit "
+        "is automatically updated.");
+
+    ui->stations->setWhatsThis(strList);
+}
+
+bool StationsWidget::showAll()
+{
+    return ui->comboBoxFilterTime->currentIndex()==0;
+}
diff --git a/src/GUI-QT/stationswidget.h b/src/GUI-QT/stationswidget.h
new file mode 100644
index 0000000..ec5c509
--- /dev/null
+++ b/src/GUI-QT/stationswidget.h
@@ -0,0 +1,86 @@
+#ifndef STATIONSWIDGET_H
+#define STATIONSWIDGET_H
+
+#include <QWidget>
+#include <QTreeWidgetItem>
+#include <QMutex>
+#include <QTimer>
+#include "Schedule.h"
+#include "../Parameter.h"
+#include "../util-QT/scheduleloader.h"
+
+namespace Ui {
+class StationsWidget;
+}
+
+class CSettings;
+class ReceiverController;
+class QNetworkAccessManager;
+class QNetworkReply;
+
+/* Classes ********************************************************************/
+class CaseInsensitiveTreeWidgetItem : public QTreeWidgetItem
+{
+public:
+    CaseInsensitiveTreeWidgetItem(QTreeWidget* parent=0) : QTreeWidgetItem(parent)
+    {
+    }
+
+    bool operator< ( const QTreeWidgetItem & rhs) const
+    {
+        // bug 29 - sort frequency and power numerically
+        int col = treeWidget()->sortColumn();
+        if (col == 0) // online/offline
+            return data(0, Qt::UserRole).toInt() < rhs.data(0, Qt::UserRole).toInt();
+        else if (col == 3) // integer frequency
+            return text( col ).toInt() < rhs.text( col ).toInt();
+        else if (col == 4) // real power
+            return text( col ).toDouble() < rhs.text( col ).toDouble();
+        else
+            return text( col ).toLower() < rhs.text( col ).toLower();
+    }
+};
+
+class StationsWidget : public QWidget
+{
+    Q_OBJECT
+public:
+    explicit StationsWidget(ReceiverController*, QWidget *parent = 0);
+    ~StationsWidget();
+
+signals:
+    void frequencyChanged(int);
+    void modeChanged(int);
+
+public slots:
+    void SetFrequency(int);
+private:
+    Ui::StationsWidget* ui;
+    CSchedule   schedule;
+    ScheduleLoader scheduleLoader;
+    QIcon		greenCube,redCube,orangeCube,pinkCube;
+    QMutex      mutex;
+    QTimer      Timer;
+    Qt::SortOrder        sortOrder;
+    int			iSortColumn;
+    QString     strColumnParam, drm_url;
+
+    void        updateTransmissionStatus();
+    void        AddWhatsThisHelp();
+    bool        showAll();
+    void        loadSchedule();
+    void        loadScheduleView(QTreeWidgetItem *parent=0);
+    void        loadSettings(const CSettings &settings);
+    void        saveSettings(CSettings &settings);
+
+private slots:
+    void on_comboBoxFilterTarget_activated(const QString&);
+    void on_comboBoxFilterCountry_activated(const QString&);
+    void on_comboBoxFilterLanguage_activated(const QString&);
+    void on_comboBoxFilterTime_activated(int);
+    void OnTimer();
+    void OnUpdate();
+    void on_stations_itemSelectionChanged();
+};
+
+#endif // STATIONSWIDGET_H
diff --git a/src/GUI-QT/stationswidget.ui b/src/GUI-QT/stationswidget.ui
new file mode 100644
index 0000000..f892b29
--- /dev/null
+++ b/src/GUI-QT/stationswidget.ui
@@ -0,0 +1,141 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>StationsWidget</class>
+ <widget class="QWidget" name="StationsWidget">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>526</width>
+    <height>182</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Form</string>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <item>
+    <widget class="QTreeWidget" name="stations">
+     <property name="rootIsDecorated">
+      <bool>false</bool>
+     </property>
+     <property name="uniformRowHeights">
+      <bool>true</bool>
+     </property>
+     <column>
+      <property name="text">
+       <string/>
+      </property>
+     </column>
+    </widget>
+   </item>
+   <item>
+    <widget class="QGroupBox" name="groupBox">
+     <property name="title">
+      <string>Filters</string>
+     </property>
+     <layout class="QHBoxLayout" name="horizontalLayout">
+      <item>
+       <widget class="QLabel" name="label">
+        <property name="text">
+         <string>Time</string>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QComboBox" name="comboBoxFilterTime">
+        <item>
+         <property name="text">
+          <string>Any</string>
+         </property>
+        </item>
+        <item>
+         <property name="text">
+          <string>Active</string>
+         </property>
+        </item>
+        <item>
+         <property name="text">
+          <string>Coming (5min)</string>
+         </property>
+        </item>
+        <item>
+         <property name="text">
+          <string>Coming (15min)</string>
+         </property>
+        </item>
+        <item>
+         <property name="text">
+          <string>Coming (30min)</string>
+         </property>
+        </item>
+       </widget>
+      </item>
+      <item>
+       <widget class="QLabel" name="TextLabelTarget">
+        <property name="text">
+         <string>Target</string>
+        </property>
+        <property name="wordWrap">
+         <bool>false</bool>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QComboBox" name="comboBoxFilterTarget">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QLabel" name="TextLabelCountry">
+        <property name="text">
+         <string>Country</string>
+        </property>
+        <property name="wordWrap">
+         <bool>false</bool>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QComboBox" name="comboBoxFilterCountry">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QLabel" name="TextLabelLanguage">
+        <property name="text">
+         <string>Language</string>
+        </property>
+        <property name="wordWrap">
+         <bool>false</bool>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QComboBox" name="comboBoxFilterLanguage">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/GUI-QT/streamwidget.cpp b/src/GUI-QT/streamwidget.cpp
new file mode 100644
index 0000000..02c0732
--- /dev/null
+++ b/src/GUI-QT/streamwidget.cpp
@@ -0,0 +1,101 @@
+#include "streamwidget.h"
+#include "ui_streamwidget.h"
+#include <../Parameter.h>
+
+StreamWidget::StreamWidget(ReceiverController* rc, QWidget *parent) :
+    QWidget(parent),
+    ui(new Ui::StreamWidget),
+    stream(),
+     msc(NULL),
+     cc(),
+     service()
+{
+    ui->setupUi(this);
+    QStringList headers;
+    headers
+        << tr("Stream")
+        << tr("Type")
+        << tr("bit/s");
+    ui->treeWidget->setHeaderLabels(headers);
+    QStringList l;
+    l.clear(); l << "FAC" << tr("Fast Access Channel") << "160";
+    ui->treeWidget->addTopLevelItem(new QTreeWidgetItem(l));
+    l.clear(); l << "SDC" << tr("Service Description Channel") << "?";
+    ui->treeWidget->addTopLevelItem(new QTreeWidgetItem(l));
+    l.clear(); l << "MSC" << tr("Main Service Channel") << "?";
+    ui->treeWidget->addTopLevelItem(msc = new QTreeWidgetItem(l));
+    connect(rc, SIGNAL(serviceChanged(int,CService)), this, SLOT(setService(int, CService)));
+    connect(rc, SIGNAL(channelConfigurationChanged(ChannelConfiguration)), this, SLOT(setChannel(ChannelConfiguration)));
+    //CParameter* p = rc->getReceiver()->GetParameters();
+}
+
+StreamWidget::~StreamWidget()
+{
+    delete ui;
+}
+
+void StreamWidget::setService(int n, CService s)
+{
+    service[n] = s;
+    int sid = s.AudioParam.iStreamID;
+    if(sid!=STREAM_ID_NOT_USED)
+    {
+        stream[sid].audio=true;
+        QString id = QString("%1").arg(sid);
+        QList<QTreeWidgetItem*> w = ui->treeWidget->findItems(id, Qt::MatchFixedString|Qt::MatchRecursive);
+        if(w.count()==0)
+        {
+            QStringList l;
+            l << id;
+            if(s.AudioParam.bTextflag)
+                l << tr("audio+text");
+            else
+                l << tr("audio");
+            l << QString("%1").arg(1000.0*s.AudioParam.rBitRate);
+            msc->addChild(new QTreeWidgetItem(l));
+        }
+    }
+    sid = s.DataParam.iStreamID;
+    if(sid!=STREAM_ID_NOT_USED)
+    {
+        stream[sid].audio=false;
+        QString id = QString("%1").arg(sid);
+        QList<QTreeWidgetItem*> w = ui->treeWidget->findItems(id, Qt::MatchFixedString|Qt::MatchRecursive);
+        QTreeWidgetItem* str;
+        if(w.count()==0)
+        {
+            QStringList l;
+            l << id;
+            if(s.DataParam.ePacketModInd)
+            {
+                l << QString(tr("%1 byte packets")).arg(s.DataParam.iPacketLen);
+            }
+            else
+            {
+                l << tr("data stream");
+            }
+            l << "?";
+            msc->addChild(str=new QTreeWidgetItem(l));
+        }
+        else
+        {
+            str = w.first();
+        }
+        if(s.DataParam.ePacketModInd)
+        {
+            QString p = QString("%1/%2").arg(sid).arg(s.DataParam.iPacketID);
+            QList<QTreeWidgetItem*> wp = ui->treeWidget->findItems(p, Qt::MatchFixedString|Qt::MatchRecursive);
+            if(wp.count()==0)
+            {
+                QStringList l;
+                l << p << tr("packet mode app") << "?";
+                str->addChild(new QTreeWidgetItem(l));
+            }
+        }
+    }
+}
+
+void StreamWidget::setChannel(ChannelConfiguration c)
+{
+    cc = c;
+}
diff --git a/src/GUI-QT/streamwidget.h b/src/GUI-QT/streamwidget.h
new file mode 100644
index 0000000..ce52c9a
--- /dev/null
+++ b/src/GUI-QT/streamwidget.h
@@ -0,0 +1,41 @@
+#ifndef STREAMWIDGET_H
+#define STREAMWIDGET_H
+
+#include "receivercontroller.h"
+#include <../Parameter.h>
+#include <QWidget>
+
+namespace Ui {
+class StreamWidget;
+}
+
+class QTreeWidgetItem;
+
+class StreamWidget : public QWidget
+{
+    Q_OBJECT
+
+public:
+    explicit StreamWidget(ReceiverController*, QWidget *parent = 0);
+    ~StreamWidget();
+
+private:
+    struct Stream {
+        bool audio;
+        double bitrate;
+        int bits; // TODO - UEP
+
+    };
+
+    Ui::StreamWidget *ui;
+    Stream stream[4];
+    QTreeWidgetItem* msc;
+    ChannelConfiguration cc;
+    CService service[4];
+
+private slots:
+    void setService(int, CService);
+    void setChannel(ChannelConfiguration);
+};
+
+#endif // STREAMWIDGET_H
diff --git a/src/GUI-QT/streamwidget.ui b/src/GUI-QT/streamwidget.ui
new file mode 100644
index 0000000..18ace75
--- /dev/null
+++ b/src/GUI-QT/streamwidget.ui
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>StreamWidget</class>
+ <widget class="QWidget" name="StreamWidget">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>400</width>
+    <height>300</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Form</string>
+  </property>
+  <layout class="QHBoxLayout" name="horizontalLayout">
+   <item>
+    <widget class="QTreeWidget" name="treeWidget">
+     <column>
+      <property name="text">
+       <string notr="true">1</string>
+      </property>
+     </column>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/GUI-QT/systemevalDlgbase.ui b/src/GUI-QT/systemevalDlgbase.ui
new file mode 100644
index 0000000..a299a09
--- /dev/null
+++ b/src/GUI-QT/systemevalDlgbase.ui
@@ -0,0 +1,1739 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>SystemEvaluationWindow</class>
+ <widget class="QMainWindow" name="SystemEvaluationWindow">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>968</width>
+    <height>539</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>System Evaluation</string>
+  </property>
+  <property name="windowIcon">
+   <iconset resource="res/icons.qrc">
+    <normaloff>:/icons/MainIcon.svg</normaloff>:/icons/MainIcon.svg</iconset>
+  </property>
+  <widget class="QWidget" name="centralwidget">
+   <layout class="QVBoxLayout" name="verticalLayout">
+    <item>
+     <layout class="QHBoxLayout">
+      <property name="spacing">
+       <number>6</number>
+      </property>
+      <property name="margin">
+       <number>0</number>
+      </property>
+      <item>
+       <widget class="QFrame" name="FrameParamStatusLEDs">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="frameShape">
+         <enum>QFrame::Box</enum>
+        </property>
+        <property name="frameShadow">
+         <enum>QFrame::Sunken</enum>
+        </property>
+        <layout class="QHBoxLayout" name="_2">
+         <property name="spacing">
+          <number>6</number>
+         </property>
+         <property name="leftMargin">
+          <number>6</number>
+         </property>
+         <property name="topMargin">
+          <number>4</number>
+         </property>
+         <property name="rightMargin">
+          <number>6</number>
+         </property>
+         <property name="bottomMargin">
+          <number>4</number>
+         </property>
+         <item>
+          <layout class="QVBoxLayout" name="_3">
+           <property name="spacing">
+            <number>6</number>
+           </property>
+           <property name="margin">
+            <number>0</number>
+           </property>
+           <item>
+            <widget class="QLabel" name="TextSNRText">
+             <property name="sizePolicy">
+              <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+               <horstretch>0</horstretch>
+               <verstretch>0</verstretch>
+              </sizepolicy>
+             </property>
+             <property name="minimumSize">
+              <size>
+               <width>0</width>
+               <height>0</height>
+              </size>
+             </property>
+             <property name="text">
+              <string>SNR:</string>
+             </property>
+             <property name="wordWrap">
+              <bool>false</bool>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="QLabel" name="TextMERWMER">
+             <property name="sizePolicy">
+              <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+               <horstretch>0</horstretch>
+               <verstretch>0</verstretch>
+              </sizepolicy>
+             </property>
+             <property name="minimumSize">
+              <size>
+               <width>0</width>
+               <height>0</height>
+              </size>
+             </property>
+             <property name="text">
+              <string>MSC WMER / MSC MER:</string>
+             </property>
+             <property name="wordWrap">
+              <bool>false</bool>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="QLabel" name="TextFreqOffset">
+             <property name="sizePolicy">
+              <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+               <horstretch>0</horstretch>
+               <verstretch>0</verstretch>
+              </sizepolicy>
+             </property>
+             <property name="minimumSize">
+              <size>
+               <width>0</width>
+               <height>0</height>
+              </size>
+             </property>
+             <property name="text">
+              <string>DC Frequency of DRM Signal:</string>
+             </property>
+             <property name="wordWrap">
+              <bool>false</bool>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="QLabel" name="TextSampFreqOffset">
+             <property name="sizePolicy">
+              <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+               <horstretch>0</horstretch>
+               <verstretch>0</verstretch>
+              </sizepolicy>
+             </property>
+             <property name="text">
+              <string>Sample Frequency Offset:</string>
+             </property>
+             <property name="wordWrap">
+              <bool>false</bool>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="QLabel" name="TextWiener">
+             <property name="sizePolicy">
+              <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+               <horstretch>0</horstretch>
+               <verstretch>0</verstretch>
+              </sizepolicy>
+             </property>
+             <property name="minimumSize">
+              <size>
+               <width>0</width>
+               <height>0</height>
+              </size>
+             </property>
+             <property name="text">
+              <string>Doppler / Delay:</string>
+             </property>
+             <property name="wordWrap">
+              <bool>false</bool>
+             </property>
+            </widget>
+           </item>
+          </layout>
+         </item>
+         <item>
+          <layout class="QVBoxLayout" name="_4">
+           <property name="spacing">
+            <number>6</number>
+           </property>
+           <property name="margin">
+            <number>0</number>
+           </property>
+           <item>
+            <widget class="QLabel" name="ValueSNR">
+             <property name="sizePolicy">
+              <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+               <horstretch>0</horstretch>
+               <verstretch>0</verstretch>
+              </sizepolicy>
+             </property>
+             <property name="minimumSize">
+              <size>
+               <width>0</width>
+               <height>0</height>
+              </size>
+             </property>
+             <property name="text">
+              <string>SNR</string>
+             </property>
+             <property name="wordWrap">
+              <bool>false</bool>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="QLabel" name="ValueMERWMER">
+             <property name="sizePolicy">
+              <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+               <horstretch>0</horstretch>
+               <verstretch>0</verstretch>
+              </sizepolicy>
+             </property>
+             <property name="minimumSize">
+              <size>
+               <width>0</width>
+               <height>0</height>
+              </size>
+             </property>
+             <property name="text">
+              <string>MER</string>
+             </property>
+             <property name="wordWrap">
+              <bool>false</bool>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="QLabel" name="ValueFreqOffset">
+             <property name="sizePolicy">
+              <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+               <horstretch>0</horstretch>
+               <verstretch>0</verstretch>
+              </sizepolicy>
+             </property>
+             <property name="minimumSize">
+              <size>
+               <width>0</width>
+               <height>0</height>
+              </size>
+             </property>
+             <property name="text">
+              <string>FreqOffset</string>
+             </property>
+             <property name="wordWrap">
+              <bool>false</bool>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="QLabel" name="ValueSampFreqOffset">
+             <property name="sizePolicy">
+              <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+               <horstretch>0</horstretch>
+               <verstretch>0</verstretch>
+              </sizepolicy>
+             </property>
+             <property name="text">
+              <string>SampFreqOffset</string>
+             </property>
+             <property name="wordWrap">
+              <bool>false</bool>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="QLabel" name="ValueWiener">
+             <property name="sizePolicy">
+              <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+               <horstretch>0</horstretch>
+               <verstretch>0</verstretch>
+              </sizepolicy>
+             </property>
+             <property name="minimumSize">
+              <size>
+               <width>100</width>
+               <height>0</height>
+              </size>
+             </property>
+             <property name="text">
+              <string>Wiener</string>
+             </property>
+             <property name="wordWrap">
+              <bool>false</bool>
+             </property>
+            </widget>
+           </item>
+          </layout>
+         </item>
+        </layout>
+       </widget>
+      </item>
+      <item>
+       <widget class="QFrame" name="FrameParamStatusLEDs_2">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="frameShape">
+         <enum>QFrame::Box</enum>
+        </property>
+        <property name="frameShadow">
+         <enum>QFrame::Sunken</enum>
+        </property>
+        <layout class="QVBoxLayout" name="verticalLayout_3">
+         <property name="spacing">
+          <number>4</number>
+         </property>
+         <property name="margin">
+          <number>6</number>
+         </property>
+         <item>
+          <layout class="QHBoxLayout" name="_7">
+           <property name="spacing">
+            <number>6</number>
+           </property>
+           <property name="margin">
+            <number>0</number>
+           </property>
+           <item>
+            <widget class="QLabel" name="TextLabelLEDMSCCRC">
+             <property name="sizePolicy">
+              <sizepolicy hsizetype="Minimum" vsizetype="Maximum">
+               <horstretch>0</horstretch>
+               <verstretch>0</verstretch>
+              </sizepolicy>
+             </property>
+             <property name="text">
+              <string>MSC CRC:</string>
+             </property>
+             <property name="alignment">
+              <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+             </property>
+             <property name="wordWrap">
+              <bool>false</bool>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="CMultColorLED" name="LEDMSC" native="true">
+             <property name="sizePolicy">
+              <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+               <horstretch>0</horstretch>
+               <verstretch>0</verstretch>
+              </sizepolicy>
+             </property>
+             <property name="minimumSize">
+              <size>
+               <width>13</width>
+               <height>13</height>
+              </size>
+             </property>
+             <property name="maximumSize">
+              <size>
+               <width>13</width>
+               <height>13</height>
+              </size>
+             </property>
+            </widget>
+           </item>
+          </layout>
+         </item>
+         <item>
+          <layout class="QHBoxLayout" name="_8">
+           <property name="spacing">
+            <number>6</number>
+           </property>
+           <property name="margin">
+            <number>0</number>
+           </property>
+           <item>
+            <widget class="QLabel" name="TextLabelLEDSDCCRC">
+             <property name="sizePolicy">
+              <sizepolicy hsizetype="Minimum" vsizetype="Maximum">
+               <horstretch>0</horstretch>
+               <verstretch>0</verstretch>
+              </sizepolicy>
+             </property>
+             <property name="text">
+              <string>SDC CRC:</string>
+             </property>
+             <property name="alignment">
+              <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+             </property>
+             <property name="wordWrap">
+              <bool>false</bool>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="CMultColorLED" name="LEDSDC" native="true">
+             <property name="sizePolicy">
+              <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+               <horstretch>0</horstretch>
+               <verstretch>0</verstretch>
+              </sizepolicy>
+             </property>
+             <property name="minimumSize">
+              <size>
+               <width>13</width>
+               <height>13</height>
+              </size>
+             </property>
+             <property name="maximumSize">
+              <size>
+               <width>13</width>
+               <height>13</height>
+              </size>
+             </property>
+            </widget>
+           </item>
+          </layout>
+         </item>
+         <item>
+          <layout class="QHBoxLayout" name="_9">
+           <property name="spacing">
+            <number>6</number>
+           </property>
+           <property name="margin">
+            <number>0</number>
+           </property>
+           <item>
+            <widget class="QLabel" name="TextLabelLEDFACCRC">
+             <property name="sizePolicy">
+              <sizepolicy hsizetype="Minimum" vsizetype="Maximum">
+               <horstretch>0</horstretch>
+               <verstretch>0</verstretch>
+              </sizepolicy>
+             </property>
+             <property name="text">
+              <string>FAC CRC:</string>
+             </property>
+             <property name="alignment">
+              <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+             </property>
+             <property name="wordWrap">
+              <bool>false</bool>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="CMultColorLED" name="LEDFAC" native="true">
+             <property name="sizePolicy">
+              <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+               <horstretch>0</horstretch>
+               <verstretch>0</verstretch>
+              </sizepolicy>
+             </property>
+             <property name="minimumSize">
+              <size>
+               <width>13</width>
+               <height>13</height>
+              </size>
+             </property>
+             <property name="maximumSize">
+              <size>
+               <width>13</width>
+               <height>13</height>
+              </size>
+             </property>
+            </widget>
+           </item>
+          </layout>
+         </item>
+         <item>
+          <layout class="QHBoxLayout" name="_10">
+           <property name="spacing">
+            <number>6</number>
+           </property>
+           <property name="margin">
+            <number>0</number>
+           </property>
+           <item>
+            <widget class="QLabel" name="TextLabelLEDFrameSync">
+             <property name="sizePolicy">
+              <sizepolicy hsizetype="Minimum" vsizetype="Maximum">
+               <horstretch>0</horstretch>
+               <verstretch>0</verstretch>
+              </sizepolicy>
+             </property>
+             <property name="text">
+              <string>Frame Sync:</string>
+             </property>
+             <property name="alignment">
+              <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+             </property>
+             <property name="wordWrap">
+              <bool>false</bool>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="CMultColorLED" name="LEDFrameSync" native="true">
+             <property name="sizePolicy">
+              <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+               <horstretch>0</horstretch>
+               <verstretch>0</verstretch>
+              </sizepolicy>
+             </property>
+             <property name="minimumSize">
+              <size>
+               <width>13</width>
+               <height>13</height>
+              </size>
+             </property>
+             <property name="maximumSize">
+              <size>
+               <width>13</width>
+               <height>13</height>
+              </size>
+             </property>
+            </widget>
+           </item>
+          </layout>
+         </item>
+         <item>
+          <layout class="QHBoxLayout" name="_11">
+           <property name="spacing">
+            <number>6</number>
+           </property>
+           <property name="margin">
+            <number>0</number>
+           </property>
+           <item>
+            <widget class="QLabel" name="TextLabelLEDTimeSyncAcq">
+             <property name="sizePolicy">
+              <sizepolicy hsizetype="Minimum" vsizetype="Maximum">
+               <horstretch>0</horstretch>
+               <verstretch>0</verstretch>
+              </sizepolicy>
+             </property>
+             <property name="text">
+              <string>Time Sync Acq:</string>
+             </property>
+             <property name="alignment">
+              <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+             </property>
+             <property name="wordWrap">
+              <bool>false</bool>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="CMultColorLED" name="LEDTimeSync" native="true">
+             <property name="sizePolicy">
+              <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+               <horstretch>0</horstretch>
+               <verstretch>0</verstretch>
+              </sizepolicy>
+             </property>
+             <property name="minimumSize">
+              <size>
+               <width>13</width>
+               <height>13</height>
+              </size>
+             </property>
+             <property name="maximumSize">
+              <size>
+               <width>13</width>
+               <height>13</height>
+              </size>
+             </property>
+            </widget>
+           </item>
+          </layout>
+         </item>
+         <item>
+          <layout class="QHBoxLayout" name="_12">
+           <property name="spacing">
+            <number>6</number>
+           </property>
+           <property name="margin">
+            <number>0</number>
+           </property>
+           <item>
+            <widget class="QLabel" name="TextLabelLEDIOInterface">
+             <property name="sizePolicy">
+              <sizepolicy hsizetype="Minimum" vsizetype="Maximum">
+               <horstretch>0</horstretch>
+               <verstretch>0</verstretch>
+              </sizepolicy>
+             </property>
+             <property name="text">
+              <string>I/O Interface:</string>
+             </property>
+             <property name="alignment">
+              <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+             </property>
+             <property name="wordWrap">
+              <bool>false</bool>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="CMultColorLED" name="LEDIOInterface" native="true">
+             <property name="sizePolicy">
+              <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+               <horstretch>0</horstretch>
+               <verstretch>0</verstretch>
+              </sizepolicy>
+             </property>
+             <property name="minimumSize">
+              <size>
+               <width>13</width>
+               <height>13</height>
+              </size>
+             </property>
+             <property name="maximumSize">
+              <size>
+               <width>13</width>
+               <height>13</height>
+              </size>
+             </property>
+            </widget>
+           </item>
+          </layout>
+         </item>
+        </layout>
+       </widget>
+      </item>
+      <item>
+       <widget class="QFrame" name="FrameFACParams">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="frameShape">
+         <enum>QFrame::Box</enum>
+        </property>
+        <property name="frameShadow">
+         <enum>QFrame::Sunken</enum>
+        </property>
+        <layout class="QHBoxLayout" name="_13">
+         <property name="spacing">
+          <number>6</number>
+         </property>
+         <property name="leftMargin">
+          <number>6</number>
+         </property>
+         <property name="topMargin">
+          <number>4</number>
+         </property>
+         <property name="rightMargin">
+          <number>6</number>
+         </property>
+         <property name="bottomMargin">
+          <number>4</number>
+         </property>
+         <item>
+          <layout class="QVBoxLayout" name="_14">
+           <property name="spacing">
+            <number>0</number>
+           </property>
+           <property name="margin">
+            <number>0</number>
+           </property>
+           <item>
+            <widget class="QLabel" name="FACDRMModeBWL">
+             <property name="sizePolicy">
+              <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+               <horstretch>0</horstretch>
+               <verstretch>0</verstretch>
+              </sizepolicy>
+             </property>
+             <property name="text">
+              <string>DRM Mode / Bandwidth:</string>
+             </property>
+             <property name="wordWrap">
+              <bool>false</bool>
+             </property>
+             <property name="indent">
+              <number>-1</number>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="QLabel" name="FACInterleaverDepthL">
+             <property name="sizePolicy">
+              <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+               <horstretch>0</horstretch>
+               <verstretch>0</verstretch>
+              </sizepolicy>
+             </property>
+             <property name="text">
+              <string>Interleaver Depth:</string>
+             </property>
+             <property name="wordWrap">
+              <bool>false</bool>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="QLabel" name="FACSDCMSCModeL">
+             <property name="sizePolicy">
+              <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+               <horstretch>0</horstretch>
+               <verstretch>0</verstretch>
+              </sizepolicy>
+             </property>
+             <property name="text">
+              <string>SDC / MSC Mode:</string>
+             </property>
+             <property name="wordWrap">
+              <bool>false</bool>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="QLabel" name="FACCodeRateL">
+             <property name="sizePolicy">
+              <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+               <horstretch>0</horstretch>
+               <verstretch>0</verstretch>
+              </sizepolicy>
+             </property>
+             <property name="text">
+              <string>Prot. Level (B / A):</string>
+             </property>
+             <property name="wordWrap">
+              <bool>false</bool>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="QLabel" name="FACNumServicesL">
+             <property name="sizePolicy">
+              <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+               <horstretch>0</horstretch>
+               <verstretch>0</verstretch>
+              </sizepolicy>
+             </property>
+             <property name="text">
+              <string>Number of Services:</string>
+             </property>
+             <property name="wordWrap">
+              <bool>false</bool>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="QLabel" name="FACTimeDateL">
+             <property name="sizePolicy">
+              <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+               <horstretch>0</horstretch>
+               <verstretch>0</verstretch>
+              </sizepolicy>
+             </property>
+             <property name="text">
+              <string>Received time - date:</string>
+             </property>
+             <property name="wordWrap">
+              <bool>false</bool>
+             </property>
+            </widget>
+           </item>
+          </layout>
+         </item>
+         <item>
+          <layout class="QVBoxLayout" name="_15">
+           <property name="spacing">
+            <number>0</number>
+           </property>
+           <property name="margin">
+            <number>0</number>
+           </property>
+           <item>
+            <widget class="QLabel" name="FACDRMModeBWV">
+             <property name="sizePolicy">
+              <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+               <horstretch>0</horstretch>
+               <verstretch>0</verstretch>
+              </sizepolicy>
+             </property>
+             <property name="text">
+              <string>FACDRMModeBWV</string>
+             </property>
+             <property name="wordWrap">
+              <bool>false</bool>
+             </property>
+             <property name="indent">
+              <number>-1</number>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="QLabel" name="FACInterleaverDepthV">
+             <property name="sizePolicy">
+              <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+               <horstretch>0</horstretch>
+               <verstretch>0</verstretch>
+              </sizepolicy>
+             </property>
+             <property name="text">
+              <string>FACInterleaverDepthV</string>
+             </property>
+             <property name="wordWrap">
+              <bool>false</bool>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="QLabel" name="FACSDCMSCModeV">
+             <property name="sizePolicy">
+              <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+               <horstretch>0</horstretch>
+               <verstretch>0</verstretch>
+              </sizepolicy>
+             </property>
+             <property name="text">
+              <string>FACSDCMSCModeV</string>
+             </property>
+             <property name="wordWrap">
+              <bool>false</bool>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="QLabel" name="FACCodeRateV">
+             <property name="sizePolicy">
+              <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+               <horstretch>0</horstretch>
+               <verstretch>0</verstretch>
+              </sizepolicy>
+             </property>
+             <property name="text">
+              <string>FACCodeRateV</string>
+             </property>
+             <property name="wordWrap">
+              <bool>false</bool>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="QLabel" name="FACNumServicesV">
+             <property name="sizePolicy">
+              <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+               <horstretch>0</horstretch>
+               <verstretch>0</verstretch>
+              </sizepolicy>
+             </property>
+             <property name="text">
+              <string>FACNumServicesV</string>
+             </property>
+             <property name="wordWrap">
+              <bool>false</bool>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="QLabel" name="FACTimeDateV">
+             <property name="sizePolicy">
+              <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+               <horstretch>0</horstretch>
+               <verstretch>0</verstretch>
+              </sizepolicy>
+             </property>
+             <property name="minimumSize">
+              <size>
+               <width>200</width>
+               <height>0</height>
+              </size>
+             </property>
+             <property name="text">
+              <string>FACTimeDateV</string>
+             </property>
+             <property name="wordWrap">
+              <bool>false</bool>
+             </property>
+            </widget>
+           </item>
+          </layout>
+         </item>
+        </layout>
+       </widget>
+      </item>
+     </layout>
+    </item>
+    <item>
+     <layout class="QHBoxLayout" name="horizontalLayout">
+      <item>
+       <widget class="QTreeWidget" name="chartSelector">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Minimum" vsizetype="Expanding">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="iconSize">
+         <size>
+          <width>16</width>
+          <height>16</height>
+         </size>
+        </property>
+        <property name="verticalScrollMode">
+         <enum>QAbstractItemView::ScrollPerPixel</enum>
+        </property>
+        <property name="rootIsDecorated">
+         <bool>true</bool>
+        </property>
+        <column>
+         <property name="text">
+          <string>Chart Selector</string>
+         </property>
+        </column>
+        <item>
+         <property name="text">
+          <string>Spectrum</string>
+         </property>
+         <property name="flags">
+          <set>ItemIsDragEnabled|ItemIsUserCheckable|ItemIsEnabled</set>
+         </property>
+         <item>
+          <property name="text">
+           <string>Input PSD</string>
+          </property>
+          <property name="icon">
+           <iconset resource="res/icons.qrc">
+            <normaloff>:/icons/CSSpectrumInpPSD.png</normaloff>:/icons/CSSpectrumInpPSD.png</iconset>
+          </property>
+         </item>
+         <item>
+          <property name="text">
+           <string>Input Spectrum</string>
+          </property>
+          <property name="icon">
+           <iconset resource="res/icons.qrc">
+            <normaloff>:/icons/CSSpectrumInpSpectr.png</normaloff>:/icons/CSSpectrumInpSpectr.png</iconset>
+          </property>
+         </item>
+         <item>
+          <property name="text">
+           <string>Waterfall Input Spectrum</string>
+          </property>
+          <property name="icon">
+           <iconset resource="res/icons.qrc">
+            <normaloff>:/icons/CSSpectrumWaterf.png</normaloff>:/icons/CSSpectrumWaterf.png</iconset>
+          </property>
+         </item>
+         <item>
+          <property name="text">
+           <string>Shifted PSD</string>
+          </property>
+          <property name="icon">
+           <iconset resource="res/icons.qrc">
+            <normaloff>:/icons/CSSpectrumShiftedPSD.png</normaloff>:/icons/CSSpectrumShiftedPSD.png</iconset>
+          </property>
+         </item>
+         <item>
+          <property name="text">
+           <string>Audio Spectrum</string>
+          </property>
+          <property name="icon">
+           <iconset resource="res/icons.qrc">
+            <normaloff>:/icons/CSSpectrumAudio.png</normaloff>:/icons/CSSpectrumAudio.png</iconset>
+          </property>
+         </item>
+         <item>
+          <property name="text">
+           <string>SNR Spectrum</string>
+          </property>
+          <property name="icon">
+           <iconset resource="res/icons.qrc">
+            <normaloff>:/icons/CSSpectrumSNR.png</normaloff>:/icons/CSSpectrumSNR.png</iconset>
+          </property>
+         </item>
+        </item>
+        <item>
+         <property name="text">
+          <string>Channel</string>
+         </property>
+         <property name="flags">
+          <set>ItemIsDragEnabled|ItemIsUserCheckable|ItemIsEnabled</set>
+         </property>
+         <item>
+          <property name="text">
+           <string>Impulse Response</string>
+          </property>
+          <property name="icon">
+           <iconset resource="res/icons.qrc">
+            <normaloff>:/icons/CSChannel.png</normaloff>:/icons/CSChannel.png</iconset>
+          </property>
+         </item>
+         <item>
+          <property name="text">
+           <string>Transfer Function</string>
+          </property>
+          <property name="icon">
+           <iconset resource="res/icons.qrc">
+            <normaloff>:/icons/CSTF.png</normaloff>:/icons/CSTF.png</iconset>
+          </property>
+         </item>
+        </item>
+        <item>
+         <property name="text">
+          <string>Constellation</string>
+         </property>
+         <property name="flags">
+          <set>ItemIsDragEnabled|ItemIsUserCheckable|ItemIsEnabled</set>
+         </property>
+         <item>
+          <property name="text">
+           <string>FAC / SDC / MSC</string>
+          </property>
+          <property name="icon">
+           <iconset resource="res/icons.qrc">
+            <normaloff>:/icons/CSConstellation.png</normaloff>:/icons/CSConstellation.png</iconset>
+          </property>
+         </item>
+         <item>
+          <property name="text">
+           <string>FAC</string>
+          </property>
+          <property name="icon">
+           <iconset resource="res/icons.qrc">
+            <normaloff>:/icons/CSFAC.png</normaloff>:/icons/CSFAC.png</iconset>
+          </property>
+         </item>
+         <item>
+          <property name="text">
+           <string>SDC</string>
+          </property>
+          <property name="icon">
+           <iconset resource="res/icons.qrc">
+            <normaloff>:/icons/CSSDC.png</normaloff>:/icons/CSSDC.png</iconset>
+          </property>
+         </item>
+         <item>
+          <property name="text">
+           <string>MSC</string>
+          </property>
+          <property name="icon">
+           <iconset resource="res/icons.qrc">
+            <normaloff>:/icons/CSMSC.png</normaloff>:/icons/CSMSC.png</iconset>
+          </property>
+         </item>
+        </item>
+        <item>
+         <property name="text">
+          <string>History</string>
+         </property>
+         <property name="flags">
+          <set>ItemIsDragEnabled|ItemIsUserCheckable|ItemIsEnabled</set>
+         </property>
+         <item>
+          <property name="text">
+           <string>SNR / Audio</string>
+          </property>
+          <property name="icon">
+           <iconset resource="res/icons.qrc">
+            <normaloff>:/icons/CSAudSNRHist.png</normaloff>:/icons/CSAudSNRHist.png</iconset>
+          </property>
+         </item>
+         <item>
+          <property name="text">
+           <string>Delay / Doppler</string>
+          </property>
+          <property name="icon">
+           <iconset resource="res/icons.qrc">
+            <normaloff>:/icons/CSHistoryDelDopp.png</normaloff>:/icons/CSHistoryDelDopp.png</iconset>
+          </property>
+         </item>
+         <item>
+          <property name="text">
+           <string>Frequency / Sample Rate</string>
+          </property>
+          <property name="icon">
+           <iconset resource="res/icons.qrc">
+            <normaloff>:/icons/CSHistoryFreqSam.png</normaloff>:/icons/CSHistoryFreqSam.png</iconset>
+          </property>
+         </item>
+        </item>
+       </widget>
+      </item>
+      <item>
+       <widget class="QFrame" name="frame">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="frameShape">
+         <enum>QFrame::Panel</enum>
+        </property>
+        <property name="frameShadow">
+         <enum>QFrame::Sunken</enum>
+        </property>
+        <layout class="QVBoxLayout" name="verticalLayout_2">
+         <property name="spacing">
+          <number>0</number>
+         </property>
+         <property name="margin">
+          <number>0</number>
+         </property>
+         <item>
+          <widget class="QwtPlot" name="plot">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="lineWidth">
+            <number>0</number>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </widget>
+      </item>
+     </layout>
+    </item>
+    <item>
+     <layout class="QHBoxLayout" name="horizontalLayout_2">
+      <item>
+       <layout class="QVBoxLayout" name="_18">
+        <property name="spacing">
+         <number>4</number>
+        </property>
+        <property name="margin">
+         <number>0</number>
+        </property>
+        <item>
+         <widget class="QGroupBox" name="ButtonGroupChanEstFreqInt">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="title">
+           <string>Channel Estimation: Frequency Interpolation</string>
+          </property>
+          <property name="alignment">
+           <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+          </property>
+          <layout class="QHBoxLayout" name="_19">
+           <property name="spacing">
+            <number>6</number>
+           </property>
+           <property name="margin">
+            <number>9</number>
+           </property>
+           <item>
+            <widget class="QRadioButton" name="RadioButtonFreqWiener">
+             <property name="sizePolicy">
+              <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+               <horstretch>0</horstretch>
+               <verstretch>0</verstretch>
+              </sizepolicy>
+             </property>
+             <property name="text">
+              <string>Wiener</string>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="QRadioButton" name="RadioButtonFreqLinear">
+             <property name="sizePolicy">
+              <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+               <horstretch>0</horstretch>
+               <verstretch>0</verstretch>
+              </sizepolicy>
+             </property>
+             <property name="text">
+              <string>Linear</string>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="QRadioButton" name="RadioButtonFreqDFT">
+             <property name="sizePolicy">
+              <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+               <horstretch>0</horstretch>
+               <verstretch>0</verstretch>
+              </sizepolicy>
+             </property>
+             <property name="text">
+              <string>DFT Zero Pad.</string>
+             </property>
+            </widget>
+           </item>
+          </layout>
+         </widget>
+        </item>
+        <item>
+         <widget class="QGroupBox" name="ButtonGroupChanEstTimeInt">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="title">
+           <string>Channel Estimation: Time Interpolation</string>
+          </property>
+          <property name="alignment">
+           <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+          </property>
+          <layout class="QHBoxLayout" name="_20">
+           <property name="spacing">
+            <number>6</number>
+           </property>
+           <property name="margin">
+            <number>9</number>
+           </property>
+           <item>
+            <widget class="QRadioButton" name="RadioButtonTiWiener">
+             <property name="sizePolicy">
+              <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+               <horstretch>0</horstretch>
+               <verstretch>0</verstretch>
+              </sizepolicy>
+             </property>
+             <property name="text">
+              <string>Wiener</string>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="QRadioButton" name="RadioButtonTiLinear">
+             <property name="sizePolicy">
+              <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+               <horstretch>0</horstretch>
+               <verstretch>0</verstretch>
+              </sizepolicy>
+             </property>
+             <property name="text">
+              <string>Linear</string>
+             </property>
+            </widget>
+           </item>
+          </layout>
+         </widget>
+        </item>
+        <item>
+         <widget class="QGroupBox" name="ButtonGroupTimeSyncTrack">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="title">
+           <string>Time Sync Tracking</string>
+          </property>
+          <property name="alignment">
+           <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+          </property>
+          <layout class="QHBoxLayout" name="_21">
+           <property name="spacing">
+            <number>6</number>
+           </property>
+           <property name="margin">
+            <number>9</number>
+           </property>
+           <item>
+            <widget class="QRadioButton" name="RadioButtonTiSyncEnergy">
+             <property name="sizePolicy">
+              <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+               <horstretch>0</horstretch>
+               <verstretch>0</verstretch>
+              </sizepolicy>
+             </property>
+             <property name="text">
+              <string>Guard Energy</string>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="QRadioButton" name="RadioButtonTiSyncFirstPeak">
+             <property name="sizePolicy">
+              <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+               <horstretch>0</horstretch>
+               <verstretch>0</verstretch>
+              </sizepolicy>
+             </property>
+             <property name="text">
+              <string>First Peak</string>
+             </property>
+            </widget>
+           </item>
+          </layout>
+         </widget>
+        </item>
+       </layout>
+      </item>
+      <item>
+       <layout class="QVBoxLayout" name="_22">
+        <property name="spacing">
+         <number>6</number>
+        </property>
+        <property name="margin">
+         <number>0</number>
+        </property>
+        <item>
+         <widget class="QGroupBox" name="GroupBoxMiscSettings">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="title">
+           <string>Misc Settings</string>
+          </property>
+          <property name="alignment">
+           <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+          </property>
+          <layout class="QHBoxLayout" name="_23">
+           <property name="spacing">
+            <number>30</number>
+           </property>
+           <property name="margin">
+            <number>9</number>
+           </property>
+           <item>
+            <layout class="QVBoxLayout" name="_24">
+             <property name="spacing">
+              <number>6</number>
+             </property>
+             <property name="margin">
+              <number>0</number>
+             </property>
+             <item>
+              <widget class="QCheckBox" name="CheckBoxFlipSpec">
+               <property name="sizePolicy">
+                <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+                 <horstretch>0</horstretch>
+                 <verstretch>0</verstretch>
+                </sizepolicy>
+               </property>
+               <property name="text">
+                <string>&Flip Input Spectrum</string>
+               </property>
+              </widget>
+             </item>
+             <item>
+              <widget class="QCheckBox" name="CheckBoxWriteLog">
+               <property name="sizePolicy">
+                <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+                 <horstretch>0</horstretch>
+                 <verstretch>0</verstretch>
+                </sizepolicy>
+               </property>
+               <property name="text">
+                <string>&Log to file</string>
+               </property>
+              </widget>
+             </item>
+            </layout>
+           </item>
+           <item>
+            <layout class="QVBoxLayout" name="_25">
+             <property name="spacing">
+              <number>6</number>
+             </property>
+             <property name="margin">
+              <number>0</number>
+             </property>
+             <item>
+              <widget class="QLabel" name="TextNumOfIterations">
+               <property name="sizePolicy">
+                <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+                 <horstretch>0</horstretch>
+                 <verstretch>0</verstretch>
+                </sizepolicy>
+               </property>
+               <property name="text">
+                <string>TextNumOfIterations</string>
+               </property>
+               <property name="alignment">
+                <set>Qt::AlignCenter</set>
+               </property>
+               <property name="wordWrap">
+                <bool>false</bool>
+               </property>
+              </widget>
+             </item>
+             <item>
+              <widget class="QSlider" name="SliderNoOfIterations">
+               <property name="sizePolicy">
+                <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+                 <horstretch>0</horstretch>
+                 <verstretch>0</verstretch>
+                </sizepolicy>
+               </property>
+               <property name="minimumSize">
+                <size>
+                 <width>100</width>
+                 <height>0</height>
+                </size>
+               </property>
+               <property name="maximum">
+                <number>4</number>
+               </property>
+               <property name="pageStep">
+                <number>1</number>
+               </property>
+               <property name="orientation">
+                <enum>Qt::Horizontal</enum>
+               </property>
+               <property name="tickPosition">
+                <enum>QSlider::TicksBothSides</enum>
+               </property>
+              </widget>
+             </item>
+            </layout>
+           </item>
+          </layout>
+         </widget>
+        </item>
+        <item>
+         <widget class="QGroupBox" name="GroupBoxLogFileSaveData">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="title">
+           <string>Audio</string>
+          </property>
+          <property name="alignment">
+           <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+          </property>
+          <layout class="QVBoxLayout" name="verticalLayout_4">
+           <item>
+            <layout class="QHBoxLayout" name="horizontalLayout_3">
+             <item>
+              <widget class="QCheckBox" name="CheckBoxMuteAudio">
+               <property name="sizePolicy">
+                <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+                 <horstretch>0</horstretch>
+                 <verstretch>0</verstretch>
+                </sizepolicy>
+               </property>
+               <property name="text">
+                <string>Mute &Audio</string>
+               </property>
+              </widget>
+             </item>
+             <item>
+              <widget class="QCheckBox" name="CheckBoxReverb">
+               <property name="sizePolicy">
+                <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+                 <horstretch>0</horstretch>
+                 <verstretch>0</verstretch>
+                </sizepolicy>
+               </property>
+               <property name="text">
+                <string>&Reverberation</string>
+               </property>
+              </widget>
+             </item>
+            </layout>
+           </item>
+           <item>
+            <layout class="QHBoxLayout" name="_28">
+             <property name="spacing">
+              <number>6</number>
+             </property>
+             <property name="margin">
+              <number>0</number>
+             </property>
+             <item>
+              <widget class="QCheckBox" name="CheckBoxSaveAudioWave">
+               <property name="sizePolicy">
+                <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+                 <horstretch>0</horstretch>
+                 <verstretch>0</verstretch>
+                </sizepolicy>
+               </property>
+               <property name="text">
+                <string>&Save Audio as WAV</string>
+               </property>
+              </widget>
+             </item>
+             <item>
+              <spacer name="horizontalSpacer">
+               <property name="orientation">
+                <enum>Qt::Horizontal</enum>
+               </property>
+               <property name="sizeHint" stdset="0">
+                <size>
+                 <width>13</width>
+                 <height>13</height>
+                </size>
+               </property>
+              </spacer>
+             </item>
+            </layout>
+           </item>
+          </layout>
+         </widget>
+        </item>
+       </layout>
+      </item>
+      <item>
+       <layout class="QVBoxLayout" name="_29">
+        <property name="spacing">
+         <number>6</number>
+        </property>
+        <property name="margin">
+         <number>0</number>
+        </property>
+        <item>
+         <widget class="QGroupBox" name="GroupBoxInterfRej">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="title">
+           <string>Interferer Rejection</string>
+          </property>
+          <property name="alignment">
+           <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+          </property>
+          <layout class="QHBoxLayout" name="_30">
+           <property name="spacing">
+            <number>6</number>
+           </property>
+           <property name="margin">
+            <number>11</number>
+           </property>
+           <item>
+            <widget class="QCheckBox" name="CheckBoxRecFilter">
+             <property name="text">
+              <string>&Bandpass Filter</string>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="QCheckBox" name="CheckBoxModiMetric">
+             <property name="text">
+              <string>Modified &Metrics</string>
+             </property>
+            </widget>
+           </item>
+          </layout>
+         </widget>
+        </item>
+        <item>
+         <widget class="QGroupBox" name="GroupBoxGPSStatus">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="title">
+           <string>GPS</string>
+          </property>
+          <layout class="QVBoxLayout" name="_31">
+           <property name="spacing">
+            <number>6</number>
+           </property>
+           <property name="margin">
+            <number>11</number>
+           </property>
+           <item>
+            <layout class="QHBoxLayout" name="_32">
+             <property name="spacing">
+              <number>6</number>
+             </property>
+             <property name="margin">
+              <number>0</number>
+             </property>
+             <item>
+              <layout class="QVBoxLayout" name="_33">
+               <property name="spacing">
+                <number>6</number>
+               </property>
+               <property name="margin">
+                <number>0</number>
+               </property>
+               <item>
+                <widget class="QLabel" name="TextLabelGPSPosition">
+                 <property name="text">
+                  <string>Lat: 53.123°   Long: 00.456°</string>
+                 </property>
+                 <property name="wordWrap">
+                  <bool>false</bool>
+                 </property>
+                </widget>
+               </item>
+               <item>
+                <widget class="QLabel" name="TextLabelGPSTime">
+                 <property name="text">
+                  <string>24/01/2007 15:14.33 UTC</string>
+                 </property>
+                 <property name="wordWrap">
+                  <bool>false</bool>
+                 </property>
+                </widget>
+               </item>
+               <item>
+                <widget class="QLabel" name="TextLabelGPSSpeedHeading">
+                 <property name="text">
+                  <string>10.0 m/s  151°</string>
+                 </property>
+                 <property name="wordWrap">
+                  <bool>false</bool>
+                 </property>
+                </widget>
+               </item>
+              </layout>
+             </item>
+             <item>
+              <spacer name="Spacer18">
+               <property name="orientation">
+                <enum>Qt::Horizontal</enum>
+               </property>
+               <property name="sizeType">
+                <enum>QSizePolicy::Expanding</enum>
+               </property>
+               <property name="sizeHint" stdset="0">
+                <size>
+                 <width>20</width>
+                 <height>20</height>
+                </size>
+               </property>
+              </spacer>
+             </item>
+             <item>
+              <layout class="QVBoxLayout" name="_34">
+               <property name="spacing">
+                <number>6</number>
+               </property>
+               <property name="margin">
+                <number>0</number>
+               </property>
+               <item>
+                <spacer name="Spacer21">
+                 <property name="orientation">
+                  <enum>Qt::Vertical</enum>
+                 </property>
+                 <property name="sizeType">
+                  <enum>QSizePolicy::MinimumExpanding</enum>
+                 </property>
+                 <property name="sizeHint" stdset="0">
+                  <size>
+                   <width>20</width>
+                   <height>20</height>
+                  </size>
+                 </property>
+                </spacer>
+               </item>
+               <item>
+                <widget class="CMultColorLED" name="LEDGPS" native="true">
+                 <property name="minimumSize">
+                  <size>
+                   <width>13</width>
+                   <height>13</height>
+                  </size>
+                 </property>
+                 <property name="maximumSize">
+                  <size>
+                   <width>13</width>
+                   <height>13</height>
+                  </size>
+                 </property>
+                </widget>
+               </item>
+              </layout>
+             </item>
+            </layout>
+           </item>
+          </layout>
+         </widget>
+        </item>
+        <item>
+         <layout class="QHBoxLayout" name="_35">
+          <property name="spacing">
+           <number>6</number>
+          </property>
+          <property name="margin">
+           <number>0</number>
+          </property>
+          <item>
+           <spacer name="Spacer3">
+            <property name="orientation">
+             <enum>Qt::Horizontal</enum>
+            </property>
+            <property name="sizeType">
+             <enum>QSizePolicy::Expanding</enum>
+            </property>
+            <property name="sizeHint" stdset="0">
+             <size>
+              <width>20</width>
+              <height>20</height>
+             </size>
+            </property>
+           </spacer>
+          </item>
+          <item>
+           <widget class="QPushButton" name="buttonOk">
+            <property name="windowTitle">
+             <string/>
+            </property>
+            <property name="text">
+             <string>&Close</string>
+            </property>
+            <property name="default">
+             <bool>true</bool>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </item>
+       </layout>
+      </item>
+     </layout>
+    </item>
+   </layout>
+  </widget>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>QwtPlot</class>
+   <extends>QFrame</extends>
+   <header>qwt_plot.h</header>
+   <container>1</container>
+  </customwidget>
+  <customwidget>
+   <class>CMultColorLED</class>
+   <extends>QWidget</extends>
+   <header>MultColorLED.h</header>
+  </customwidget>
+ </customwidgets>
+ <resources>
+  <include location="res/icons.qrc"/>
+ </resources>
+ <connections/>
+</ui>
diff --git a/src/GUI-QT/waterfallwidget.cpp b/src/GUI-QT/waterfallwidget.cpp
new file mode 100644
index 0000000..b79a361
--- /dev/null
+++ b/src/GUI-QT/waterfallwidget.cpp
@@ -0,0 +1,181 @@
+#include "waterfallwidget.h"
+#include <QPainter>
+#include <QPaintEvent>
+#include <QResizeEvent>
+#include <../matlib/MatlibStdToolbox.h>
+#include <algorithm>
+
+/* Init some constants */
+static const int maxHue = 359; /* Range of "Hue" is 0-359 */
+static const int maxSat = 255; /* Range of saturation is 0-255 */
+
+static QColor fromReal(_REAL val)
+{
+    int hue = maxHue - 60 - int(Round(val * maxHue));
+
+    /* Prevent out-of-range */
+    if(hue>maxHue) hue = maxHue;
+    if (hue < 0) hue = 0;
+
+    /* Also change saturation to get dark colors when low level */
+    int sat = int((1 - double(hue) / maxHue) * maxSat);
+    /* Prevent out-of-range */
+    if (sat > maxSat) sat = maxSat;
+    if (sat < 0) sat = 0;
+
+    return QColor::fromHsv(hue, sat, sat);
+}
+#if 0
+SimpleWaterfallWidget::SimpleWaterfallWidget(QWidget *parent) :
+    QWidget(parent),Canvas()
+{
+    setAttribute(Qt::WA_OpaquePaintEvent, true);
+    setAttribute(Qt::WA_TransparentForMouseEvents, true);
+    setCursor(Qt::CrossCursor);
+    setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+}
+
+void SimpleWaterfallWidget::paintEvent(QPaintEvent *)
+{
+    QPainter painter(this);
+    // let the painter scale the data to the window
+    painter.setWindow(Canvas.rect());
+    painter.drawPixmap(0, 0, Canvas);
+}
+
+void SimpleWaterfallWidget::resizeEvent(QResizeEvent *e)
+{
+    if(e->size().height() != e->oldSize().height())
+    {
+        // increase/decrease the vertical history
+        QPixmap tmp = Canvas;
+
+        Canvas = QPixmap(Canvas.width(), e->size().height());
+        Canvas.fill(QColor::fromRgb(0, 0, 0));
+
+        QRect r(QPoint(0,0), tmp.size());
+
+        QPainter p(&Canvas);
+        p.drawPixmap(r, tmp, r);
+    }
+}
+
+void SimpleWaterfallWidget::updatePlot(const vector<_REAL>& vec, _REAL min, _REAL max)
+{
+    if(int(vec.size()) != Canvas.width())
+    {
+        // size the canvas to the data
+        Canvas = QPixmap(vec.size(), height());
+
+        // always use a black background
+        Canvas.fill(QColor::fromRgb(0, 0, 0));
+    }
+
+    /* Scroll Canvas */
+    Canvas.scroll(0, 1, Canvas.rect());
+
+    QPainter painter;
+    painter.begin(&Canvas);
+
+    /* Actual waterfall data */
+    for (size_t i = 0; i <  vec.size(); i++)
+    {
+        /* Translate dB-values to colors */
+        _REAL norm = (vec[i] - min) / (max - min);
+
+        /* Generate pixel */
+        painter.setPen(fromReal(norm));
+        painter.drawPoint(i, 0);
+    }
+
+    painter.end();
+    update();
+}
+#endif
+WaterfallWidget::WaterfallWidget(QWidget *parent) :
+    QWidget(parent), resizeGlitch(false)
+{
+    setAttribute(Qt::WA_OpaquePaintEvent, true);
+    setAttribute(Qt::WA_TransparentForMouseEvents, true);
+    setCursor(Qt::CrossCursor);
+    setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+}
+
+void WaterfallWidget::paintEvent(QPaintEvent *)
+{
+    QPainter painter(this);
+    painter.drawPixmap(0, 0, Canvas);
+}
+
+void WaterfallWidget::resizeEvent(QResizeEvent *e)
+{
+    // prevent resize glitch when the widget is created,
+    // the fist resizeEvent() is bogus
+    if(!resizeGlitch)
+    {
+        resizeGlitch = true;
+        return;
+    }
+
+    QPixmap tmp = Canvas;
+    Canvas = QPixmap(e->size());
+    image = QImage(e->size().width(), 1, QImage::Format_RGB32);
+
+    // first time ever - initialise to black
+    if(tmp.size().width()==0)
+    {
+        tmp = QPixmap(e->size());
+        // always use a black background
+        tmp.fill(QColor::fromRgb(0, 0, 0));
+    }
+    // vertical stretch - fill below old with black
+    if(Canvas.height()>tmp.height())
+        Canvas.fill(QColor::fromRgb(0, 0, 0));
+
+    // copy old data, scaling to fit horizontally but making space below
+    // TODO - the width scaling is slightly off.
+    QPainter p(&Canvas);
+    QPoint origin(0,0);
+    QSize top(Canvas.width(), tmp.height());
+    p.drawPixmap(QRect(origin, top), tmp);
+}
+
+void WaterfallWidget::updatePlot(const vector<_REAL>& vec, _REAL min, _REAL max)
+{
+    int w = image.width();
+    if (w == 0)
+        return;
+
+    QPainter painter;
+    if(!painter.begin(&Canvas)) // David had problems on Linux without this
+        return;
+
+    /* Scroll Canvas */
+    Canvas.scroll(0, 1, Canvas.rect());
+
+    // cast from u_char (8bits wide) to QRgb (probably 24bits wide)
+    QRgb* scanLine = ((QRgb*)image.scanLine(0));
+
+    // scaling factor between data and image
+    _REAL ratio = _REAL(vec.size())/_REAL(w);
+    if(ratio<1.0)
+    {
+        ratio = 1.0; // TODO handle stretching
+    }
+    vector<_REAL>::const_iterator vi = vec.begin();
+    size_t l=0; // index of left edge of bin
+    for(int i=0; i<w; i++)
+    {
+        // calculate right edge of current bin - not all bins are same width for all possible ratios
+        size_t r = size_t((i+1)*ratio); // index of right edge (ie left edge of following bin
+        vector<_REAL>::const_iterator biggest = max_element(vi+l, vi+r);
+        // reduce dB value by 6 dB to avoid FSD and normalise
+        _REAL norm = ((*biggest) - 6.0 - min) / (max - min);
+        // Translate normalised value to a color and generate pixel
+        scanLine[i] = fromReal(norm).rgb();
+        l = r;
+    }
+    painter.drawImage(0, 0, image);
+    painter.end();
+    update();
+}
diff --git a/src/GUI-QT/waterfallwidget.h b/src/GUI-QT/waterfallwidget.h
new file mode 100644
index 0000000..1c10e2a
--- /dev/null
+++ b/src/GUI-QT/waterfallwidget.h
@@ -0,0 +1,45 @@
+#ifndef WATERFALLWIDGET_H
+#define WATERFALLWIDGET_H
+
+#include <QWidget>
+#include <QPixmap>
+#include <vector>
+#include <../GlobalDefinitions.h>
+
+class QPaintEvent;
+class QResizeEvent;
+
+#if 0
+class SimpleWaterfallWidget : public QWidget
+{
+    Q_OBJECT
+public:
+    explicit SimpleWaterfallWidget(QWidget *parent = 0);
+
+public slots:
+    void     updatePlot(const std::vector<_REAL>& vec, _REAL min, _REAL max);
+
+protected:
+    QPixmap	 Canvas;
+    void     paintEvent(QPaintEvent *);
+    void     resizeEvent(QResizeEvent *);
+};
+#endif
+class WaterfallWidget : public QWidget
+{
+    Q_OBJECT
+public:
+    explicit WaterfallWidget(QWidget *parent = 0);
+
+public slots:
+    void     updatePlot(const std::vector<_REAL>& vec, _REAL min, _REAL max);
+
+protected:
+    QPixmap Canvas;
+    QImage  image;
+    void    paintEvent(QPaintEvent *);
+    void    resizeEvent(QResizeEvent *);
+    bool    resizeGlitch;
+};
+
+#endif // WATERFALLWIDGET_H
diff --git a/src/GlobalDefinitions.h b/src/GlobalDefinitions.h
new file mode 100644
index 0000000..aa04b42
--- /dev/null
+++ b/src/GlobalDefinitions.h
@@ -0,0 +1,356 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *	Global definitions
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#ifndef _GLOBALDEFINITIONS_H
+#define _GLOBALDEFINITIONS_H
+
+#include <complex>
+using namespace std; /* Because of the library: "complex" */
+#include <string>
+#include <cstdio>
+#include <cmath>
+#include "tables/TableDRMGlobal.h"
+
+
+/* Definitions ****************************************************************/
+/* When you define the following flag, a directory called
+   "test" MUST EXIST in the windows directory (or linux directory if you use
+   Linux)! */
+#define _DEBUG_
+#undef _DEBUG_
+
+#ifdef _WIN32 /* For Windows set flags here, otherwise it is set by configure */
+
+# undef NOMINMAX
+# define NOMINMAX 1
+
+# define DLL_EXPORT 1
+//# undef DLL_EXPORT 1
+
+#endif /* _WIN32 */
+
+/* set sensible defaults for QT */
+#ifdef QT_CORE_LIB
+# include <qglobal.h>
+# if QT_VERSION < 0x040600
+#  error Qt version too old, need at least Qt 4.6
+# endif
+#else
+# define qDebug(...) do {} while (0)
+#endif
+
+#ifndef TRUE
+# define TRUE 1
+#endif
+#ifndef FALSE
+# define FALSE 0
+#endif
+
+/* Choose algorithms -------------------------------------------------------- */
+/* There are two algorithms available for frequency offset estimation for
+   tracking mode: Using frequency pilots or the guard-interval correlation. In
+   case of guard-interval correlation (which will be chosen if this macro is
+   defined), the Hilbert filter in TimeSync must be used all the time -> more
+   CPU usage. Also, the frequency tracking range is smaller */
+#undef USE_FRQOFFS_TRACK_GUARDCORR
+
+/* The sample rate offset estimation can be done using the frequency pilots or
+   the movement of the estimated impulse response. Defining this macro will
+   enable the frequency pilot based estimation. Simulations showed that this
+   method is more vulnerable to bad channel situations */
+#undef USE_SAMOFFS_TRACK_FRE_PIL
+
+/* Using max-log MAP decoder. A lot more memory and CPU is needed for this
+   method. This is just for showing the potential of an improved decoding
+   method and should not be activated for the "regular" version of Dream */
+#undef USE_MAX_LOG_MAP
+
+/* This method tries to speed up the audio output after a re-synchronization
+   when long symbol interleaver is used. We work with erasure symbols to mark
+   data which is not yet received. We hope that the channel decoder can still
+   decode audio even if not all data is yet received to fill the interleaver
+   history */
+#define USE_ERASURE_FOR_FASTER_ACQ
+
+/* If the following macro is defined, the Wiener filter for channel estimation
+   in time direction will be a Decision-Directed channel estimation ->
+   additional to the actual pilot cells, hard decisions about the data cells
+   are used as new pilots, too */
+#undef USE_DD_WIENER_FILT_TIME
+
+
+/* Define the application specific data-types ------------------------------- */
+typedef	double							_REAL;
+typedef	complex<_REAL>					_COMPLEX;
+typedef short							_SAMPLE;
+typedef unsigned char					_BYTE;
+typedef bool							_BOOLEAN;
+
+// bool seems not to work with linux TODO: Fix Me!
+typedef unsigned char/*bool*/			_BINARY;
+
+#if HAVE_STDINT_H
+# include <stdint.h>
+#elif HAVE_INTTYPES_H
+# include <inttypes.h>
+#elif defined(_WIN32)
+# ifndef HAVE_INT8_T
+#  define HAVE_INT8_T 1
+typedef signed char int8_t;
+# endif
+# ifndef HAVE_INT16_T
+#  define HAVE_INT16_T 1
+typedef signed __int16 int16_t;
+# endif
+# ifndef HAVE_INT32_T
+#  define HAVE_INT32_T 1
+typedef signed __int32 int32_t;
+# endif
+typedef unsigned char uint8_t;
+# ifndef HAVE_U_INT16_T
+#  define HAVE_U_INT16_T 1
+typedef unsigned __int16 uint16_t;
+# endif
+# ifndef HAVE_U_INT32_T
+#  define HAVE_U_INT32_T 1
+typedef unsigned __int32 uint32_t;
+# endif
+typedef signed __int64 int64_t;
+typedef unsigned __int64 uint64_t;
+#else
+typedef signed char int8_t;
+typedef unsigned char uint8_t;
+typedef signed int int16_t;
+typedef unsigned int uint16_t;
+typedef signed long int32_t;
+typedef unsigned long uint32_t;
+typedef signed long long int64_t;
+typedef unsigned long long uint64_t;
+#endif
+
+/* Define type-specific information */
+#define SIZEOF__BYTE					8
+#define _MAXSHORT						32767
+#define _MAXREAL						((_REAL) 3.4e38) /* Max for float */
+
+#ifdef USE_ERASURE_FOR_FASTER_ACQ
+/* Use max-value for showing that this is an erasure */
+# define ERASURE_TAG_VALUE				_MAXREAL
+#endif
+
+
+/* MAP ---------------------------------------------------------------------- */
+#ifdef USE_MAX_LOG_MAP
+typedef _REAL							_DECISION;
+# define ML_SOFT_INF_MAX_VALUE			((_DECISION) 1e10)
+inline _BINARY ExtractBit(_DECISION dD) {
+    return dD > 0 ? 1 : 0;
+}
+inline _DECISION BitToSoft(_BINARY biB) {
+    return biB == 0 ? -1.0 : 1.0;
+}
+#else
+typedef _BINARY							_DECISION;
+#define ExtractBit(a)					(a)
+#define BitToSoft(a)					(a)
+#endif
+
+
+/* Definitions for window message system ------------------------------------ */
+typedef unsigned int					_MESSAGE_IDENT;
+#define MS_FAC_CRC						1	/* MS: Message */
+#define MS_SDC_CRC						2
+#define MS_MSC_CRC						3
+#define MS_FRAME_SYNC					4
+#define MS_TIME_SYNC					5
+#define MS_IOINTERFACE					6
+#define MS_RESET_ALL					7
+#define MS_MOT_OBJ_STAT					8
+
+#define GUI_CONTROL_UPDATE_TIME			500	/* Milliseconds */
+#define GUI_CONTROL_UPDATE_TIME_FAST	250	/* Milliseconds */
+
+
+/* Global enumerations ------------------------------------------------------ */
+enum ESpecOcc {SO_0, SO_1, SO_2, SO_3, SO_4, SO_5, SO_6}; /* SO: Spectrum Occupancy */
+enum ERobMode {RM_ROBUSTNESS_MODE_A, RM_ROBUSTNESS_MODE_B,
+               RM_ROBUSTNESS_MODE_C, RM_ROBUSTNESS_MODE_D, RM_ROBUSTNESS_MODE_E,
+               RM_NO_MODE_DETECTED
+              }; /* RM: Robustness Mode */
+
+
+/* Constants ---------------------------------------------------------------- */
+const _REAL crPi = ((_REAL) 3.14159265358979323846);
+
+
+#define S9_DBUV 34.0 /* S9 in dBuV for converting HamLib S-meter readings to RSCI format */
+
+/* Define a number for the case: log10(0), which would lead to #inf */
+#define RET_VAL_LOG_0					((_REAL) -200.0)
+
+
+
+
+/* Classes ********************************************************************/
+/* For metric */
+class CDistance
+{
+public:
+    /* Distance towards 0 or towards 1 */
+    _REAL rTow0;
+    _REAL rTow1;
+};
+
+/* Viterbi needs information of equalized received signal and channel */
+class CEquSig
+{
+public:
+    CEquSig() : cSig(_COMPLEX((_REAL) 0.0, (_REAL) 0.0)), rChan((_REAL) 0.0) {}
+    CEquSig(const _COMPLEX cNS, const _REAL rNC) : cSig(cNS), rChan(rNC) {}
+
+    _COMPLEX	cSig; /* Actual signal */
+    _REAL		rChan; /* Channel power at this cell */
+};
+
+
+#ifdef QT_CORE_LIB
+# include <QMutex>
+# include <QWaitCondition>
+
+/* Mutex object to access data safely from different threads */
+
+class CMutex
+{
+public:
+    void Lock() {
+        Mutex.lock();
+    }
+    void Unlock() {
+        Mutex.unlock();
+    }
+protected:
+    QMutex Mutex;
+friend class CWaitCondition;
+};
+
+class CWaitCondition
+{
+public:
+    void WakeOne() {
+        WaitCond.wakeOne();
+    }
+    _BOOLEAN Wait(CMutex* mutex, unsigned long time) {
+        return WaitCond.wait(&mutex->Mutex, time);
+    }
+protected:
+    QWaitCondition WaitCond;
+};
+
+#else
+/* No GUI and no threads, we do not need mutex in this case */
+
+class CMutex
+{
+public:
+    void Lock() {}
+    void Unlock() {}
+};
+
+class CWaitCondition
+{
+public:
+    void WakeOne() {}
+    _BOOLEAN Wait(CMutex*, unsigned long) {return TRUE;}
+};
+
+#endif
+
+class CGenErr
+{
+public:
+    CGenErr(string strNE) : strError(strNE) {}
+    string strError;
+};
+
+
+// FIXME something nicer than using "MAX_NUM_TAPS_DRM_CHAN"
+/* For simulation, data from channel simulation */
+#define MAX_NUM_TAPS_DRM_CHAN			4
+template<class T> class CChanSimData
+{
+public:
+    T					tIn; /* Channel input data */
+    T					tOut; /* Output of the channel (with noise) */
+    T					tRef; /* Channel reference signal (without noise) */
+    _COMPLEX			veccTap[MAX_NUM_TAPS_DRM_CHAN]; /* Tap gains */
+    _COMPLEX			veccTapBackw[MAX_NUM_TAPS_DRM_CHAN];
+};
+typedef CChanSimData<_REAL>		CChanSimDataMod; /* OFDM modulated signals */
+typedef CChanSimData<_COMPLEX>	CChanSimDataDemod; /* Demodulated signals */
+
+/* Path for simulation output and status files */
+#define SIM_OUT_FILES_PATH				"test/"
+
+
+/* Prototypes for global functions ********************************************/
+/* Posting a window message */
+//void PostWinMessage(const _MESSAGE_IDENT MessID, const int iMessageParam = 0);
+
+/* Debug error handling */
+void DebugError(const char* pchErDescr, const char* pchPar1Descr,
+                const double dPar1, const char* pchPar2Descr,
+                const double dPar2);
+
+void ErrorMessage(string strErrorString);
+
+
+/* Global functions ***********************************************************/
+/* Converting _REAL to _SAMPLE */
+inline _SAMPLE Real2Sample(const _REAL rInput)
+{
+    /* Lower bound */
+    if (rInput < -_MAXSHORT)
+        return -_MAXSHORT;
+
+    /* Upper bound */
+    if (rInput > _MAXSHORT)
+        return _MAXSHORT;
+
+    return (_SAMPLE) rInput;
+}
+
+#ifdef _WIN32
+# define PATH_SEPARATOR "\\"
+# define PATH_SEPARATORS "/\\"
+#else
+# define PATH_SEPARATOR "/"
+# define PATH_SEPARATORS "/"
+#endif
+#define DEFAULT_DATA_FILES_DIRECTORY "data" PATH_SEPARATOR
+
+#endif // !defined(DEF_H__3B0BA660_CA63_4344_BB2B_23E7A0D31912__INCLUDED_)
diff --git a/src/IQInputFilter.cpp b/src/IQInputFilter.cpp
new file mode 100644
index 0000000..e864003
--- /dev/null
+++ b/src/IQInputFilter.cpp
@@ -0,0 +1,287 @@
+/* Automatically generated file with GNU Octave */
+
+/* File name: "IQInputFilter.octave" */
+/* Filter taps in time-domain */
+
+#include "IQInputFilter.h"
+
+/* Low pass prototype for Hilbert-filter */
+const float fHilFiltIQ[NUM_TAPS_IQ_INPUT_FILT] =
+{
+	-3.736957051449150360e-06f,
+	-1.949361188773379022e-03f,
+	1.203244046696168841e-06f,
+	-1.377938922973749505e-03f,
+	-7.286442527055340922e-07f,
+	-1.853062624290775263e-03f,
+	-8.208564673110997449e-07f,
+	-2.427196128945900352e-03f,
+	-9.107156265071787189e-07f,
+	-3.113364316704105191e-03f,
+	-9.962980523727442819e-07f,
+	-3.925998868143509325e-03f,
+	-1.075640558807862836e-06f,
+	-4.881296663153458608e-03f,
+	-1.146799840353189473e-06f,
+	-5.997740248464871610e-03f,
+	-1.207908898204542781e-06f,
+	-7.296844830686835537e-03f,
+	-1.257215753211608818e-06f,
+	-8.804233870279051799e-03f,
+	-1.293138791114585299e-06f,
+	-1.055120063798133632e-02f,
+	-1.314295988998222096e-06f,
+	-1.257700496665508164e-02f,
+	-1.319551455844310813e-06f,
+	-1.493231281675627339e-02f,
+	-1.308060329496818497e-06f,
+	-1.768446856730550992e-02f,
+	-1.279281200862170237e-06f,
+	-2.092581418178510524e-02f,
+	-1.233001879515619054e-06f,
+	-2.478729096468635859e-02f,
+	-1.169359383011782991e-06f,
+	-2.946166242553371548e-02f,
+	-1.088842349510299921e-06f,
+	-3.524532409956730034e-02f,
+	-9.922747961742540110e-07f,
+	-4.261870013437370902e-02f,
+	-8.808166293594269658e-07f,
+	-5.241431744885489963e-02f,
+	-7.559565538325407336e-07f,
+	-6.620892100050541906e-02f,
+	-6.194455619809827864e-07f,
+	-8.738768368296170874e-02f,
+	-4.733006012279122596e-07f,
+	-1.247623388759305785e-01f,
+	-3.197412292910920716e-07f,
+	-2.106614869578013749e-01f,
+	-1.611402251605884152e-07f,
+	-6.361033760689378536e-01f,
+	0.000000000000000000e+00f,
+	6.361033760689378536e-01f,
+	1.611402251605884152e-07f,
+	2.106614869578013749e-01f,
+	3.197412292910920716e-07f,
+	1.247623388759305785e-01f,
+	4.733006012279122596e-07f,
+	8.738768368296170874e-02f,
+	6.194455619809827864e-07f,
+	6.620892100050541906e-02f,
+	7.559565538325407336e-07f,
+	5.241431744885489963e-02f,
+	8.808166293594269658e-07f,
+	4.261870013437370902e-02f,
+	9.922747961742540110e-07f,
+	3.524532409956730034e-02f,
+	1.088842349510299921e-06f,
+	2.946166242553371548e-02f,
+	1.169359383011782991e-06f,
+	2.478729096468635859e-02f,
+	1.233001879515619054e-06f,
+	2.092581418178510524e-02f,
+	1.279281200862170237e-06f,
+	1.768446856730550992e-02f,
+	1.308060329496818497e-06f,
+	1.493231281675627339e-02f,
+	1.319551455844310813e-06f,
+	1.257700496665508164e-02f,
+	1.314295988998222096e-06f,
+	1.055120063798133632e-02f,
+	1.293138791114585299e-06f,
+	8.804233870279051799e-03f,
+	1.257215753211608818e-06f,
+	7.296844830686835537e-03f,
+	1.207908898204542781e-06f,
+	5.997740248464871610e-03f,
+	1.146799840353189473e-06f,
+	4.881296663153458608e-03f,
+	1.075640558807862836e-06f,
+	3.925998868143509325e-03f,
+	9.962980523727442819e-07f,
+	3.113364316704105191e-03f,
+	9.107156265071787189e-07f,
+	2.427196128945900352e-03f,
+	8.208564673110997449e-07f,
+	1.853062624290775263e-03f,
+	7.286442527055340922e-07f,
+	1.377938922973749505e-03f,
+	-1.203244046696168841e-06f,
+	1.949361188773379022e-03f,
+	3.736957051449150360e-06f
+};
+
+/* Low pass prototype for Hilbert-filter */
+const float fHilFiltIQ_HQ[NUM_TAPS_IQ_INPUT_FILT_HQ] =
+{
+	-1.226258402072385792e-07f,
+	-6.344131316253802041e-05f,
+	8.763557749303082328e-10f,
+	-6.454320957518009478e-05f,
+	-5.596875625153797922e-08f,
+	-9.659922296564428057e-05f,
+	-7.063921113268617515e-08f,
+	-1.385017946816760896e-04f,
+	-8.735068117873291853e-08f,
+	-1.922072086705507124e-04f,
+	-1.061337803566609823e-07f,
+	-2.599041576042332500e-04f,
+	-1.269822129221368638e-07f,
+	-3.440241415944334013e-04f,
+	-1.498494967453782799e-07f,
+	-4.472516335660407945e-04f,
+	-1.746461276235194533e-07f,
+	-5.725342781603536685e-04f,
+	-2.012374884271508677e-07f,
+	-7.230936352007661825e-04f,
+	-2.294430227159935611e-07f,
+	-9.024371778710166010e-04f,
+	-2.590354220464479370e-07f,
+	-1.114372498927933448e-03f,
+	-2.897421753357808548e-07f,
+	-1.363024979218761638e-03f,
+	-3.212466662637170086e-07f,
+	-1.652860559171375789e-03f,
+	-3.531914864893319845e-07f,
+	-1.988715741512401235e-03f,
+	-3.851823320293415928e-07f,
+	-2.375837587117932397e-03f,
+	-4.167929639053793991e-07f,
+	-2.819937306634932514e-03f,
+	-4.475708560364068113e-07f,
+	-3.327262168092496187e-03f,
+	-4.770447635279037635e-07f,
+	-3.904691969774144733e-03f,
+	-5.047313215156279398e-07f,
+	-4.559868443534851983e-03f,
+	-5.301436491963180533e-07f,
+	-5.301368929956902162e-03f,
+	-5.528001554742405718e-07f,
+	-6.138939931598003975e-03f,
+	-5.722332677822749246e-07f,
+	-7.083812366357549427e-03f,
+	-5.879983332398304033e-07f,
+	-8.149129563060044518e-03f,
+	-5.996830287159760983e-07f,
+	-9.350532997154707704e-03f,
+	-6.069155222519978535e-07f,
+	-1.070697232748035570e-02f,
+	-6.093731110843049963e-07f,
+	-1.224184037048531119e-02f,
+	-6.067895759210528696e-07f,
+	-1.398458889782749383e-02f,
+	-5.989618684516634425e-07f,
+	-1.597307322204400554e-02f,
+	-5.857559156969221161e-07f,
+	-1.825703195709484430e-02f,
+	-5.671108560123735984e-07f,
+	-2.090339076029891843e-02f,
+	-5.430427025556160579e-07f,
+	-2.400460342064479266e-02f,
+	-5.136460035177536040e-07f,
+	-2.769226521415005596e-02f,
+	-4.790942379441818571e-07f,
+	-3.216033673148437771e-02f,
+	-4.396387083845123631e-07f,
+	-3.770694369644753824e-02f,
+	-3.956059360423114216e-07f,
+	-4.481475276181230011e-02f,
+	-3.473939483006568497e-07f,
+	-5.431901427851942160e-02f,
+	-2.954665617549686223e-07f,
+	-6.779963620325431262e-02f,
+	-2.403467022480780095e-07f,
+	-8.864534342092801611e-02f,
+	-1.826085354912623787e-07f,
+	-1.256717514931474933e-01f,
+	-1.228683322311516902e-07f,
+	-2.112116074231530638e-01f,
+	-6.177523940835616117e-08f,
+	-6.362874989825990646e-01f,
+	0.000000000000000000e+00f,
+	6.362874989825990646e-01f,
+	6.177523940835616117e-08f,
+	2.112116074231530638e-01f,
+	1.228683322311516902e-07f,
+	1.256717514931474933e-01f,
+	1.826085354912623787e-07f,
+	8.864534342092801611e-02f,
+	2.403467022480780095e-07f,
+	6.779963620325431262e-02f,
+	2.954665617549686223e-07f,
+	5.431901427851942160e-02f,
+	3.473939483006568497e-07f,
+	4.481475276181230011e-02f,
+	3.956059360423114216e-07f,
+	3.770694369644753824e-02f,
+	4.396387083845123631e-07f,
+	3.216033673148437771e-02f,
+	4.790942379441818571e-07f,
+	2.769226521415005596e-02f,
+	5.136460035177536040e-07f,
+	2.400460342064479266e-02f,
+	5.430427025556160579e-07f,
+	2.090339076029891843e-02f,
+	5.671108560123735984e-07f,
+	1.825703195709484430e-02f,
+	5.857559156969221161e-07f,
+	1.597307322204400554e-02f,
+	5.989618684516634425e-07f,
+	1.398458889782749383e-02f,
+	6.067895759210528696e-07f,
+	1.224184037048531119e-02f,
+	6.093731110843049963e-07f,
+	1.070697232748035570e-02f,
+	6.069155222519978535e-07f,
+	9.350532997154707704e-03f,
+	5.996830287159760983e-07f,
+	8.149129563060044518e-03f,
+	5.879983332398304033e-07f,
+	7.083812366357549427e-03f,
+	5.722332677822749246e-07f,
+	6.138939931598003975e-03f,
+	5.528001554742405718e-07f,
+	5.301368929956902162e-03f,
+	5.301436491963180533e-07f,
+	4.559868443534851983e-03f,
+	5.047313215156279398e-07f,
+	3.904691969774144733e-03f,
+	4.770447635279037635e-07f,
+	3.327262168092496187e-03f,
+	4.475708560364068113e-07f,
+	2.819937306634932514e-03f,
+	4.167929639053793991e-07f,
+	2.375837587117932397e-03f,
+	3.851823320293415928e-07f,
+	1.988715741512401235e-03f,
+	3.531914864893319845e-07f,
+	1.652860559171375789e-03f,
+	3.212466662637170086e-07f,
+	1.363024979218761638e-03f,
+	2.897421753357808548e-07f,
+	1.114372498927933448e-03f,
+	2.590354220464479370e-07f,
+	9.024371778710166010e-04f,
+	2.294430227159935611e-07f,
+	7.230936352007661825e-04f,
+	2.012374884271508677e-07f,
+	5.725342781603536685e-04f,
+	1.746461276235194533e-07f,
+	4.472516335660407945e-04f,
+	1.498494967453782799e-07f,
+	3.440241415944334013e-04f,
+	1.269822129221368638e-07f,
+	2.599041576042332500e-04f,
+	1.061337803566609823e-07f,
+	1.922072086705507124e-04f,
+	8.735068117873291853e-08f,
+	1.385017946816760896e-04f,
+	7.063921113268617515e-08f,
+	9.659922296564428057e-05f,
+	5.596875625153797922e-08f,
+	6.454320957518009478e-05f,
+	-8.763557749303082328e-10f,
+	6.344131316253802041e-05f,
+	1.226258402072385792e-07f
+};
+
diff --git a/src/IQInputFilter.h b/src/IQInputFilter.h
new file mode 100644
index 0000000..3e49f49
--- /dev/null
+++ b/src/IQInputFilter.h
@@ -0,0 +1,21 @@
+/* Automatically generated file with GNU Octave */
+
+/* File name: "IQInputFilter.octave" */
+/* Filter taps in time-domain */
+
+#ifndef _IQINPUTFILTER_H_
+#define _IQINPUTFILTER_H_
+
+#define NUM_TAPS_IQ_INPUT_FILT        101
+#define IQ_INP_HIL_FILT_DELAY         50
+
+/* Low pass prototype for Hilbert-filter */
+extern const float fHilFiltIQ[NUM_TAPS_IQ_INPUT_FILT];
+
+#define NUM_TAPS_IQ_INPUT_FILT_HQ        169
+#define IQ_INP_HIL_FILT_DELAY_HQ         84
+
+/* Low pass prototype for Hilbert-filter */
+extern const float fHilFiltIQ_HQ[NUM_TAPS_IQ_INPUT_FILT_HQ];
+
+#endif /* _IQINPUTFILTER_H_ */
diff --git a/src/IQInputFilter.octave b/src/IQInputFilter.octave
new file mode 100644
index 0000000..044203a
--- /dev/null
+++ b/src/IQInputFilter.octave
@@ -0,0 +1,109 @@
+%******************************************************************************\
+%* Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+%* Copyright (c) 2001-2014
+%*
+%* Author:
+%*	Volker Fischer, modified by David Flamand (bandwith increased)
+%*
+%* Description:
+%* 	Hilbert Filter for I / Q input
+%*
+%******************************************************************************
+%*
+%* This program is free software; you can redistribute it and/or modify it under
+%* the terms of the GNU General Public License as published by the Free Software
+%* Foundation; either version 2 of the License, or (at your option) any later 
+%* version.
+%*
+%* This program is distributed in the hope that it will be useful, but WITHOUT 
+%* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+%* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 
+%* details.
+%*
+%* You should have received a copy of the GNU General Public License along with
+%* this program; if not, write to the Free Software Foundation, Inc., 
+%* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+%*
+%******************************************************************************/
+
+function [b] = DesignFilter(filterbw, nhil, fs)
+    % Parks-McClellan optimal equiripple FIR filter design
+    trans = (fs / 2 - filterbw) / 2 / (fs / 2);
+    f = [trans  1 - trans];
+    a = [1 1];
+    b = remez(nhil - 1, f, a, 'hilbert', 8192);
+endfunction
+
+
+% Number of taps (should be odd)
+nhil = 151;
+
+% Sampling frequency
+fs = 48000;
+
+% Filter bandwidth
+%filterbw = 18000; # 75% of fs/2 (18000 = 24000 - 24000/4)
+filterbw = 22500; # 93.75% of fs/2 (22500 = 24000 - 24000/16)
+
+
+function MakeFilter(fid_cpp, fid_h, fs, filterbw, nhil, sufix)
+    % Generate filter coefficients
+    b = DesignFilter(filterbw, nhil, fs);
+    % Display the filter
+    PLOT = 1;
+    if (PLOT == 1)
+        close all;
+        plot(b);
+        figure;
+        freqz(b);
+    end
+    % Write to header file
+    fprintf(fid_h, '#define NUM_TAPS_IQ_INPUT_FILT%s        %i\n', sufix, nhil);
+    fprintf(fid_h, '#define IQ_INP_HIL_FILT_DELAY%s         %i\n', sufix, floor(nhil / 2));
+    fprintf(fid_h, '\n');
+    fprintf(fid_h, '/* Low pass prototype for Hilbert-filter */\n');
+    fprintf(fid_h, 'extern const float fHilFiltIQ%s[NUM_TAPS_IQ_INPUT_FILT%s];\n', sufix, sufix);
+    fprintf(fid_h, '\n');
+    % Write filter taps to cpp file
+    fprintf(fid_cpp, '/* Low pass prototype for Hilbert-filter */\n');
+    fprintf(fid_cpp, 'const float fHilFiltIQ%s[NUM_TAPS_IQ_INPUT_FILT%s] =\n', sufix, sufix);
+    fprintf(fid_cpp, '{\n');
+    fprintf(fid_cpp, '	%.18ef,\n', b(1:end - 1));
+    fprintf(fid_cpp, '	%.18ef\n', b(end));
+    fprintf(fid_cpp, '};\n');
+    fprintf(fid_cpp, '\n');
+endfunction
+
+
+% Export coefficients to file ****************************************
+
+% Open/Write header file
+fid_h = fopen('IQInputFilter.h', 'w');
+fprintf(fid_h, '/* Automatically generated file with GNU Octave */\n');
+fprintf(fid_h, '\n');
+fprintf(fid_h, '/* File name: "IQInputFilter.octave" */\n');
+fprintf(fid_h, '/* Filter taps in time-domain */\n');
+fprintf(fid_h, '\n');
+fprintf(fid_h, '#ifndef _IQINPUTFILTER_H_\n');
+fprintf(fid_h, '#define _IQINPUTFILTER_H_\n');
+fprintf(fid_h, '\n');
+
+% Open/Write cpp file
+fid_cpp = fopen('IQInputFilter.cpp', 'w');
+fprintf(fid_cpp, '/* Automatically generated file with GNU Octave */\n');
+fprintf(fid_cpp, '\n');
+fprintf(fid_cpp, '/* File name: "IQInputFilter.octave" */\n');
+fprintf(fid_cpp, '/* Filter taps in time-domain */\n');
+fprintf(fid_cpp, '\n');
+fprintf(fid_cpp, '#include "IQInputFilter.h"\n');
+fprintf(fid_cpp, '\n');
+
+MakeFilter(fid_cpp, fid_h, fs, filterbw, 101, "")
+MakeFilter(fid_cpp, fid_h, fs, filterbw, 169, "_HQ")
+
+fclose(fid_cpp);
+
+fprintf(fid_h, '#endif /* _IQINPUTFILTER_H_ */\n');
+fclose(fid_h);
+
+
diff --git a/src/InputResample.cpp b/src/InputResample.cpp
new file mode 100644
index 0000000..1ee6f6f
--- /dev/null
+++ b/src/InputResample.cpp
@@ -0,0 +1,87 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *	Resample input DRM stream
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "InputResample.h"
+
+
+/* Implementation *************************************************************/
+void CInputResample::ProcessDataInternal(CParameter& Parameters)
+{
+    if (bSyncInput == TRUE)
+    {
+        /* Only copy input data to output buffer, do not resample data */
+        for (int i = 0; i < iInputBlockSize; i++)
+            (*pvecOutputData)[i] = (*pvecInputData)[i];
+
+        iOutputBlockSize = iInputBlockSize;
+    }
+    else
+    {
+        Parameters.Lock();
+        _REAL rSamRateOffset = Parameters.rResampleOffset;
+        _REAL rSigSampleRate = _REAL(Parameters.GetSigSampleRate());
+        Parameters.Unlock();
+
+        /* Adjust maximum resample offset to sample rate */
+        const _REAL rMaxResampleOffset = ADJ_FOR_SRATE(_REAL(MAX_RESAMPLE_OFFSET), rSigSampleRate);
+
+        /* Constrain the sample rate offset estimation to prevent from an
+           output buffer overrun */
+        if (rSamRateOffset > rMaxResampleOffset)
+            rSamRateOffset = rMaxResampleOffset;
+        if (rSamRateOffset < -rMaxResampleOffset)
+            rSamRateOffset = -rMaxResampleOffset;
+
+        /* Do actual resampling */
+        iOutputBlockSize = ResampleObj.Resample(pvecInputData, pvecOutputData,
+                                                rSigSampleRate /
+                                                (rSigSampleRate - rSamRateOffset));
+    }
+}
+
+void CInputResample::InitInternal(CParameter& Parameters)
+{
+    Parameters.Lock();
+    /* Init resample object */
+    ResampleObj.Init(Parameters.CellMappingTable.iSymbolBlockSize);
+
+    /* Define block-sizes for input and output */
+    iInputBlockSize = Parameters.CellMappingTable.iSymbolBlockSize;
+
+    /* With this parameter we define the maximum lenght of the output buffer
+       Due to the constrained sample rate offset estimation the output
+       buffer size is also constrained to a certain number of samples. The
+       maximum possible number of samples defines the output buffer maximum
+       memory allocation.
+       We have to consider the following case: The output block size is
+       smaller than one symbol -> no data is read by the next unit, but
+       after that the output block size is bigger than one symbol, therefore
+       we have to allocate three symbols for output buffer */
+    iMaxOutputBlockSize = 3 * Parameters.CellMappingTable.iSymbolBlockSize;
+    Parameters.Unlock();
+}
diff --git a/src/InputResample.h b/src/InputResample.h
new file mode 100644
index 0000000..a39d3d7
--- /dev/null
+++ b/src/InputResample.h
@@ -0,0 +1,62 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *	See InputResample.cpp
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#if !defined(INPUTRESAMPLE_H__3B0BA660_CA63_4344_BB2B_2OJVBEWJBWV_INCLUDED_)
+#define INPUTRESAMPLE_H__3B0BA660_CA63_4344_BB2B_2OJVBEWJBWV_INCLUDED_
+
+#include "Parameter.h"
+#include "util/Modul.h"
+#include "resample/Resample.h"
+
+
+/* Definitions ****************************************************************/
+#define MAX_RESAMPLE_OFFSET			200 /* Hz */
+
+
+/* Classes ********************************************************************/
+class CInputResample : public CReceiverModul<_REAL, _REAL>
+{
+public:
+    CInputResample() : bSyncInput(FALSE) {}
+    virtual ~CInputResample() {}
+
+    /* To set the module up for synchronized DRM input data stream */
+    void SetSyncInput(_BOOLEAN bNewS) {
+        bSyncInput = bNewS;
+    }
+
+protected:
+    CResample	ResampleObj;
+    _BOOLEAN	bSyncInput;
+
+    virtual void InitInternal(CParameter& Parameters);
+    virtual void ProcessDataInternal(CParameter& Parameters);
+};
+
+
+#endif // !defined(INPUTRESAMPLE_H__3B0BA660_CA63_4344_BB2B_2OJVBEWJBWV_INCLUDED_)
diff --git a/src/MDI/AFPacketGenerator.cpp b/src/MDI/AFPacketGenerator.cpp
new file mode 100644
index 0000000..e9586e3
--- /dev/null
+++ b/src/MDI/AFPacketGenerator.cpp
@@ -0,0 +1,150 @@
+/******************************************************************************\
+ * British Broadcasting Corporation
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer, Julian Cable, Oliver Haffenden
+ *
+ * Description:
+ *	Implements Digital Radio Mondiale (DRM) Multiplex Distribution Interface
+ *	(MDI), Receiver Status and Control Interface (RSCI)  
+ *  and Distribution and Communications Protocol (DCP) as described in
+ *	ETSI TS 102 820,  ETSI TS 102 349 and ETSI TS 102 821 respectively.
+ *
+ *  This module defines the CAFPacketGenerator class
+ *
+ *  This class generates the AF packet header and CRC, and takes as an argument a TAG packet
+ *  generator which generates the tag packet, i.e. the payload.
+ *  
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "AFPacketGenerator.h"
+#include "TagPacketGenerator.h"
+#include <iostream>
+
+#include "../util/LogPrint.h"
+// CAFPacketGenerator
+
+CVector<_BYTE> CAFPacketGenerator::GenAFPacket(const _BOOLEAN bUseAFCRC, CTagPacketGenerator& TagPacketGenerator)
+{
+/*
+	The AF layer encapsulates a single TAG Packet. Mandatory TAG items:
+	*ptr, dlfc, fac_, sdc_, sdci, robm, str0-3
+*/
+	CVector<_BINARY>	vecbiAFPkt;
+
+	/* Payload length in bytes */
+// TODO: check if padding bits are needed to get byte alignment!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+	int iPayloadLenBytes = TagPacketGenerator.GetTagPacketLength();
+		
+	/* 10 bytes AF header, 2 bytes CRC, payload */
+	const int iAFPktLenBits =
+		iPayloadLenBytes * SIZEOF__BYTE + 12 * SIZEOF__BYTE;
+
+	/* Init vector length */
+	vecbiAFPkt.Init(iAFPktLenBits);
+	vecbiAFPkt.ResetBitAccess();
+
+	/* SYNC: two-byte ASCII representation of "AF" */
+	vecbiAFPkt.Enqueue((uint32_t) 'A', SIZEOF__BYTE);
+	vecbiAFPkt.Enqueue((uint32_t) 'F', SIZEOF__BYTE);
+
+	/* LEN: length of the payload, in bytes (4 bytes long -> 32 bits) */
+	vecbiAFPkt.Enqueue((uint32_t) iPayloadLenBytes, 32);
+
+	/* SEQ: sequence number. Each AF Packet shall increment the sequence number
+	   by one for each packet sent, regardless of content. There shall be no
+	   requirement that the first packet received shall have a specific value.
+	   The counter shall wrap from FFFF_[16] to 0000_[16], thus the value shall
+	   count, FFFE_[16], FFFF_[16], 0000_[16], 0001_[16], etc.
+	   (2 bytes long -> 16 bits) */
+	vecbiAFPkt.Enqueue((uint32_t) iSeqNumber, 16);
+
+	iSeqNumber++;
+	if (iSeqNumber > 0xFFFF)
+		iSeqNumber = 0;
+
+	/* AR: AF protocol Revision -
+	   a field combining the CF, MAJ and MIN fields */
+	/* CF: CRC Flag, 0 if the CRC field is not used (CRC value shall be
+	   0000_[16]) or 1 if the CRC field contains a valid CRC (1 bit long) */
+	if (bUseAFCRC == TRUE)
+		vecbiAFPkt.Enqueue((uint32_t) 1, 1);
+	else
+		vecbiAFPkt.Enqueue((uint32_t) 0, 1);
+
+	/* MAJ: major revision of the AF protocol in use (3 bits long) */
+	vecbiAFPkt.Enqueue((uint32_t) AF_MAJOR_REVISION, 3);
+
+	/* MIN: minor revision of the AF protocol in use (4 bits long) */
+	vecbiAFPkt.Enqueue((uint32_t) AF_MINOR_REVISION, 4);
+
+	/* Protocol Type (PT): single byte encoding the protocol of the data carried
+	   in the payload. For TAG Packets, the value shall be the ASCII
+	   representation of "T" */
+	vecbiAFPkt.Enqueue((uint32_t) 'T', SIZEOF__BYTE);
+
+
+	/* Payload -------------------------------------------------------------- */
+
+// TODO: copy data byte wise -> check if possible to do that...
+
+	TagPacketGenerator.PutTagPacketData(vecbiAFPkt);
+
+	/* CRC: CRC calculated as described in annex A if the CF field is 1,
+	   otherwise 0000_[16] */
+	if (bUseAFCRC == TRUE)
+	{
+		CCRC CRCObject;
+
+		/* CRC -------------------------------------------------------------- */
+		/* Calculate the CRC and put at the end of the stream */
+		CRCObject.Reset(16);
+
+		vecbiAFPkt.ResetBitAccess();
+
+		/* 2 bytes CRC -> "- 2" */
+		for (int i = 0; i < iAFPktLenBits / SIZEOF__BYTE - 2; i++)
+			CRCObject.AddByte((_BYTE) vecbiAFPkt.Separate(SIZEOF__BYTE));
+
+		/* Now, pointer in "enqueue"-function is back at the same place, 
+		   add CRC */
+		vecbiAFPkt.Enqueue(CRCObject.GetCRC(), 16);
+	}
+	else
+		vecbiAFPkt.Enqueue((uint32_t) 0, 16);
+
+	return PackBytes(vecbiAFPkt);
+}
+
+CVector<_BYTE> CAFPacketGenerator::PackBytes(CVector<_BINARY> &vecbiPacket)
+{
+	/* Convert to bytes and return */
+	CVector<_BYTE> vecbyPacket;
+	vecbiPacket.ResetBitAccess();
+	size_t bits = vecbiPacket.Size();
+	size_t bytes = bits / SIZEOF__BYTE;
+	vecbyPacket.reserve(bytes);
+	for(size_t i=0; i<bytes; i++)
+	{
+	 	_BYTE byte = (_BYTE)vecbiPacket.Separate(SIZEOF__BYTE);
+		vecbyPacket.push_back(byte);
+	}
+	return vecbyPacket;
+}
diff --git a/src/MDI/AFPacketGenerator.h b/src/MDI/AFPacketGenerator.h
new file mode 100644
index 0000000..d306c3d
--- /dev/null
+++ b/src/MDI/AFPacketGenerator.h
@@ -0,0 +1,51 @@
+/******************************************************************************\
+ * British Broadcasting Corporation
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer, Oliver Haffenden
+ *
+ * Description:
+ *	see AFPacketGenerator.cpp
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+#ifndef AF_PACKET_GENERATOR_H_INCLUDED
+#define AF_PACKET_GENERATOR_H_INCLUDED
+
+#include "../GlobalDefinitions.h"
+#include "../Parameter.h"
+#include "../util/Vector.h"
+#include "../util/Buffer.h"
+#include "../util/CRC.h"
+
+class CTagPacketGenerator;
+
+class CAFPacketGenerator
+{
+public:
+	CAFPacketGenerator() : iSeqNumber(0) {}
+
+	CVector<_BYTE> GenAFPacket(const _BOOLEAN bUseAFCRC, CTagPacketGenerator& TagPacketGenerator);
+
+private:
+	CVector<_BYTE> PackBytes(CVector<_BINARY> &vecbiPacket);
+	int							iSeqNumber;
+};
+
+#endif
diff --git a/src/MDI/MDIDecode.cpp b/src/MDI/MDIDecode.cpp
new file mode 100644
index 0000000..9fe14f6
--- /dev/null
+++ b/src/MDI/MDIDecode.cpp
@@ -0,0 +1,237 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer, Julian Cable
+ *
+ * Description:
+ *	Implements Digital Radio Mondiale (DRM) Multiplex Distribution Interface
+ *	(MDI), Receiver Status and Control Interface (RSCI)
+ *  and Distribution and Communications Protocol (DCP) as described in
+ *	ETSI TS 102 820,  ETSI TS 102 349 and ETSI TS 102 821 respectively.
+ *
+ *	This module implements a buffer for decoded Digital Radio Mondiale (DRM)
+ *  Multiplex Distribution Interface (MDI) packets at the receiver input.
+ *
+ *	see ETSI TS 102 820 and ETSI TS 102 821.
+ *
+ *
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "MDIDecode.h"
+
+void CDecodeRSIMDI::ProcessDataInternal(CParameter& Parameters)
+{
+	// pass receiver parameter structure to all the decoders that need it
+	TagPacketDecoderMDI.SetParameterPtr(&Parameters);
+
+	CTagPacketDecoder::Error err = TagPacketDecoderMDI.DecodeAFPacket(*pvecInputData);
+
+	if(err != CTagPacketDecoder::E_OK)
+	{
+		Parameters.Lock();
+		Parameters.ReceiveStatus.InterfaceI.SetStatus(CRC_ERROR);
+		Parameters.Unlock();
+		return;
+	}
+
+	if (TagPacketDecoderMDI.TagItemDecoderLoFrCnt.IsReady()) {
+        bool ok=true;
+		uint32_t dlfc = TagPacketDecoderMDI.TagItemDecoderLoFrCnt.dlfc;
+		if(dlfc == last_dlfc)
+            ok = false; // duplicate packet - might be a network thing, not an error but don't process again.
+		if(dlfc < last_dlfc) {
+			if( (last_dlfc - dlfc) < 10 )
+                ok = false; // recent packet - could be out of order or duplicate, not interested
+		}
+        if(ok)
+        {
+            // if we get here, dlfc is newer, or much older, than last_dlfc, assume its OK
+            // this includes the case where last_dlfc has not been initialised yet.
+            last_dlfc = dlfc;
+        }
+        else
+        {
+            if(dlfc!=0) // allow Newstar dr111
+                return;
+        }
+	}
+
+	Parameters.Lock();
+
+	Parameters.ReceiveStatus.InterfaceI.SetStatus(RX_OK);
+
+	if (TagPacketDecoderMDI.TagItemDecoderRobMod.IsReady())
+		Parameters.SetWaveMode(TagPacketDecoderMDI.TagItemDecoderRobMod.eRobMode);
+	CVector<_BINARY>& vecbiFACData = TagPacketDecoderMDI.TagItemDecoderFAC.vecbidata;
+	CVector<_BINARY>& vecbiSDCData = TagPacketDecoderMDI.TagItemDecoderSDC.vecbidata;
+	pvecOutputData->Reset(0);
+	if (TagPacketDecoderMDI.TagItemDecoderFAC.IsReady() && vecbiFACData.Size() > 0)
+	{
+		/* Copy incoming MDI FAC data */
+		pvecOutputData->ResetBitAccess();
+		vecbiFACData.ResetBitAccess();
+        int n = vecbiFACData.Size(); // 72 for DRM30, 120 for DRM+
+
+        /* copy data byte-wise */
+        for (int i = 0; i < n / SIZEOF__BYTE; i++)
+		{
+			pvecOutputData->Enqueue(vecbiFACData.Separate(SIZEOF__BYTE), SIZEOF__BYTE);
+		}
+        iOutputBlockSize = n;
+	}
+	else
+	{
+		iOutputBlockSize = 0;
+		Parameters.ReceiveStatus.FAC.SetStatus(NOT_PRESENT);
+	}
+
+	pvecOutputData2->Reset(0);
+	const int iLenBitsMDISDCdata = vecbiSDCData.Size();
+	if (TagPacketDecoderMDI.TagItemDecoderSDC.IsReady() && iLenBitsMDISDCdata > 0)
+	{
+		/* If receiver is correctly initialized, the input vector should be
+		   large enough for the SDC data */
+		const int iLenSDCDataBits = pvecOutputData2->Size();
+		Parameters.SetNumDecodedBitsSDC(iLenBitsMDISDCdata);
+
+		if (iLenSDCDataBits >= iLenBitsMDISDCdata)
+		{
+			/* Copy incoming MDI SDC data */
+			pvecOutputData2->ResetBitAccess();
+            vecbiSDCData.ResetBitAccess();
+
+			/* We have to copy bits instead of bytes since the length of SDC
+			   data is usually not a multiple of 8 */
+			for (int i = 0; i < iLenBitsMDISDCdata; i++)
+				pvecOutputData2->Enqueue(vecbiSDCData.Separate(1), 1);
+
+			iOutputBlockSize2 = iLenBitsMDISDCdata;
+		}
+		iFramesSinceSDC = 0;
+	}
+	else
+	{
+
+		pvecOutputData2->Reset(0);
+		iOutputBlockSize2 = 0;
+		if(iFramesSinceSDC>2)
+			Parameters.ReceiveStatus.SDC.SetStatus(NOT_PRESENT);
+		else
+			iFramesSinceSDC++;
+   }
+
+	/* Get stream data from received RSCI / MDI packets */
+	for(size_t i=0; i<vecpvecOutputData.size(); i++)
+	{
+		CVector<_BINARY>& vecbiStr = TagPacketDecoderMDI.TagItemDecoderStr[i].vecbidata;
+		CVector<_BINARY>* pvecOutputData = vecpvecOutputData[i];
+		/* Now check length of data vector */
+		const int iLen = pvecOutputData->Size();
+		const int iStreamLen = vecbiStr.Size();
+		if (iLen >= iStreamLen)
+		{
+			/* Copy data */
+			vecbiStr.ResetBitAccess();
+			pvecOutputData->ResetBitAccess();
+
+			/* Data is always a multiple of 8 -> copy bytes */
+			for (int j = 0; j < iStreamLen / SIZEOF__BYTE; j++)
+			{
+				pvecOutputData->Enqueue(
+					vecbiStr.Separate(SIZEOF__BYTE), SIZEOF__BYTE);
+			}
+			veciOutputBlockSize[i] = iStreamLen;
+		}
+    }
+
+	if (TagPacketDecoderMDI.TagItemDecoderRxDemodMode.IsReady() &&
+		TagPacketDecoderMDI.TagItemDecoderAMAudio.IsReady() &&
+		TagPacketDecoderMDI.TagItemDecoderRxDemodMode.eMode == RM_AM)
+	{
+		CVector<_BINARY>& vecbiAMAudio = TagPacketDecoderMDI.TagItemDecoderAMAudio.vecbidata;
+		CVector<_BINARY>* pvecOutputData = vecpvecOutputData[0];
+		// Now check length of data vector
+		const int iLen = pvecOutputData->Size();
+		const int iStreamLen = vecbiAMAudio.Size();
+		if (iLen >= iStreamLen)
+		{
+			// Copy data
+			vecbiAMAudio.ResetBitAccess();
+			pvecOutputData->ResetBitAccess();
+			// Data is always a multiple of 8 -> copy bytes
+			for (int j = 0; j < iStreamLen / SIZEOF__BYTE; j++)
+			{
+				pvecOutputData->Enqueue(
+				vecbiAMAudio.Separate(SIZEOF__BYTE), SIZEOF__BYTE);
+			}
+			veciOutputBlockSize[0] = iStreamLen;
+		}
+		//if (iLen != 0)
+		//{
+			/* Get the audio parameters for decoding the coded AM */
+			CAudioParam AudioParam = TagPacketDecoderMDI.TagItemDecoderAMAudio.AudioParams;
+			/* Write the audio settings into the parameter object
+			 * CParameter takes care of keeping separate data for AM and DRM
+			 */
+			AudioParam.iStreamID = 0;
+
+			Parameters.SetAudioParam(0, AudioParam);
+
+			Parameters.SetStreamLen(0, 0, iStreamLen/SIZEOF__BYTE);
+			Parameters.SetNumOfServices(1,0);
+			Parameters.SetCurSelAudioService(0);
+			Parameters.SetNumDecodedBitsMSC(iStreamLen); // is this necessary?
+		//}
+
+		Parameters.Service[0].strLabel = "";
+		Parameters.Service[0].strCountryCode = "";
+		Parameters.Service[0].iLanguage = 0;
+		Parameters.Service[0].strLanguageCode = "";
+		Parameters.Service[0].iServiceDescr = 0;
+		Parameters.Service[0].iServiceID = 0;
+	}
+
+	// TODO RSCI Data Items, MER, etc.
+
+	Parameters.Unlock();
+}
+
+void CDecodeRSIMDI::InitInternal(CParameter& Parameters)
+{
+	Parameters.Lock();
+
+    iOutputBlockSize = Parameters.iNumFACBitsPerBlock;
+	//iOutputBlockSize2 = Parameters.iNumSDCBitsPerSFrame;
+	iMaxOutputBlockSize2 = 1024;
+	size_t numstreams = Parameters.Stream.size();
+	//vecpvecOutputData.resize(numstreams);
+	for(size_t i=0; i<numstreams; i++)
+	{
+		int streamlen = Parameters.Stream[i].iLenPartA;
+		streamlen += Parameters.Stream[i].iLenPartB;
+		//veciMaxOutputBlockSize[i] = 16384;
+		veciOutputBlockSize[i] = streamlen*SIZEOF__BYTE;
+	}
+	iFramesSinceSDC = 3;
+
+	Parameters.Unlock();
+}
diff --git a/src/MDI/MDIDecode.h b/src/MDI/MDIDecode.h
new file mode 100644
index 0000000..14ea459
--- /dev/null
+++ b/src/MDI/MDIDecode.h
@@ -0,0 +1,54 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer, Oliver Haffenden
+ *
+ * Description:
+ *	see MDIInBuffer.cpp
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#ifndef MDIDECODE_H_INCLUDED
+#define MDIDECODE_H_INCLUDED
+
+#include "../GlobalDefinitions.h"
+#include "../Parameter.h"
+#include "../util/Modul.h"
+#include "MDIDefinitions.h"
+#include "TagPacketDecoderMDI.h"
+
+class CDecodeRSIMDI : public CReceiverModul<_BINARY, _BINARY>
+{
+public:
+	CDecodeRSIMDI():TagPacketDecoderMDI() {}
+	virtual ~CDecodeRSIMDI() {}
+
+protected:
+
+	virtual void InitInternal(CParameter& Parameters);
+	virtual void ProcessDataInternal(CParameter& Parameters);
+
+	CTagPacketDecoderMDI TagPacketDecoderMDI;
+	int iFramesSinceSDC;
+	uint32_t last_dlfc;
+};
+
+#endif
diff --git a/src/MDI/MDIDefinitions.h b/src/MDI/MDIDefinitions.h
new file mode 100644
index 0000000..1bf08f1
--- /dev/null
+++ b/src/MDI/MDIDefinitions.h
@@ -0,0 +1,64 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer, Oliver Haffenden
+ *
+ * Description:
+ *	Definitions used by the other MDI classes
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+
+
+#ifndef MDI_DEFINITIONS_H_INCLUDED
+#define MDI_DEFINITIONS_H_INCLUDED
+
+#include "../GlobalDefinitions.h"
+#include "../util/Vector.h"
+
+
+/* Definitions ****************************************************************/
+/* Major revision: Currently 0000_[16] */
+#define MDI_MAJOR_REVISION			0
+
+/* Minor revision: Currently 0000_[16] */
+#define MDI_MINOR_REVISION			0
+
+/* Major revision: Currently 0003_[16] */
+#define RSCI_MAJOR_REVISION			3
+
+/* Minor revision: Currently 0000_[16] */
+#define RSCI_MINOR_REVISION			0
+
+/* Major revision of the AF protocol in use: Currently 01_[16] */
+#define AF_MAJOR_REVISION			1
+
+/* Minor revision of the AF protocol in use: Currently 00_[16] */
+#define AF_MINOR_REVISION			0
+
+/* MDI input */
+
+/* Length of the MDI in buffer */
+#define MDI_IN_BUF_LEN				4
+
+
+
+#endif
diff --git a/src/MDI/MDIInBuffer.cpp b/src/MDI/MDIInBuffer.cpp
new file mode 100644
index 0000000..a2f8fcf
--- /dev/null
+++ b/src/MDI/MDIInBuffer.cpp
@@ -0,0 +1,76 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer, Oliver Haffenden
+ *
+ * Description:
+ *	simple blocking buffer
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "MDIInBuffer.h"
+#include <iostream>
+
+/* write the received packet to the buffer, if the previous one was not read yet
+ * it will be lost, but we need new data in preference to old and we should be
+ * able to keep up, so that's OK
+ */
+void
+CMDIInBuffer::Put(const vector<_BYTE>& data)
+{
+	guard.Lock();
+	buffer.push(data);
+	blocker.WakeOne();
+	guard.Unlock();
+}
+
+/* get the buffer contents, but if it takes more than a second, return an empty buffer
+ * clear the buffer after reading it so we don't read the same buffer twice
+ * Its possible signals could get lost :(
+ */
+void
+CMDIInBuffer::Get(vector<_BYTE>& data)
+{
+	guard.Lock();
+	if(buffer.empty())
+	{
+		if(blocker.Wait(&guard, 1000))
+		{
+			if(buffer.empty())
+				data.clear();
+			else
+			{
+				data = buffer.front();
+				buffer.pop();
+			}
+		}
+		else
+		{
+			data.clear();
+		}
+	}
+	else
+	{
+		data = buffer.front();
+		buffer.pop();
+	}
+	guard.Unlock();
+}
diff --git a/src/MDI/MDIInBuffer.h b/src/MDI/MDIInBuffer.h
new file mode 100644
index 0000000..3b7a2e2
--- /dev/null
+++ b/src/MDI/MDIInBuffer.h
@@ -0,0 +1,51 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer, Oliver Haffenden
+ *
+ * Description:
+ *	see MDIInBuffer.cpp
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#ifndef MDI_IN_BUFFER_H_INCLUDED
+#define MDI_IN_BUFFER_H_INCLUDED
+
+#include "../GlobalDefinitions.h"
+#include <vector>
+#include <queue>
+
+class CMDIInBuffer
+{
+public:
+	CMDIInBuffer() : buffer() ,guard(),blocker()
+	{}
+
+	void Put(const vector<_BYTE>& data);
+	void Get(vector<_BYTE>& data);
+
+protected:
+	queue< vector<_BYTE> > buffer;
+	CMutex guard;
+	CWaitCondition blocker;
+};
+
+#endif
diff --git a/src/MDI/MDIRSCI.cpp b/src/MDI/MDIRSCI.cpp
new file mode 100644
index 0000000..d4430e2
--- /dev/null
+++ b/src/MDI/MDIRSCI.cpp
@@ -0,0 +1,653 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer, Julian Cable, Oliver Haffenden, Andrew Murphy
+ *
+ * Description:
+  *	Implements Digital Radio Mondiale (DRM) Multiplex Distribution Interface
+ *	(MDI), Receiver Status and Control Interface (RSCI)
+ *  and Distribution and Communications Protocol (DCP) as described in
+ *	ETSI TS 102 820,  ETSI TS 102 349 and ETSI TS 102 821 respectively.
+ *
+ *  All modules that generate MDI information are given (normally at construction) a pointer to an MDI object.
+ *  They call methods in this interface when they have MDI/RSCI data to impart.
+ *
+ *	Note that this previously needed QT, but now the QT socket is wrapped in an abstract class so
+ *  this class can be compiled without QT. (A null socket is instantiated instead in this case, so
+ *  nothing will actually happen.) This could be developed further by using a factory class to make
+ *  the socket, in which case this class would only need to know about the abstract interface
+ *  CPacketSocket.
+ *
+ *  This class is now almost a facade for all of the DCP and TAG classes, designed to have the
+ *  same interface as the old CMDI class had. It could be improved further by moving the
+ *  MDI generation into a separate class.
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "PacketSocket.h"
+#include "../DrmReceiver.h"
+#include "PacketSourceFile.h"
+#include <sstream>
+#include <iomanip>
+#include "MDIRSCI.h"
+
+/* Implementation *************************************************************/
+CDownstreamDI::CDownstreamDI() : iLogFraCnt(0), pDrmReceiver(NULL),
+	bMDIOutEnabled(FALSE), bMDIInEnabled(FALSE),bIsRecording(FALSE),
+	iFrequency(0), strRecordType(),
+	vecTagItemGeneratorStr(MAX_NUM_STREAMS), vecTagItemGeneratorRBP(MAX_NUM_STREAMS),
+	RSISubscribers(),pRSISubscriberFile(new CRSISubscriberFile)
+{
+	/* Initialise all the generators for strx and rbpx tags */
+	for (int i=0; i<MAX_NUM_STREAMS; i++)
+	{
+		vecTagItemGeneratorStr[i].SetStreamNumber(i);
+		vecTagItemGeneratorRBP[i].SetStreamNumber(i);
+	}
+
+	/* Reset all tags for initialization */
+	ResetTags();
+
+	/* Init constant tag */
+	TagItemGeneratorProTyMDI.GenTag();
+	TagItemGeneratorProTyRSCI.GenTag();
+
+	/* Add the file subscriber to the list of subscribers */
+	RSISubscribers.push_back(pRSISubscriberFile);
+
+}
+
+CDownstreamDI::~CDownstreamDI()
+{
+	for(vector<CRSISubscriber*>::iterator i = RSISubscribers.begin();
+			i!=RSISubscribers.end(); i++)
+	{
+		delete *i;
+	}
+}
+
+/******************************************************************************\
+* DI send status, receive control                                             *
+\******************************************************************************/
+/* Access functions ***********************************************************/
+void CDownstreamDI::SendLockedFrame(CParameter& Parameter,
+						CSingleBuffer<_BINARY>& FACData,
+						CSingleBuffer<_BINARY>& SDCData,
+						vector<CSingleBuffer<_BINARY> >& vecMSCData
+)
+{
+	TagItemGeneratorFAC.GenTag(Parameter, FACData);
+	TagItemGeneratorSDC.GenTag(Parameter, SDCData);
+	//for (size_t i = 0; i < vecMSCData.size(); i++)
+	for (size_t i = 0; i < MAX_NUM_STREAMS; i++)
+	{
+		vecTagItemGeneratorStr[i].GenTag(Parameter, vecMSCData[i]);
+	}
+	TagItemGeneratorRobMod.GenTag(Parameter.GetWaveMode());
+	TagItemGeneratorRxDemodMode.GenTag(Parameter.GetReceiverMode());
+
+	/* SDC channel information tag must be created here because it must be sent
+	   with each AF packet */
+	TagItemGeneratorSDCChanInf.GenTag(Parameter);
+
+	TagItemGeneratorRINF.GenTag(Parameter.sReceiverID);	/* rinf */
+
+	/* RSCI tags ------------------------------------------------------------ */
+	TagItemGeneratorRAFS.GenTag(Parameter);
+	TagItemGeneratorRWMF.GenTag(TRUE, Parameter.rWMERFAC); /* WMER for FAC */
+	TagItemGeneratorRWMM.GenTag(TRUE, Parameter.rWMERMSC); /* WMER for MSC */
+	TagItemGeneratorRMER.GenTag(TRUE, Parameter.rMER); /* MER for MSC */
+	TagItemGeneratorRDEL.GenTag(TRUE, Parameter.vecrRdelThresholds, Parameter.vecrRdelIntervals);
+	TagItemGeneratorRDOP.GenTag(TRUE, Parameter.rRdop);
+	TagItemGeneratorRINT.GenTag(TRUE,Parameter.rIntFreq, Parameter.rINR, Parameter.rICR);
+	TagItemGeneratorRNIP.GenTag(TRUE,Parameter.rMaxPSDFreq, Parameter.rMaxPSDwrtSig);
+	TagItemGeneratorRxService.GenTag(TRUE, Parameter.GetCurSelAudioService());
+	TagItemGeneratorReceiverStatus.GenTag(Parameter);
+	TagItemGeneratorRxFrequency.GenTag(TRUE, Parameter.GetFrequency()); /* rfre */
+	TagItemGeneratorRxActivated.GenTag(TRUE); /* ract */
+	TagItemGeneratorPowerSpectralDensity.GenTag(Parameter);
+	TagItemGeneratorPowerImpulseResponse.GenTag(Parameter);
+	TagItemGeneratorPilots.GenTag(Parameter);
+
+	/* Generate some other tags */
+	_REAL rSigStr = Parameter.SigStrstat.getCurrent();
+	TagItemGeneratorSignalStrength.GenTag(TRUE, rSigStr + S9_DBUV);
+
+	TagItemGeneratorGPS.GenTag(TRUE, Parameter.gps_data);	// rgps
+
+	GenDIPacket();
+}
+
+void CDownstreamDI::SendUnlockedFrame(CParameter& Parameter)
+{
+	/* This is called once per frame if the receiver is unlocked */
+
+	/* In the MDI profile, we used to ignore this altogether since "I assume there's no point */
+	/* in generating empty packets with no reception monitoring information" */
+	/* But now there could be multiple profiles at the same time. TODO: decide what to do! */
+/*	if (cProfile == 'M')
+		return;*/
+
+	/* Send empty tags for most tag items */
+	ResetTags();
+
+	TagItemGeneratorFAC.GenEmptyTag();
+	TagItemGeneratorSDC.GenEmptyTag();
+
+	/* mode is unknown - make empty robm tag */
+	TagItemGeneratorRobMod.GenEmptyTag();
+
+	TagItemGeneratorRxDemodMode.GenTag(Parameter.GetReceiverMode());
+
+	TagItemGeneratorSDCChanInf.GenEmptyTag();
+
+	TagItemGeneratorReceiverStatus.GenTag(Parameter);
+
+	TagItemGeneratorPowerSpectralDensity.GenTag(Parameter);
+
+	TagItemGeneratorPowerImpulseResponse.GenEmptyTag();
+
+	TagItemGeneratorPilots.GenEmptyTag();
+
+	TagItemGeneratorRNIP.GenTag(TRUE,Parameter.rMaxPSDFreq, Parameter.rMaxPSDwrtSig);
+
+	/* Generate some other tags */
+	TagItemGeneratorRINF.GenTag(Parameter.sReceiverID);	/* rinf */
+	TagItemGeneratorRxFrequency.GenTag(TRUE, Parameter.GetFrequency()); /* rfre */
+	TagItemGeneratorRxActivated.GenTag(TRUE); /* ract */
+	_REAL rSigStr = Parameter.SigStrstat.getCurrent();
+	TagItemGeneratorSignalStrength.GenTag(TRUE, rSigStr + S9_DBUV);
+
+	TagItemGeneratorGPS.GenTag(TRUE, Parameter.gps_data);	/* rgps */
+
+	GenDIPacket();
+}
+
+void CDownstreamDI::SendAMFrame(CParameter& Parameter, CSingleBuffer<_BINARY>& CodedAudioData)
+{
+		/* This is called once per 400ms if the receiver is in AM mode */
+
+	/* In the MDI profile, ignore this altogether since there's no DRM information */
+	/*if (cProfile == 'M')
+		return;*/
+
+	/* Send empty tags for most tag items */
+	ResetTags();
+
+	TagItemGeneratorFAC.GenEmptyTag();
+	TagItemGeneratorSDC.GenEmptyTag();
+	/* mode is unknown - make empty robm tag */
+	TagItemGeneratorRobMod.GenEmptyTag();
+
+	/* demod mode */
+	TagItemGeneratorRxDemodMode.GenTag(Parameter.GetReceiverMode());
+
+	TagItemGeneratorSDCChanInf.GenEmptyTag();
+
+	/* These will be set appropriately when the rx is put into AM mode */
+	/* We need to decide what "appropriate" settings are */
+	TagItemGeneratorReceiverStatus.GenTag(Parameter);
+
+	TagItemGeneratorPowerSpectralDensity.GenTag(Parameter);
+
+	TagItemGeneratorPowerImpulseResponse.GenEmptyTag();
+
+	TagItemGeneratorPilots.GenEmptyTag();
+
+	TagItemGeneratorRNIP.GenTag(TRUE, Parameter.rMaxPSDFreq, Parameter.rMaxPSDwrtSig);
+
+	// Generate a rama tag with the encoded audio data
+	TagItemGeneratorAMAudio.GenTag(Parameter, CodedAudioData);
+
+	/* Generate some other tags */
+	TagItemGeneratorRINF.GenTag(Parameter.sReceiverID);	/* rinf */
+	TagItemGeneratorRxFrequency.GenTag(TRUE, Parameter.GetFrequency()); /* rfre */
+	TagItemGeneratorRxActivated.GenTag(TRUE); /* ract */
+	_REAL rSigStr = Parameter.SigStrstat.getCurrent();
+	TagItemGeneratorSignalStrength.GenTag(TRUE, rSigStr + S9_DBUV);
+
+	TagItemGeneratorGPS.GenTag(TRUE, Parameter.gps_data);	/* rgps */
+
+	GenDIPacket();
+}
+
+void CDownstreamDI::SetReceiver(CDRMReceiver *pReceiver)
+{
+	pDrmReceiver = pReceiver;
+	for(vector<CRSISubscriber*>::iterator i = RSISubscribers.begin();
+			i!=RSISubscribers.end(); i++)
+			(*i)->SetReceiver(pReceiver);
+}
+
+/* Actual DRM DI protocol implementation *****************************************/
+void CDownstreamDI::GenDIPacket()
+{
+	/* Reset the tag packet generator */
+	TagPacketGenerator.Reset();
+
+	/* Increment MDI packet counter and generate counter tag */
+	TagItemGeneratorLoFrCnt.GenTag();
+
+	/* dlfc tag */
+	TagPacketGenerator.AddTagItem(&TagItemGeneratorLoFrCnt);
+
+	/* *ptr tag */
+	TagPacketGenerator.AddTagItem(&TagItemGeneratorProTyMDI);
+	TagPacketGenerator.AddTagItem(&TagItemGeneratorProTyRSCI);
+
+	/* rinf taf */
+	TagPacketGenerator.AddTagItem(&TagItemGeneratorRINF);
+
+	/* rgps tag */
+	TagPacketGenerator.AddTagItem(&TagItemGeneratorGPS);
+
+	/* rpro tag */
+	TagPacketGenerator.AddTagItem(&TagItemGeneratorProfile);
+
+	/* rdmo - note that this is currently empty */
+	TagPacketGenerator.AddTagItem(&TagItemGeneratorRxDemodMode);
+
+	/* ract */
+	TagPacketGenerator.AddTagItem(&TagItemGeneratorRxActivated);
+
+	/* rfre tag */
+	TagPacketGenerator.AddTagItem(&TagItemGeneratorRxFrequency);
+
+	/* fac_ tag */
+	TagPacketGenerator.AddTagItem(&TagItemGeneratorFAC);
+
+	/* sdc_ tag - don't send if empty */
+	if(TagItemGeneratorSDC.GetTotalLength()>64)
+		TagPacketGenerator.AddTagItem(&TagItemGeneratorSDC);
+
+	/* sdci tag */
+	TagPacketGenerator.AddTagItem(&TagItemGeneratorSDCChanInf);
+
+	/* robm tag */
+	TagPacketGenerator.AddTagItem(&TagItemGeneratorRobMod);
+
+	/* strx tag */
+	size_t i;
+	for (i = 0; i < MAX_NUM_STREAMS; i++)
+	{
+		TagPacketGenerator.AddTagItem(&vecTagItemGeneratorStr[i]);
+	}
+	TagPacketGenerator.AddTagItem(&TagItemGeneratorAMAudio);
+
+	TagPacketGenerator.AddTagItem(&TagItemGeneratorSignalStrength);
+	TagPacketGenerator.AddTagItem(&TagItemGeneratorRAFS);
+	TagPacketGenerator.AddTagItem(&TagItemGeneratorRMER);
+	TagPacketGenerator.AddTagItem(&TagItemGeneratorRWMM);
+	TagPacketGenerator.AddTagItem(&TagItemGeneratorRWMF);
+	TagPacketGenerator.AddTagItem(&TagItemGeneratorRDEL);
+	TagPacketGenerator.AddTagItem(&TagItemGeneratorRDOP);
+	TagPacketGenerator.AddTagItem(&TagItemGeneratorRINT);
+	TagPacketGenerator.AddTagItem(&TagItemGeneratorRNIP);
+	TagPacketGenerator.AddTagItem(&TagItemGeneratorReceiverStatus);
+
+	TagPacketGenerator.AddTagItem(&TagItemGeneratorPowerSpectralDensity);
+	TagPacketGenerator.AddTagItem(&TagItemGeneratorPowerImpulseResponse);
+	TagPacketGenerator.AddTagItem(&TagItemGeneratorPilots);
+
+
+	for (i = 0; i < MAX_NUM_STREAMS; i++)
+	{
+		TagPacketGenerator.AddTagItem(&vecTagItemGeneratorRBP[i]);
+	}
+
+	/*return TagPacketGenerator.GenAFPacket(bUseAFCRC);*/
+
+	/* transmit a packet to each subscriber */
+	for(vector<CRSISubscriber*>::iterator s = RSISubscribers.begin();
+			s!=RSISubscribers.end(); s++)
+	{
+		// re-generate the profile tag for each subscriber
+		TagItemGeneratorProfile.GenTag((*s)->GetProfile());
+		(*s)->TransmitPacket(TagPacketGenerator);
+	}
+}
+
+void CDownstreamDI::ResetTags()
+{
+	/* Do not reset "*ptr" tag because this one is static */
+	/* This group of tags are generated each time so don't need empty tags generated */
+	TagItemGeneratorLoFrCnt.Reset(); /* dlfc tag */
+	TagItemGeneratorFAC.Reset(); /* fac_ tag */
+	TagItemGeneratorSDCChanInf.Reset(); /* sdci tag */
+	TagItemGeneratorRobMod.Reset(); /* robm tag */
+	TagItemGeneratorRINF.Reset(); /* info tag */
+	TagItemGeneratorReceiverStatus.Reset(); /* rsta */
+
+	TagItemGeneratorProfile.Reset(); /* rpro */
+	TagItemGeneratorGPS.Reset();	/* rgps */
+
+	TagItemGeneratorPowerSpectralDensity.Reset();
+    TagItemGeneratorPowerImpulseResponse.Reset();
+	TagItemGeneratorPilots.Reset();
+
+	/* This group of tags might not be generated, so make an empty version in case */
+
+	TagItemGeneratorSignalStrength.GenEmptyTag(); /* rdbv tag */
+	TagItemGeneratorRWMF.GenEmptyTag(); /* rwmf tag */
+	TagItemGeneratorRWMM.GenEmptyTag(); /* rwmm tag */
+	TagItemGeneratorRMER.GenEmptyTag(); /* rmer tag */
+	TagItemGeneratorRDEL.GenEmptyTag(); /* rdel tag */
+	TagItemGeneratorRDOP.GenEmptyTag(); /* rdop tag */
+	TagItemGeneratorRINT.GenEmptyTag(); /* rint tag */
+	TagItemGeneratorRNIP.GenEmptyTag(); /* rnip tag */
+	TagItemGeneratorRAFS.GenEmptyTag(); /* rafs tag */
+
+	/* Tags that are not fully implemented yet */
+	TagItemGeneratorRxBandwidth.GenEmptyTag(); /* rbw_ */
+	TagItemGeneratorRxService.GenEmptyTag(); /* rser */
+
+	for (int i = 0; i < MAX_NUM_STREAMS; i++)
+	{
+		vecTagItemGeneratorStr[i].Reset(); // strx tag
+		vecTagItemGeneratorRBP[i].GenEmptyTag(); // make empty version of mandatory tag that isn't implemented
+	}
+
+	TagItemGeneratorAMAudio.Reset(); // don't make the tag in DRM mode
+
+	TagItemGeneratorSDC.GenEmptyTag();
+}
+
+void CDownstreamDI::GetNextPacket(CSingleBuffer<_BINARY>&)
+{
+	// TODO
+}
+
+_BOOLEAN
+CDownstreamDI::AddSubscriber(const string& dest, const char profile, const string& origin)
+{
+	CRSISubscriber* subs = NULL;
+	/* heuristic to test for file or socket - TODO - better syntax */
+	size_t p = dest.find_first_not_of("TPtp0123456789.:");
+	if (p != string::npos)
+	{
+		subs = new CRSISubscriberFile();
+	}
+	else
+	{
+		subs = new CRSISubscriberSocket(NULL);
+	}
+
+	if(subs == NULL)
+	{
+		cerr << "can't make RSI Subscriber" << endl;
+		return FALSE;
+	}
+
+	// Delegate
+	_BOOLEAN bOK = TRUE;
+	if (dest != "")
+	{
+		bOK &= subs->SetDestination(dest);
+		if (bOK)
+		{
+			bMDIOutEnabled = TRUE;
+			subs->SetProfile(profile);
+		}
+	}
+	if (origin != "")
+	{
+		bOK &= subs->SetOrigin(origin);
+		if (bOK)
+		{
+			bMDIInEnabled = TRUE;
+		}
+	}
+	if (bOK)
+	{
+		subs->SetReceiver(pDrmReceiver);
+		RSISubscribers.push_back(subs);
+		return TRUE;
+	}
+	else
+	{
+		bMDIInEnabled = FALSE;
+		bMDIOutEnabled = FALSE;
+		delete subs;
+	}
+	return FALSE;
+}
+
+_BOOLEAN CDownstreamDI::SetOrigin(const string&)
+{
+	return FALSE;
+}
+
+_BOOLEAN CDownstreamDI::SetDestination(const string&)
+{
+	return FALSE;
+}
+
+_BOOLEAN CDownstreamDI::GetDestination(string&)
+{
+	return FALSE; // makes no sense
+}
+
+void CDownstreamDI::SetAFPktCRC(const _BOOLEAN bNAFPktCRC)
+{
+	for(vector<CRSISubscriber*>::iterator i = RSISubscribers.begin();
+			i!=RSISubscribers.end(); i++)
+			(*i)->SetAFPktCRC(bNAFPktCRC);
+}
+
+string CDownstreamDI::GetRSIfilename(CParameter& Parameter, const char cProfile)
+{
+	/* Get current UTC time */
+	time_t ltime;
+	time(&ltime);
+	struct tm* gmtCur = gmtime(&ltime);
+
+	iFrequency = Parameter.GetFrequency(); // remember this for later
+
+	stringstream filename;
+	filename << Parameter.sReceiverID << "_";
+	filename << setw(4) << setfill('0') << gmtCur->tm_year + 1900 << "-" << setw(2) << setfill('0')<< gmtCur->tm_mon + 1;
+	filename << "-" << setw(2) << setfill('0')<< gmtCur->tm_mday << "_";
+	filename << setw(2) << setfill('0') << gmtCur->tm_hour << "-" << setw(2) << setfill('0')<< gmtCur->tm_min;
+	filename << "-" << setw(2) << setfill('0')<< gmtCur->tm_sec << "_";
+	filename << setw(8) << setfill('0') << (iFrequency*1000) << ".rs" << char(toupper(cProfile));
+	return filename.str();
+}
+
+void CDownstreamDI::SetRSIRecording(CParameter& Parameter, const _BOOLEAN bOn, char cPro, const string& type)
+{
+	strRecordType = type;
+	if (bOn)
+	{
+		pRSISubscriberFile->SetProfile(cPro);
+		string fn = GetRSIfilename(Parameter, cPro);
+		if(strRecordType != "" && strRecordType != "raw")
+			fn += "." + strRecordType;
+
+		pRSISubscriberFile->SetDestination(fn);
+		pRSISubscriberFile->StartRecording();
+		bMDIOutEnabled = TRUE;
+		bIsRecording = TRUE;
+	}
+	else
+	{
+		pRSISubscriberFile->StopRecording();
+		bIsRecording = FALSE;
+	}
+}
+
+ /* needs to be called in case a new RSCI file needs to be started */
+void CDownstreamDI::NewFrequency(CParameter& Parameter)
+{
+	/* Has it really changed? */
+	int iNewFrequency = Parameter.GetFrequency();
+
+	if (iNewFrequency != iFrequency)
+	{
+		if (bIsRecording)
+		{
+			pRSISubscriberFile->StopRecording();
+			string fn = GetRSIfilename(Parameter, pRSISubscriberFile->GetProfile());
+			if(strRecordType != "" && strRecordType != "raw")
+				fn += "." + strRecordType;
+			pRSISubscriberFile->SetDestination(fn);
+			pRSISubscriberFile->StartRecording();
+		}
+	}
+}
+
+void CDownstreamDI::SendPacket(const vector<_BYTE>&, uint32_t, uint16_t)
+{
+	cerr << "this shouldn't get called CDownstreamDI::SendPacket" << endl;
+}
+
+void CDownstreamDI::poll()
+{
+	for(vector<CRSISubscriber*>::iterator i = RSISubscribers.begin();
+		i!=RSISubscribers.end(); i++) {
+		CRSISubscriber *s = *i;
+		string origin; 
+		bool hasOrigin = s->GetOrigin(origin);
+		if(hasOrigin)
+			s->poll();
+	}
+}
+
+/* allow multiple destinations, allow destinations to send cpro instructions back */
+/******************************************************************************\
+* DI receive status, send control                                             *
+\******************************************************************************/
+CUpstreamDI::CUpstreamDI() : source(NULL), sink(), bUseAFCRC(TRUE), bMDIOutEnabled(FALSE), bMDIInEnabled(FALSE)
+{
+	/* Init constant tag */
+	TagItemGeneratorProTyRSCI.GenTag();
+}
+
+CUpstreamDI::~CUpstreamDI()
+{
+	if(source)
+	{
+		delete source;
+	}
+}
+
+_BOOLEAN CUpstreamDI::SetOrigin(const string& str)
+{
+	/* only allow one listening address */
+	if(bMDIInEnabled == TRUE)
+		return FALSE;
+
+	if(source)
+		return FALSE;
+
+	strOrigin = str;
+
+	// try a file
+	source = new CPacketSourceFile;
+	_BOOLEAN bOK = source->SetOrigin(str);
+
+	if(!bOK)
+	{
+		// try a socket
+		delete source;
+		source = new CPacketSocketNative;
+		bOK = source->SetOrigin(str);
+	}
+	if (bOK)
+	{
+		source->SetPacketSink(this);
+		bMDIInEnabled = TRUE;
+		return TRUE;
+	}
+	return FALSE;
+}
+
+_BOOLEAN CUpstreamDI::SetDestination(const string& str)
+{
+
+	bMDIOutEnabled = sink.SetDestination(str);
+
+	return bMDIOutEnabled;
+}
+
+_BOOLEAN CUpstreamDI::GetDestination(string& str)
+{
+	return sink.GetDestination(str);
+}
+
+void CUpstreamDI::SetFrequency(int iNewFreqkHz)
+{
+	if(bMDIOutEnabled==FALSE)
+		return;
+	TagPacketGenerator.Reset();
+	TagItemGeneratorCfre.GenTag(iNewFreqkHz);
+	TagPacketGenerator.AddTagItem(&TagItemGeneratorProTyRSCI);
+	TagPacketGenerator.AddTagItem(&TagItemGeneratorCfre);
+	sink.TransmitPacket(TagPacketGenerator);
+}
+
+void CUpstreamDI::SetReceiverMode(ERecMode eNewMode)
+{
+	if(bMDIOutEnabled==FALSE)
+		return;
+	TagPacketGenerator.Reset();
+	TagItemGeneratorCdmo.GenTag(eNewMode);
+	TagPacketGenerator.AddTagItem(&TagItemGeneratorProTyRSCI);
+	TagPacketGenerator.AddTagItem(&TagItemGeneratorCdmo);
+	sink.TransmitPacket(TagPacketGenerator);
+}
+
+/* we only support one upstream RSCI source, so ignore the source address */
+void CUpstreamDI::SendPacket(const vector<_BYTE>& vecbydata, uint32_t, uint16_t)
+{
+	if(!vecbydata.size())
+		return;
+	if(vecbydata[0]=='P')
+	{
+		vector<_BYTE> vecOut;
+		if(Pft.DecodePFTPacket(vecbydata, vecOut))
+		{
+			queue.Put(vecOut);
+		}
+	}
+	else
+		queue.Put(vecbydata);
+}
+
+void CUpstreamDI::InitInternal(CParameter&)
+{
+	iInputBlockSize = 1; /* anything is enough but not zero */
+	iMaxOutputBlockSize = 2048*SIZEOF__BYTE; /* bigger than an ethernet packet */
+}
+
+void CUpstreamDI::ProcessDataInternal(CParameter&)
+{
+	vector<_BYTE> vecbydata;
+	source->poll();
+	queue.Get(vecbydata);
+	size_t bytes = vecbydata.size();
+	iOutputBlockSize = bytes*SIZEOF__BYTE;
+	pvecOutputData->Init(iOutputBlockSize);
+	pvecOutputData->ResetBitAccess();
+	for(size_t i=0; i<bytes; i++)
+	{
+		pvecOutputData->Enqueue(vecbydata[i], SIZEOF__BYTE);
+	}
+}
diff --git a/src/MDI/MDIRSCI.h b/src/MDI/MDIRSCI.h
new file mode 100644
index 0000000..efa6972
--- /dev/null
+++ b/src/MDI/MDIRSCI.h
@@ -0,0 +1,208 @@
+/******************************************************************************\
+ * British Broadcasting Corporation
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer, Oliver Haffenden, Julian Cable, Andrew Murphy
+ *
+ * Description:
+ *	see MDIRSCI.cpp
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+
+#if !defined(MDI_CONCRETE_H_INCLUDED)
+#define MDI_CONCRETE_H_INCLUDED
+
+#include "../GlobalDefinitions.h"
+
+#include "MDIInBuffer.h"
+
+#include "../util/Modul.h"
+#include "../util/CRC.h"
+#include "Pft.h"
+
+#include "MDIDefinitions.h"
+#include "MDITagItems.h"
+#include "RCITagItems.h"
+#include "TagPacketDecoderRSCIControl.h"
+#include "TagPacketGenerator.h"
+#include "RSISubscriber.h"
+#include <vector>
+
+/* Classes ********************************************************************/
+class CUpstreamDI : public CReceiverModul<_BINARY, _BINARY> , public CPacketSink
+{
+public:
+	CUpstreamDI();
+	virtual ~CUpstreamDI();
+
+	/* CRSIMDIInInterface */
+	_BOOLEAN SetOrigin(const string& strAddr);
+	_BOOLEAN GetInEnabled() {return bMDIInEnabled;}
+
+	/* CRCIOutInterface */
+	_BOOLEAN SetDestination(const string& strArgument);
+	_BOOLEAN GetOutEnabled() {return bMDIOutEnabled;}
+	void SetAFPktCRC(const _BOOLEAN bNAFPktCRC) {bUseAFCRC=bNAFPktCRC;}
+	void SetFrequency(int iNewFreqkHz);
+	void SetReceiverMode(ERecMode eNewMode);
+
+	/* CPacketSink */
+	virtual void SendPacket(const vector<_BYTE>& vecbydata, uint32_t addr=0, uint16_t port=0);
+
+	_BOOLEAN GetDestination(string& strArgument);
+
+	/* CReceiverModul */
+	void InitInternal(CParameter& Parameters);
+	void ProcessDataInternal(CParameter& Parameters);
+
+protected:
+
+	string						strOrigin;
+	string						strDestination;
+	CMDIInBuffer	  			queue;
+	CPacketSource*				source;
+	CRSISubscriberSocket		sink;
+	CPft						Pft;
+
+	_BOOLEAN					bUseAFCRC;
+
+	CSingleBuffer<_BINARY>		MDIInBuffer;
+	_BOOLEAN					bMDIOutEnabled;
+	_BOOLEAN					bMDIInEnabled;
+	_BOOLEAN					bNeedPft;
+
+	/* Tag Item Generators */
+
+	CTagItemGeneratorProTyRSCI TagItemGeneratorProTyRSCI; /* *ptr tag */
+	CTagItemGeneratorCfre TagItemGeneratorCfre;
+	CTagItemGeneratorCdmo TagItemGeneratorCdmo;
+
+	/* TAG Packet generator */
+	CTagPacketGenerator TagPacketGenerator;
+	CAFPacketGenerator AFPacketGenerator;
+
+};
+
+class CDownstreamDI: public CPacketSink
+{
+public:
+	CDownstreamDI();
+	virtual ~CDownstreamDI();
+
+	void GenDIPacket();
+	void poll();
+
+	void SendLockedFrame(CParameter& Parameter,
+						CSingleBuffer<_BINARY>& FACData,
+						CSingleBuffer<_BINARY>& SDCData,
+						vector<CSingleBuffer<_BINARY> >& vecMSCData
+	);
+	void SendUnlockedFrame(CParameter& Parameter); /* called once per frame even if the Rx isn't synchronised */
+	void SendAMFrame(CParameter& Parameter, CSingleBuffer<_BINARY>& CodedAudioData);
+
+	void SetAFPktCRC(const _BOOLEAN bNAFPktCRC);
+
+	_BOOLEAN AddSubscriber(const string& dest, const char profile, const string& origin="");
+
+	_BOOLEAN SetOrigin(const string& strAddr);
+	void SetRSIRecording(CParameter& Parameter, _BOOLEAN bOn, char cPro, const string& type="");
+	void NewFrequency(CParameter& Parameter); /* needs to be called in case a new RSCI file needs to be started */
+
+	virtual _BOOLEAN GetOutEnabled() {return bMDIOutEnabled;}
+	virtual _BOOLEAN GetInEnabled() {return bMDIInEnabled;}
+	void GetNextPacket(CSingleBuffer<_BINARY>&	buf);
+	void SetReceiver(CDRMReceiver *pReceiver);
+
+	/* CPacketSink */
+	virtual void SendPacket(const vector<_BYTE>& vecbydata, uint32_t addr=0, uint16_t port=0);
+	_BOOLEAN SetDestination(const string& strArgument);
+	_BOOLEAN GetDestination(string& strArgument);
+
+	string GetRSIfilename(CParameter& Parameter, const char cProfile);
+
+protected:
+
+	void ResetTags();
+
+	uint32_t					iLogFraCnt;
+	CDRMReceiver*				pDrmReceiver;
+
+	_BOOLEAN					bMDIOutEnabled;
+	_BOOLEAN					bMDIInEnabled;
+	_BOOLEAN					bNeedPft;
+
+	_BOOLEAN					bIsRecording;
+	int							iFrequency;
+	string						strRecordType;
+
+
+	/* Generators for all of the MDI and RSCI tags */
+
+	CTagItemGeneratorProTyMDI TagItemGeneratorProTyMDI; /* *ptr tag */
+	CTagItemGeneratorProTyRSCI TagItemGeneratorProTyRSCI; /* *ptr tag */
+	CTagItemGeneratorLoFrCnt TagItemGeneratorLoFrCnt ; /* dlfc tag */
+	CTagItemGeneratorFAC TagItemGeneratorFAC; /* fac_ tag */
+	CTagItemGeneratorSDC TagItemGeneratorSDC; /* sdc_ tag */
+	CTagItemGeneratorSDC TagItemGeneratorSDCEmpty; /* empty sdc_ tag for use in non-SDC frames */
+	CTagItemGeneratorSDCChanInf TagItemGeneratorSDCChanInf; /* sdci tag */
+	CTagItemGeneratorRobMod TagItemGeneratorRobMod; /* robm tag */
+	CTagItemGeneratorRINF TagItemGeneratorRINF; /* info tag */
+	CTagItemGeneratorRWMF TagItemGeneratorRWMF; /* RWMF tag */
+	CTagItemGeneratorRWMM TagItemGeneratorRWMM; /* RWMM tag */
+	CTagItemGeneratorRMER TagItemGeneratorRMER; /* RMER tag */
+	CTagItemGeneratorRDOP TagItemGeneratorRDOP; /* RDOP tag */
+	CTagItemGeneratorRDEL TagItemGeneratorRDEL; /* RDEL tag */
+	CTagItemGeneratorRAFS TagItemGeneratorRAFS; /* RAFS tag */
+	CTagItemGeneratorRINT TagItemGeneratorRINT; /* RINT tag */
+	CTagItemGeneratorRNIP TagItemGeneratorRNIP; /* RNIP tag */
+	CTagItemGeneratorSignalStrength TagItemGeneratorSignalStrength; /* rdbv tag */
+	CTagItemGeneratorReceiverStatus TagItemGeneratorReceiverStatus; /* rsta tag */
+
+	CTagItemGeneratorProfile TagItemGeneratorProfile; /* rpro */
+	CTagItemGeneratorRxDemodMode TagItemGeneratorRxDemodMode; /* rdmo */
+	CTagItemGeneratorRxFrequency TagItemGeneratorRxFrequency; /* rfre */
+	CTagItemGeneratorRxActivated TagItemGeneratorRxActivated; /* ract */
+	CTagItemGeneratorRxBandwidth TagItemGeneratorRxBandwidth; /* rbw_ */
+	CTagItemGeneratorRxService TagItemGeneratorRxService; /* rser */
+
+	CTagItemGeneratorGPS TagItemGeneratorGPS; /* rgps */
+	CTagItemGeneratorPowerSpectralDensity TagItemGeneratorPowerSpectralDensity; /* rpsd */
+    CTagItemGeneratorPowerImpulseResponse TagItemGeneratorPowerImpulseResponse; /* rpir */
+	CTagItemGeneratorPilots TagItemGeneratorPilots; /* rpil */
+
+	CVector<CTagItemGeneratorStr>	vecTagItemGeneratorStr; /* strx tag */
+	CTagItemGeneratorAMAudio TagItemGeneratorAMAudio; /* rama tag */
+
+	/* Mandatory tags but not implemented yet */
+	CVector<CTagItemGeneratorRBP>	vecTagItemGeneratorRBP;
+
+	/* TAG Packet generator */
+	CTagPacketGeneratorWithProfiles TagPacketGenerator;
+
+	vector< CRSISubscriber *>		RSISubscribers;
+	CRSISubscriberFile*				pRSISubscriberFile;
+	CPacketSource*					source;
+	CPacketSink*					sink;
+	CSingleBuffer<_BINARY>			MDIInBuffer;
+
+};
+
+#endif // !defined(MDI_H__3B0346264660_CA63_3452345DGERH31912__INCLUDED_)
diff --git a/src/MDI/MDITagItemDecoders.cpp b/src/MDI/MDITagItemDecoders.cpp
new file mode 100644
index 0000000..54be9d9
--- /dev/null
+++ b/src/MDI/MDITagItemDecoders.cpp
@@ -0,0 +1,355 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer, Julian Cable, Oliver Haffenden
+ *
+ * Description:
+  *	Implements Digital Radio Mondiale (DRM) Multiplex Distribution Interface
+ *	(MDI), Receiver Status and Control Interface (RSCI)
+ *  and Distribution and Communications Protocol (DCP) as described in
+ *	ETSI TS 102 820,  ETSI TS 102 349 and ETSI TS 102 821 respectively.
+ *
+ *  This module derives, from the CTagItemDecoder base class, tag item decoders specialised to decode each of the tag
+ *  items defined in MDI.
+ *  They generally write the decoded data into the CMDIPacket object which they hold a
+ *  pointer to.
+ *
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+
+#include "MDITagItemDecoders.h"
+#include "../Parameter.h"
+#include <iostream>
+
+string CTagItemDecoderProTy::GetTagName(void) {return "*ptr";}
+void CTagItemDecoderProTy::DecodeTag(CVector<_BINARY>& vecbiTag, const int iLen)
+{
+/*
+	Changes to the protocol which will allow existing decoders to still function
+	will be represented by an increment of the minor version number only. Any
+	new features added by the change will obviously not need to be supported by
+	older modulators. Existing TAG Items will not be altered except for the
+	definition of bits previously declared Rfu. New TAG Items may be added.
+
+	Changes to the protocol which will render previous implementations unable to
+	correctly process the new format will be represented by an increment of the
+	major version number. Older implementations should not attempt to decode
+	such MDI packets. Changes may include modification to or removal of existing
+	TAG Item definitions.
+*/
+
+	/* Protocol type and revision (*ptr) always 8 bytes long */
+	if (iLen != 64)
+		return; // TODO: error handling!!!!!!!!!!!!!!!!!!!!!!
+
+	CDCPProtocol p;
+	/* Decode protocol type (32 bits = 4 bytes) */
+	p.protocol = "";
+	for (int i = 0; i < 4 /* bytes */; i++)
+		p.protocol += (_BYTE) vecbiTag.Separate(SIZEOF__BYTE);
+
+
+	/* Get major and minor revision of protocol */
+	p.major = (int) vecbiTag.Separate(16);
+	p.minor = (int) vecbiTag.Separate(16);
+
+	protocols.push_back(p);
+
+	SetReady(TRUE);
+}
+
+string CTagItemDecoderLoFrCnt::GetTagName(void) {return "dlfc";}
+void CTagItemDecoderLoFrCnt::DecodeTag(CVector<_BINARY>& vecbiTag, const int iLen)
+{
+	/* DRM logical frame count (dlfc) always 4 bytes long */
+	if (iLen != 32)
+		return; // TODO: error handling!!!!!!!!!!!!!!!!!!!!!!
+
+	dlfc = (uint32_t) vecbiTag.Separate(32);
+
+	SetReady(TRUE);
+}
+
+
+
+string CTagItemDecoderFAC::GetTagName(void) {return "fac_";}
+void CTagItemDecoderFAC::DecodeTag(CVector<_BINARY>& vecbiTag, const int iLen)
+{
+    /* Fast access channel (fac_) either 9 or 13 bytes long */
+    if (
+        (iLen != NUM_FAC_BITS_PER_BLOCK_DRM30)
+        &&
+        (iLen != NUM_FAC_BITS_PER_BLOCK_DRMPLUS)
+    )
+    {
+		return; // TODO: error handling!!!!!!!!!!!!!!!!!!!!!!
+    }
+
+	/* Copy incoming FAC data */
+    vecbidata.Init(iLen);
+	vecbidata.ResetBitAccess();
+
+    for (int i = 0; i < iLen / SIZEOF__BYTE; i++)
+	{
+		vecbidata.
+			Enqueue(vecbiTag.Separate(SIZEOF__BYTE), SIZEOF__BYTE);
+	}
+
+	SetReady(TRUE);
+}
+
+
+string CTagItemDecoderSDC::GetTagName(void) {return "sdc_";}
+void CTagItemDecoderSDC::DecodeTag(CVector<_BINARY>& vecbiTag, const int iLen)
+{
+	/* Check that this is not a dummy packet with zero length */
+	if (iLen == 0)
+		return; // TODO: error handling!!!!!!!!!!!!!!!!!!!!!!
+
+	/* Rfu */
+	vecbiTag.Separate(4);
+
+	/* Copy incoming SDC data */
+	const int iSDCDataSize = iLen - 4;
+
+	vecbidata.Init(iSDCDataSize);
+	vecbidata.ResetBitAccess();
+
+	/* We have to copy bits instead of bytes since the length of SDC data is
+	   usually not a multiple of 8 */
+	for (int i = 0; i < iSDCDataSize; i++)
+		vecbidata.Enqueue(vecbiTag.Separate(1), 1);
+
+	SetReady(TRUE);
+}
+
+
+
+string CTagItemDecoderRobMod::GetTagName(void) {return "robm";}
+void CTagItemDecoderRobMod::DecodeTag(CVector<_BINARY>& vecbiTag, const int iLen)
+{
+	/* Robustness mode (robm) always one byte long */
+	if (iLen != 8)
+		return; // TODO: error handling!!!!!!!!!!!!!!!!!!!!!!
+
+	switch (vecbiTag.Separate(8))
+	{
+	case 0:
+		/* Robustness mode A */
+		eRobMode = RM_ROBUSTNESS_MODE_A;
+		break;
+
+	case 1:
+		/* Robustness mode B */
+		eRobMode = RM_ROBUSTNESS_MODE_B;
+		break;
+
+	case 2:
+		/* Robustness mode C */
+		eRobMode = RM_ROBUSTNESS_MODE_C;
+		break;
+
+	case 3:
+		/* Robustness mode D */
+		eRobMode = RM_ROBUSTNESS_MODE_D;
+		break;
+	}
+
+	SetReady(TRUE);
+}
+
+
+string CTagItemDecoderStr::GetTagName(void)
+{
+	switch (iStreamNumber)
+	{
+	case 0: return "str0";
+	case 1: return "str1";
+	case 2: return "str2";
+	case 3: return "str3";
+	default: return "str?";
+	}
+	SetReady(TRUE);
+}
+
+void CTagItemDecoderStr::DecodeTag(CVector<_BINARY>& vecbiTag, const int iLen)
+{
+	/* Copy stream data */
+	vecbidata.Init(iLen);
+	vecbidata.ResetBitAccess();
+
+	for (int i = 0; i < iLen / SIZEOF__BYTE; i++)
+	{
+		vecbidata.
+			Enqueue(vecbiTag.Separate(SIZEOF__BYTE), SIZEOF__BYTE);
+	}
+	SetReady(TRUE);
+}
+
+
+
+string CTagItemDecoderSDCChanInf::GetTagName(void) {return "sdci";}
+
+void CTagItemDecoderSDCChanInf::DecodeTag(CVector<_BINARY>& vecbiTag, const int iLen)
+{
+	if (iLen == 0)
+		return;
+
+	/* Get the number of streams */
+	const int iNumStreams = (iLen - 8) / 3 / SIZEOF__BYTE;
+
+	/* Get protection levels */
+	/* Rfu */
+	vecbiTag.Separate(4);
+
+	/* Protection level for part A */ // TODO
+    CMSCProtLev MSCProtLev;
+    MSCProtLev.iPartA = vecbiTag.Separate(2);
+
+	/* Protection level for part B */ // TODO
+    MSCProtLev.iPartB = vecbiTag.Separate(2);
+
+	/* Get stream parameters */
+
+	/* Determine if hierarchical modulation is used */ // TODO
+	_BOOLEAN bHierarchical = FALSE;
+
+    // don't store these if sdci tag packet signals zero length - dr111 bug
+    // rely on the sdc_ tag packet to do something sensible.
+    pParameter->Lock();
+	for (int i = 0; i < iNumStreams; i++)
+	{
+		/* In case of hirachical modulation stream 0 describes the protection
+		   level and length of hierarchical data */
+		if ((i == 0) && (bHierarchical == TRUE))
+		{
+			/* Protection level for hierarchical */ // TODO
+			vecbiTag.Separate(2);
+
+			/* rfu */
+			vecbiTag.Separate(10);
+
+            /* Data length for hierarchical */
+            int iLenPartB = vecbiTag.Separate(12);
+
+            /* Set new parameters in global struct. Length of part A is zero
+               with hierarchical modulation */
+            if(iLenPartB>0)
+                pParameter->SetStreamLen(i, 0, iLenPartB);
+        }
+		else
+		{
+            /* Data length for part A */
+            int iLenPartA = vecbiTag.Separate(12);
+
+            /* Data length for part B */
+            int iLenPartB = vecbiTag.Separate(12);
+
+            if(iLenPartA>0 || iLenPartB>0)
+                pParameter->SetStreamLen(i, iLenPartA, iLenPartB);
+        }
+	}
+    pParameter->Unlock();
+	SetReady(TRUE);
+}
+
+string CTagItemDecoderRxDemodMode::GetTagName(void) {return "rdmo";}
+
+void CTagItemDecoderRxDemodMode::DecodeTag(CVector<_BINARY>& vecbiTag, int iLen)
+{
+	string strMode = "";
+	for (int i = 0; i < iLen / SIZEOF__BYTE; i++)
+		strMode += (_BYTE) vecbiTag.Separate(SIZEOF__BYTE);
+	if (strMode == "drm_")
+		eMode = RM_DRM;
+	else if (strMode == "am__")
+		eMode = RM_AM;
+	else if (strMode == "fm__")
+		eMode = RM_FM;
+	else
+		eMode = RM_AM;
+
+	SetReady(TRUE);
+}
+
+string CTagItemDecoderAMAudio::GetTagName(void) { return "rama";}
+
+void CTagItemDecoderAMAudio::DecodeTag(CVector<_BINARY>& vecbiTag, int iLen)
+{
+
+	/* Audio coding */
+	int iVal = vecbiTag.Separate(2);
+	switch (iVal)
+	{
+		case 0: AudioParams.eAudioCoding = CAudioParam::AC_AAC;
+			break;
+		case 1: AudioParams.eAudioCoding = CAudioParam::AC_CELP; /* 01 */
+			break;
+		case 2: AudioParams.eAudioCoding = CAudioParam::AC_HVXC; /* 10 */
+			break;
+		default: AudioParams.eAudioCoding = CAudioParam::AC_AAC;/* reserved */
+	}
+
+	/* SBR flag */
+	iVal = vecbiTag.Separate(1);
+	AudioParams.eSBRFlag = (iVal == 1 ? CAudioParam::SB_USED : CAudioParam::SB_NOT_USED);
+	/* Audio mode */
+	iVal = vecbiTag.Separate(2);
+	switch (iVal)
+	{
+		case 0: AudioParams.eAudioMode = CAudioParam::AM_MONO; break;
+		case 1: AudioParams.eAudioMode = CAudioParam::AM_P_STEREO; break;
+		case 2: AudioParams.eAudioMode = CAudioParam::AM_STEREO; break;
+		default: AudioParams.eAudioMode = CAudioParam::AM_MONO;
+	}
+	/* Audio sampling rate */
+	iVal = vecbiTag.Separate(3);
+	switch (iVal)
+	{
+		case 0: AudioParams.eAudioSamplRate = CAudioParam::AS_8_KHZ; break;
+		case 1: AudioParams.eAudioSamplRate = CAudioParam::AS_12KHZ; break;
+		case 2: AudioParams.eAudioSamplRate = CAudioParam::AS_16KHZ; break;
+		case 3: AudioParams.eAudioSamplRate = CAudioParam::AS_24KHZ; break;
+		default: AudioParams.eAudioSamplRate = CAudioParam::AS_24KHZ;
+	}
+	// coder field and some rfus (TODO: code the coder field correctly for all cases)
+	vecbiTag.Separate(8);
+	/* Copy stream data */
+	vecbidata.Init(iLen-16);
+	vecbidata.ResetBitAccess();
+	for (int i = 0; i < (iLen-16) / SIZEOF__BYTE; i++)
+		vecbidata.Enqueue(vecbiTag.Separate(SIZEOF__BYTE), SIZEOF__BYTE);
+
+	SetReady(TRUE);
+}
+
+string CTagItemDecoderInfo::GetTagName(void) {return "info";}
+
+void CTagItemDecoderInfo::DecodeTag(CVector<_BINARY>& vecbiTag, const int iLen)
+{
+	/* Decode info string */
+	strInfo = "";
+	for (int i = 0; i < iLen / SIZEOF__BYTE; i++)
+		strInfo += (_BYTE) vecbiTag.Separate(SIZEOF__BYTE);
+
+	SetReady(TRUE);
+}
diff --git a/src/MDI/MDITagItemDecoders.h b/src/MDI/MDITagItemDecoders.h
new file mode 100644
index 0000000..fd5a23d
--- /dev/null
+++ b/src/MDI/MDITagItemDecoders.h
@@ -0,0 +1,136 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer, Oliver Haffenden
+ *
+ * Description:
+ *	see MDITagItemDecoders.cpp
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#ifndef MDI_TAG_ITEM_DECODERS_H_INCLUDED
+#define MDI_TAG_ITEM_DECODERS_H_INCLUDED
+
+#include "../GlobalDefinitions.h"
+#include "../Parameter.h"
+#include "TagItemDecoder.h"
+
+class CTagItemDecoderProTy : public CTagItemDecoder
+{
+public:
+	class CDCPProtocol
+	{
+     public:
+      string protocol;
+      int major;
+      int minor;
+	};
+	CTagItemDecoderProTy(){}
+	virtual string GetTagName(void);
+	virtual void DecodeTag(CVector<_BINARY>& vecbiTag, const int iLenDataBits);
+	vector<CDCPProtocol> protocols;
+};
+
+class CTagItemDecoderLoFrCnt : public CTagItemDecoder   
+{
+public:
+	CTagItemDecoderLoFrCnt(){}
+	virtual string GetTagName(void);
+	virtual void DecodeTag(CVector<_BINARY>& vecbiTag, const int iLenDataBits);
+	uint32_t dlfc;
+};
+
+class CTagItemDecoderFAC : public CTagItemDecoder       
+{
+public:
+	CTagItemDecoderFAC(){}
+	virtual string GetTagName(void);
+	virtual void DecodeTag(CVector<_BINARY>& vecbiTag, const int iLenDataBits);
+	CVector<_BINARY> vecbidata;
+};
+
+class CTagItemDecoderSDC : public CTagItemDecoder       
+{
+public:
+	CTagItemDecoderSDC(){}
+	virtual string GetTagName(void);
+	virtual void DecodeTag(CVector<_BINARY>& vecbiTag, const int iLenDataBits);
+	CVector<_BINARY> vecbidata;
+};
+
+class CTagItemDecoderRobMod : public CTagItemDecoder    
+{
+public:
+	CTagItemDecoderRobMod(){}
+	virtual string GetTagName(void);
+	virtual void DecodeTag(CVector<_BINARY>& vecbiTag, const int iLenDataBits);
+	CVector<_BINARY> vecbidata;
+	ERobMode	eRobMode;
+};
+
+class CTagItemDecoderStr : public CTagItemDecoder       
+{
+public:
+	CTagItemDecoderStr() : vecbidata(),iStreamNumber(0) {}
+	virtual void DecodeTag(CVector<_BINARY>& vecbiTag, const int iLenDataBits);
+	virtual string GetTagName(void);
+	CVector<_BINARY> vecbidata;
+	int iStreamNumber;
+};
+
+class CTagItemDecoderSDCChanInf : public CTagItemDecoderRSI
+{
+public:
+    CTagItemDecoderSDCChanInf(CParameter* pP) : CTagItemDecoderRSI(pP, "sdci") {}
+	virtual string GetTagName(void);
+	virtual void DecodeTag(CVector<_BINARY>& vecbiTag, const int iLenDataBits);
+	CVector<_BINARY> vecbidata;
+};
+
+class CTagItemDecoderInfo : public CTagItemDecoder      
+{
+public:
+	CTagItemDecoderInfo(){}
+	virtual string GetTagName(void);
+	virtual void DecodeTag(CVector<_BINARY>& vecbiTag, const int iLenDataBits);
+	string strInfo;
+};
+
+class CTagItemDecoderRxDemodMode : public CTagItemDecoder
+{
+public:
+		CTagItemDecoderRxDemodMode() : eMode(RM_DRM){}
+		virtual string GetTagName(void);
+		virtual void DecodeTag(CVector<_BINARY>& vecbiTag, const int iLenDataBits);
+		ERecMode eMode;
+};
+
+class CTagItemDecoderAMAudio : public CTagItemDecoder
+{
+public:
+		CTagItemDecoderAMAudio() : vecbidata() {}
+		virtual void DecodeTag(CVector<_BINARY>& vecbiTag, const int iLenDataBits);
+		virtual string GetTagName(void);
+		CVector<_BINARY> vecbidata;
+		CAudioParam AudioParams;
+};
+
+#endif
diff --git a/src/MDI/MDITagItems.cpp b/src/MDI/MDITagItems.cpp
new file mode 100644
index 0000000..37062cc
--- /dev/null
+++ b/src/MDI/MDITagItems.cpp
@@ -0,0 +1,1448 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer, Julian Cable, Oliver Haffenden, Andrew Murphy
+ *
+ * Description:
+ *	Implements Digital Radio Mondiale (DRM) Multiplex Distribution Interface
+ *	(MDI), Receiver Status and Control Interface (RSCI)
+ *  and Distribution and Communications Protocol (DCP) as described in
+ *	ETSI TS 102 820,  ETSI TS 102 349 and ETSI TS 102 821 respectively.
+ *
+ *  This module derives, from the CTagItemGenerator base class, tag item generators
+ *  specialised to generate each of the tag items defined in MDI and RSCI.
+ *  .
+ *  An intermediate derived class, CTagItemGeneratorWithProfiles, is used as the
+ *  base class for all these tag item generators. This takes care of the common
+ *	task of checking whether a given tag is in a particular profile.
+ *  The profiles for each tag are defined by the GetProfiles() member function.
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include <time.h>
+#include "MDITagItems.h"
+#include <iostream>
+#include <fstream>
+using namespace std;
+
+#include "../util/LogPrint.h"
+
+CTagItemGeneratorWithProfiles::CTagItemGeneratorWithProfiles()
+{
+}
+
+_BOOLEAN
+CTagItemGeneratorWithProfiles::IsInProfile(char cProfile)
+{
+	string strProfiles = GetProfiles();
+
+	for (size_t i = 0; i < strProfiles.length(); i++)
+		if (strProfiles[i] == char (toupper(cProfile)))
+			return TRUE;
+
+	return FALSE;
+}
+
+_BOOLEAN
+CTagItemGenerator::IsInProfile(char)
+{
+	return TRUE;
+}
+
+/* Default implementation: unless otherwise specified, tag will be in all RSCI profiles, but not MDI */
+/* Make this pure virtual and remove the implementation if you want to force all tags to specify the profiles explicitly */
+string
+CTagItemGeneratorWithProfiles::GetProfiles()
+{
+	return "ABCDQ";
+}
+
+void
+CTagItemGeneratorProTyMDI::GenTag()
+{
+	/* Length: 8 bytes = 64 bits */
+	PrepareTag(64);
+
+	/* Protocol type: DMDI */
+	Enqueue((uint32_t) 'D', SIZEOF__BYTE);
+	Enqueue((uint32_t) 'M', SIZEOF__BYTE);
+	Enqueue((uint32_t) 'D', SIZEOF__BYTE);
+	Enqueue((uint32_t) 'I', SIZEOF__BYTE);
+
+	/* Major revision */
+	Enqueue((uint32_t) MDI_MAJOR_REVISION, 16);
+
+	/* Minor revision */
+	Enqueue((uint32_t) MDI_MINOR_REVISION, 16);
+}
+
+string
+CTagItemGeneratorProTyMDI::GetTagName()
+{
+	return "*ptr";
+}
+
+string
+CTagItemGeneratorProTyMDI::GetProfiles()
+{
+	return "ADM";
+}
+
+void
+CTagItemGeneratorProTyRSCI::GenTag()
+{
+	/* Length: 8 bytes = 64 bits */
+	PrepareTag(64);
+
+	/* Protocol type: DMDI */
+	Enqueue((uint32_t) 'R', SIZEOF__BYTE);
+	Enqueue((uint32_t) 'S', SIZEOF__BYTE);
+	Enqueue((uint32_t) 'C', SIZEOF__BYTE);
+	Enqueue((uint32_t) 'I', SIZEOF__BYTE);
+
+	/* Major revision */
+	Enqueue((uint32_t) RSCI_MAJOR_REVISION, 16);
+
+	/* Minor revision */
+	Enqueue((uint32_t) RSCI_MINOR_REVISION, 16);
+}
+
+string
+CTagItemGeneratorProTyRSCI::GetTagName()
+{
+	return "*ptr";
+}
+
+string
+CTagItemGeneratorProTyRSCI::GetProfiles()
+{
+	return "ABCDQ";
+}
+
+CTagItemGeneratorLoFrCnt::CTagItemGeneratorLoFrCnt():iLogFraCnt(0)
+{
+}
+
+void
+CTagItemGeneratorLoFrCnt::GenTag()
+{
+	/* Length: 4 bytes = 32 bits */
+	PrepareTag(32);
+
+	/* Logical frame count */
+	Enqueue(iLogFraCnt, 32);
+
+	/* Count: the value shall be incremented by one by the device generating the
+	   MDI Packets for each MDI Packet sent. Wraps around at a value of
+	   "(1 << 32)" since the variable type is "uint32_t" */
+	iLogFraCnt++;
+}
+
+string
+CTagItemGeneratorLoFrCnt::GetTagName()
+{
+	return "dlfc";
+}
+
+string
+CTagItemGeneratorLoFrCnt::GetProfiles()
+{
+	return "ABCDQM";
+}
+
+void
+CTagItemGeneratorFAC::GenTag(CParameter & Parameter, CSingleBuffer < _BINARY > &FACData)
+{
+	if (Parameter.ReceiveStatus.FAC.GetStatus() == FALSE)
+	{
+		/* Empty tag if FAC is invalid */
+		PrepareTag(0);
+		FACData.Clear();
+	}
+	else
+	{
+		/* Length: 9 bytes = 72 bits */
+        PrepareTag(Parameter.iNumFACBitsPerBlock);
+        CVectorEx < _BINARY > *pvecbiFACData = FACData.Get(Parameter.iNumFACBitsPerBlock);
+
+		/* Channel parameters, service parameters, CRC */
+		pvecbiFACData->ResetBitAccess();
+
+        /* FAC data is always n bytes, copy data byte-wise */
+        for (int i = 0; i < Parameter.iNumFACBitsPerBlock / SIZEOF__BYTE; i++)
+			Enqueue(pvecbiFACData->Separate(SIZEOF__BYTE), SIZEOF__BYTE);
+	}
+}
+
+string
+CTagItemGeneratorFAC::GetTagName()
+{
+	return "fac_";
+}
+
+string
+CTagItemGeneratorFAC::GetProfiles()
+{
+	return "ACDQM";
+}
+
+void
+CTagItemGeneratorSDC::GenTag(CParameter & Parameter, CSingleBuffer < _BINARY > &SDCData)
+{
+	if (Parameter.ReceiveStatus.SDC.GetStatus() == FALSE)
+	{
+		PrepareTag(0);
+		SDCData.Clear();
+		return;
+	}
+
+	if (SDCData.GetFillLevel() < Parameter.iNumSDCBitsPerSFrame)
+	{
+		PrepareTag(0);
+		return;
+	}
+
+	/* Fixed by O.Haffenden, BBC R&D */
+	/* The input SDC vector is 4 bits SDC index + a whole number of bytes plus padding. */
+	/* The padding is not sent in the MDI */
+	const int iLenSDCDataBits = SIZEOF__BYTE * ((Parameter.iNumSDCBitsPerSFrame - 4) / SIZEOF__BYTE) + 4;
+
+	/* Length: "length SDC block" bytes. Our SDC data vector does not
+	   contain the 4 bits "Rfu" */
+	PrepareTag(iLenSDCDataBits + 4);
+	CVectorEx < _BINARY > *pvecbiSDCData = SDCData.Get(Parameter.iNumSDCBitsPerSFrame);
+
+	/* Service Description Channel Block */
+	pvecbiSDCData->ResetBitAccess();
+
+	Enqueue((uint32_t) 0, 4);	/* Rfu */
+
+	/* We have to copy bits instead of bytes since the length of SDC data is
+	   usually not a multiple of 8 */
+	for (int i = 0; i < iLenSDCDataBits; i++)
+		Enqueue(pvecbiSDCData->Separate(1), 1);
+}
+
+string
+CTagItemGeneratorSDC::GetTagName()
+{
+	return "sdc_";
+}
+
+string
+CTagItemGeneratorSDC::GetProfiles()
+{
+	return "ACDM";
+}
+
+void
+CTagItemGeneratorSDCChanInf::GenTag(CParameter & Parameter)
+{
+	set<int> actStreams;
+
+	/* Get active streams */
+	Parameter.GetActiveStreams(actStreams);
+
+	/* Get number of active streams */
+	const size_t iNumActStreams = actStreams.size();
+
+	/* Length: 1 + n * 3 bytes */
+	PrepareTag((1 + 3 * iNumActStreams) * SIZEOF__BYTE);
+
+	/* Protection */
+	/* Rfu */
+	Enqueue((uint32_t) 0, 4);
+
+	/* PLA */
+	Enqueue((uint32_t) Parameter.MSCPrLe.iPartA, 2);
+
+	/* PLB */
+	Enqueue((uint32_t) Parameter.MSCPrLe.iPartB, 2);
+
+	/* n + 1 stream description(s) */
+	for (set<int>::iterator i = actStreams.begin(); i!=actStreams.end(); i++)
+	{
+		/* In case of hirachical modulation stream 0 describes the protection
+		   level and length of hierarchical data */
+		if ((*i == 0) &&
+			((Parameter.eMSCCodingScheme == CS_3_HMSYM) ||
+			 (Parameter.eMSCCodingScheme == CS_3_HMMIX)))
+		{
+			/* Protection level for hierarchical */
+			Enqueue((uint32_t) Parameter.MSCPrLe.iHierarch, 2);
+
+			/* rfu */
+			Enqueue((uint32_t) 0, 10);
+
+			/* Data length for hierarchical (always stream 0) */
+			Enqueue((uint32_t) Parameter.Stream[0].iLenPartB, 12);
+		}
+		else
+		{
+			/* Data length for part A */
+			Enqueue((uint32_t) Parameter.Stream[*i].iLenPartA, 12);
+
+			/* Data length for part B */
+			Enqueue((uint32_t) Parameter.Stream[*i].iLenPartB, 12);
+		}
+	}
+}
+
+string
+CTagItemGeneratorSDCChanInf::GetTagName()
+{
+	return "sdci";
+}
+
+string
+CTagItemGeneratorSDCChanInf::GetProfiles()
+{
+	return "ACDQM";
+}
+
+void
+CTagItemGeneratorRobMod::GenTag(ERobMode eCurRobMode)
+{
+	/* Length: 1 byte */
+	PrepareTag(SIZEOF__BYTE);
+
+	/* Robustness mode */
+	switch (eCurRobMode)
+	{
+	case RM_ROBUSTNESS_MODE_A:
+		Enqueue((uint32_t) 0, 8);
+		break;
+
+	case RM_ROBUSTNESS_MODE_B:
+		Enqueue((uint32_t) 1, 8);
+		break;
+
+	case RM_ROBUSTNESS_MODE_C:
+		Enqueue((uint32_t) 2, 8);
+		break;
+
+	case RM_ROBUSTNESS_MODE_D:
+		Enqueue((uint32_t) 3, 8);
+		break;
+
+	default:
+		break;
+	}
+}
+
+string
+CTagItemGeneratorRobMod::GetTagName()
+{
+	return "robm";
+}
+
+string
+CTagItemGeneratorRobMod::GetProfiles()
+{
+	return "ABCDQM";
+}
+
+void
+CTagItemGeneratorRINF::GenTag(string strUTF8Text)
+{
+	/* Data length: n * 8 bits */
+	PrepareTag(16 * SIZEOF__BYTE);
+
+	/* UTF-8 text */
+	for (int i = 0; i < 16; i++)	// truncate to 16 chars as this is the max the TAG item can have
+	{
+		const char cNewChar = strUTF8Text[i];
+
+		/* Set character */
+		Enqueue((uint32_t) cNewChar, SIZEOF__BYTE);
+	}
+}
+
+string
+CTagItemGeneratorRINF::GetTagName()
+{
+	return "rinf";
+}
+
+string
+CTagItemGeneratorRINF::GetProfiles()
+{
+	return "ABCDQ";
+}
+
+CTagItemGeneratorStr::CTagItemGeneratorStr():iStreamNumber(0)
+{
+}
+
+// Sets the stream number. Should be called just after construction. (can't have it in the constructor because
+// we want a vector of them
+
+void
+CTagItemGeneratorStr::SetStreamNumber(int iStrNum)
+{
+	iStreamNumber = iStrNum;
+}
+
+void
+CTagItemGeneratorStr::GenTag(CParameter & Parameter, CSingleBuffer < _BINARY > &MSCData)
+{
+	const int iLenStrData = SIZEOF__BYTE * Parameter.GetStreamLen(iStreamNumber);
+	/* Only generate this tag if stream input data is not of zero length */
+	if (iLenStrData == 0)
+		return;
+
+	CVectorEx < _BINARY > *pvecbiStrData = MSCData.Get(iLenStrData);
+	/* check we have data in the vector */
+	if (iLenStrData != pvecbiStrData->Size())
+		return;
+
+	if (iStreamNumber >= MAX_NUM_STREAMS)
+		return;
+
+	PrepareTag(iLenStrData);
+
+	pvecbiStrData->ResetBitAccess();
+	/* Data is always a multiple of 8 -> copy bytes */
+	for (int i = 0; i < iLenStrData / SIZEOF__BYTE; i++)
+	{
+		Enqueue(pvecbiStrData->Separate(SIZEOF__BYTE), SIZEOF__BYTE);
+	}
+}
+
+string
+CTagItemGeneratorStr::GetProfiles()
+{
+	return "ADM";
+}
+
+string
+CTagItemGeneratorStr::GetTagName()
+{
+	switch (iStreamNumber)
+	{
+	case 0:
+		return "str0";
+	case 1:
+		return "str1";
+	case 2:
+		return "str2";
+	case 3:
+		return "str3";
+	default:
+		return "str?";
+	}
+}
+
+void
+CTagItemGeneratorMERFormat::GenTag(_BOOLEAN bIsValid, _REAL rMER)
+{
+	/* Common routine for rmer, rwmf, rwmm tags (all have the same format) */
+	/* If no MER value is available, set tag length to zero */
+	if (bIsValid == FALSE)
+	{
+		/* Length: 0 byte */
+		PrepareTag(0);
+	}
+	else
+	{
+		/* Length: 2 bytes = 16 bits */
+		PrepareTag(16);
+
+		/* Set value: the format of this single value is (Byte1 + Byte2 / 256)
+		   = (Byte1.Byte2) in [dB] with: Byte1 is an 8-bit signed integer value;
+		   and Byte2 is an 8-bit unsigned integer value */
+		/* Integer part */
+		Enqueue((uint32_t) rMER, SIZEOF__BYTE);
+
+		/* Fractional part */
+		const _REAL rFracPart = rMER - (int) rMER;
+		Enqueue((uint32_t) (rFracPart * 256), SIZEOF__BYTE);
+	}
+}
+
+string
+CTagItemGeneratorRWMF::GetTagName()
+{
+	return "rwmf";
+}
+
+string
+CTagItemGeneratorRWMF::GetProfiles()
+{
+	return "ABCDQ";
+}
+
+string
+CTagItemGeneratorRWMM::GetTagName()
+{
+	return "rwmm";
+}
+
+string
+CTagItemGeneratorRWMM::GetProfiles()
+{
+	return "ABCDQ";
+}
+
+string
+CTagItemGeneratorRMER::GetTagName()
+{
+	return "rmer";
+}
+
+string
+CTagItemGeneratorRMER::GetProfiles()
+{
+	return "ABCDQ";
+}
+
+string
+CTagItemGeneratorRDOP::GetTagName()
+{
+	return "rdop";
+}
+
+string
+CTagItemGeneratorRDOP::GetProfiles()
+{
+	return "ABCDQ";
+}
+
+void
+CTagItemGeneratorRDEL::GenTag(_BOOLEAN bIsValid, const CRealVector & vecrThresholds, const CRealVector & vecrIntervals)
+{
+	/* If no value is available, set tag length to zero */
+	if (bIsValid == FALSE)
+	{
+		/* Length: 0 byte */
+		PrepareTag(0);
+	}
+	else
+	{
+		/* Length: 3 bytes per value = 16 bits */
+		PrepareTag(24 * vecrThresholds.GetSize());
+
+		for (int i = 0; i < vecrThresholds.GetSize(); i++)
+		{
+			/* percentage for this window */
+			Enqueue((uint32_t) vecrThresholds[i], SIZEOF__BYTE);
+			/* Set value: the format of this single value is (Byte1 + Byte2 / 256)
+			   = (Byte1.Byte2) in [dB] with: Byte1 is an 8-bit signed integer value;
+			   and Byte2 is an 8-bit unsigned integer value */
+			/* Integer part */
+			_REAL rDelay = vecrIntervals[i];
+			Enqueue((uint32_t) rDelay, SIZEOF__BYTE);
+
+			/* Fractional part */
+			const _REAL rFracPart = rDelay - (int) rDelay;
+			Enqueue((uint32_t) (rFracPart * 256), SIZEOF__BYTE);
+		}
+	}
+}
+
+string
+CTagItemGeneratorRDEL::GetTagName()
+{
+	return "rdel";
+}
+
+string
+CTagItemGeneratorRDEL::GetProfiles()
+{
+	return "ABCDQ";
+}
+
+void
+CTagItemGeneratorRAFS::GenTag(CParameter & Parameter)
+{
+	const int iNumUnits = Parameter.vecbiAudioFrameStatus.Size();
+
+	if (iNumUnits == 0)
+	{
+		/* zero length tag item */
+		PrepareTag(0);
+	}
+	else
+	{
+		/* Header - length is always 48 */
+		PrepareTag(48);
+
+		/* data */
+		Parameter.vecbiAudioFrameStatus.ResetBitAccess();
+
+		/* number of units: 8 bits */
+		Enqueue(iNumUnits, 8);
+
+		/* status for each unit */
+		for (int i = 0; i < iNumUnits; i++)
+		{
+			Enqueue(Parameter.vecbiAudioFrameStatus.Separate(1), 1);
+		}
+		/* pad the rest with zeros */
+		Enqueue(0, 40 - iNumUnits);
+	}
+}
+
+string
+CTagItemGeneratorRAFS::GetTagName()
+{
+	return "rafs";
+}
+
+string
+CTagItemGeneratorRAFS::GetProfiles()
+{
+	return "ABCDQ";
+}
+
+void
+CTagItemGeneratorRINT::GenTag(_BOOLEAN bIsValid, CReal rIntFreq, CReal rINR, CReal rICR)
+{
+
+	/* Use Bint (BBC proprietary tag name) until tag is accepted by SE group */
+	/* If no value is available, set tag length to zero */
+	if (bIsValid == FALSE)
+	{
+		/* Length: 0 byte */
+		PrepareTag(0);
+	}
+	else
+	{
+		/* Length: 2 bytes per value, 3 values = 48 bits */
+		PrepareTag(48);
+
+		/* Interference frequency (Hz) : signed value */
+		Enqueue((uint32_t) ((int) rIntFreq), 16);
+
+		/* Interference-to-noise ratio */
+		/* integer part */
+		Enqueue((uint32_t) rINR, SIZEOF__BYTE);
+		/* Fractional part */
+		Enqueue((uint32_t) ((rINR - (int) rINR) * 256), SIZEOF__BYTE);
+
+		/* Interference-to-carrier ratio */
+		/* integer part */
+		Enqueue((uint32_t) rICR, SIZEOF__BYTE);
+		/* Fractional part */
+		Enqueue((uint32_t) ((rICR - (int) rICR) * 256), SIZEOF__BYTE);
+
+	}
+
+}
+
+string
+CTagItemGeneratorRINT::GetTagName()
+{
+	return "Bint";
+}
+
+string
+CTagItemGeneratorRINT::GetProfiles()
+{
+	return "ABCDQ";
+}
+
+void
+CTagItemGeneratorRNIP::GenTag(_BOOLEAN bIsValid, CReal rIntFreq, CReal rISR)
+{
+
+	/* If no value is available, set tag length to zero */
+	if (bIsValid == FALSE)
+	{
+		/* Length: 0 byte */
+		PrepareTag(0);
+	}
+	else
+	{
+		/* Length: 2 bytes per value, 2 values = 32 bits */
+		PrepareTag(32);
+
+		/* Interference frequency (Hz) : signed value */
+		Enqueue((uint32_t) ((int) rIntFreq), 16);
+
+		/* Interference-to-signal ratio */
+		/* integer part */
+		Enqueue((uint32_t) ((int) (rISR * 256)), 16);
+	}
+}
+
+string
+CTagItemGeneratorRNIP::GetTagName()
+{
+	return "rnip";
+}
+
+string
+CTagItemGeneratorRNIP::GetProfiles()
+{
+	return "ABCDQ";
+}
+
+void
+CTagItemGeneratorSignalStrength::GenTag(_BOOLEAN bIsValid, _REAL rSigStrength)
+{
+	if (bIsValid == FALSE)
+	{
+		PrepareTag(0);
+	}
+	else
+	{
+		PrepareTag(16);
+		Enqueue((uint32_t) ((int) (rSigStrength * 256)), 16);
+	}
+}
+
+string
+CTagItemGeneratorSignalStrength::GetTagName()
+{
+	return "rdbv";
+}
+
+string
+CTagItemGeneratorSignalStrength::GetProfiles()
+{
+	return "ABCDQ";
+}
+
+void
+CTagItemGeneratorReceiverStatus::GenTag(CParameter & Parameter)
+{
+	PrepareTag(4 * SIZEOF__BYTE);
+	Enqueue(Parameter.ReceiveStatus.TSync.GetStatus() == RX_OK ? 0 : 1, SIZEOF__BYTE);	/* 0=ok, 1=bad */
+	Enqueue(Parameter.ReceiveStatus.FAC.GetStatus() == RX_OK ? 0 : 1, SIZEOF__BYTE);	/* 0=ok, 1=bad */
+	Enqueue(Parameter.ReceiveStatus.SDC.GetStatus() == RX_OK ? 0 : 1, SIZEOF__BYTE);	/* 0=ok, 1=bad */
+	int iShortID = Parameter.GetCurSelAudioService();
+	Enqueue(Parameter.AudioComponentStatus[iShortID].GetStatus() == RX_OK ? 0 : 1, SIZEOF__BYTE);	/* 0=ok, 1=bad */
+}
+
+string
+CTagItemGeneratorReceiverStatus::GetTagName()
+{
+	return "rsta";
+}
+
+string
+CTagItemGeneratorReceiverStatus::GetProfiles()
+{
+	return "ABCDQ";
+}
+
+void
+CTagItemGeneratorProfile::GenTag(char cProfile)
+{
+	PrepareTag(8);
+	Enqueue((uint32_t) cProfile, SIZEOF__BYTE);
+}
+
+string
+CTagItemGeneratorProfile::GetTagName()
+{
+	return "rpro";
+}
+
+string
+CTagItemGeneratorProfile::GetProfiles()
+{
+	return "ABCDQ";
+}
+
+void
+CTagItemGeneratorRxDemodMode::GenTag(ERecMode eMode)	// rdmo
+{
+	PrepareTag(4 * SIZEOF__BYTE);
+	switch (eMode)
+	{
+	case RM_DRM:
+		Enqueue((uint32_t) 'd', SIZEOF__BYTE);
+		Enqueue((uint32_t) 'r', SIZEOF__BYTE);
+		Enqueue((uint32_t) 'm', SIZEOF__BYTE);
+		Enqueue((uint32_t) '_', SIZEOF__BYTE);
+		break;
+	case RM_AM:
+		Enqueue((uint32_t) 'a', SIZEOF__BYTE);
+		Enqueue((uint32_t) 'm', SIZEOF__BYTE);
+		Enqueue((uint32_t) '_', SIZEOF__BYTE);
+		Enqueue((uint32_t) '_', SIZEOF__BYTE);
+		break;
+	case RM_FM:
+		Enqueue((uint32_t) 'f', SIZEOF__BYTE);
+		Enqueue((uint32_t) 'm', SIZEOF__BYTE);
+		Enqueue((uint32_t) '_', SIZEOF__BYTE);
+		Enqueue((uint32_t) '_', SIZEOF__BYTE);
+		break;
+	default:
+		Enqueue((uint32_t) ' ', SIZEOF__BYTE);
+		Enqueue((uint32_t) ' ', SIZEOF__BYTE);
+		Enqueue((uint32_t) ' ', SIZEOF__BYTE);
+		Enqueue((uint32_t) ' ', SIZEOF__BYTE);
+		break;
+	}
+
+}
+
+string
+CTagItemGeneratorRxDemodMode::GetTagName()
+{
+	return "rdmo";
+}
+
+string
+CTagItemGeneratorRxDemodMode::GetProfiles()
+{
+	return "ABCDQ";
+}
+
+void
+CTagItemGeneratorRxFrequency::GenTag(_BOOLEAN bIsValid, int iFrequency)	// Frequency in kHz
+{
+	if (bIsValid == FALSE)
+	{
+		PrepareTag(0);
+	}
+	else
+	{
+		PrepareTag(4 * SIZEOF__BYTE);
+		Enqueue((uint32_t) iFrequency * 1000, 4 * SIZEOF__BYTE);
+	}
+}
+
+string
+CTagItemGeneratorRxFrequency::GetTagName()
+{
+	return "rfre";
+}
+
+string
+CTagItemGeneratorRxFrequency::GetProfiles()
+{
+	return "ABCDQ";
+}
+
+void
+CTagItemGeneratorRxActivated::GenTag(_BOOLEAN bActivated)
+{
+	PrepareTag(SIZEOF__BYTE);
+	Enqueue(bActivated == TRUE ? '0' : '1', SIZEOF__BYTE);
+}
+
+string
+CTagItemGeneratorRxActivated::GetTagName()
+{
+	return "ract";
+}
+
+string
+CTagItemGeneratorRxActivated::GetProfiles()
+{
+	return "ABCDQ";
+}
+
+void
+CTagItemGeneratorRxBandwidth::GenTag(_BOOLEAN bIsValid, _REAL rBandwidth)
+{
+	if (bIsValid == FALSE)
+	{
+		PrepareTag(0);
+	}
+	else
+	{
+		PrepareTag(2 * SIZEOF__BYTE);
+		Enqueue((uint32_t) ((int) (rBandwidth * 256.0)), 2 * SIZEOF__BYTE);
+	}
+}
+
+string
+CTagItemGeneratorRxBandwidth::GetTagName()
+{
+	return "rbw_";
+}
+
+string
+CTagItemGeneratorRxBandwidth::GetProfiles()
+{
+	return "ABCDQ";
+}
+
+void
+CTagItemGeneratorRxService::GenTag(_BOOLEAN bIsValid, int iService)
+{
+	if (bIsValid == FALSE)
+	{
+		PrepareTag(0);
+	}
+	else
+	{
+		PrepareTag(SIZEOF__BYTE);
+		Enqueue((uint32_t) iService, SIZEOF__BYTE);
+	}
+}
+
+string
+CTagItemGeneratorRxService::GetTagName()
+{
+	return "rser";
+}
+
+string
+CTagItemGeneratorRxService::GetProfiles()
+{
+	return "ABCDQ";
+}
+
+CTagItemGeneratorRBP::CTagItemGeneratorRBP()
+{
+}
+
+void
+CTagItemGeneratorRBP::SetStreamNumber(int iStrNum)
+{
+	iStreamNumber = iStrNum;
+}
+
+void
+CTagItemGeneratorRBP::GenTag()	// Not yet implemented
+{
+}
+
+string
+CTagItemGeneratorRBP::GetTagName()
+{
+	switch (iStreamNumber)
+	{
+	case 0:
+		return "rbp0";
+	case 1:
+		return "rbp1";
+	case 2:
+		return "rbp2";
+	case 3:
+		return "rbp3";
+	default:
+		return "rbp?";			// error!
+	}
+}
+
+string
+CTagItemGeneratorRBP::GetProfiles()
+{
+	return "ABCD";
+}
+
+// Call this to write the binary data (header + payload) to the vector
+void
+CTagItemGenerator::PutTagItemData(CVector < _BINARY > &vecbiDestination)
+{
+	vecbiTagData.ResetBitAccess();
+	for (int i = 0; i < vecbiTagData.Size(); i++)
+		vecbiDestination.Enqueue(vecbiTagData.Separate(1), 1);
+}
+
+void
+CTagItemGenerator::Reset()	// Resets bit vector to zero length (i.e. no header)
+{
+	vecbiTagData.Init(0);
+}
+
+void
+CTagItemGenerator::GenEmptyTag()	// Generates valid tag item with zero payload length
+{
+	PrepareTag(0);
+}
+
+// Prepare vector and make the header
+void
+CTagItemGenerator::PrepareTag(int iLenDataBits)
+{
+	string strTagName = GetTagName();
+	/* Init vector length. 4 bytes for tag name and 4 bytes for data length
+	   plus the length of the actual data */
+	vecbiTagData.Init(8 * SIZEOF__BYTE + iLenDataBits);
+	vecbiTagData.ResetBitAccess();
+
+	/* Set tag name (always four bytes long) */
+	for (int i = 0; i < 4; i++)
+		vecbiTagData.Enqueue((uint32_t) strTagName[i], SIZEOF__BYTE);
+
+	/* Set tag data length */
+	vecbiTagData.Enqueue((uint32_t) iLenDataBits, 32);
+
+}
+
+// Put the bits to the bit vector (avoids derived classes needing to access the bit vector directly
+void
+CTagItemGenerator::Enqueue(uint32_t iInformation, int iNumOfBits)
+{
+	vecbiTagData.Enqueue(iInformation, iNumOfBits);
+}
+
+/* TODO: there are still some RSCI tags left to implement */
+/* e.g. rpil, rpsd, ... */
+
+//andrewm - 2001-2014-12-08
+void
+CTagItemGeneratorGPS::GenTag(_BOOLEAN bIsValid, gps_data_t& gps_data)	// Long/Lat in degrees
+{
+	if (bIsValid == FALSE)
+	{
+		PrepareTag(0);
+	}
+	else
+	{
+		uint32_t source = 0xff; // GPS_SOURCE_NOT_AVAILABLE
+		PrepareTag(26 * SIZEOF__BYTE);
+		if(gps_data.set&STATUS_SET) {
+			switch(gps_data.status) {
+			case 0: source = 3; break; // manual
+			case 1: source = 1; break; // gps
+			case 2: source = 2; break; // differential
+			}
+		}
+		Enqueue(source, SIZEOF__BYTE);
+
+		if (gps_data.set&SATELLITE_SET)
+		{
+			Enqueue((uint32_t) gps_data.satellites_used, SIZEOF__BYTE);
+		}
+		else
+		{
+			Enqueue((uint32_t) 0xff, SIZEOF__BYTE);
+		}
+
+		if (gps_data.set&LATLON_SET)
+		{
+			double latitude, longitude;
+			int iLatitudeDegrees;
+			uint8_t uiLatitudeMinutes;
+			uint16_t uiLatitudeMinuteFractions;
+
+			int iLongitudeDegrees;
+			uint8_t uiLongitudeMinutes;
+			uint16_t uiLongitudeMinuteFractions;
+
+			latitude = gps_data.fix.latitude;
+			longitude = gps_data.fix.longitude;
+
+			if (latitude >= 0)
+				iLatitudeDegrees = (int) latitude;
+			else
+				iLatitudeDegrees = (int) latitude - 1;
+
+			uiLatitudeMinutes =
+				(uint8_t) (60.0 * (latitude - iLatitudeDegrees));
+			uiLatitudeMinuteFractions =
+				(uint16_t) (((60.0 * (latitude - iLatitudeDegrees)) -
+							 uiLatitudeMinutes) * 65536.0);
+
+			if (longitude >= 0)
+				iLongitudeDegrees = (int) longitude;
+			else
+				iLongitudeDegrees = (int) longitude - 1;
+
+			uiLongitudeMinutes =
+				(uint8_t) (60.0 * (longitude - iLongitudeDegrees));
+			uiLongitudeMinuteFractions =
+				(uint16_t) (((60.0 * (longitude - iLongitudeDegrees)) -
+							 uiLongitudeMinutes) * 65536.0);
+
+			Enqueue((uint32_t) iLatitudeDegrees, 2 * SIZEOF__BYTE);
+			Enqueue((uint32_t) uiLatitudeMinutes, SIZEOF__BYTE);
+			Enqueue((uint32_t) uiLatitudeMinuteFractions, 2 * SIZEOF__BYTE);
+			Enqueue((uint32_t) iLongitudeDegrees, 2 * SIZEOF__BYTE);
+			Enqueue((uint32_t) uiLongitudeMinutes, SIZEOF__BYTE);
+			Enqueue((uint32_t) uiLongitudeMinuteFractions, 2 * SIZEOF__BYTE);
+		}
+		else
+		{
+			Enqueue((uint32_t) 0xffff, 2 * SIZEOF__BYTE);
+			Enqueue((uint32_t) 0xffff, SIZEOF__BYTE);
+			Enqueue((uint32_t) 0xffff, 2 * SIZEOF__BYTE);
+			Enqueue((uint32_t) 0xffff, 2 * SIZEOF__BYTE);
+			Enqueue((uint32_t) 0xffff, SIZEOF__BYTE);
+			Enqueue((uint32_t) 0xffff, 2 * SIZEOF__BYTE);
+		}
+
+		if (gps_data.set&ALTITUDE_SET)
+		{
+			double altitude = gps_data.fix.altitude;
+			int iAltitudeMetres;
+			uint8_t uiAltitudeMetreFractions;
+
+			if (altitude >= 0)
+				iAltitudeMetres = (int) altitude;
+			else
+				iAltitudeMetres = (int) (altitude - 1);
+
+			uiAltitudeMetreFractions = (uint8_t) (256.0 * (altitude - iAltitudeMetres));
+
+			Enqueue((uint32_t) iAltitudeMetres, 2 * SIZEOF__BYTE);
+			Enqueue((uint32_t) uiAltitudeMetreFractions, SIZEOF__BYTE);
+		}
+		else
+		{
+			Enqueue((uint32_t) 0xffff, 2 * SIZEOF__BYTE);
+			Enqueue((uint32_t) 0xff, SIZEOF__BYTE);
+		}
+
+		if (gps_data.set&TIME_SET)
+		{
+			time_t time = (time_t)gps_data.fix.time;
+			struct tm * ptm;
+			ptm = gmtime ( &time );
+			Enqueue((uint32_t) ptm->tm_hour, SIZEOF__BYTE);
+			Enqueue((uint32_t) ptm->tm_min, SIZEOF__BYTE);
+			Enqueue((uint32_t) ptm->tm_sec, SIZEOF__BYTE);
+			Enqueue(1900+ptm->tm_year, 2*SIZEOF__BYTE);
+			Enqueue((uint32_t) ptm->tm_mon+1, SIZEOF__BYTE);
+			Enqueue((uint32_t) ptm->tm_mday, SIZEOF__BYTE);
+		}
+		else
+		{
+			Enqueue((uint32_t) 0xff, SIZEOF__BYTE);
+			Enqueue((uint32_t) 0xff, SIZEOF__BYTE);
+			Enqueue((uint32_t) 0xff, SIZEOF__BYTE);
+			Enqueue((uint32_t) 0xff, SIZEOF__BYTE);
+			Enqueue((uint32_t) 0xffff, 2 * SIZEOF__BYTE);
+			Enqueue((uint32_t) 0xff, SIZEOF__BYTE);
+		}
+
+		if (gps_data.set&SPEED_SET)
+		{
+			Enqueue((uint32_t) (gps_data.fix.speed * 10.0), 2 * SIZEOF__BYTE);
+		}
+		else
+		{
+			Enqueue((uint32_t) 0xffff, 2 * SIZEOF__BYTE);
+		}
+
+		if (gps_data.set&TRACK_SET)
+		{
+			Enqueue((uint32_t) gps_data.fix.track, 2 * SIZEOF__BYTE);
+		}
+		else
+		{
+			Enqueue((uint32_t) 0xffff, 2 * SIZEOF__BYTE);
+		}
+	}
+}
+
+string
+CTagItemGeneratorGPS::GetTagName()
+{
+	return "rgps";
+}
+
+string
+CTagItemGeneratorGPS::GetProfiles()
+{
+	return "AD";
+}
+
+void
+CTagItemGeneratorPowerSpectralDensity::GenTag(CParameter & Parameter)
+{
+	PrepareTag(Parameter.vecrPSD.Size() * SIZEOF__BYTE);
+
+	for (int i = 0; i < Parameter.vecrPSD.Size(); i++)
+	{
+		uint32_t p = uint8_t(Parameter.vecrPSD[i] * _REAL(-2.0));
+		Enqueue((uint32_t) p, SIZEOF__BYTE);
+	}
+
+}
+
+string
+CTagItemGeneratorPowerSpectralDensity::GetTagName()
+{
+	return "rpsd";
+}
+
+string
+CTagItemGeneratorPowerSpectralDensity::GetProfiles()
+{
+	return "AD";
+}
+
+void
+CTagItemGeneratorPowerImpulseResponse::GenTag(CParameter & Parameter)
+{
+	int samples = Parameter.vecrPIR.Size();
+	if(samples>0)
+	{
+		const _REAL rOffset = _REAL(-60.0);
+		PrepareTag(samples * SIZEOF__BYTE + 4 * SIZEOF__BYTE);
+
+		Enqueue(uint32_t(int(Parameter.rPIRStart * _REAL(256.0))), 2*SIZEOF__BYTE);
+		Enqueue(uint32_t(int(Parameter.rPIREnd * _REAL(256.0))), 2*SIZEOF__BYTE);
+		for (int i = 0; i < samples; i++)
+		{
+			uint32_t p = uint8_t((Parameter.vecrPIR[i]+rOffset) * _REAL(-2.0));
+			Enqueue((uint32_t) p, SIZEOF__BYTE);
+		}
+	} // else generate empty tag
+}
+
+string
+CTagItemGeneratorPowerImpulseResponse::GetTagName()
+{
+	return "rpir";
+}
+
+string
+CTagItemGeneratorPowerImpulseResponse::GetProfiles()
+{
+	return "ADG";
+}
+
+string
+CTagItemGeneratorPilots::GetTagName()
+{
+	return "rpil";
+}
+
+string
+CTagItemGeneratorPilots::GetProfiles()
+{
+	return "AD";
+}
+
+void
+CTagItemGeneratorPilots::GenTag(CParameter & Parameter)
+{
+	const CCellMappingTable& Param = Parameter.CellMappingTable;
+	// Get parameters from parameter struct
+	int iScatPilTimeInt = Param.iScatPilTimeInt;
+	int iScatPilFreqInt = Param.iScatPilFreqInt;
+	int iNumCarrier = Param.iNumCarrier;
+	int iNumSymPerFrame = Param.iNumSymPerFrame;
+	/* do we need these ? */
+	//int iNumIntpFreqPil = Param.iNumIntpFreqPil;
+	//int iFFTSizeN = Param.iFFTSizeN;
+
+	// calculate the spacing between scattered pilots in a given symbol
+	int iScatPilFreqSpacing = iScatPilFreqInt * iScatPilTimeInt;
+
+	// Calculate how long the tag will be and write the fields that apply to the whole frame
+
+	// Total number of pilots = number of pilot bearing carriers * number of pilot pattern repeats per frame
+	// NB the DC carrier in mode D is INCLUDED in this calculation (and in the tag)
+	int iTotalNumPilots =
+		((iNumCarrier - 1) / iScatPilFreqInt +
+		 1) * iNumSymPerFrame / iScatPilTimeInt;
+
+	int iTagLen = 4 * SIZEOF__BYTE;	// first 4 bytes apply to the whole frame
+	iTagLen += iNumSymPerFrame * 4 * SIZEOF__BYTE;	// 4 bytes at start of each symbol (spec typo?)
+	iTagLen += iTotalNumPilots * 2 * 2 * SIZEOF__BYTE;	// 4 bytes per pilot value (2 byte re, 2 byte imag)
+
+	//log.GetStatus("rpil gentag: pilots %d tag length %d", iTotalNumPilots, iTagLen);
+
+	PrepareTag(iTagLen);
+
+	// fields for the whole frame
+	Enqueue((uint32_t) iNumSymPerFrame, SIZEOF__BYTE);	// SN = number of symbols
+	Enqueue((uint32_t) iScatPilTimeInt, SIZEOF__BYTE);	// SR = symbol repetition
+	Enqueue((uint32_t) 0, 2 * SIZEOF__BYTE);	// rfu
+
+	// Check that the matrix has the expected dimensions (in case of a mode change)
+	if (Parameter.matcReceivedPilotValues.NumRows() !=
+		iNumSymPerFrame / iScatPilTimeInt
+		|| Parameter.matcReceivedPilotValues.NumColumns() !=
+		((iNumCarrier - 1) / iScatPilFreqInt + 1))
+	{
+		GenEmptyTag();
+#if 0
+		log.GetStatus("Wrong size: %d x %d, expected %d x %d",
+				  Parameter.matcReceivedPilotValues.NumRows(),
+				  Parameter.matcReceivedPilotValues.NumColumns(),
+				  iNumSymPerFrame / iScatPilTimeInt,
+				  ((iNumCarrier - 1) / iScatPilFreqInt + 1));
+#endif
+		return;
+	}
+
+	// Now do each symbol in turn
+	for (int iSymbolNumber = 0; iSymbolNumber < iNumSymPerFrame;
+		 iSymbolNumber++)
+	{
+		// Which row of the matrix?
+		int iRow = iSymbolNumber / iScatPilTimeInt;
+		int i, iCarrier;
+
+		// Find the first pilot in this symbol (this could be calculated directly,
+		// but that calculation would belong in the CellMappingTable class)
+		int iFirstPilotCarrier = 0;
+
+		while (!_IsScatPil(Param.matiMapTab[iSymbolNumber][iFirstPilotCarrier]))
+		{
+			iFirstPilotCarrier += iScatPilFreqInt;
+		}
+
+		// Find the biggest value we need to represent for this symbol
+
+		_REAL rMax = _REAL(0.0);
+		int iNumPilots = 0;
+
+		// Start from first pilot and step by the pilot spacing (iScatPilFreqInt*iScatPilTimeInt)
+		for (i = iFirstPilotCarrier / iScatPilFreqInt, iCarrier =
+			 iFirstPilotCarrier; iCarrier < iNumCarrier;
+			 i += iScatPilTimeInt, iCarrier += iScatPilFreqSpacing)
+		{
+			iNumPilots++;
+			// Is it really a pilot? This will be false only in Mode D for the DC carrier
+			if (_IsScatPil(Param.matiMapTab[iSymbolNumber][iCarrier]))
+			{
+				_COMPLEX cPil = Parameter.matcReceivedPilotValues[iRow][i];
+				if (cPil.real() > rMax)
+					rMax = cPil.real();
+				if (-cPil.real() > rMax)
+					rMax = -cPil.real();
+				if (cPil.imag() > rMax)
+					rMax = cPil.imag();
+				if (-cPil.imag() > rMax)
+					rMax = -cPil.imag();
+			}
+		}
+
+		// Calculate the exponent for the block
+		_REAL rExponent = Ceil(Log(rMax) / Log(_REAL(2.0)));
+		_REAL rScale = 32767 * pow(_REAL(2.0), -rExponent);
+
+		// Put to the tag
+		Enqueue((uint32_t) iNumPilots, SIZEOF__BYTE);	// PN = number of pilots
+		Enqueue((uint32_t) iFirstPilotCarrier, SIZEOF__BYTE);	// PO = pilot offset
+		Enqueue((uint32_t) rExponent, 2 * SIZEOF__BYTE);
+
+		// Step through the pilots again and write the values
+		for (i = iFirstPilotCarrier / iScatPilFreqInt, iCarrier =
+			 iFirstPilotCarrier; iCarrier < iNumCarrier;
+			 i += iScatPilTimeInt, iCarrier += iScatPilFreqSpacing)
+		{
+			Enqueue((uint32_t)
+					(Parameter.matcReceivedPilotValues[iRow][i].real() *
+					 rScale), 2 * SIZEOF__BYTE);
+			Enqueue((uint32_t)
+					(Parameter.matcReceivedPilotValues[iRow][i].imag() *
+					 rScale), 2 * SIZEOF__BYTE);
+		}
+	}	// next symbol
+}
+
+void
+CTagItemGeneratorAMAudio::GenTag(CParameter & Parameter, CSingleBuffer < _BINARY > &AudioData)
+{
+
+	const int iLenStrData =
+		SIZEOF__BYTE * (Parameter.Stream[0].iLenPartA + Parameter.Stream[0].iLenPartB);
+	// Only generate this tag if stream input data is not of zero length
+	if (iLenStrData == 0)
+		return;
+
+	CVectorEx < _BINARY > *pvecbiStrData = AudioData.Get(iLenStrData);
+	// check we have data in the vector
+	if (iLenStrData != pvecbiStrData->Size())
+		return;
+
+	PrepareTag(iLenStrData + 16);
+
+	// Send audio parameters
+
+	// Audio coding
+	int iVal = 0;
+	switch (Parameter.Service[0].AudioParam.eAudioCoding)
+	{
+	case CAudioParam::AC_AAC:	// 00
+		iVal = 0;
+		break;
+	case CAudioParam::AC_CELP:	// 01
+		iVal = 1;
+		break;
+	case CAudioParam::AC_HVXC:	// 10
+		iVal = 2;
+		break;
+	default:
+		iVal = 0;				// reserved
+	}
+
+	Enqueue(iVal, 2);
+
+	// SBR flag
+	Enqueue(Parameter.Service[0].AudioParam.eSBRFlag == CAudioParam::SB_USED ? 1 : 0, 1);
+
+	// Audio mode
+	switch (Parameter.Service[0].AudioParam.eAudioMode)
+	{
+	case CAudioParam::AM_MONO:
+		iVal = 0;
+		break;
+	case CAudioParam::AM_P_STEREO:
+		iVal = 1;
+		break;
+	case CAudioParam::AM_STEREO:
+		iVal = 2;
+		break;
+	default:
+		iVal = 0;
+	}
+	Enqueue(iVal, 2);
+
+	// Audio sampling rate
+	switch (Parameter.Service[0].AudioParam.eAudioSamplRate)
+	{
+	case CAudioParam::AS_8_KHZ:
+		iVal = 0;
+		break;
+	case CAudioParam::AS_12KHZ:
+		iVal = 1;
+		break;
+	case CAudioParam::AS_16KHZ:
+		iVal = 2;
+		break;
+	case CAudioParam::AS_24KHZ:
+		iVal = 3;
+		break;
+	default:
+		iVal = 3;
+	}
+
+	Enqueue(iVal, 3);
+
+	// coder field and some rfus (TODO: code the coder field correctly for all cases
+	Enqueue(0, 8);
+
+	// Now send the stream data
+	pvecbiStrData->ResetBitAccess();
+	// Data is always a multiple of 8 -> copy bytes
+	for (int i = 0; i < iLenStrData / SIZEOF__BYTE; i++)
+	{
+		Enqueue(pvecbiStrData->Separate(SIZEOF__BYTE), SIZEOF__BYTE);
+	}
+}
+
+string
+CTagItemGeneratorAMAudio::GetProfiles()
+{
+	return "AD";
+}
+
+string
+CTagItemGeneratorAMAudio::GetTagName()
+{
+	return "rama";
+}
diff --git a/src/MDI/MDITagItems.h b/src/MDI/MDITagItems.h
new file mode 100644
index 0000000..7cfd644
--- /dev/null
+++ b/src/MDI/MDITagItems.h
@@ -0,0 +1,365 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer, Oliver Haffenden, Andrew Murphy
+ *
+ * Description:
+ *	see MDITagItems.cpp
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#ifndef MDI_TAG_ITEMS_H_INCLUDED
+#define MDI_TAG_ITEMS_H_INCLUDED
+
+#include "../GlobalDefinitions.h"
+#include "MDIDefinitions.h"
+#include "../Parameter.h"
+#include "../util/Buffer.h"
+
+/* Base class for all of the tag item generators. Handles some of the functions common to all tag items */
+class CTagItemGenerator
+{
+public:
+	void PutTagItemData(CVector<_BINARY> &vecbiDestination); // Call this to write the binary data (header + payload) to the vector
+	int GetTotalLength() { return vecbiTagData.Size();}; // returns the length in bits
+	void Reset(); // Resets bit vector to zero length (i.e. no header)
+	void GenEmptyTag(); // Generates valid tag item with zero payload length
+	virtual ~CTagItemGenerator() {}
+	virtual _BOOLEAN IsInProfile(char cProfile);
+
+protected:
+	virtual string GetTagName() = 0; // Return the tag name
+	virtual string GetProfiles() = 0;
+
+	// Prepare vector and make the header
+	void PrepareTag(int iLenDataBits);
+
+	void Enqueue(uint32_t iInformation, int iNumOfBits);
+
+private:
+	CVector<_BINARY> vecbiTagData; // Stores the generated data
+};
+
+/* Base class for tag items for applications with different profiles */
+class CTagItemGeneratorWithProfiles : public CTagItemGenerator
+{
+public:
+	CTagItemGeneratorWithProfiles();
+	virtual _BOOLEAN IsInProfile(char cProfile);
+protected:
+	virtual string GetTagName() =0;
+//private:
+	virtual string GetProfiles()=0; // Return a string containing the set of profiles for this tag
+};
+
+class CTagItemGeneratorProTyMDI : public CTagItemGeneratorWithProfiles /* *ptr tag for MDI */
+{
+public:
+	void GenTag();
+protected:
+	virtual string GetTagName();
+	virtual string GetProfiles(); // Return a string containing the set of profiles for this tag
+};
+
+class CTagItemGeneratorProTyRSCI : public CTagItemGeneratorWithProfiles /* *ptr tag for RSCI */
+{
+public:
+	void GenTag();
+protected:
+	virtual string GetTagName();
+	virtual string GetProfiles(); // Return a string containing the set of profiles for this tag
+};
+
+class CTagItemGeneratorLoFrCnt : public CTagItemGeneratorWithProfiles /* dlfc tag */
+{
+public:
+	CTagItemGeneratorLoFrCnt();
+	void GenTag();
+protected:
+	virtual string GetTagName();
+	virtual string GetProfiles(); // Return a string containing the set of profiles for this tag
+	int iLogFraCnt;
+};
+
+class CTagItemGeneratorFAC : public CTagItemGeneratorWithProfiles /* fac_ tag */
+{
+public:
+	void GenTag(CParameter& Parameter, CSingleBuffer<_BINARY>& FACData);
+protected:
+	virtual string GetTagName();
+	virtual string GetProfiles(); // Return a string containing the set of profiles for this tag
+};
+
+class CTagItemGeneratorSDC : public CTagItemGeneratorWithProfiles /* sdc_ tag */
+{
+public:
+	void GenTag(CParameter& Parameter, CSingleBuffer<_BINARY>& FACData);
+protected:
+	virtual string GetTagName();
+	virtual string GetProfiles(); // Return a string containing the set of profiles for this tag
+};
+
+class CTagItemGeneratorSDCChanInf : public CTagItemGeneratorWithProfiles /* sdci tag */
+{
+public:
+	void GenTag(CParameter& Parameter);
+protected:
+	virtual string GetTagName();
+	virtual string GetProfiles(); // Return a string containing the set of profiles for this tag
+};
+
+class CTagItemGeneratorRobMod : public CTagItemGeneratorWithProfiles /* robm tag */
+{
+public:
+	void GenTag(ERobMode eCurRobMode);
+protected:
+	virtual string GetTagName();
+	virtual string GetProfiles(); // Return a string containing the set of profiles for this tag
+};
+
+class CTagItemGeneratorRINF : public CTagItemGeneratorWithProfiles /* info tag */
+{
+public:
+	void GenTag(string strUTF8Text);
+protected:
+	virtual string GetTagName();
+	virtual string GetProfiles(); // Return a string containing the set of profiles for this tag
+};
+
+class CTagItemGeneratorStr : public CTagItemGeneratorWithProfiles /* strx tag */
+{
+public:
+	CTagItemGeneratorStr();
+	void SetStreamNumber(int iStrNum);
+	void GenTag(CParameter& Parameter, CSingleBuffer<_BINARY>& FACData);
+protected:
+	virtual string GetTagName();
+	virtual string GetProfiles(); // Return a string containing the set of profiles for this tag
+	int iStreamNumber;
+};
+
+/* all MER tags have the same format, only the name is different */
+class CTagItemGeneratorMERFormat : public CTagItemGeneratorWithProfiles
+{
+public:
+	void GenTag(_BOOLEAN bIsValid, _REAL rMER);
+protected:
+	virtual string GetTagName() {return "";}
+	virtual string GetProfiles() {return "";} // Return a string containing the set of profiles for this tag
+};
+
+class CTagItemGeneratorRWMF : public CTagItemGeneratorMERFormat /* RWMF tag */
+{
+protected:
+	virtual string GetTagName();
+	virtual string GetProfiles(); // Return a string containing the set of profiles for this tag
+};
+
+class CTagItemGeneratorRWMM : public CTagItemGeneratorMERFormat /* RWMM tag */
+{
+protected:
+	virtual string GetTagName();
+	virtual string GetProfiles(); // Return a string containing the set of profiles for this tag
+};
+
+class CTagItemGeneratorRMER : public CTagItemGeneratorMERFormat /* RMER tag */
+{
+protected:
+	virtual string GetTagName();
+	virtual string GetProfiles(); // Return a string containing the set of profiles for this tag
+};
+
+class CTagItemGeneratorRDOP : public CTagItemGeneratorMERFormat /* RDOP tag */
+{
+protected:
+	virtual string GetTagName();
+	virtual string GetProfiles(); // Return a string containing the set of profiles for this tag
+};
+
+class CTagItemGeneratorRDEL : public CTagItemGeneratorWithProfiles /* RDEL tag */
+{
+public:
+	void GenTag(_BOOLEAN bIsValid, const CRealVector &vecrThresholds, const CRealVector &vecrIntervals);
+protected:
+	virtual string GetTagName();
+	virtual string GetProfiles(); // Return a string containing the set of profiles for this tag
+};
+
+class CTagItemGeneratorRAFS : public CTagItemGeneratorWithProfiles /* RAFS tag */
+{
+public:
+	void GenTag(CParameter& Parameter);
+protected:
+	virtual string GetTagName();
+	virtual string GetProfiles(); // Return a string containing the set of profiles for this tag
+};
+
+class CTagItemGeneratorRINT : public CTagItemGeneratorWithProfiles /* rnic tag */
+{
+public:
+	void GenTag(_BOOLEAN bIsValid, CReal rIntFreq, CReal rINR, CReal rICR);
+protected:
+	virtual string GetTagName();
+	virtual string GetProfiles(); // Return a string containing the set of profiles for this tag
+};
+
+class CTagItemGeneratorRNIP : public CTagItemGeneratorWithProfiles /* rnic tag */
+{
+public:
+	void GenTag(_BOOLEAN bIsValid, CReal rIntFreq, CReal rISR);
+protected:
+	virtual string GetTagName();
+	virtual string GetProfiles(); // Return a string containing the set of profiles for this tag
+};
+
+class CTagItemGeneratorSignalStrength : public CTagItemGeneratorWithProfiles /* rdbv tag */
+{
+public:
+	void GenTag(_BOOLEAN bIsValid, _REAL rSigStrength);
+protected:
+	virtual string GetTagName();
+	virtual string GetProfiles(); // Return a string containing the set of profiles for this tag
+};
+
+class CTagItemGeneratorReceiverStatus : public CTagItemGeneratorWithProfiles /* rsta tag */
+{
+public:
+	void GenTag(CParameter& Parameter);
+protected:
+	virtual string GetTagName();
+	virtual string GetProfiles(); // Return a string containing the set of profiles for this tag
+};
+
+class CTagItemGeneratorProfile : public CTagItemGeneratorWithProfiles /* rpro */
+{
+public:
+	void GenTag(char cProfile);
+protected:
+	virtual string GetTagName();
+	virtual string GetProfiles(); // Return a string containing the set of profiles for this tag
+};
+
+class CTagItemGeneratorRxDemodMode : public CTagItemGeneratorWithProfiles /* rdmo */
+{
+public:
+	void GenTag(ERecMode eMode); /* ERecMode defined in DRMReceiver.h but can't include it! */
+protected:
+	virtual string GetTagName();
+	virtual string GetProfiles(); // Return a string containing the set of profiles for this tag
+};
+
+class CTagItemGeneratorRxFrequency : public CTagItemGeneratorWithProfiles /* rfre */
+{
+public:
+	void GenTag(_BOOLEAN bIsValid, int iFrequency);
+protected:
+	virtual string GetTagName();
+	virtual string GetProfiles(); // Return a string containing the set of profiles for this tag
+};
+
+class CTagItemGeneratorRxActivated : public CTagItemGeneratorWithProfiles /* ract */
+{
+public:
+	void GenTag(_BOOLEAN bActivated);
+protected:
+	virtual string GetTagName();
+	virtual string GetProfiles(); // Return a string containing the set of profiles for this tag
+};
+
+class CTagItemGeneratorRxBandwidth : public CTagItemGeneratorWithProfiles /* rbw_ */
+{
+public:
+	void GenTag(_BOOLEAN bIsValid, _REAL rBandwidth);
+protected:
+	virtual string GetTagName();
+	virtual string GetProfiles(); // Return a string containing the set of profiles for this tag
+};
+
+class CTagItemGeneratorRxService : public CTagItemGeneratorWithProfiles /* rser */
+{
+public:
+	void GenTag(_BOOLEAN bIsValid, int iService);
+protected:
+	virtual string GetTagName();
+	virtual string GetProfiles(); // Return a string containing the set of profiles for this tag
+};
+
+class CTagItemGeneratorRBP : public CTagItemGeneratorWithProfiles /*rbp0 etc  */
+{
+public:
+	CTagItemGeneratorRBP();
+	void SetStreamNumber(int iStrNum);
+	void GenTag(); // Not yet implemented
+protected:
+	virtual string GetTagName();
+	virtual string GetProfiles(); // Return a string containing the set of profiles for this tag
+	int iStreamNumber;
+};
+
+//andrewm - 7/11/2001-2014
+class CTagItemGeneratorGPS : public CTagItemGeneratorWithProfiles /* rgps */
+{
+public:
+	void GenTag(_BOOLEAN bIsValid, gps_data_t& GPSData);
+protected:
+	virtual string GetTagName();
+	virtual string GetProfiles(); // Return a string containing the set of profiles for this tag
+};
+
+// oliver 17/1/2001-2014
+class CTagItemGeneratorPowerSpectralDensity : public CTagItemGeneratorWithProfiles /* rpsd */
+{
+public:
+	void GenTag(CParameter& Parameter);
+protected:
+	virtual string GetTagName();
+	virtual string GetProfiles(); // Return a string containing the set of profiles for this tag
+};
+
+class CTagItemGeneratorPowerImpulseResponse : public CTagItemGeneratorWithProfiles /* rpir */
+{
+public:
+	void GenTag(CParameter& Parameter);
+protected:
+	virtual string GetTagName();
+	virtual string GetProfiles(); // Return a string containing the set of profiles for this tag
+};
+
+class CTagItemGeneratorPilots : public CTagItemGeneratorWithProfiles /* rpil */
+{
+public:
+	void GenTag(CParameter& Parameter);
+protected:
+	virtual string GetTagName();
+	virtual string GetProfiles(); // Return a string containing the set of profiles for this tag
+};
+
+class CTagItemGeneratorAMAudio : public CTagItemGeneratorWithProfiles /* rama */
+{
+public:
+		void GenTag(CParameter& Parameter, CSingleBuffer<_BINARY>& AudioData
+);
+protected:
+		virtual string GetTagName(void);
+		virtual string GetProfiles(void); // Return a string containing the set of profiles for this tag
+};
+
+#endif
diff --git a/src/MDI/PacketInOut.h b/src/MDI/PacketInOut.h
new file mode 100644
index 0000000..382a377
--- /dev/null
+++ b/src/MDI/PacketInOut.h
@@ -0,0 +1,82 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer, Oliver Haffenden
+ *
+ * Description:
+ *	This defines some pure abstract base classes. A CPacketSink is anything that can receive a
+ *  packet, while a CPacketSource is anything that can produce packets.
+ *  It's intended to be used for DCP packets although it could be used for IPIO as well.
+ *
+ *  A CPacketSocket is both a source and a sink, and is used to wrap up a concrete socket
+ *  implementation such as QSocket or CSocket.
+ *
+ *  The intention is that this could be expanded to support RS232 and file as sources and sinks
+ *  of DCP packets. The File version should support the FF (file framing) layer of DCP,
+ *  by defining a new CTagPacketDecoder subclass and CTagItemDecoder subclasses.
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#ifndef PACKET_IN_OUT_H_INCLUDED
+#define PACKET_IN_OUT_H_INCLUDED
+
+#include "../GlobalDefinitions.h"
+#include "../util/Vector.h"
+
+
+// Pure abstract class (interface) representing a sink of packets (e.g. DCP, IPIO)
+class CPacketSink
+{
+public:
+	virtual ~CPacketSink() {}
+	virtual void SendPacket(const vector<_BYTE>& vecbydata, uint32_t addr=0, uint16_t port=0) = 0;
+	virtual _BOOLEAN SetDestination(const string& str) = 0;
+	virtual _BOOLEAN GetDestination(string& str) = 0;
+};
+
+
+// Pure abstract class (interface) representing a source of packets (e.g. DCP, IPIO)
+
+class CPacketSource
+{
+public:
+	virtual ~CPacketSource() {}
+	// Set the sink which will receive the packets
+	virtual void SetPacketSink(CPacketSink *pSink) = 0;
+	// Stop sending packets to the sink
+	virtual void ResetPacketSink() = 0;
+	virtual _BOOLEAN SetOrigin(const string& str) = 0;
+	virtual _BOOLEAN GetOrigin(string& str) = 0;
+	virtual void poll() = 0;
+};
+
+
+// Pure abstract class representing a socket (which can send and receive)
+// used to wrap up QT or Windows socket
+// Multiple inheritance is ok because both parents are pure abstract (interfaces). Discuss.
+class CPacketSocket : public CPacketSink, public CPacketSource
+{
+public:
+
+};
+
+
+#endif
diff --git a/src/MDI/PacketSinkFile.cpp b/src/MDI/PacketSinkFile.cpp
new file mode 100644
index 0000000..69c3b27
--- /dev/null
+++ b/src/MDI/PacketSinkFile.cpp
@@ -0,0 +1,279 @@
+/******************************************************************************\
+ * British Broadcasting Corporation
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Oliver Haffenden, Julian Cable
+ *
+ * Description:
+ *
+ * See PacketSinkFile.h
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "PacketSinkFile.h"
+
+/* include this here mostly for htonl */
+#ifdef _WIN32
+  /* Always include winsock2.h before windows.h */
+    /* winsock2.h is already included into libpcap */
+# include <winsock2.h>
+# include <ws2tcpip.h>
+# include <windows.h>
+#else
+# include <netinet/in.h>
+# include <arpa/inet.h>
+/* Some defines needed for compatibility when using Linux, Darwin, ... */
+typedef int SOCKET;
+# define SOCKET_ERROR				(-1)
+# define INVALID_SOCKET				(-1)
+#endif
+
+#ifdef HAVE_LIBPCAP
+# include <pcap.h>
+#endif
+
+CPacketSinkFile::CPacketSinkFile()
+: pFile(0), bIsRecording(0), bChangeReceived(FALSE)
+{
+}
+
+_BOOLEAN CPacketSinkFile::SetDestination(const string& strFName)
+{
+	strFileName = strFName;
+	bChangeReceived = TRUE;
+	return TRUE;
+}
+
+void CPacketSinkFile::StartRecording()
+{
+	bIsRecording = TRUE;
+	bChangeReceived = TRUE;
+}
+
+void CPacketSinkFile::StopRecording()
+{
+	bIsRecording = FALSE;
+	bChangeReceived = TRUE;
+}
+
+void CPacketSinkFile::SendPacket(const vector<_BYTE>& vecbydata, uint32_t, uint16_t)
+{
+	if (bChangeReceived) // something has changed, so close the file if it's open
+	{
+        if (pFile)
+        {
+			close();
+		}
+        pFile = 0;
+		bChangeReceived = FALSE;
+	}
+
+    if (!bIsRecording) // not recording
+    {
+            if (pFile != 0) // close file if one is open
+            {
+                    close();
+                    pFile = 0;
+            }
+            return;
+    }
+
+    if (!pFile) // either wasn't open, or we just closed it
+    {
+            open();
+            if (!pFile)
+          {
+                    // Failed to open
+                    bIsRecording = FALSE;
+                    return;
+            }
+    }
+
+	write(vecbydata);
+}
+
+CPacketSinkRawFile::CPacketSinkRawFile():CPacketSinkFile() {}
+
+CPacketSinkRawFile::~CPacketSinkRawFile()
+{
+	if(pFile)
+		fclose(pFile);
+}
+
+void
+CPacketSinkRawFile::open()
+{
+	pFile = fopen(strFileName.c_str(), "wb");
+}
+
+void
+CPacketSinkRawFile::close()
+{
+	fclose(pFile);
+}
+
+void
+CPacketSinkRawFile::write(const vector<_BYTE>& vecbydata)
+{
+	fwrite(&vecbydata[0],1,vecbydata.size(),pFile);
+}
+
+/* File: ETSI TS 102 821 V0.0.2f (2003-10)
+
+PFT Fragments or AF Packets may be stored in a file for offline distribution,
+  archiving or any other purpose.  A standard mapping has been defined using
+   the Hierarchical TAG Item option available,  however other mappings may be
+    (or this one extended) in the future.  The top level TAG Item has the TAG
+    Name fio_ and is used to encapsulate a TAG packet,  one part of which is
+    the AF Packet or PFT Fragment in an afpf TAG Item.  Additional TAG Items
+    have been defined to monitor the reception or control the replay of the packets.
+
+B.3.1	File IO (fio_)
+The fio_ TAG Item is the highest layer TAG Item in the file TAG Item hierarchy.
+
+Tag name: fio_
+Tag length: 8*n bits
+Tag Value: This TAG Item acts as a container for an afpf TAG Item.  A time TAG Item
+may optionally be present.
+
+B.3.1.1	AF Packet / PFT Fragment (afpf)
+The afpf TAG Item contains an entire AF Packet or PFT Fragment as the TAG Value.
+
+Figure 16: AF Packet or PFT Fragment
+
+B.3.1.2	Timestamp (time)
+The time TAG Item may occur in the payload of any fio_ TAG Item.
+It may record the time of reception of the payload,  or it may indicate
+the intended time of replay.  The time value given in the TI_SEC and TI_NSEC
+ fields may be relative to the start of the file,  or any other reference desired.
+
+Figure 17: File timestamp
+TI_SEC:  the number of whole SI seconds,  in the range 0-2^32-1)
+TI_NSEC:  the number of whole SI nanoseconds,  in the range 0-999 999 999.
+  Values outside of this range are not defined
+*/
+
+CPacketSinkFileFraming::CPacketSinkFileFraming():CPacketSinkFile() {}
+
+CPacketSinkFileFraming::~CPacketSinkFileFraming()
+{
+	if(pFile)
+		fclose(pFile);
+}
+
+void
+CPacketSinkFileFraming::open()
+{
+	pFile = fopen(strFileName.c_str(), "wb");
+}
+
+void
+CPacketSinkFileFraming::close()
+{
+	fclose(pFile);
+}
+
+void
+CPacketSinkFileFraming::write(const vector<_BYTE>& vecbydata)
+{
+	uint32_t p, n;
+	n = 4+4+vecbydata.size(); // afpf
+	// Tag Item fio_
+	fwrite("fio_",4,1,pFile);
+	p = htonl(8*n);
+    fwrite(&p,4,1,pFile);
+	// nested tag packets
+	// Tag Item afpf
+	fwrite("afpf",4,1,pFile);
+	n = vecbydata.size();
+	p = htonl(8*n);
+    fwrite(&p,4,1,pFile);
+	fwrite(&vecbydata[0], 1, n, pFile);
+}
+
+CPacketSinkPcapFile::CPacketSinkPcapFile():CPacketSinkFile() {}
+
+CPacketSinkPcapFile::~CPacketSinkPcapFile()
+{
+#ifdef HAVE_LIBPCAP
+	if(pFile)
+    	pcap_dump_close((pcap_dumper_t *)pFile);
+#endif
+}
+
+void
+CPacketSinkPcapFile::open()
+{
+#ifdef HAVE_LIBPCAP
+    pcap_t *p = pcap_open_dead(DLT_RAW, 65536);
+	pFile = (FILE*)pcap_dump_open(p, strFileName.c_str());
+#endif
+}
+
+void
+CPacketSinkPcapFile::close()
+{
+#ifdef HAVE_LIBPCAP
+    pcap_dump_close((pcap_dumper_t *)pFile);
+#endif
+}
+
+void
+CPacketSinkPcapFile::write(const vector<_BYTE>& vecbydata)
+{
+#ifdef HAVE_LIBPCAP
+	vector<_BYTE> out;
+	size_t u = vecbydata.size()+8;
+	size_t c = u+20;
+    // Ip header - fields in network byte order
+	out.push_back(0x45);
+	out.push_back(0x00);
+    out.push_back(c >> 8);
+    out.push_back(c & 0xff);
+    out.push_back(0x08);
+    out.push_back(0xd8);
+    out.push_back(0x40);
+    out.push_back(0x00);
+    out.push_back(0x7f);
+    out.push_back(0x11); // udp
+	out.insert(out.end(), 10, 0);
+    // udp header - fields in network byte order
+    out.push_back(0);
+    out.push_back(0);
+    out.push_back(4);
+    out.push_back(0);
+    out.push_back(u >> 8);
+    out.push_back(u & 0xff);
+    out.push_back(0); out.push_back(0); // TODO UDP Header CRC
+	out.insert(out.end(), vecbydata.begin(), vecbydata.end());
+    pcap_pkthdr hdr;
+	time_t t;
+	time(&t);
+    hdr.ts.tv_sec = t;
+    hdr.ts.tv_usec = 0; /* TODO more precise timestamps */
+	hdr.caplen = c;
+	hdr.len = c;
+    pcap_dump((u_char*)pFile, &hdr, (u_char*)&out[0]);
+    pcap_dump_flush((pcap_dumper_t *)pFile);
+#else
+	(void)vecbydata;
+#endif
+}
+
diff --git a/src/MDI/PacketSinkFile.h b/src/MDI/PacketSinkFile.h
new file mode 100644
index 0000000..a1ddedc
--- /dev/null
+++ b/src/MDI/PacketSinkFile.h
@@ -0,0 +1,95 @@
+/******************************************************************************\
+ * British Broadcasting Corporation
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Oliver Haffenden
+ *
+ * Description:
+ *	
+ *  This defines a concrete subclass of CPacketSink that writes to a file
+ *  For the moment this will be a raw file but FF could be added as a decorator
+ *  The writing can be stopped and started - if it is not currently writing,
+ *  any packets it receives will be silently discarded
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#ifndef PACKET_SINK_FILE_INCLUDED
+#define PACKET_SINK_FILE_INCLUDED
+
+#include "PacketInOut.h"
+
+class CPacketSinkFile : public CPacketSink
+{
+public:
+	CPacketSinkFile();
+	virtual ~CPacketSinkFile() {}
+
+	virtual void SendPacket(const vector<_BYTE>& vecbydata, uint32_t addr=0, uint16_t port=0);
+
+	virtual _BOOLEAN SetDestination(const string& strFName);
+	virtual _BOOLEAN GetDestination(string& strFName) { strFName = strFileName; return TRUE; }
+	void StartRecording();
+	void StopRecording();
+
+protected:
+	virtual void open()=0;
+	virtual void close()=0;
+	virtual void write(const vector<_BYTE>& vecbydata)=0;
+
+	FILE *pFile;
+	_BOOLEAN bIsRecording;
+	_BOOLEAN bChangeReceived;
+	string strFileName;
+};
+
+class CPacketSinkRawFile : public CPacketSinkFile
+{
+public:
+	CPacketSinkRawFile();
+	virtual ~CPacketSinkRawFile();
+protected:
+	virtual void open();
+	virtual void close();
+	virtual void write(const vector<_BYTE>& vecbydata);
+};
+
+class CPacketSinkFileFraming : public CPacketSinkFile
+{
+public:
+	CPacketSinkFileFraming();
+	virtual ~CPacketSinkFileFraming();
+protected:
+	virtual void open();
+	virtual void close();
+	virtual void write(const vector<_BYTE>& vecbydata);
+};
+
+class CPacketSinkPcapFile : public CPacketSinkFile
+{
+public:
+	CPacketSinkPcapFile();
+	virtual ~CPacketSinkPcapFile();
+protected:
+	virtual void open();
+	virtual void close();
+	virtual void write(const vector<_BYTE>& vecbydata);
+};
+
+#endif
diff --git a/src/MDI/PacketSocket.cpp b/src/MDI/PacketSocket.cpp
new file mode 100644
index 0000000..1c43e24
--- /dev/null
+++ b/src/MDI/PacketSocket.cpp
@@ -0,0 +1,427 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright(c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer, Julian Cable, Oliver Haffenden
+ *
+ * Description:
+ *
+ * This is an implementation of the CPacketSocket interface that wraps up a socket.
+ *
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or(at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+/*
+--rsiout 127.0.0.1:60023 --rciin 60021 --rsioutprofile D
+
+if I run it with the command:
+--rsiout 127.0.0.1:60023 --rciin 60021 --rsiout 127.0.0.1:60022 --rciin 60021 --rsioutprofile D
+*/
+
+#include "PacketSocket.h"
+#include <iostream>
+#include <sstream>
+#include <cerrno>
+#include <cctype>
+#include <cstring>
+#include <stdlib.h> /* for atol() */
+
+#ifdef _WIN32
+/* Always include winsock2.h before windows.h */
+# include <Ws2tcpip.h>
+# include <windows.h>
+inline int inet_aton(const char*s, void * a) {
+    ((in_addr*)a)->s_addr = inet_addr(s);
+    return 1;
+}
+# define inet_pton(a, b, c) inet_aton(b, c)
+# define inet_ntop(a, b, c, d) inet_ntoa(*(in_addr*)b)
+#else
+# include <arpa/inet.h>
+# include <sys/types.h>
+# include <sys/socket.h>
+# include <unistd.h>
+# include <fcntl.h>
+# define SOCKET_ERROR				(-1)
+# define INVALID_SOCKET				(-1)
+#endif
+
+CPacketSocketNative::CPacketSocketNative():
+        pPacketSink(NULL), HostAddrOut(),
+        writeBuf(),udp(true),
+        s(INVALID_SOCKET), origin(""), dest("")
+{
+	memset(&sourceAddr, 0, sizeof(sourceAddr));
+	memset(&destAddr, 0, sizeof(destAddr));
+	memset(&HostAddrOut, 0, sizeof(HostAddrOut));
+}
+
+CPacketSocketNative::~CPacketSocketNative()
+{
+}
+
+// Set the sink which will receive the packets
+void
+CPacketSocketNative::SetPacketSink(CPacketSink * pSink)
+{
+    pPacketSink = pSink;
+}
+
+// Stop sending packets to the sink
+void
+CPacketSocketNative::ResetPacketSink()
+{
+    pPacketSink = NULL;
+}
+
+// Send packet to the socket
+void
+CPacketSocketNative::SendPacket(const vector < _BYTE > &vecbydata, uint32_t, uint16_t)
+{
+    if (s == INVALID_SOCKET)
+        return;
+    if (udp)
+    {
+        string ss;
+        GetDestination(ss);
+        cerr << "send packet " << ss << endl;
+        int n = sendto(s, (char*)&vecbydata[0], vecbydata.size(), 0, (sockaddr*)&HostAddrOut, sizeof(HostAddrOut));
+		if(n==SOCKET_ERROR) {
+#ifdef _WIN32
+			int err = GetLastError();
+			cerr << "socket send failed " << err << endl;
+#endif
+		}
+    }
+    else
+        (void)send(s, (char*)&vecbydata[0], vecbydata.size(), 0);
+}
+
+vector<string>
+CPacketSocketNative::parseDest(const string& input)
+{
+    istringstream iss(input);
+    string item;
+    vector<string> v;
+    for (string item; getline(iss, item, ':'); )
+    {
+        v.push_back(item);
+    }
+    return v;
+}
+
+bool
+CPacketSocketNative::SetDestination(const string & strNewAddr)
+{
+	dest = strNewAddr;
+    /* syntax
+       1:  <port>                send to port on localhost
+       2:  <ip>:<port>           send to port on host or port on m/c group
+       3:  <ip>:<ip>:<port>      send to port on m/c group via interface
+       prefix with "t" for tcp
+     */
+    int ttl = 127;
+    bool bAddressOK = TRUE;
+    in_addr AddrInterface;
+    AddrInterface.s_addr = htonl(INADDR_ANY);
+    vector<string> parts = parseDest(strNewAddr);
+	HostAddrOut.sin_family = AF_INET; 
+    if (tolower(parts[0][0])=='t')
+    {
+        udp = false;
+        parts[0] = parts[0].substr(1);
+    }
+    switch (parts.size())
+    {
+    case 1: // Just a port - send to ourselves
+        bAddressOK = inet_pton(AF_INET, "127.0.0.1", &HostAddrOut.sin_addr.s_addr);
+        HostAddrOut.sin_port = ntohs(atol(parts[0].c_str()));
+        break;
+    case 2: // host and port, unicast
+        bAddressOK = inet_pton(AF_INET, parts[0].c_str(), &HostAddrOut.sin_addr.s_addr);
+        HostAddrOut.sin_port = ntohs(atol(parts[1].c_str()));
+        {
+            string s;
+            GetDestination(s);
+            cerr << "host and port, unicast " << s << endl;
+        }
+        break;
+    case 3: // interface, host and port, usually multicast udp
+        inet_pton(AF_INET, parts[0].c_str(), &AddrInterface.s_addr);
+        bAddressOK = inet_pton(AF_INET, parts[1].c_str(), &HostAddrOut.sin_addr.s_addr);
+        HostAddrOut.sin_port = ntohs(atol(parts[2].c_str()));
+        break;
+    default:
+        bAddressOK = FALSE;
+    }
+    if (udp)
+    {
+        if (s == INVALID_SOCKET)
+            s = socket(AF_INET, SOCK_DGRAM, 0);
+
+        if (setsockopt(s, IPPROTO_IP, IP_TTL, (char*)&ttl, sizeof(ttl))==SOCKET_ERROR)
+            bAddressOK = FALSE;
+        if (AddrInterface.s_addr != htonl(INADDR_ANY))
+        {
+            if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF,
+                           (char *) &AddrInterface, sizeof(AddrInterface)) == SOCKET_ERROR)
+            {
+                bAddressOK = FALSE;
+            }
+        }
+    }
+    else
+    {
+        if (s == INVALID_SOCKET)
+            s = socket(AF_INET, SOCK_STREAM, 0);
+        int n = connect(s, (sockaddr*)&HostAddrOut, sizeof(HostAddrOut));
+        bAddressOK = n==0;
+    }
+    return bAddressOK;
+}
+
+bool
+CPacketSocketNative::GetDestination(string & str)
+{
+    stringstream s;
+    char buf[32];
+    s << inet_ntop(AF_INET, &HostAddrOut.sin_addr.s_addr, buf, sizeof(buf)) << ":" << ntohs(HostAddrOut.sin_port);
+    str = s.str();
+    (void)buf; // MSVC2008 warning C4101: 'buf' : unreferenced local variable
+    return TRUE;
+}
+
+bool
+CPacketSocketNative::GetOrigin(string& str)
+{
+	if(sourceAddr.sin_family == 0)
+		return false;
+    stringstream s;
+    char buf[32];
+	(void)buf;
+    s << inet_ntop(AF_INET, &sourceAddr.sin_addr.s_addr, buf, sizeof(buf)) << ":" << ntohs(sourceAddr.sin_port);
+    str = s.str();
+    return TRUE;
+}
+
+bool
+CPacketSocketNative::SetOrigin(const string & strNewAddr)
+{
+	origin = strNewAddr;
+    /* syntax (unwanted fields can be empty, e.g. <source ip>::<group ip>:<port>
+       1:  <port>
+       2:  <group ip>:<port>
+       3:  <interface ip>:<group ip>:<port>
+       4:  <source ip>:<interface ip>:<group ip>:<port>
+       5: - for TCP - no need to separately set origin
+     */
+    if (strNewAddr == "-")
+    {
+        udp = false;
+        if (s == INVALID_SOCKET)
+            s = socket(AF_INET, SOCK_STREAM, 0);
+        return TRUE;
+    }
+
+    if (s == INVALID_SOCKET)
+    {
+        s = socket(AF_INET, SOCK_DGRAM, 0);
+    }
+
+    int port=-1;
+    in_addr gp, ifc;
+    vector<string> parts = parseDest(strNewAddr);
+	sourceAddr.sin_family = AF_INET;
+	bool ok=true;
+    int p=-1,o=-1,g=-1,i=-1;
+    switch (parts.size())
+    {
+    case 1:
+        p=0;
+        break;
+    case 2:
+        p=1;
+        g=0;
+        break;
+    case 3:
+        p=2;
+        i=0;
+        g=1;
+        break;
+    case 4:
+        p=3;
+        o=0;
+        i=1;
+        g=2;
+        break;
+    default:
+        ok = false;
+    }
+
+    if (p>=0 && parts[p].length() > 0)
+        port = atol(parts[p].c_str());
+
+    if (o>=0 && parts[o].length() > 0)
+    {
+        inet_pton(AF_INET, parts[o].c_str(), &sourceAddr.sin_addr);
+    }
+    else
+    {
+        sourceAddr.sin_addr.s_addr=INADDR_ANY;
+    }
+
+    if (i>=0 && parts[i].length() > 0)
+        inet_pton(AF_INET, parts[i].c_str(), &ifc.s_addr);
+    else
+        ifc.s_addr=INADDR_ANY;
+
+    if (g>=0 && parts[g].length() > 0)
+    {
+        inet_pton(AF_INET, parts[g].c_str(), &gp.s_addr);
+
+        /* Multicast ? */
+        uint32_t mc = htonl(0xe0000000);
+        if ((gp.s_addr & mc) == mc)	/* multicast! */
+        {
+            int optval = 1;
+            setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char*)&optval, sizeof optval);
+            sockaddr_in sa;
+            sa.sin_family = AF_INET;
+            sa.sin_addr.s_addr = gp.s_addr;
+            sa.sin_port = htons(port);
+            ::bind(s, (sockaddr*)&sa, sizeof(sa));
+            if (ok == false)
+            {
+                throw CGenErr("Can't bind to port to receive packets");
+            }
+            struct ip_mreq mreq;
+            mreq.imr_multiaddr.s_addr = gp.s_addr;
+            mreq.imr_interface.s_addr = ifc.s_addr;
+            int n = setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP,(char *) &mreq, sizeof(mreq));
+            if (n == SOCKET_ERROR)
+                ok = false;
+            if (!ok)
+            {
+                cerr << "Can't join multicast group" << endl;
+            }
+        }
+        else /* one address specified, but not multicast - listen on a specific interface */
+        {
+            cerr << "listen on interface " << endl;
+            sockaddr_in sa;
+            sa.sin_family = AF_INET;
+            sa.sin_addr.s_addr = gp.s_addr;
+            sa.sin_port = htons(port);
+            ::bind(s, (sockaddr*)&sa, sizeof(sa));
+        }
+    }
+    else
+    {
+        /* bind to a port on any interface. */
+        sourceAddr.sin_family = AF_INET;
+        sourceAddr.sin_addr.s_addr = htonl(INADDR_ANY);
+        sourceAddr.sin_port = htons(port);
+        int r = ::bind(s, (sockaddr*)&sourceAddr, sizeof(sourceAddr));
+        if (r < 0)
+        {
+            perror("bind() failed");
+        }
+    }
+#ifdef _WIN32
+    u_long mode = 1;
+    (void)ioctlsocket(s, FIONBIO, &mode);
+#else
+    fcntl(s, F_SETFL, O_NONBLOCK);  // set to non-blocking
+#endif
+    return TRUE;
+}
+
+void
+CPacketSocketNative::poll()
+{
+    if (udp)
+        pollDatagram();
+    else
+        pollStream();
+}
+
+void
+CPacketSocketNative::pollStream()
+{
+    vector < _BYTE > vecbydata(MAX_SIZE_BYTES_NETW_BUF);
+    /* Read block from network interface */
+    int iNumBytesRead = ::recv(s, (char *) &vecbydata[0], MAX_SIZE_BYTES_NETW_BUF, 0);
+    if (iNumBytesRead > 0)
+    {
+        /* Decode the incoming packet */
+        if (pPacketSink != NULL)
+        {
+            vecbydata.resize(iNumBytesRead);
+            // TODO - is there any reason or possibility to optionally filter on source address?
+            pPacketSink->SendPacket(vecbydata, 0, 0);
+        }
+    }
+}
+
+void
+CPacketSocketNative::pollDatagram()
+{
+    vector < _BYTE > vecbydata(MAX_SIZE_BYTES_NETW_BUF);
+    int readBytes = 0;
+	{
+		stringstream s;
+		char buf[32];
+		(void)buf;
+		s << "poll src: " << inet_ntop(AF_INET, &sourceAddr.sin_addr.s_addr, buf, sizeof(buf))
+		  << ":" << ntohs(sourceAddr.sin_port)
+		  << " dst: " << inet_ntop(AF_INET, &HostAddrOut.sin_addr.s_addr, buf, sizeof(buf)) 
+		  << ":" << ntohs(HostAddrOut.sin_port);
+		//qDebug(s.str().c_str());
+	}
+
+    do {
+        sockaddr_in sender;
+        socklen_t l = sizeof(sender);
+        readBytes = ::recvfrom(s, (char*)&vecbydata[0], MAX_SIZE_BYTES_NETW_BUF, 0, (sockaddr*)&sender, &l);
+        if (readBytes>0) {
+			{
+				static int n=0;
+				stringstream s;
+				char buf[32];
+				(void)buf;
+				s << (n++) << " got from: " << inet_ntop(AF_INET, &sender.sin_addr.s_addr, buf, sizeof(buf))
+				  << ":" << ntohs(sender.sin_port);
+				//qDebug(s.str().c_str());
+			}
+            vecbydata.resize(readBytes);
+            if (sourceAddr.sin_addr.s_addr == htonl(INADDR_ANY))
+            {
+                pPacketSink->SendPacket(vecbydata, sender.sin_addr.s_addr, sender.sin_port);
+            }
+            else
+            {
+                if (sourceAddr.sin_addr.s_addr == sender.sin_addr.s_addr) // optionally filter on source address
+                {
+                    pPacketSink->SendPacket(vecbydata, sender.sin_addr.s_addr, sender.sin_port);
+                }
+            }
+        }
+    } while (readBytes>0);
+}
diff --git a/src/MDI/PacketSocket.h b/src/MDI/PacketSocket.h
new file mode 100644
index 0000000..50d6810
--- /dev/null
+++ b/src/MDI/PacketSocket.h
@@ -0,0 +1,84 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer, Oliver Haffenden
+ *
+ * Description:
+ *	Implementation of CPacketSocket interface that wraps up a Socket. See PacketSocket.cpp.
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#ifndef PACKET_SOCKET_H_INCLUDED
+#define PACKET_SOCKET_H_INCLUDED
+
+#ifdef _WIN32
+# include <winsock2.h>
+#else
+  typedef int SOCKET;
+# include <netinet/in.h>
+#endif
+
+
+/* Maximum number of bytes received from the network interface. Maximum data
+   rate of DRM is approx. 80 kbps. One MDI packet must be sent each DRM frame
+   which is every 400 ms -> 0.4 * 80000 / 8 = 4000 bytes. Allocating more than
+   double of this size should be ok for all possible cases */
+#define MAX_SIZE_BYTES_NETW_BUF		10000
+
+#include "PacketInOut.h"
+
+class CPacketSocketNative :
+	public CPacketSocket
+{
+public:
+	CPacketSocketNative();
+	virtual ~CPacketSocketNative();
+	// Set the sink which will receive the packets
+	virtual void SetPacketSink(CPacketSink *pSink);
+	// Stop sending packets to the sink
+	virtual void ResetPacketSink(void);
+
+	// Send packet to the socket
+	void SendPacket(const vector<_BYTE>& vecbydata, uint32_t addr=0, uint16_t port=0);
+
+	virtual bool SetDestination(const string& str);
+	virtual bool SetOrigin(const string& str);
+
+	virtual bool GetDestination(string& str);
+	virtual bool GetOrigin(string& str);
+
+	void poll();
+
+private:
+	void pollStream();
+	void pollDatagram();
+
+	vector<string> parseDest(const string & strNewAddr);
+	CPacketSink *pPacketSink;
+
+	sockaddr_in sourceAddr, destAddr;
+	sockaddr_in HostAddrOut;
+	vector<_BYTE>	writeBuf;
+	bool udp;
+	SOCKET s;
+	string origin, dest;
+};
+#endif
diff --git a/src/MDI/PacketSocketNull.cpp b/src/MDI/PacketSocketNull.cpp
new file mode 100644
index 0000000..73a4a11
--- /dev/null
+++ b/src/MDI/PacketSocketNull.cpp
@@ -0,0 +1,67 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer, Julian Cable, Oliver Haffenden
+ *
+ * Description:
+ *
+ * This is a dummy implementation of the CPacketSocket interface to enable the CMDI
+ * class to work even if no socket support is available. Packets are silently discarded
+ * and there are never any incoming packets.
+ *
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "PacketSocketNull.h"
+
+// Set the sink which will receive the packets
+void CPacketSocketNull::SetPacketSink(CPacketSink*)
+{
+}
+
+// Stop sending packets to the sink
+void CPacketSocketNull::ResetPacketSink(void)
+{
+}
+
+// Send packet to the socket
+void CPacketSocketNull::SendPacket(const vector<_BYTE>&, uint32_t, uint16_t)
+{
+}
+
+void CPacketSocketNull::poll()
+{
+}
+
+_BOOLEAN CPacketSocketNull::SetOrigin(const string&)
+{
+	return FALSE;
+}
+
+_BOOLEAN CPacketSocketNull::SetDestination(const string&)
+{
+	return FALSE;
+}
+
+_BOOLEAN CPacketSocketNull::GetDestination(string&)
+{
+	return FALSE;
+}
diff --git a/src/MDI/PacketSocketNull.h b/src/MDI/PacketSocketNull.h
new file mode 100644
index 0000000..6b29f5e
--- /dev/null
+++ b/src/MDI/PacketSocketNull.h
@@ -0,0 +1,54 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer, Oliver Haffenden
+ *
+ * Description: Null implementation of CPacketSocket. See PacketSocketNull.cpp
+ *
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#ifndef PACKET_SOCKET_NULL_H_INCLUDED
+#define PACKET_SOCKET_NULL_H_INCLUDED
+
+#include "PacketInOut.h"
+
+class CPacketSocketNull : public CPacketSocket
+{
+
+public:
+
+	// Set the sink which will receive the packets
+	virtual void SetPacketSink(CPacketSink *pSink);
+	// Stop sending packets to the sink
+	virtual void ResetPacketSink(void);
+
+	// Send packet to the socket
+	virtual void SendPacket(const vector<_BYTE>& vecbydata, uint32_t addr=0, uint16_t port=0);
+
+	virtual void poll();
+
+	_BOOLEAN SetDestination(const string&);
+	_BOOLEAN SetOrigin(const string&);
+	_BOOLEAN GetDestination(string&);
+};
+
+#endif
diff --git a/src/MDI/PacketSourceFile.cpp b/src/MDI/PacketSourceFile.cpp
new file mode 100644
index 0000000..03b58b5
--- /dev/null
+++ b/src/MDI/PacketSourceFile.cpp
@@ -0,0 +1,388 @@
+/******************************************************************************\
+ * British Broadcasting Corporation
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Julian Cable, Oliver Haffenden
+ *
+ * Description:
+ *
+ * see PacketSourceFile.h
+ *
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "PacketSourceFile.h"
+#include <iostream>
+#include <cstdlib>
+#include <cerrno>
+
+#ifdef _WIN32
+/* Always include winsock2.h before windows.h */
+/* winsock2.h is already included into libpcap */
+# include <winsock2.h>
+# include <ws2tcpip.h>
+# include <windows.h>
+#else
+# include <netinet/in.h>
+# include <arpa/inet.h>
+/* Some defines needed for compatibility when using Linux, Darwin, ... */
+typedef int SOCKET;
+# define SOCKET_ERROR				(-1)
+# define INVALID_SOCKET				(-1)
+#endif
+
+#include "../util/Pacer.h"
+
+#ifdef HAVE_LIBPCAP
+# include <pcap.h>
+#endif
+
+const size_t iMaxPacketSize = 4096;
+const size_t iAFHeaderLen = 10;
+const size_t iAFCRCLen = 2;
+
+CPacketSourceFile::CPacketSourceFile():pPacketSink(NULL),
+    last_packet_time(0),pacer(NULL),
+    pF(NULL), wanted_dest_port(-1), eFileType(pcap)
+{
+    pacer = new CPacer(400000000ULL);
+}
+
+void CPacketSourceFile::poll()
+{
+    pacer->wait();
+    vector<_BYTE> vecbydata (iMaxPacketSize);
+    int interval;
+    if(pF)
+    {
+        vecbydata.resize(0); // in case we don't find anything
+        switch(eFileType)
+        {
+        case pcap:
+            readPcap(vecbydata, interval);
+            break;
+        case ff:
+            readFF(vecbydata, interval);
+            break;
+        case af:
+            readRawAF(vecbydata, interval);
+            break;
+        case pf:
+            readRawPFT(vecbydata, interval);
+            break;
+        }
+
+        /* Decode the incoming packet */
+        if (pPacketSink != NULL)
+            pPacketSink->SendPacket(vecbydata);
+    }
+}
+
+_BOOLEAN
+CPacketSourceFile::SetOrigin(const string& origin)
+{
+    string str = origin;
+    size_t p = str.find_last_of('#');
+    if(p!=string::npos)
+    {
+        wanted_dest_port = atoi(str.substr(p+1).c_str());
+        str = str.substr(0, p);
+    }
+    if(str.rfind(".pcap") == str.length()-5)
+    {
+#ifdef HAVE_LIBPCAP
+        char errbuf[PCAP_ERRBUF_SIZE];
+        pF = pcap_open_offline(str.c_str(), errbuf);
+#endif
+        eFileType = pcap;
+    }
+    else
+    {
+        pF = fopen(str.c_str(), "rb");
+        if ( pF != NULL)
+        {
+            char c;
+            size_t n = fread(&c, sizeof(c), 1, (FILE *) pF);
+            (void)n;
+            fseek ( (FILE *) pF , 0 , SEEK_SET );
+            if(c=='A') eFileType = af;
+            if(c=='P') eFileType = pf;
+            if(c=='f') eFileType = ff;
+        }
+    }
+    return pF != NULL;
+}
+
+CPacketSourceFile::~CPacketSourceFile()
+{
+    if(eFileType != pcap && pF)
+        fclose((FILE*)pF);
+    else if(pF)
+    {
+#ifdef HAVE_LIBPCAP
+        pcap_close((pcap_t*)pF);
+#endif
+    }
+    pF = 0;
+}
+
+// Set the sink which will receive the packets
+void
+CPacketSourceFile::SetPacketSink(CPacketSink * pSink)
+{
+    pPacketSink = pSink;
+}
+
+// Stop sending packets to the sink
+void
+CPacketSourceFile::ResetPacketSink()
+{
+    pPacketSink = NULL;
+}
+
+void
+CPacketSourceFile::readTagPacketHeader(string& tag, uint32_t& len)
+{
+    uint32_t bytes;
+    size_t n;
+
+    tag = "";
+    for(int i=0; i<4; i++)
+    {
+        char c;
+        n = fread(&c, sizeof(char), 1, (FILE *) pF);
+        tag += c;
+    }
+
+    n = fread(&bytes, sizeof(bytes), 1, (FILE *) pF);
+    len = ntohl(bytes)/8;
+
+    (void)n;
+}
+
+void
+CPacketSourceFile::readFF(vector<_BYTE>& vecbydata, int& interval)
+{
+
+    string tag;
+    uint32_t fflen,len;
+    readTagPacketHeader(tag, fflen);
+
+    interval = 400;
+
+    if(tag != "fio_")
+    {
+        fclose((FILE *) pF);
+        pF = 0;
+        return;
+    }
+
+    long remaining = fflen; // use a signed number here to help loop exit
+    while(remaining>0)
+    {
+        readTagPacketHeader(tag, len);
+        remaining -= 8; // 4 bytes tag, 4 bytes length;
+        remaining -= len;
+
+        if(tag=="time")
+        {
+            if(len != 8)
+            {
+                cout << "weird length in FF " << int(len) << " expected 8" << endl;
+                fclose((FILE *) pF);
+                pF = 0;
+                return;
+            }
+            // read the time tag packet payload
+            uint32_t s,ns;
+            size_t n = fread(&s, sizeof(s), 1, (FILE *) pF);
+            n = fread(&ns, sizeof(ns), 1, (FILE *) pF);
+            (void)n;
+            //TODO update last packet and interval times
+            readTagPacketHeader(tag, len);
+            remaining -= 8; // 4 bytes tag, 4 bytes length;
+            remaining -= len;
+        }
+
+        if(tag=="afpf")
+        {
+            uint32_t l = readRawAF(vecbydata, interval);
+            if(l!=len) {
+                qDebug("why not");
+            }
+        }
+        else
+        {
+            cout << "unkown tag packet in FF " << tag << endl;
+            fseek((FILE*)pF, len, SEEK_CUR);
+        }
+    }
+}
+
+int
+CPacketSourceFile::readRawAF(vector<_BYTE>& vecbydata, int& interval)
+{
+    char sync[2];
+    uint32_t bytes;
+
+    interval = 400;
+
+    size_t n = fread(sync, 2, 1, (FILE *) pF);
+    n = fread(&bytes, 4, 1, (FILE *) pF);
+    fseek((FILE*)pF, -6, SEEK_CUR);
+
+    if (sync[0] != 'A' || sync[1] != 'F')
+    {
+        // throw?
+        fclose((FILE *) pF);
+        pF = 0;
+        return 0;
+    }
+    // get the length
+    size_t iAFPacketLen = iAFHeaderLen + ntohl(bytes) + iAFCRCLen;
+
+    if (iAFPacketLen > iMaxPacketSize)
+    {
+        // throw?
+        fclose((FILE *) pF);
+        pF = 0;
+        return 0;
+    }
+
+    // initialise the output vector
+    vecbydata.resize(iAFPacketLen);
+
+    n = fread(&vecbydata[0], 1, iAFPacketLen, (FILE *)pF);
+
+    last_packet_time += interval;
+
+    return n;
+}
+
+// not robust against the sync characters appearing in the payload!!!!
+void
+CPacketSourceFile::readRawPFT(vector<_BYTE>& vecbydata, int& interval)
+{
+    char sync[2];
+
+    interval = 400;
+
+    size_t n = fread(sync, 2, 1, (FILE *) pF);
+    if (sync[0] != 'P' || sync[1] != 'F')
+    {
+        // throw?
+        fclose((FILE *) pF);
+        pF = 0;
+        return;
+    }
+    vecbydata.resize(0);
+    vecbydata.push_back(sync[0]);
+    vecbydata.push_back(sync[1]);
+    char prev = '\0';;
+    while(true)
+    {
+        char c;
+        n = fread(&c, 1, 1, (FILE *) pF);
+        if(prev == 'P' && c == 'F')
+        {
+            fseek((FILE*)pF, -2, SEEK_CUR);
+            vecbydata.pop_back();
+            break;
+        }
+        prev = c;
+        vecbydata.push_back(c);
+    }
+
+    (void)n;
+}
+
+void
+CPacketSourceFile::readPcap(vector<_BYTE>& vecbydata, int& interval)
+{
+    int link_len = 0;
+    const _BYTE* pkt_data = NULL;
+    timeval packet_time = { 0, 0 };
+    while(true)
+    {
+#ifdef HAVE_LIBPCAP
+        struct pcap_pkthdr *header;
+        int res;
+        const u_char* data;
+        /* Retrieve the packet from the file */
+        if((res = pcap_next_ex( (pcap_t*)pF, &header, &data)) != 1)
+        {
+            pcap_close((pcap_t*)pF);
+            pF = NULL;
+            return;
+        }
+        int lt = pcap_datalink((pcap_t*)pF);
+        pkt_data = (_BYTE*)data;
+        /* 14 bytes ethernet header */
+        if(lt==DLT_EN10MB)
+        {
+            link_len=14;
+        }
+#ifdef DLT_LINUX_SLL
+        /* linux cooked */
+        if(lt==DLT_LINUX_SLL)
+        {
+            link_len=16;
+        }
+#endif
+        /* raw IP header ? */
+        if(lt==DLT_RAW)
+        {
+            link_len=0;
+        }
+        //packet_time = header->ts; try this for BSD
+		packet_time.tv_sec = header->ts.tv_sec;
+		packet_time.tv_usec = header->ts.tv_usec;
+#endif
+        if(pkt_data == NULL)
+            return;
+
+        /* 4n bytes IP header, 8 bytes UDP header */
+        uint8_t proto = pkt_data[link_len+9];
+        if(proto == 0x11) // UDP
+        {
+            int udp_ip_hdr_len = 4*(pkt_data[link_len] & 0x0f) + 8;
+            int ip_packet_len = ntohs(*(uint16_t*)&pkt_data[link_len+2]);
+            int dest_port = ntohs(*(uint16_t*)&pkt_data[link_len+udp_ip_hdr_len-6]);
+            if((wanted_dest_port==-1) || (dest_port == wanted_dest_port)) // wanted port
+            {
+                int data_len = ip_packet_len - udp_ip_hdr_len;
+                vecbydata.resize (data_len);
+                for(int i=0; i<data_len; i++)
+                    vecbydata[i] = pkt_data[link_len+udp_ip_hdr_len+i];
+                break;
+            }
+        }
+    }
+    if(last_packet_time == 0)
+    {
+        last_packet_time = 1000*uint64_t(packet_time.tv_sec);
+        last_packet_time += uint64_t(packet_time.tv_usec)/1000;
+    }
+    uint64_t pt;
+    pt = 1000*uint64_t(packet_time.tv_sec);
+    pt += uint64_t(packet_time.tv_usec)/1000;
+    interval = pt - last_packet_time;
+    last_packet_time = pt;
+}
diff --git a/src/MDI/PacketSourceFile.h b/src/MDI/PacketSourceFile.h
new file mode 100644
index 0000000..6290fcb
--- /dev/null
+++ b/src/MDI/PacketSourceFile.h
@@ -0,0 +1,69 @@
+/******************************************************************************\
+ * British Broadcasting Corporation
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Juian Cable
+ *
+ * Description:
+ *	Implementation of a CPacketSource that reads from a file
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#ifndef _PACKETSOURCE_FILE_H
+#define _PACKETSOURCE_FILE_H
+
+#include "../GlobalDefinitions.h"
+#include "../util/Vector.h"
+#include "../util/Buffer.h"
+#include "PacketInOut.h"
+
+class CPacer;
+
+class CPacketSourceFile : public CPacketSource
+{
+public:
+	CPacketSourceFile();
+	~CPacketSourceFile();
+	// Set the sink which will receive the packets
+	void SetPacketSink(CPacketSink *pSink);
+	// Stop sending packets to the sink
+	void ResetPacketSink(void);
+	_BOOLEAN SetOrigin(const string& str);
+	bool GetOrigin(string& str) { (void)str; return false; }
+	void poll();
+
+private:
+
+    int readRawAF(vector<_BYTE>& vecbydata, int& interval);
+    void readRawPFT(vector<_BYTE>& vecbydata, int& interval);
+    void readFF(vector<_BYTE>& vecbydata, int& interval);
+
+    void readPcap(vector<_BYTE>& vecbydata, int& interval);
+    void readTagPacketHeader(string& tag, uint32_t& len);
+
+    CPacketSink		*pPacketSink;
+    uint64_t		last_packet_time;
+    CPacer*		pacer;
+    void*		pF;
+    int 		wanted_dest_port;
+    enum {pcap,ff,af,pf}    eFileType;
+};
+
+#endif
diff --git a/src/MDI/Pft.cpp b/src/MDI/Pft.cpp
new file mode 100644
index 0000000..d03cb1c
--- /dev/null
+++ b/src/MDI/Pft.cpp
@@ -0,0 +1,202 @@
+/******************************************************************************\
+ * British Broadcasting Corporation
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Julian Cable
+ *
+ * Description:
+ *	Implements the PFT (Protection, Fragmentation and Transport) layer of the
+ *	Communications Protocol (DCP) as described in ETSI TS 102 821.
+ *
+ *  TODO: support RS FEC and any other missing features
+ *  In this version, only in-order delivery is supported.
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "Pft.h"
+#include "../util/CRC.h"
+#include <iostream>
+
+CPft::CPft(int isrc, int idst):
+iSource(isrc),
+iDest(idst),
+mapFragments()
+{
+}
+
+bool CPft::DecodePFTPacket(const vector < _BYTE > &vecIn,
+						   vector < _BYTE > &vecOut)
+{
+	/* SYNC: two-byte ASCII representation of "PF" (2 bytes) */
+
+	/* Check if string is correct */
+	if ((vecIn[0] != 'P') && (vecIn[1] != 'F'))
+	{
+		cerr << "PF not found" << endl;
+		return false;
+	}
+
+	iHeaderLen = 14;
+	iPseq = (uint16_t(vecIn[2]) << 8) + vecIn[3];
+	iFindex =
+		(uint32_t(vecIn[4]) << 16) + (uint32_t(vecIn[5]) << 8) + vecIn[6];
+	iFcount =
+		(uint32_t(vecIn[7]) << 16) + (uint32_t(vecIn[8]) << 8) + vecIn[9];
+	uint16_t
+		n = (uint16_t(vecIn[10]) << 8) + vecIn[11];
+	iFEC = (n & 0x8000) ? 1 : 0;
+	iAddr = (n & 0x4000) ? 1 : 0;
+	iPlen = n & 0x3FFF;
+
+//	int iRSk, iRSz;
+	if (iFEC == 1)
+	{
+//		iRSk = (int) vecIn[12];
+//		iRSz = (int) vecIn[13];
+		iHeaderLen += 2;
+	}
+
+	int iPktSource = 0, iPktDest = 0;
+	if (iAddr == 1)
+	{
+		iPktSource = (uint16_t(vecIn[iHeaderLen - 2]) << 8) + vecIn[iHeaderLen - 1];
+		iPktDest = (uint16_t(vecIn[iHeaderLen]) << 8) + vecIn[iHeaderLen + 1];
+		iHeaderLen += 4;
+	}
+
+	const int
+		iHCRC =
+		(uint16_t(vecIn[iHeaderLen - 2]) << 8) + vecIn[iHeaderLen - 1];
+
+	/* CRC check ------------------------------------------------------------ */
+	CCRC CRCObject;
+	CRCObject.Reset(16);
+
+	int i;
+	for (i = 0; i < iHeaderLen - 2; i++)
+		CRCObject.AddByte(vecIn[i]);
+	const _BOOLEAN
+		bCRCOk = CRCObject.CheckCRC(iHCRC);
+	if (!bCRCOk)
+	{
+		cerr << "PFT CRC Error" << endl;
+		return false;
+	}
+
+	if ((iSource != -1) && (iSource != iPktSource))
+		return false;
+	if ((iDest != -1) && (iDest != iPktDest))
+		return false;
+
+	vector < _BYTE > frag;
+	for (size_t j = iHeaderLen; j < vecIn.size(); j++)
+		frag.push_back(vecIn[j]);
+	if (iFEC == 1)
+		return DecodePFTPacketWithFEC(frag, vecOut);
+	else
+		return DecodeSimplePFTPacket(frag, vecOut);
+}
+
+bool CPft::DecodeSimplePFTPacket(const vector < _BYTE > &vecIn,
+								 vector < _BYTE > &vecOut)
+{
+	if (iFcount == 1)
+	{
+		vecOut = vecIn;
+		return true;
+	}
+	/* CReassembler does not modify the input vector, but its derived classes using CVectors do. */
+	mapFragments[iPseq].AddSegment(const_cast < vector < _BYTE > &>(vecIn),
+								   iFindex, iFindex == (iFcount - 1));
+
+	if (mapFragments[iPseq].Ready())
+	{
+		vecOut = mapFragments[iPseq].vecData;
+		return true;
+	}
+
+	return false;
+}
+
+bool CPft::DecodePFTPacketWithFEC(const vector < _BYTE > &,
+								  vector < _BYTE > &)
+{
+	cerr << "sorry, PFT/FEC not implemented yet" << endl;
+	return false;
+}
+
+void
+CPft::MakePFTPackets(const vector < _BYTE > &vecbydata, vector < vector < _BYTE > >&packets,
+	uint16_t sequence_counter, size_t fragment_size)
+{
+	uint32_t num_packets, data_size = vecbydata.size();
+	size_t header_bytesize, payload_bytesize;
+	header_bytesize = 14;		// no addressing or FEC
+	if ((fragment_size > 0) && (fragment_size < (data_size + header_bytesize)))
+	{
+		payload_bytesize = fragment_size - header_bytesize;
+		num_packets = data_size / payload_bytesize;
+		if (num_packets * payload_bytesize < data_size)
+			num_packets++;
+		payload_bytesize = data_size / num_packets;
+		if (num_packets * payload_bytesize < data_size)
+			payload_bytesize++;
+	}
+	else
+	{
+		num_packets = 1;
+		payload_bytesize = data_size;
+	}
+	size_t bytes_remaining = data_size;
+	packets.clear();
+	packets.resize(num_packets);
+	vector<_BYTE>::const_iterator p = vecbydata.begin();
+	for (uint32_t n = 0; n < num_packets; n++)
+	{
+		if (bytes_remaining < payload_bytesize)
+			payload_bytesize = bytes_remaining;	// last packet
+
+		CCRC CRCObject;
+		CRCObject.Reset(16);
+
+		// write PFT Packet Header
+		uint8_t c;
+		c='P'; CRCObject.AddByte(c); packets[n].push_back(c);
+		c='F'; CRCObject.AddByte(c); packets[n].push_back(c);
+		c=sequence_counter >> 8; CRCObject.AddByte(c); packets[n].push_back(c);
+		c=sequence_counter & 0xff; CRCObject.AddByte(c); packets[n].push_back(c);
+		c=n >> 16; CRCObject.AddByte(c); packets[n].push_back(c);
+		c=(n >> 8) & 0xff; CRCObject.AddByte(c); packets[n].push_back(c);
+		c=n & 0xff; CRCObject.AddByte(c); packets[n].push_back(c);
+		c=num_packets >> 16; CRCObject.AddByte(c); packets[n].push_back(c);
+		c=(num_packets >> 8) & 0xff; CRCObject.AddByte(c); packets[n].push_back(c);
+		c=num_packets & 0xff; CRCObject.AddByte(c); packets[n].push_back(c);
+		c=payload_bytesize >> 8; CRCObject.AddByte(c); packets[n].push_back(c);
+		c=payload_bytesize & 0xff; CRCObject.AddByte(c); packets[n].push_back(c);
+		// CRC
+		uint16_t crc_val = uint16_t(CRCObject.GetCRC());
+		c=crc_val >> 8; CRCObject.AddByte(c); packets[n].push_back(c);
+		c=crc_val & 0xff; CRCObject.AddByte(c); packets[n].push_back(c);
+		// write PFT Packet Payload
+		packets[n].insert(packets[n].end(), p, p+payload_bytesize);
+		p += payload_bytesize;
+		bytes_remaining -= payload_bytesize;
+	}
+}
diff --git a/src/MDI/Pft.h b/src/MDI/Pft.h
new file mode 100644
index 0000000..5fe60fa
--- /dev/null
+++ b/src/MDI/Pft.h
@@ -0,0 +1,61 @@
+/******************************************************************************\
+ * British Broadcasting Corporation
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Julian Cable
+ *
+ * Description:
+ *	see Pft.cpp
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#ifndef PFT_H_INCLUDED
+#define PFT_H_INCLUDED
+
+#include "../util/Reassemble.h"
+#include <map>
+
+class CPft
+{
+public:
+	CPft(int isrc=-1, int idst=-1);
+
+	bool DecodePFTPacket(const vector<_BYTE>& vecIn, vector<_BYTE>& vecOut);
+	static void MakePFTPackets(const vector < _BYTE > &vecbydata,
+					 vector < vector < _BYTE > >&packets, 
+					uint16_t sequence_counter, size_t fragment_size);
+
+protected:
+
+	bool DecodeSimplePFTPacket(const vector<_BYTE>& vecIn, vector<_BYTE>& vecOut);
+	bool DecodePFTPacketWithFEC(const vector<_BYTE>& vecIn, vector<_BYTE>& vecOut);
+
+	int iSource, iDest;
+	map<int,CReassemblerN> mapFragments;
+	int iHeaderLen;
+	int iPseq;
+	int iFindex;
+	int iFcount;
+	int iFEC;
+	int iAddr;
+	int iPlen;
+};
+
+#endif
diff --git a/src/MDI/RCITagItems.cpp b/src/MDI/RCITagItems.cpp
new file mode 100644
index 0000000..a8572e3
--- /dev/null
+++ b/src/MDI/RCITagItems.cpp
@@ -0,0 +1,86 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer, Julian Cable, Oliver Haffenden
+ *
+ * Description:
+ *	Implements Digital Radio Mondiale (DRM)
+ *	(RCI), Receiver Status and Control Interface (RSCI)
+ *  and Distribution and Communications Protocol (DCP) as described in
+ *	ETSI TS 102 349 and ETSI TS 102 821 respectively.
+ *
+ *  This module derives, from the CTagItemGenerator base class, tag item generators
+ *  specialised to generate each of the tag items defined in RCI and RSCI.
+ *  .
+ *  An intermediate derived class, CTagItemGeneratorWithProfiles, is used as the
+ *  base class for all these tag item generators. This takes care of the common
+ *	task of checking whether a given tag is in a particular profile.
+ *  The profiles for each tag are defined by the GetProfiles() member function.
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "RCITagItems.h"
+
+void CTagItemGeneratorCfre::GenTag(int iNewFreqkHz)
+{
+	/* Length: 4 bytes = 32 bits */
+	PrepareTag(32);
+
+	/* RF Frequency */
+	Enqueue(1000*iNewFreqkHz, 32);
+
+}
+
+string CTagItemGeneratorCfre::GetTagName(void) {return "cfre";}
+
+void CTagItemGeneratorCdmo::GenTag(const ERecMode eMode) // cdmo
+{
+	PrepareTag(4*SIZEOF__BYTE);
+	switch (eMode)
+	{
+	case RM_DRM:
+		Enqueue((uint32_t) 'd', SIZEOF__BYTE);
+		Enqueue((uint32_t) 'r', SIZEOF__BYTE);
+		Enqueue((uint32_t) 'm', SIZEOF__BYTE);
+		Enqueue((uint32_t) '_', SIZEOF__BYTE);
+		break;
+	case RM_FM:
+		Enqueue((uint32_t) 'f', SIZEOF__BYTE);
+		Enqueue((uint32_t) 'm', SIZEOF__BYTE);
+		Enqueue((uint32_t) '_', SIZEOF__BYTE);
+		Enqueue((uint32_t) '_', SIZEOF__BYTE);
+		break;
+	case RM_AM:
+		Enqueue((uint32_t) 'a', SIZEOF__BYTE);
+		Enqueue((uint32_t) 'm', SIZEOF__BYTE);
+		Enqueue((uint32_t) '_', SIZEOF__BYTE);
+		Enqueue((uint32_t) '_', SIZEOF__BYTE);
+		break;
+	default:
+		Enqueue((uint32_t) ' ', SIZEOF__BYTE);
+		Enqueue((uint32_t) ' ', SIZEOF__BYTE);
+		Enqueue((uint32_t) ' ', SIZEOF__BYTE);
+		Enqueue((uint32_t) ' ', SIZEOF__BYTE);
+		break;
+	}
+}
+
+string CTagItemGeneratorCdmo::GetTagName(void) {return "cdmo";}
diff --git a/src/MDI/RCITagItems.h b/src/MDI/RCITagItems.h
new file mode 100644
index 0000000..4e161cd
--- /dev/null
+++ b/src/MDI/RCITagItems.h
@@ -0,0 +1,52 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer, Oliver Haffenden, Julian Cable
+ *
+ * Description:
+ *	see RCITagItems.cpp
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#ifndef RCI_TAG_ITEMS_H_INCLUDED
+#define RCI_TAG_ITEMS_H_INCLUDED
+
+#include "MDITagItems.h"
+
+class CTagItemGeneratorCfre : public CTagItemGenerator /* cfre tag */
+{
+public:
+	void GenTag(int iNewFreqkHz);
+protected:
+	string GetTagName(void);
+	string GetProfiles(void) { return ""; }
+};
+
+class CTagItemGeneratorCdmo : public CTagItemGenerator /* cdmo tag */
+{
+public:
+	void GenTag(const ERecMode eMode);
+protected:
+	string GetTagName(void);
+	string GetProfiles(void) { return ""; }
+};
+
+#endif
diff --git a/src/MDI/RSCITagItemDecoders.cpp b/src/MDI/RSCITagItemDecoders.cpp
new file mode 100644
index 0000000..2a4884e
--- /dev/null
+++ b/src/MDI/RSCITagItemDecoders.cpp
@@ -0,0 +1,368 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer, Julian Cable, Oliver Haffenden
+ *
+ * Description:
+ *	Implements Digital Radio Mondiale (DRM) Multiplex Distribution Interface
+ *	(MDI), Receiver Status and Control Interface (RSCI)
+ *  and Distribution and Communications Protocol (DCP) as described in
+ *	ETSI TS 102 820,  ETSI TS 102 349 and ETSI TS 102 821 respectively.
+ *
+ *  This module derives, from the CTagItemDecoder base class, tag item decoders specialised to decode each of the tag
+ *  items defined in the control part of RSCI.
+ *  Decoded commands are generally sent straight to the CDRMReceiver object which
+ *	they hold a pointer to.
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+
+#include "RSCITagItemDecoders.h"
+#include "../DrmReceiver.h"
+#include <time.h>
+#include <stdlib.h>
+
+/* RX_STAT Items */
+
+_REAL CTagItemDecoderRSI::decodeDb(CVector<_BINARY>& vecbiTag)
+{
+    int8_t n = (int8_t)vecbiTag.Separate(8);
+    uint8_t m = (uint8_t)vecbiTag.Separate(8);
+    return _REAL(n)+_REAL(m)/256.0;
+}
+
+void CTagItemDecoderRdbv::DecodeTag(CVector<_BINARY>& vecbiTag, const int iLen)
+{
+    if (iLen != 16)
+        return;
+    _REAL rSigStr = decodeDb(vecbiTag);
+    pParameter->SigStrstat.addSample(rSigStr);
+    /* this is the only signal strength we have so update the IF level too.
+     * TODO scaling factor ? */
+    pParameter->SetIFSignalLevel(rSigStr);
+}
+
+void CTagItemDecoderRsta::DecodeTag(CVector<_BINARY>& vecbiTag, const int iLen)
+{
+    if (iLen != 32)
+        return;
+    uint8_t sync = (uint8_t)vecbiTag.Separate(8);
+    uint8_t fac = (uint8_t)vecbiTag.Separate(8);
+    uint8_t sdc = (uint8_t)vecbiTag.Separate(8);
+    uint8_t audio = (uint8_t)vecbiTag.Separate(8);
+    if(sync==0)
+        pParameter->ReceiveStatus.TSync.SetStatus(RX_OK);
+    else
+        pParameter->ReceiveStatus.TSync.SetStatus(CRC_ERROR);
+    if(fac==0)
+        pParameter->ReceiveStatus.FAC.SetStatus(RX_OK);
+    else
+        pParameter->ReceiveStatus.FAC.SetStatus(CRC_ERROR);
+    if(sdc==0)
+        pParameter->ReceiveStatus.SDC.SetStatus(RX_OK);
+    else
+        pParameter->ReceiveStatus.SDC.SetStatus(CRC_ERROR);
+
+	int iShortID = pParameter->GetCurSelAudioService();
+    if(audio==0)
+        pParameter->AudioComponentStatus[iShortID].SetStatus(RX_OK);
+    else
+        pParameter->AudioComponentStatus[iShortID].SetStatus(CRC_ERROR);
+}
+
+void CTagItemDecoderRwmf::DecodeTag(CVector<_BINARY>& vecbiTag, const int iLen)
+{
+    if (iLen != 16)
+        return;
+    pParameter->rWMERFAC = decodeDb(vecbiTag);
+}
+
+void CTagItemDecoderRwmm::DecodeTag(CVector<_BINARY>& vecbiTag, const int iLen)
+{
+    if (iLen != 16)
+        return;
+    pParameter->rWMERMSC = decodeDb(vecbiTag);
+}
+
+void CTagItemDecoderRmer::DecodeTag(CVector<_BINARY>& vecbiTag, const int iLen)
+{
+    if (iLen != 16)
+        return;
+    pParameter->rMER = decodeDb(vecbiTag);
+}
+
+void CTagItemDecoderRdop::DecodeTag(CVector<_BINARY>& vecbiTag, const int iLen)
+{
+    if (iLen != 16)
+        return;
+    pParameter->rRdop = decodeDb(vecbiTag);
+}
+
+void CTagItemDecoderRdel::DecodeTag(CVector<_BINARY>& vecbiTag, const int iLen)
+{
+    int iNumEntries = iLen/(3*SIZEOF__BYTE);
+    pParameter->vecrRdelIntervals.Init(iNumEntries);
+    pParameter->vecrRdelThresholds.Init(iNumEntries);
+
+    for (int i=0; i<iNumEntries; i++)
+    {
+        pParameter->vecrRdelThresholds[i] = vecbiTag.Separate(SIZEOF__BYTE);
+        pParameter->vecrRdelIntervals[i] = decodeDb(vecbiTag);
+    }
+}
+
+void CTagItemDecoderRpsd::DecodeTag(CVector<_BINARY>& vecbiTag, const int iLen)
+{
+    if (iLen != 680 && iLen !=1112)
+        return;
+
+    int iVectorLen = iLen/SIZEOF__BYTE;
+
+    pParameter->vecrPSD.Init(iVectorLen);
+
+    for (int i = 0; i < iVectorLen; i++)
+    {
+        pParameter->vecrPSD[i] = -(_REAL(vecbiTag.Separate(SIZEOF__BYTE))/_REAL(2.0));
+    }
+
+}
+
+void CTagItemDecoderRpir::DecodeTag(CVector<_BINARY>& vecbiTag, const int iLen)
+{
+    const _REAL rOffset = _REAL(-60.0);
+
+    if (iLen == 0)
+    {
+        pParameter->vecrPIR.Init(0);
+        return;
+    }
+
+    int iVectorLen = iLen/SIZEOF__BYTE - 4; // 4 bytes for the scale start and end
+
+    pParameter->rPIRStart = _REAL(int16_t(vecbiTag.Separate(2 * SIZEOF__BYTE))) / _REAL(256.0);
+    pParameter->rPIREnd = _REAL(int16_t(vecbiTag.Separate(2 * SIZEOF__BYTE))) / _REAL(256.0);
+
+    pParameter->vecrPIR.Init(iVectorLen);
+
+    for (int i = 0; i < iVectorLen; i++)
+    {
+        pParameter->vecrPIR[i] = -(_REAL(vecbiTag.Separate(SIZEOF__BYTE))/_REAL(2.0)) - rOffset;
+    }
+}
+
+void CTagItemDecoderRgps::DecodeTag(CVector<_BINARY>& vecbiTag, const int iLen)
+{
+    if (iLen != 26 * SIZEOF__BYTE)
+        return;
+
+    gps_data_t& gps_data = pParameter->gps_data;
+
+    gps_data.set=0;
+    uint16_t source = (uint16_t)vecbiTag.Separate(SIZEOF__BYTE);
+    switch(source)
+    {
+    case 0:
+        gps_data.set=0;
+        break;
+    case 1:
+        gps_data.set=STATUS_SET;
+        gps_data.status=1;
+        break;
+    case 2:
+        gps_data.set=STATUS_SET;
+        gps_data.status=2;
+        break;
+    case 3:
+        gps_data.set=STATUS_SET;
+        gps_data.status=0;
+        break;
+    case 0xff:
+        gps_data.set=0;
+        gps_data.status=0;
+        break;
+    default:
+        cerr << "error decoding rgps" << endl;
+    }
+
+    uint8_t nSats = (uint8_t)vecbiTag.Separate(SIZEOF__BYTE);
+    if(nSats != 0xff)
+    {
+        gps_data.set |= SATELLITE_SET;
+        gps_data.satellites_used = nSats;
+    }
+
+    uint16_t val;
+    val = uint16_t(vecbiTag.Separate(2 * SIZEOF__BYTE));
+    int16_t iLatitudeDegrees = *(int16_t*)&val;
+    uint8_t uiLatitudeMinutes = (uint8_t)vecbiTag.Separate(SIZEOF__BYTE);
+    uint16_t uiLatitudeMinuteFractions = (uint16_t)vecbiTag.Separate(2 * SIZEOF__BYTE);
+    val = uint16_t(vecbiTag.Separate(2 * SIZEOF__BYTE));
+    int16_t iLongitudeDegrees = *(int16_t*)&val;
+    uint8_t uiLongitudeMinutes = (uint8_t)vecbiTag.Separate(SIZEOF__BYTE);
+    uint16_t uiLongitudeMinuteFractions = (uint16_t)vecbiTag.Separate(2 * SIZEOF__BYTE);
+    if(uiLatitudeMinutes != 0xff)
+    {
+        gps_data.fix.latitude = double(iLatitudeDegrees)
+                   + (double(uiLatitudeMinutes) + double(uiLatitudeMinuteFractions)/65536.0)/60.0;
+        gps_data.fix.longitude = double(iLongitudeDegrees)
+                    + (double(uiLongitudeMinutes) + double(uiLongitudeMinuteFractions)/65536.0)/60.0;
+        gps_data.set |= LATLON_SET;
+    }
+
+    val = uint16_t(vecbiTag.Separate(2 * SIZEOF__BYTE));
+    uint8_t uiAltitudeMetreFractions = (uint8_t)vecbiTag.Separate(SIZEOF__BYTE);
+    if(val != 0xffff)
+    {
+        uint16_t iAltitudeMetres = *(int16_t*)&val;
+        gps_data.fix.altitude = double(iAltitudeMetres+uiAltitudeMetreFractions)/256.0;
+        gps_data.set |= ALTITUDE_SET;
+    }
+
+    struct tm tm;
+    tm.tm_hour = uint8_t(vecbiTag.Separate(SIZEOF__BYTE));
+    tm.tm_min = uint8_t(vecbiTag.Separate(SIZEOF__BYTE));
+    tm.tm_sec = uint8_t(vecbiTag.Separate(SIZEOF__BYTE));
+    uint16_t year = uint16_t(vecbiTag.Separate(2*SIZEOF__BYTE));
+    tm.tm_year = year - 1900;
+    tm.tm_mon = uint8_t(vecbiTag.Separate(SIZEOF__BYTE))-1;
+    tm.tm_mday = uint8_t(vecbiTag.Separate(SIZEOF__BYTE));
+
+    if(tm.tm_hour != 0xff)
+    {
+        string se;
+        char *e = getenv("TZ");
+        if(e)
+            se = e;
+#ifdef _WIN32
+        _putenv("TZ=UTC");
+        _tzset();
+        time_t t = mktime(&tm);
+        stringstream ss("TZ=");
+        ss << se;
+        _putenv(ss.str().c_str());
+#else
+        putenv(const_cast<char*>("TZ=UTC"));
+        tzset();
+        time_t t = mktime(&tm);
+        if(e)
+            setenv("TZ", se.c_str(), 1);
+        else
+            unsetenv("TZ");
+#endif
+        gps_data.fix.time = t;
+        gps_data.set |= TIME_SET;
+    }
+
+    uint16_t speed = (uint16_t)vecbiTag.Separate(2*SIZEOF__BYTE);
+    if(speed != 0xffff)
+    {
+        gps_data.fix.speed = double(speed)/10.0;
+        gps_data.set |= SPEED_SET;
+    }
+
+    uint16_t track = (uint16_t)vecbiTag.Separate(2*SIZEOF__BYTE);
+    if(track != 0xffff)
+    {
+        gps_data.fix.track = track;
+        gps_data.set |= TRACK_SET;
+    }
+}
+
+/* RX_CTRL Items */
+
+void CTagItemDecoderCact::DecodeTag(CVector<_BINARY>& vecbiTag, const int iLen)
+{
+    if (iLen != 8)
+        return;
+
+    const int iNewState = vecbiTag.Separate(8) - '0';
+
+    if (pDRMReceiver == NULL)
+        return;
+
+    // TODO pDRMReceiver->SetState(iNewState);
+    (void)iNewState;
+
+}
+
+void CTagItemDecoderCfre::DecodeTag(CVector<_BINARY>& vecbiTag, const int iLen)
+{
+    if (iLen != 32)
+        return;
+
+    if (pDRMReceiver == NULL)
+        return;
+
+    const int iNewFrequency = vecbiTag.Separate(32);
+    pDRMReceiver->SetFrequency(iNewFrequency/1000);
+
+}
+
+void CTagItemDecoderCdmo::DecodeTag(CVector<_BINARY>& vecbiTag, const int iLen)
+{
+    if (iLen != 32)
+        return;
+
+    string s = "";
+    for (int i = 0; i < iLen / SIZEOF__BYTE; i++)
+        s += (_BYTE) vecbiTag.Separate(SIZEOF__BYTE);
+
+    if (pDRMReceiver == NULL)
+        return;
+
+    if(s == "drm_")
+        pDRMReceiver->SetReceiverMode(RM_DRM);
+    if(s == "am__")
+        pDRMReceiver->SetReceiverMode(RM_AM);
+    if(s == "fm__")
+        pDRMReceiver->SetReceiverMode(RM_FM);
+}
+
+void CTagItemDecoderCrec::DecodeTag(CVector<_BINARY>& vecbiTag, const int iLen)
+{
+    if (iLen != 32)
+        return;
+
+    string s = "";
+    for (int i = 0; i < 2; i++)
+        s += (_BYTE) vecbiTag.Separate(SIZEOF__BYTE);
+    char c3 = (char) vecbiTag.Separate(SIZEOF__BYTE);
+    char c4 = (char) vecbiTag.Separate(SIZEOF__BYTE);
+
+    if (pDRMReceiver == NULL)
+        return;
+
+    if(s == "st")
+        pDRMReceiver->SetRSIRecording(c4=='1', c3);
+    if(s == "iq")
+        pDRMReceiver->SetIQRecording(c4=='1');
+}
+
+void CTagItemDecoderCpro::DecodeTag(CVector<_BINARY>& vecbiTag, const int iLen)
+{
+    if (iLen != 8)
+        return;
+
+    char c = char(vecbiTag.Separate(SIZEOF__BYTE));
+    if (pRSISubscriber != NULL)
+        pRSISubscriber->SetProfile(c);
+}
+/* TODO: other control tag items */
diff --git a/src/MDI/RSCITagItemDecoders.h b/src/MDI/RSCITagItemDecoders.h
new file mode 100644
index 0000000..1af87b0
--- /dev/null
+++ b/src/MDI/RSCITagItemDecoders.h
@@ -0,0 +1,158 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer, Oliver Haffenden
+ *
+ * Description:
+ *	see RSCITagItemDecoders.cpp
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#ifndef RSCI_TAG_ITEM_DECODERS_H_INCLUDED
+#define RSCI_TAG_ITEM_DECODERS_H_INCLUDED
+
+#include "TagItemDecoder.h"
+
+class CDRMReceiver;
+class CRSISubscriber;
+
+class CTagItemDecoderRdbv : public CTagItemDecoderRSI
+{
+public:
+	CTagItemDecoderRdbv(CParameter* pP) : CTagItemDecoderRSI(pP, "rdbv") {}
+	virtual void DecodeTag(CVector<_BINARY>& vecbiTag, const int iLenDataBits);
+};
+
+class CTagItemDecoderRsta : public CTagItemDecoderRSI
+{
+public:
+	CTagItemDecoderRsta(CParameter* pP) : CTagItemDecoderRSI(pP, "rsta") {}
+	virtual void DecodeTag(CVector<_BINARY>& vecbiTag, const int iLenDataBits);
+};
+
+class CTagItemDecoderRwmf : public CTagItemDecoderRSI
+{
+public:
+	CTagItemDecoderRwmf(CParameter* pP) : CTagItemDecoderRSI(pP, "rwmf") {}
+	virtual void DecodeTag(CVector<_BINARY>& vecbiTag, const int iLenDataBits);
+};
+
+class CTagItemDecoderRwmm : public CTagItemDecoderRSI
+{
+public:
+	CTagItemDecoderRwmm(CParameter* pP) : CTagItemDecoderRSI(pP, "rwmm") {}
+	virtual void DecodeTag(CVector<_BINARY>& vecbiTag, const int iLenDataBits);
+};
+
+class CTagItemDecoderRmer : public CTagItemDecoderRSI
+{
+public:
+	CTagItemDecoderRmer(CParameter* pP) : CTagItemDecoderRSI(pP, "rmer") {}
+	virtual void DecodeTag(CVector<_BINARY>& vecbiTag, const int iLenDataBits);
+};
+
+class CTagItemDecoderRdel : public CTagItemDecoderRSI
+{
+public:
+	CTagItemDecoderRdel(CParameter* pP) : CTagItemDecoderRSI(pP, "rdel") {}
+	virtual void DecodeTag(CVector<_BINARY>& vecbiTag, const int iLenDataBits);
+};
+
+class CTagItemDecoderRdop : public CTagItemDecoderRSI
+{
+public:
+	CTagItemDecoderRdop(CParameter* pP) : CTagItemDecoderRSI(pP, "rdop") {}
+	virtual void DecodeTag(CVector<_BINARY>& vecbiTag, const int iLenDataBits);
+};
+
+class CTagItemDecoderRpsd : public CTagItemDecoderRSI
+{
+public:
+	CTagItemDecoderRpsd(CParameter* pP) : CTagItemDecoderRSI(pP, "rpsd") {}
+	virtual void DecodeTag(CVector<_BINARY>& vecbiTag, const int iLenDataBits);
+};
+
+class CTagItemDecoderRpir : public CTagItemDecoderRSI
+{
+public:
+	CTagItemDecoderRpir(CParameter* pP) : CTagItemDecoderRSI(pP, "rpir") {}
+	virtual void DecodeTag(CVector<_BINARY>& vecbiTag, const int iLenDataBits);
+};
+
+class CTagItemDecoderRgps : public CTagItemDecoderRSI
+{
+public:
+	CTagItemDecoderRgps(CParameter* pP) : CTagItemDecoderRSI(pP, "rgps") {}
+	virtual void DecodeTag(CVector<_BINARY>& vecbiTag, const int iLenDataBits);
+};
+
+// RSCI control
+
+class CTagItemDecoderRCI : public CTagItemDecoder
+{
+public:
+	CTagItemDecoderRCI(const string& s) : pDRMReceiver(NULL),tag(s) {}
+	void SetReceiver(CDRMReceiver *pReceiver) {pDRMReceiver = pReceiver;}
+	virtual string GetTagName() { return tag; }
+protected:
+	CDRMReceiver *pDRMReceiver;
+	string tag;
+};
+
+class CTagItemDecoderCact : public CTagItemDecoderRCI
+{
+public:
+	CTagItemDecoderCact() : CTagItemDecoderRCI("cact") {}
+	virtual void DecodeTag(CVector<_BINARY>& vecbiTag, const int iLenDataBits);
+};
+
+class CTagItemDecoderCfre : public CTagItemDecoderRCI
+{
+public:
+	CTagItemDecoderCfre() : CTagItemDecoderRCI("cfre") {}
+	virtual void DecodeTag(CVector<_BINARY>& vecbiTag, const int iLenDataBits);
+};
+
+class CTagItemDecoderCdmo : public CTagItemDecoderRCI
+{
+public:
+	CTagItemDecoderCdmo() : CTagItemDecoderRCI("cdmo") {}
+	virtual void DecodeTag(CVector<_BINARY>& vecbiTag, const int iLenDataBits);
+};
+
+class CTagItemDecoderCrec : public CTagItemDecoderRCI
+{
+public:
+	CTagItemDecoderCrec() : CTagItemDecoderRCI("crec") {}
+	virtual void DecodeTag(CVector<_BINARY>& vecbiTag, const int iLenDataBits);
+};
+
+class CTagItemDecoderCpro : public CTagItemDecoderRCI
+{
+public:
+	CTagItemDecoderCpro() : CTagItemDecoderRCI("crec"), pRSISubscriber(NULL) {}
+	virtual void DecodeTag(CVector<_BINARY>& vecbiTag, const int iLenDataBits);
+	void SetSubscriber(CRSISubscriber *pSubscriber) {pRSISubscriber = pSubscriber;}
+private:
+	CRSISubscriber* pRSISubscriber;
+};
+
+#endif
diff --git a/src/MDI/RSISubscriber.cpp b/src/MDI/RSISubscriber.cpp
new file mode 100644
index 0000000..e57306e
--- /dev/null
+++ b/src/MDI/RSISubscriber.cpp
@@ -0,0 +1,229 @@
+/******************************************************************************\
+ * British Broadcasting Corporation
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Oliver Haffenden
+ *
+ * Description:
+ *
+ *	This class represents a particular consumer of RSI information and supplier of
+ *  RCI commands. There could be several of these. The profile is a property of the
+ *  particular subscriber and different subscribers could have different profiles.
+ *
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "PacketSocket.h"
+#include "RSISubscriber.h"
+#include "../DrmReceiver.h"
+#include "TagPacketGenerator.h"
+
+
+CRSISubscriber::CRSISubscriber(CPacketSink *pSink) : pPacketSink(pSink),
+	cProfile(0), bNeedPft(FALSE), fragment_size(0), pDRMReceiver(0),
+	bUseAFCRC(TRUE), sequence_counter(0)
+{
+	TagPacketDecoderRSCIControl.SetSubscriber(this);
+}
+
+void CRSISubscriber::SetReceiver(CDRMReceiver *pReceiver)
+{
+	pDRMReceiver = pReceiver;
+	TagPacketDecoderRSCIControl.SetReceiver(pReceiver);
+}
+
+void CRSISubscriber::SetProfile(const char c)
+{
+	cProfile = c;
+}
+
+void CRSISubscriber::SetPFTFragmentSize(const int iFrag)
+{
+    if(iFrag>0)
+    {
+        fragment_size = iFrag;
+        bNeedPft = TRUE;
+    }
+    else
+        bNeedPft = FALSE;
+}
+
+void CRSISubscriber::TransmitPacket(CTagPacketGenerator& Generator)
+{
+	if (pPacketSink != 0)
+	{
+	 	Generator.SetProfile(cProfile);
+		vector<_BYTE> packet = AFPacketGenerator.GenAFPacket(bUseAFCRC, Generator);
+		if(bNeedPft)
+		{
+			vector< vector<_BYTE> > packets;
+			CPft::MakePFTPackets(packet, packets, sequence_counter, fragment_size);
+			sequence_counter++;
+			for(size_t i=0; i<packets.size(); i++)
+				pPacketSink->SendPacket(packets[i]);
+		}
+		else
+			pPacketSink->SendPacket(packet);
+	}
+}
+
+
+/* implementation of function from CPacketSink interface - process incoming RCI commands */
+void CRSISubscriber::SendPacket(const vector<_BYTE>& vecbydata, uint32_t, uint16_t)
+{
+	CVectorEx<_BINARY> vecbidata;
+	vecbidata.Init(vecbydata.size()*SIZEOF__BYTE);
+	vecbidata.ResetBitAccess();
+	for(size_t i=0; i<vecbydata.size(); i++)
+		vecbidata.Enqueue(vecbydata[i], SIZEOF__BYTE);
+	CTagPacketDecoder::Error err = TagPacketDecoderRSCIControl.DecodeAFPacket(vecbidata);
+	if(err != CTagPacketDecoder::E_OK)
+		cerr << "bad RSCI Control Packet Received" << endl;
+}
+
+
+/* TODO wrap a sendto in a class and store it in pPacketSink */
+CRSISubscriberSocket::CRSISubscriberSocket(CPacketSink *pSink):CRSISubscriber(pSink),pSocket(NULL)
+,uIf(0),uAddr(0),uPort(0)
+{
+	pSocket = new CPacketSocketNative;
+	pPacketSink = pSocket;
+}
+
+CRSISubscriberSocket::~CRSISubscriberSocket()
+{
+	delete pSocket;
+}
+
+_BOOLEAN CRSISubscriberSocket::SetDestination(const string& dest)
+{
+	if(pSocket==NULL)
+	{
+		return FALSE;
+	}
+	string d = dest;
+	if(d[0] == 'P' || d[0] == 'p')
+	{
+		SetPFTFragmentSize(800);
+		d.erase(0, 1);
+	}
+	_BOOLEAN bOk = pSocket->SetDestination(d);
+	if(bOk)
+		pSocket->SetPacketSink(this);
+	return bOk;
+}
+
+_BOOLEAN CRSISubscriberSocket::GetDestination(string& str)
+{
+	/* want the canonical version so incoming can match */
+	if(pSocket)
+		return pSocket->GetDestination(str);
+	return FALSE;
+}
+
+_BOOLEAN CRSISubscriberSocket::SetOrigin(const string& str)
+{
+	if(pSocket==NULL)
+	{
+		return FALSE;
+	}
+	// Delegate to socket
+	_BOOLEAN bOK = pSocket->SetOrigin(str);
+	if (bOK)
+	{
+		// Connect socket to the MDI decoder
+		pSocket->SetPacketSink(this);
+		return bOK;
+	}
+	return FALSE;
+}
+
+bool CRSISubscriberSocket::GetOrigin(string& str)
+{
+	if(pSocket==NULL)
+	{
+		return FALSE;
+	}
+	// Delegate to socket
+	return pSocket->GetOrigin(str);
+}
+
+/* poll for incoming packets */
+void CRSISubscriberSocket::poll()
+{
+	if(pSocket!=NULL)
+		pSocket->poll();
+}
+
+CRSISubscriberFile::CRSISubscriberFile(): CRSISubscriber(NULL), pPacketSinkFile(NULL)
+{
+	/* override the subscriber back to NULL to prevent Cpro doing anything */
+	TagPacketDecoderRSCIControl.SetSubscriber(NULL);
+}
+
+_BOOLEAN CRSISubscriberFile::SetDestination(const string& strFName)
+{
+    string dest = strFName;
+	if(pPacketSink)
+	{
+		delete pPacketSink;
+		pPacketSink = NULL;
+		pPacketSinkFile = NULL;
+	}
+	string ext;
+	size_t p = strFName.rfind('.');
+	if (p != string::npos)
+		ext = strFName.substr(p + 1);
+	if (ext == "pcap")
+		pPacketSinkFile = new CPacketSinkPcapFile;
+	else if(ext == "ff")
+	{
+		pPacketSinkFile = new CPacketSinkFileFraming;
+		dest.erase(p);
+	}
+	else
+		pPacketSinkFile = new CPacketSinkRawFile;
+	if(pPacketSinkFile && pPacketSinkFile->SetDestination(dest))
+	{
+		pPacketSinkFile->StartRecording();
+		pPacketSink = pPacketSinkFile;
+		return TRUE;
+	}
+	return FALSE;
+}
+
+_BOOLEAN CRSISubscriberFile::GetDestination(string& strFName)
+{
+	if(pPacketSinkFile)
+		return pPacketSinkFile->GetDestination(strFName);
+	return FALSE;
+}
+
+void CRSISubscriberFile::StartRecording()
+{
+	if(pPacketSinkFile)
+		pPacketSinkFile->StartRecording();
+}
+
+void CRSISubscriberFile::StopRecording()
+{
+	if(pPacketSinkFile)
+		pPacketSinkFile->StopRecording();
+}
diff --git a/src/MDI/RSISubscriber.h b/src/MDI/RSISubscriber.h
new file mode 100644
index 0000000..a002388
--- /dev/null
+++ b/src/MDI/RSISubscriber.h
@@ -0,0 +1,128 @@
+/******************************************************************************\
+ * British Broadcasting Corporation
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Oliver Haffenden
+ *
+ * Description:
+ *	see RSISubscriber.cpp
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#ifndef RSI_SUBSCRIBER_H_INCLUDED
+#define RSI_SUBSCRIBER_H_INCLUDED
+
+#include "../GlobalDefinitions.h"
+#include "TagPacketDecoderRSCIControl.h"
+#include "PacketInOut.h"
+#include "PacketSinkFile.h"
+#include "PacketInOut.h"
+#include "AFPacketGenerator.h"
+
+class CPacketSink;
+class CDRMReceiver;
+class CTagPacketGenerator;
+
+class CRSISubscriber : public CPacketSocket
+{
+public:
+	CRSISubscriber(CPacketSink *pSink = NULL);
+
+	/* provide a pointer to the receiver for incoming RCI commands */
+	/* leave it set to NULL if you want incoming commands to be ignored */
+	void SetReceiver(CDRMReceiver *pReceiver);
+
+	virtual _BOOLEAN SetOrigin(const string&){return FALSE;} // only relevant for network subscribers
+
+	/* Set the profile for this subscriber - could be different for different subscribers */
+	void SetProfile(const char c);
+	char GetProfile(void) const {return cProfile;}
+
+	void SetPFTFragmentSize(const int iFrag=-1);
+
+	/* Generate and send a packet */
+	void TransmitPacket(CTagPacketGenerator& Generator);
+
+	void SetAFPktCRC(const _BOOLEAN bNAFPktCRC) {bUseAFCRC = bNAFPktCRC;}
+
+
+	/* from CPacketSink interface */
+	virtual void SendPacket(const vector<_BYTE>& vecbydata, uint32_t addr=0, uint16_t port=0);
+
+	/* from CPacketSource, but we really want it for RSCI control */
+	virtual void poll()=0;
+
+protected:
+	CPacketSink *pPacketSink;
+	char cProfile;
+	_BOOLEAN bNeedPft;
+    size_t fragment_size;
+	CTagPacketDecoderRSCIControl TagPacketDecoderRSCIControl;
+private:
+	CDRMReceiver *pDRMReceiver;
+	CAFPacketGenerator AFPacketGenerator;
+
+	_BOOLEAN bUseAFCRC;
+	uint16_t sequence_counter;
+};
+
+
+class CRSISubscriberSocket : public CRSISubscriber
+{
+public:
+	CRSISubscriberSocket(CPacketSink *pSink = NULL);
+	virtual ~CRSISubscriberSocket();
+
+	_BOOLEAN SetOrigin(const string& str);
+	_BOOLEAN GetOrigin(string& addr);
+	_BOOLEAN SetDestination(const string& str);
+	_BOOLEAN GetDestination(string& addr);
+	void SetPacketSink(CPacketSink *pSink) { (void)pSink; }
+	void ResetPacketSink() {}
+	void poll();
+
+private:
+	CPacketSocket* pSocket;
+	string strDestination;
+	uint32_t uIf, uAddr;
+	uint16_t uPort;
+};
+
+
+class CRSISubscriberFile : public CRSISubscriber
+{
+public:
+	CRSISubscriberFile();
+
+	_BOOLEAN SetDestination(const string& strFName);
+	void StartRecording();
+	void StopRecording();
+	void poll() {} // Do Nothing
+
+	_BOOLEAN GetDestination(string& addr);
+	_BOOLEAN GetOrigin(string& addr) { (void)addr; return false; }
+	void SetPacketSink(CPacketSink *pSink) { (void)pSink; }
+	void ResetPacketSink() {}
+private:
+	CPacketSinkFile* pPacketSinkFile;
+};
+
+#endif
+
diff --git a/src/MDI/TagItemDecoder.h b/src/MDI/TagItemDecoder.h
new file mode 100644
index 0000000..d72f5dd
--- /dev/null
+++ b/src/MDI/TagItemDecoder.h
@@ -0,0 +1,82 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer, Oliver Haffenden
+ *
+ * Description:
+ *	Pure abstract base class for a tag item decoder. The client (CTagPacketDecoder) should read the name and length,
+ *  and check the name against the name returned by GetTagName(). If it matches, the rest of the
+ *  tag body should be passed to DecodeTag().
+ *  Specialised derived classes should be constructed with any pointers they need to act upon the
+ *  decoded information. This might be the CTagPacketDecoder subclass that owns them, or some other
+ *  object that will receive the information.
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#ifndef TAG_ITEM_DECODER_H_INCLUDED
+#define TAG_ITEM_DECODER_H_INCLUDED
+
+#include "../GlobalDefinitions.h"
+#include "../Parameter.h"
+#include "MDIDefinitions.h"
+#include "../util/Vector.h"
+
+
+class CTagItemDecoder
+{
+public:
+	// Decode the tag item body. The name and length should already have been consumed by the
+	// caller (CTagPacketDecoder).
+	virtual void DecodeTag(CVector<_BINARY>& vecbiTag, const int iLenDataBits) = 0;
+
+	// This function must return the name of the tag item that this decoder decodes.
+	virtual string GetTagName(void) = 0;
+	virtual ~CTagItemDecoder() {}
+
+	CTagItemDecoder() : bIsReady(FALSE) {};
+	// initialise any internal state variables. TODO: Make this pure to force implementer to think?
+	virtual void Init(void) {bIsReady = FALSE;}
+
+	virtual _BOOLEAN IsReady(void) {return bIsReady;}
+
+protected:
+	void SetReady(_BOOLEAN bReady) {bIsReady = bReady;}
+
+private:
+	_BOOLEAN bIsReady;
+
+};
+
+// RSCI Status
+class CTagItemDecoderRSI : public CTagItemDecoder
+{
+public:
+    CTagItemDecoderRSI(CParameter* pP, const string& s) : pParameter(pP), tag(s) {}
+    void SetParameterPtr(CParameter *pP) {pParameter = pP;}
+    virtual string GetTagName() { return tag; }
+protected:
+
+    _REAL decodeDb(CVector<_BINARY>& vecbiTag);
+    CParameter *pParameter;
+    string tag;
+};
+
+#endif
diff --git a/src/MDI/TagPacketDecoder.cpp b/src/MDI/TagPacketDecoder.cpp
new file mode 100644
index 0000000..633c8f3
--- /dev/null
+++ b/src/MDI/TagPacketDecoder.cpp
@@ -0,0 +1,225 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer, Julian Cable, Oliver Haffenden
+ *
+ * Description:
+ *	Implements Digital Radio Mondiale (DRM) Multiplex Distribution Interface
+ *	(MDI), Receiver Status and Control Interface (RSCI)
+ *  and Distribution and Communications Protocol (DCP) as described in
+ *	ETSI TS 102 820,  ETSI TS 102 349 and ETSI TS 102 821 respectively.
+ *
+ *  This module defines the base class CTagPacketDecoder which can be used to
+ *  derive a decoder specialised to a particular TAG layer application.
+ *  The class deals with AF packet decoding, and TAG packet decoding.
+ *
+ *  The TAG packet decoding works by keeping a collection (vector of pointers) of TAG item decoders. This collection
+ *  should be populated by the constructor of the derived class. This class loops through each TAG item,
+ *  checking the TAG name against all the decoders' TAG names. If it matches, it calls the TAG item decoder
+ *  itself to do the actual decoding.
+ *
+ *  TODO: It would be better to separate the AF decoding into its own class.
+ *  PFT also needs to be added (again, in its own class).
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "TagPacketDecoder.h"
+#include "TagItemDecoder.h"
+#include "../util/CRC.h"
+#include <iostream>
+
+CTagPacketDecoder::CTagPacketDecoder() : vecpTagItemDecoders(0),iSeqNumber(0xffff)
+{
+}
+
+// This should be in its own class
+CTagPacketDecoder::Error
+CTagPacketDecoder::DecodeAFPacket(CVectorEx<_BINARY>& vecbiAFPkt)
+{
+
+	int i;
+
+	/* CRC check ------------------------------------------------------------ */
+	CCRC CRCObject;
+	// FIXME: is this length always the correct length? In the actual packet
+	// there is also a value for the length included!!!???!???
+    int iLenAFPktBits = vecbiAFPkt.Size();
+    int iLenAFPktBytes = iLenAFPktBits/SIZEOF__BYTE;
+    int iLenPayloadBytes = iLenAFPktBytes - 12;
+
+	/* We do the CRC check at the beginning no matter if it is used or not
+	   since we have to reset bit access for that */
+	/* Reset bit extraction access */
+	vecbiAFPkt.ResetBitAccess();
+
+	/* Check the CRC of this packet */
+	CRCObject.Reset(16);
+
+	/* "- 2": 16 bits for CRC at the end */
+    for (i = 0; i < iLenAFPktBytes - 2; i++)
+	{
+		CRCObject.AddByte((_BYTE) vecbiAFPkt.Separate(SIZEOF__BYTE));
+	}
+
+	int iCRC = vecbiAFPkt.Separate(16);
+
+	const _BOOLEAN bCRCOk = CRCObject.CheckCRC(iCRC);
+    (void)bCRCOk;
+
+	/* Actual packet decoding ----------------------------------------------- */
+	vecbiAFPkt.ResetBitAccess();
+
+	/* SYNC: two-byte ASCII representation of "AF" (2 bytes) */
+	string strSyncASCII = "";
+	for (i = 0; i < 2; i++)
+	{
+		strSyncASCII += (_BYTE) vecbiAFPkt.Separate(SIZEOF__BYTE);
+	}
+	/* Check if string is correct */
+	if (strSyncASCII.compare("AF") != 0)
+	{
+		cerr << "not an AF packet" << endl;
+		return E_SYNC;
+	}
+
+	/* LEN: length of the payload, in bytes (4 bytes long -> 32 bits) */
+	const int iPayLLen = (int) vecbiAFPkt.Separate(32);
+    if(iLenPayloadBytes != iPayLLen)
+    {
+        // TODO
+    }
+
+	/* SEQ: sequence number. Each AF Packet shall increment the sequence number
+	   by one for each packet sent, regardless of content. There shall be no
+	   requirement that the first packet received shall have a specific value.
+	   The counter shall wrap from FFFF_[16] to 0000_[16], thus the value shall
+	   count, FFFE_[16], FFFF_[16], 0000_[16], 0001_[16], etc.
+	   (2 bytes long -> 16 bits) */
+
+	const int iCurSeqNum = (int) vecbiAFPkt.Separate(16);
+	(void)iCurSeqNum;
+	iSeqNumber++;
+	if(iSeqNumber!=iCurSeqNum)
+	{
+		if(iSeqNumber!=0xffff)
+			cerr << "AF SEQ: expected " << iSeqNumber << " got " << iCurSeqNum << endl;
+		iSeqNumber=iCurSeqNum;
+	}
+
+	/* AR: AF protocol Revision -
+	   a field combining the CF, MAJ and MIN fields */
+	/* CF: CRC Flag, 0 if the CRC field is not used (CRC value shall be
+	   0000_[16]) or 1 if the CRC field contains a valid CRC (1 bit long) */
+	if (vecbiAFPkt.Separate(1)==1)
+	{
+		/* Use CRC check which was already done */
+//		if (!bCRCOk)
+//			return E_CRC;
+	}
+
+	/* MAJ: major revision of the AF protocol in use (3 bits long) */
+	const int iMajRevAFProt = (int) vecbiAFPkt.Separate(3);
+	(void)iMajRevAFProt;
+
+	/* MIN: minor revision of the AF protocol in use (4 bits long) */
+	const int iMinRevAFProt = (int) vecbiAFPkt.Separate(4);
+	(void)iMinRevAFProt;
+
+// TODO: check if protocol versions match our version!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+
+	/* Protocol Type (PT): single byte encoding the protocol of the data carried
+	   in the payload. For TAG Packets, the value shall be the ASCII
+	   representation of "T" */
+	if ((_BYTE) vecbiAFPkt.Separate(SIZEOF__BYTE) != 'T')
+	{
+		return E_PROTO;
+	}
+
+
+	/* Payload -------------------------------------------------------------- */
+	DecodeTagPackets(vecbiAFPkt, iPayLLen);
+
+	return E_OK;
+}
+
+	// Decode all the tags in the tag packet. To do things before or after the decoding,
+	// override this and call the base class function to do the decoding
+void CTagPacketDecoder::DecodeTagPackets(CVectorEx<_BINARY>& vecbiPkt, const int iPayloadLen)
+{
+	/* Decode all tags */
+	int iCurConsBytes = 0;
+
+	/* Each tag must have at least a header with 8 bytes -> "- 8" */
+	while (iCurConsBytes < iPayloadLen - 8)
+		iCurConsBytes += DecodeTag(vecbiPkt);
+}
+
+	// Go through all the tag item decoders to find one that matches the current tag name.
+int CTagPacketDecoder::DecodeTag(CVector<_BINARY>& vecbiTag)
+{
+	int i;
+
+	/* Decode tag name (always four bytes long) */
+	string strTagName = "";
+	for (i = 0; i < 4; i++)
+		strTagName += (_BYTE) vecbiTag.Separate(SIZEOF__BYTE);
+	/* Get tag data length (4 bytes = 32 bits) */
+	const int iLenDataBits = vecbiTag.Separate(32);
+	/* Check the tag name against each tag decoder in the vector of tag decoders */
+	_BOOLEAN bTagWasDec = FALSE;
+	for (i=0; i<vecpTagItemDecoders.Size(); i++)
+	{
+		if (strTagName.compare(vecpTagItemDecoders[i]->GetTagName()) == 0) // it's this tag
+		{
+			vecpTagItemDecoders[i]->DecodeTag(vecbiTag, iLenDataBits);
+			bTagWasDec = TRUE;
+		}
+	}
+
+	/* Take care of tags which are not supported */
+	if (bTagWasDec == FALSE)
+	{
+		/* Take bits from tag vector */
+		for (i = 0; i < iLenDataBits; i++)
+			vecbiTag.Separate(1);
+	}
+
+	/* Return number of consumed bytes. This number is the actual body plus two
+	   times for bytes for the header = 8 bytes */
+	return iLenDataBits / SIZEOF__BYTE + 8;
+
+}
+
+
+void CTagPacketDecoder::AddTagItemDecoder(CTagItemDecoder *pTagItemDecoder)
+{
+	vecpTagItemDecoders.Add(pTagItemDecoder);
+}
+
+void CTagPacketDecoder::InitTagItemDecoders(void)
+{
+	for (int i=0; i<vecpTagItemDecoders.Size(); i++)
+	{
+		vecpTagItemDecoders[i]->Init();
+	}
+
+}
diff --git a/src/MDI/TagPacketDecoder.h b/src/MDI/TagPacketDecoder.h
new file mode 100644
index 0000000..906dcca
--- /dev/null
+++ b/src/MDI/TagPacketDecoder.h
@@ -0,0 +1,64 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer, Oliver Haffenden
+ *
+ * Description:
+ *	see TagPacketDecoder.cpp
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#ifndef TAG_PACKET_DECODER_H_INCLUDED
+#define TAG_PACKET_DECODER_H_INCLUDED
+
+#include "../GlobalDefinitions.h"
+#include "MDIDefinitions.h"
+#include "../util/Vector.h"
+#include "PacketInOut.h"
+
+class CTagItemDecoder;
+
+class CTagPacketDecoder
+{
+public:
+	CTagPacketDecoder();
+	enum Error { E_OK, E_CRC, E_VERSION, E_LENGTH, E_SYNC, E_PROTO };
+	// This should be in its own class
+	virtual Error DecodeAFPacket(CVectorEx<_BINARY>& vecbiAFPkt);
+
+	// Decode all the tags in the tag packet. To do things before or after the decoding,
+	// override this and call the base class function to do the decoding
+	virtual void DecodeTagPackets(CVectorEx<_BINARY>& vecbiPkt, int iPayloadLen);
+	virtual ~CTagPacketDecoder() {}
+
+protected:
+	// Go through all the tag item decoders to find one that matches the current tag name.
+	int DecodeTag(CVector<_BINARY>& vecbiTag);
+
+	void AddTagItemDecoder(CTagItemDecoder *pTagItemDecoder);
+
+	void InitTagItemDecoders(void);
+private:
+	CVector<CTagItemDecoder *> vecpTagItemDecoders;
+	uint16_t iSeqNumber;
+};
+
+#endif
diff --git a/src/MDI/TagPacketDecoderMDI.cpp b/src/MDI/TagPacketDecoderMDI.cpp
new file mode 100644
index 0000000..ffae360
--- /dev/null
+++ b/src/MDI/TagPacketDecoderMDI.cpp
@@ -0,0 +1,124 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer, Julian Cable, Oliver Haffenden
+ *
+ * Description:
+ *	Implements Digital Radio Mondiale (DRM) Multiplex Distribution Interface
+ *	(MDI), Receiver Status and Control Interface (RSCI)
+ *  and Distribution and Communications Protocol (DCP) as described in
+ *	ETSI TS 102 820,  ETSI TS 102 349 and ETSI TS 102 821 respectively.
+ *
+ *	This is a class derived from CTagPacketDecoder, specialised for the MDI application.
+ *
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+
+#include "TagPacketDecoderMDI.h"
+
+CTagPacketDecoderMDI::CTagPacketDecoderMDI()
+:	TagItemDecoderProTy()
+,	TagItemDecoderLoFrCnt()
+,	TagItemDecoderFAC()
+,	TagItemDecoderSDC()
+,	TagItemDecoderRobMod()
+,	TagItemDecoderStr()
+,	TagItemDecoderSDCChanInf(0)
+,	TagItemDecoderInfo()
+,	TagItemDecoderRxDemodMode()
+,	TagItemDecoderAMAudio()
+
+,	TagItemDecoderRmer(0)
+,	TagItemDecoderRwmf(0)
+,	TagItemDecoderRwmm(0)
+,	TagItemDecoderRdbv(0)
+,	TagItemDecoderRpsd(0)
+,	TagItemDecoderRpir(0)
+,	TagItemDecoderRdop(0)
+,	TagItemDecoderRdel(0)
+,	TagItemDecoderRgps(0)
+
+{
+
+	// Add the tag item decoders to the base class list of decoders
+	// This defines the vocabulary of this particular decoder
+	AddTagItemDecoder(&TagItemDecoderProTy);
+	AddTagItemDecoder(&TagItemDecoderLoFrCnt);
+	AddTagItemDecoder(&TagItemDecoderFAC);
+	AddTagItemDecoder(&TagItemDecoderSDC);
+	AddTagItemDecoder(&TagItemDecoderRobMod);
+	TagItemDecoderStr.resize(MAX_NUM_STREAMS);
+	for(int i=0; i<MAX_NUM_STREAMS; i++)
+	{
+		TagItemDecoderStr[i].iStreamNumber = i;
+        AddTagItemDecoder(&TagItemDecoderStr[i]);
+	}
+	AddTagItemDecoder(&TagItemDecoderSDCChanInf);
+	AddTagItemDecoder(&TagItemDecoderInfo);
+	AddTagItemDecoder(&TagItemDecoderRxDemodMode);
+	AddTagItemDecoder(&TagItemDecoderAMAudio);
+
+	// RSCI-specific
+	AddTagItemDecoder(&TagItemDecoderRmer);
+	AddTagItemDecoder(&TagItemDecoderRwmf);
+	AddTagItemDecoder(&TagItemDecoderRwmm);
+	AddTagItemDecoder(&TagItemDecoderRdbv);
+	AddTagItemDecoder(&TagItemDecoderRpsd);
+	AddTagItemDecoder(&TagItemDecoderRpir);
+	AddTagItemDecoder(&TagItemDecoderRdop);
+	AddTagItemDecoder(&TagItemDecoderRdel);
+	AddTagItemDecoder(&TagItemDecoderRgps);
+
+}
+
+void CTagPacketDecoderMDI::SetParameterPtr(CParameter *pP)
+{
+	// Pass this pointer to all of the tag item decoders that need it, i.e. the RSCI-specific ones
+    TagItemDecoderSDCChanInf.SetParameterPtr(pP);
+    TagItemDecoderRmer.SetParameterPtr(pP);
+	TagItemDecoderRwmf.SetParameterPtr(pP);
+	TagItemDecoderRwmm.SetParameterPtr(pP);
+	TagItemDecoderRdbv.SetParameterPtr(pP);
+	TagItemDecoderRpsd.SetParameterPtr(pP);
+	TagItemDecoderRpir.SetParameterPtr(pP);
+	TagItemDecoderRdop.SetParameterPtr(pP);
+	TagItemDecoderRdel.SetParameterPtr(pP);
+	TagItemDecoderRgps.SetParameterPtr(pP);
+}
+
+void CTagPacketDecoderMDI::DecodeTagPackets(CVectorEx<_BINARY>& vecbiPkt, int iPayloadLen)
+{
+	// Initialise all the decoders: this will set them to "not ready"
+	InitTagItemDecoders();
+	// Set strx tags data to zero length in case they are not present
+	for(int i=0; i<MAX_NUM_STREAMS; i++)
+	{
+		TagItemDecoderStr[i].vecbidata.Init(0);
+	}
+	TagItemDecoderAMAudio.vecbidata.Init(0);
+	TagItemDecoderFAC.vecbidata.Init(0);
+	TagItemDecoderSDC.vecbidata.Init(0);
+
+	TagItemDecoderRobMod.Init();
+	// Call base class function to do the actual decoding
+	CTagPacketDecoder::DecodeTagPackets(vecbiPkt, iPayloadLen);
+}
diff --git a/src/MDI/TagPacketDecoderMDI.h b/src/MDI/TagPacketDecoderMDI.h
new file mode 100644
index 0000000..e19081a
--- /dev/null
+++ b/src/MDI/TagPacketDecoderMDI.h
@@ -0,0 +1,75 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer, Oliver Haffenden
+ *
+ * Description:
+ *	see MDITagPacketDecoder.cpp
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#ifndef MDI_TAG_PACKET_DECODER_H_INCLUDED
+#define MDI_TAG_PACKET_DECODER_H_INCLUDED
+
+#include "TagPacketDecoder.h"
+#include "MDITagItemDecoders.h"
+#include "RSCITagItemDecoders.h"
+
+class CTagPacketDecoderMDI : public CTagPacketDecoder
+{
+public:
+	// constructor: adds all of the decoders in the vocabulary to the list
+	CTagPacketDecoderMDI();
+
+	// Set the pParameter pointer - RSCI tag item decoders will write to this directly
+	void SetParameterPtr(CParameter *pP);
+
+	// Overridden tag packet decoder function - clear the str tags before decoding
+	virtual void DecodeTagPackets(CVectorEx<_BINARY>& vecbiPkt, int iPayloadLen);
+
+	// Decoders for each of the tag items in the vocabulary
+
+	//	MDI
+	CTagItemDecoderProTy		TagItemDecoderProTy;
+	CTagItemDecoderLoFrCnt		TagItemDecoderLoFrCnt;
+	CTagItemDecoderFAC			TagItemDecoderFAC;
+	CTagItemDecoderSDC			TagItemDecoderSDC;
+	CTagItemDecoderRobMod		TagItemDecoderRobMod;
+	vector<CTagItemDecoderStr>	TagItemDecoderStr;
+	CTagItemDecoderSDCChanInf	TagItemDecoderSDCChanInf;
+	CTagItemDecoderInfo			TagItemDecoderInfo;
+	CTagItemDecoderRxDemodMode	TagItemDecoderRxDemodMode;
+	CTagItemDecoderAMAudio		TagItemDecoderAMAudio;
+
+	// RSCI-specific
+	CTagItemDecoderRmer			TagItemDecoderRmer;
+	CTagItemDecoderRwmf			TagItemDecoderRwmf;
+	CTagItemDecoderRwmm			TagItemDecoderRwmm;
+	CTagItemDecoderRdbv			TagItemDecoderRdbv;
+	CTagItemDecoderRpsd			TagItemDecoderRpsd;
+	CTagItemDecoderRpir			TagItemDecoderRpir;
+	CTagItemDecoderRdop			TagItemDecoderRdop;
+	CTagItemDecoderRdel			TagItemDecoderRdel;
+	CTagItemDecoderRgps			TagItemDecoderRgps;
+
+};
+
+#endif
diff --git a/src/MDI/TagPacketDecoderRSCIControl.cpp b/src/MDI/TagPacketDecoderRSCIControl.cpp
new file mode 100644
index 0000000..6364133
--- /dev/null
+++ b/src/MDI/TagPacketDecoderRSCIControl.cpp
@@ -0,0 +1,71 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer, Julian Cable, Oliver Haffenden
+ *
+ * Description:
+ *	Implements Digital Radio Mondiale (DRM) Multiplex Distribution Interface
+ *	(MDI), Receiver Status and Control Interface (RSCI)  
+ *  and Distribution and Communications Protocol (DCP) as described in
+ *	ETSI TS 102 820,  ETSI TS 102 349 and ETSI TS 102 821 respectively.
+ *
+ *  This module derives a class from the CTagPacketDecoder base class, specialised for the
+ *  TAG items defined in the control part of RSCI.
+ *  The TAG item decoders need to be given a pointer to the CDRMReceiver object so they
+ *  can send commands (e.g. change frequency) to it.
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+
+
+#include "TagPacketDecoderRSCIControl.h"
+
+// constructor: adds all of the decoders in the vocabulary to the list
+CTagPacketDecoderRSCIControl::CTagPacketDecoderRSCIControl(void) 
+: pDRMReceiver(NULL)
+, TagItemDecoderCact()
+, TagItemDecoderCfre()
+, TagItemDecoderCdmo()
+, TagItemDecoderCrec()
+, TagItemDecoderCpro()
+{
+	// Add each tag item decoder to the vocabulary
+	AddTagItemDecoder(&TagItemDecoderCact);
+	AddTagItemDecoder(&TagItemDecoderCfre);
+	AddTagItemDecoder(&TagItemDecoderCdmo);
+	AddTagItemDecoder(&TagItemDecoderCrec);
+	AddTagItemDecoder(&TagItemDecoderCpro);
+}
+
+
+void CTagPacketDecoderRSCIControl::SetReceiver(CDRMReceiver *pReceiver)
+{
+	pDRMReceiver = pReceiver;
+	TagItemDecoderCact.SetReceiver(pReceiver);
+	TagItemDecoderCfre.SetReceiver(pReceiver);
+	TagItemDecoderCdmo.SetReceiver(pReceiver);
+	TagItemDecoderCrec.SetReceiver(pReceiver);
+}
+
+void CTagPacketDecoderRSCIControl::SetSubscriber(CRSISubscriber *pSubscriber)
+{
+	TagItemDecoderCpro.SetSubscriber(pSubscriber);
+}
diff --git a/src/MDI/TagPacketDecoderRSCIControl.h b/src/MDI/TagPacketDecoderRSCIControl.h
new file mode 100644
index 0000000..0ca0bd9
--- /dev/null
+++ b/src/MDI/TagPacketDecoderRSCIControl.h
@@ -0,0 +1,62 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer, Oliver Haffenden
+ *
+ * Description:
+ *	see TagPacketDecoderRSCIControl.cpp
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#ifndef TAG_PACKET_DECODER_RSCI_CONTROL_H_INCLUDED
+#define TAG_PACKET_DECODER_RSCI_CONTROL_H_INCLUDED
+
+#include "TagPacketDecoder.h"
+#include "RSCITagItemDecoders.h"
+
+class CDRMReceiver;
+class CRSISubscriber;
+
+class CTagPacketDecoderRSCIControl : public CTagPacketDecoder
+{
+public:
+	// constructor: adds all of the decoders in the vocabulary to the list
+	CTagPacketDecoderRSCIControl(void);
+
+	// Sets the object's pointer to the receiver which it will send commands to.
+	// This MUST be called soon after construction.
+	void SetReceiver(CDRMReceiver *pReceiver);
+	void SetSubscriber(CRSISubscriber *pSubscriber);
+
+private:
+	// Decoders send settings to the receiver
+	CDRMReceiver * pDRMReceiver;
+
+	// Decoders for each of the tag items in the vocabulary
+	CTagItemDecoderCact			TagItemDecoderCact;
+	CTagItemDecoderCfre			TagItemDecoderCfre;
+	CTagItemDecoderCdmo			TagItemDecoderCdmo;
+	CTagItemDecoderCrec			TagItemDecoderCrec;
+	CTagItemDecoderCpro			TagItemDecoderCpro;
+	// TODO other RSCI control tag items
+};
+
+#endif
diff --git a/src/MDI/TagPacketGenerator.cpp b/src/MDI/TagPacketGenerator.cpp
new file mode 100644
index 0000000..d160f8e
--- /dev/null
+++ b/src/MDI/TagPacketGenerator.cpp
@@ -0,0 +1,111 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer, Julian Cable, Oliver Haffenden
+ *
+ * Description:
+ *	Implements Digital Radio Mondiale (DRM) Multiplex Distribution Interface
+ *	(MDI), Receiver Status and Control Interface (RSCI)  
+ *  and Distribution and Communications Protocol (DCP) as described in
+ *	ETSI TS 102 820,  ETSI TS 102 349 and ETSI TS 102 821 respectively.
+ *
+ *  This module defines both the CTagPacketGenerator base class and a CTagPacketGeneratorWithProfiles derived class.
+ *
+ *  CTagPacketGenerator does the job of putting together all the tag items, delegating the 
+ *  actual generation to each of a collection of CTagItemGenerators.
+ *  This collection should be filled up by the client code first calling Reset() and then 
+ *  repeatedly calling AddTagItem() with a generator for each tag item.
+ *  
+ *  CTagPacketGeneratorWithProfiles is a derived class that takes care of protocols like RSCI/MDI
+ *  in which a number of protocols are defined. The client should call SetProfile() before adding the
+ *  tag items. Use AddTagItemIfInProfile() instead of AddTagItem().
+ *  (Maybe this could just be an overridden version of AddTagItem()? )
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+
+
+#include "TagPacketGenerator.h"
+#include <iostream>
+
+CTagPacketGenerator::CTagPacketGenerator() : vecTagItemGenerators(0) 
+{
+}
+
+void CTagPacketGenerator::PutTagPacketData(CVector<_BINARY> &vecbiDestination)
+{
+	for (size_t i=0; i<vecTagItemGenerators.size(); i++)
+	{
+		vecTagItemGenerators[i]->PutTagItemData(vecbiDestination);
+	}
+}
+
+int CTagPacketGenerator::GetTagPacketLength()
+{
+	int iPayloadLenBytes = 0;
+		
+	for (size_t i=0; i<vecTagItemGenerators.size(); i++)
+	{
+		int n = vecTagItemGenerators[i]->GetTotalLength() / SIZEOF__BYTE;
+		iPayloadLenBytes += n;
+	}
+	return iPayloadLenBytes;
+}
+
+
+void CTagPacketGenerator::AddTagItem(CTagItemGenerator *pGenerator)
+{
+	vecTagItemGenerators.push_back(pGenerator);
+}
+
+
+CTagPacketGeneratorWithProfiles::CTagPacketGeneratorWithProfiles(char cProf) : cProfile(cProf)
+{
+}
+
+void CTagPacketGeneratorWithProfiles::SetProfile(char cProf)
+{
+	cProfile = cProf;
+}
+
+
+void CTagPacketGeneratorWithProfiles::PutTagPacketData(CVector<_BINARY> &vecbiDestination)
+{
+	for (size_t i=0; i<vecTagItemGenerators.size(); i++)
+	{
+		if (vecTagItemGenerators[i]->IsInProfile(cProfile))
+			vecTagItemGenerators[i]->PutTagItemData(vecbiDestination);
+	}
+}
+
+int CTagPacketGeneratorWithProfiles::GetTagPacketLength()
+{
+	int iPayloadLenBytes = 0;
+		
+	for (size_t i=0; i<vecTagItemGenerators.size(); i++)
+	{
+		if (vecTagItemGenerators[i]->IsInProfile(cProfile))
+		{
+			int n = vecTagItemGenerators[i]->GetTotalLength() / SIZEOF__BYTE;
+			iPayloadLenBytes += n;
+		}
+	}
+	return iPayloadLenBytes;
+}
diff --git a/src/MDI/TagPacketGenerator.h b/src/MDI/TagPacketGenerator.h
new file mode 100644
index 0000000..00b4cca
--- /dev/null
+++ b/src/MDI/TagPacketGenerator.h
@@ -0,0 +1,70 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer, Oliver Haffenden
+ *
+ * Description:
+ *	see TagPacketGenerator.cpp
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#ifndef TAG_PACKET_GENERATOR_H_INCLUDED
+#define TAG_PACKET_GENERATOR_H_INCLUDED
+
+#include "../GlobalDefinitions.h"
+#include "MDIDefinitions.h"
+#include "MDITagItems.h"
+#include "MDITagItems.h"
+#include "../Parameter.h"
+#include "../util/Vector.h"
+#include "../util/Buffer.h"
+#include "../util/CRC.h"
+
+
+class CTagPacketGenerator
+{
+public:
+	CTagPacketGenerator(); 
+	virtual ~CTagPacketGenerator(){}
+	void Reset() {vecTagItemGenerators.clear();}
+	void AddTagItem(CTagItemGenerator *pGenerator);
+	virtual void PutTagPacketData(CVector<_BINARY> &vecbiDestination); // Call this to write the tag packet (i.e. all the tag items) to the vector
+	virtual int GetTagPacketLength();
+	virtual void SetProfile(const char /*cProfile*/) {}
+protected:
+	vector<CTagItemGenerator *> vecTagItemGenerators;
+};
+
+
+class CTagPacketGeneratorWithProfiles : public CTagPacketGenerator
+{
+public:
+	CTagPacketGeneratorWithProfiles(const char cProfile = '\0');
+	virtual ~CTagPacketGeneratorWithProfiles(){}
+	/* The following functions are overridden to check the profile for each tag item */
+	virtual void PutTagPacketData(CVector<_BINARY> &vecbiDestination); // Call this to write the tag packet (i.e. all the tag items) to the vector
+	virtual int GetTagPacketLength(void);
+	virtual void SetProfile(const char cProfile);
+private:
+	char cProfile;
+};
+
+#endif
diff --git a/src/MSCMultiplexer.cpp b/src/MSCMultiplexer.cpp
new file mode 100644
index 0000000..e20a7ce
--- /dev/null
+++ b/src/MSCMultiplexer.cpp
@@ -0,0 +1,173 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *	MSC audio/data demultiplexer
+ *
+ *
+ * - (6.2.3.1) Multiplex frames (DRM standard):
+ * The multiplex frames are built by placing the logical frames from each
+ * non-hierarchical stream together. The logical frames consist, in general, of
+ * two parts each with a separate protection level. The multiplex frame is
+ * constructed by taking the data from the higher protected part of the logical
+ * frame from the lowest numbered stream (stream 0 when hierarchical modulation
+ * is not used, or stream 1 when hierarchical modulation is used) and placing
+ * it at the start of the multiplex frame. Next the data from the higher
+ * protected part of the logical frame from the next lowest numbered stream is
+ * appended and so on until all streams have been transferred. The data from
+ * the lower protected part of the logical frame from the lowest numbered
+ * stream (stream 0 when hierarchical modulation is not used, or stream 1 when
+ * hierarchical modulation is used) is then appended, followed by the data from
+ * the lower protected part of the logical frame from the next lowest numbered
+ * stream, and so on until all streams have been transferred. The higher
+ * protected part is designated part A and the lower protected part is
+ * designated part B in the multiplex description. The multiplex frame will be
+ * larger than or equal to the sum of the logical frames from which it is
+ * formed. The remainder, if any, of the multiplex frame shall be filled with
+ * 0s. These bits shall be ignored by the receiver.
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "MSCMultiplexer.h"
+
+
+/* Implementation *************************************************************/
+void CMSCDemultiplexer::ProcessDataInternal(CParameter&)
+{
+    for (size_t i=0; i<MAX_NUM_STREAMS; i++)
+        ExtractData(*pvecInputData, *vecpvecOutputData[i], StreamPos[i]);
+}
+
+void CMSCDemultiplexer::InitInternal(CParameter& Parameters)
+{
+    Parameters.Lock();
+    for (size_t i=0; i<MAX_NUM_STREAMS; i++)
+    {
+        StreamPos[i] = GetStreamPos(Parameters, i);
+        veciOutputBlockSize[i] = StreamPos[i].iLenHigh + StreamPos[i].iLenLow;
+    }
+    /* Set input block size */
+    iInputBlockSize = Parameters.iNumDecodedBitsMSC;
+    Parameters.Unlock();
+}
+
+void CMSCDemultiplexer::ExtractData(CVectorEx<_BINARY>& vecIn,
+                                    CVectorEx<_BINARY>& vecOut,
+                                    SStreamPos& StrPos)
+{
+    int i;
+
+    /* Higher protected part */
+    for (i = 0; i < StrPos.iLenHigh; i++)
+        vecOut[i] = vecIn[i + StrPos.iOffsetHigh];
+
+    /* Lower protected part */
+    for (i = 0; i < StrPos.iLenLow; i++)
+        vecOut[i + StrPos.iLenHigh] = vecIn[i + StrPos.iOffsetLow];
+}
+
+CMSCDemultiplexer::SStreamPos CMSCDemultiplexer::GetStreamPos(CParameter& Param,
+        const int iStreamID)
+{
+    CMSCDemultiplexer::SStreamPos	StPos;
+
+    /* Init positions with zeros (needed if an error occurs) */
+    StPos.iOffsetLow = 0;
+    StPos.iOffsetHigh = 0;
+    StPos.iLenLow = 0;
+    StPos.iLenHigh = 0;
+
+    if (iStreamID != STREAM_ID_NOT_USED)
+    {
+        /* Length of higher and lower protected part of audio stream (number
+           of bits) */
+        StPos.iLenHigh = Param.Stream[iStreamID].iLenPartA * SIZEOF__BYTE;
+        StPos.iLenLow = Param.Stream[iStreamID].iLenPartB *	SIZEOF__BYTE;
+
+
+        /* Byte-offset of higher and lower protected part of audio stream --- */
+        /* Get active streams */
+        set<int> actStreams;
+        Param.GetActiveStreams(actStreams);
+
+        /* Get start offset for lower protected parts in stream. Since lower
+           protected part comes after the higher protected part, the offset
+           must be shifted initially by all higher protected part lengths
+           (iLenPartA of all streams are added) 6.2.3.1 */
+        StPos.iOffsetLow = 0;
+        set<int>::iterator i;
+        for (i = actStreams.begin(); i!=actStreams.end(); i++)
+        {
+            StPos.iOffsetLow += Param.Stream[*i].iLenPartA * SIZEOF__BYTE;
+        }
+
+        /* Real start position of the streams */
+        StPos.iOffsetHigh = 0;
+        for (i = actStreams.begin(); i!=actStreams.end(); i++)
+        {
+            if (*i < iStreamID)
+            {
+                StPos.iOffsetHigh += Param.Stream[*i].iLenPartA * SIZEOF__BYTE;
+                StPos.iOffsetLow += Param.Stream[*i].iLenPartB * SIZEOF__BYTE;
+            }
+        }
+
+        /* Special case if hierarchical modulation is used */
+        if (((Param.eMSCCodingScheme == CS_3_HMSYM) ||
+                (Param.eMSCCodingScheme == CS_3_HMMIX)))
+        {
+            if (iStreamID == 0)
+            {
+                /* Hierarchical channel is selected. Data is at the beginning
+                   of incoming data block */
+                StPos.iOffsetLow = 0;
+            }
+            else
+            {
+                /* Shift all offsets by the length of the hierarchical frame. We
+                   cannot use the information about the length in
+                   "Stream[0].iLenPartB", because the real length of the frame
+                   is longer or equal to the length in "Stream[0].iLenPartB" */
+                StPos.iOffsetHigh += Param.iNumBitsHierarchFrameTotal;
+                StPos.iOffsetLow += Param.iNumBitsHierarchFrameTotal -
+                                    /* We have to subtract this because we added it in the
+                                       for loop above which we do not need here */
+                                    Param.Stream[0].iLenPartB * SIZEOF__BYTE;
+            }
+        }
+
+        /* Possibility check ------------------------------------------------ */
+        /* Test, if parameters have possible values */
+        if ((StPos.iOffsetHigh + StPos.iLenHigh > Param.iNumDecodedBitsMSC) ||
+                (StPos.iOffsetLow + StPos.iLenLow > Param.iNumDecodedBitsMSC))
+        {
+            /* Something is wrong, set everything to zero */
+            StPos.iOffsetLow = 0;
+            StPos.iOffsetHigh = 0;
+            StPos.iLenLow = 0;
+            StPos.iLenHigh = 0;
+        }
+    }
+
+    return StPos;
+}
diff --git a/src/MSCMultiplexer.h b/src/MSCMultiplexer.h
new file mode 100644
index 0000000..db5ab36
--- /dev/null
+++ b/src/MSCMultiplexer.h
@@ -0,0 +1,65 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *	See MSCMultiplexer.cpp
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#if !defined(MSCMUX_H__3B0BA660_JLBVEOUB239485BB2B_23E7A0D31912__INCLUDED_)
+#define MSCMUX_H__3B0BA660_JLBVEOUB239485BB2B_23E7A0D31912__INCLUDED_
+
+#include "GlobalDefinitions.h"
+#include "Parameter.h"
+#include "util/Buffer.h"
+#include "util/Modul.h"
+#include "util/Vector.h"
+
+/* Classes ********************************************************************/
+class CMSCDemultiplexer : public CReceiverModul<_BINARY, _BINARY>
+{
+public:
+    CMSCDemultiplexer() {}
+    virtual ~CMSCDemultiplexer() {}
+
+protected:
+    struct SStreamPos
+    {
+        int	iOffsetLow;
+        int	iOffsetHigh;
+        int	iLenLow;
+        int	iLenHigh;
+    };
+
+    SStreamPos			StreamPos[4];
+
+    SStreamPos GetStreamPos(CParameter& Param, const int iStreamID);
+    void ExtractData(CVectorEx<_BINARY>& vecIn, CVectorEx<_BINARY>& vecOut,
+                     SStreamPos& StrPos);
+
+    virtual void InitInternal(CParameter& Parameters);
+    virtual void ProcessDataInternal(CParameter& Parameters);
+};
+
+
+#endif // !defined(MSCMUX_H__3B0BA660_JLBVEOUB239485BB2B_23E7A0D31912__INCLUDED_)
diff --git a/src/OFDM.cpp b/src/OFDM.cpp
new file mode 100644
index 0000000..1247162
--- /dev/null
+++ b/src/OFDM.cpp
@@ -0,0 +1,398 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *	OFDM modulation;
+ *	OFDM demodulation, SNR estimation, PSD estimation
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "OFDM.h"
+
+
+/* Implementation *************************************************************/
+/******************************************************************************\
+* OFDM-modulation                                                              *
+\******************************************************************************/
+void COFDMModulation::ProcessDataInternal(CParameter&)
+{
+    int	i;
+
+    /* Copy input vector in matlib vector and place bins at the correct
+       position */
+    for (i = iShiftedKmin; i < iEndIndex; i++)
+        veccFFTInput[i] = (*pvecInputData)[i - iShiftedKmin];
+
+    /* Calculate inverse fast Fourier transformation */
+    veccFFTOutput = Ifft(veccFFTInput, FftPlan);
+
+    /* Copy complex FFT output in output buffer and scale */
+    for (i = 0; i < iDFTSize; i++)
+        (*pvecOutputData)[i + iGuardSize] = veccFFTOutput[i] * (CReal) iDFTSize;
+
+    /* Copy data from the end to the guard-interval (Add guard-interval) */
+    for (i = 0; i < iGuardSize; i++)
+        (*pvecOutputData)[i] = (*pvecOutputData)[iDFTSize + i];
+
+
+    /* Shift spectrum to desired IF ----------------------------------------- */
+    /* Only apply shifting if phase is not zero */
+    if (cExpStep != _COMPLEX((_REAL) 1.0, (_REAL) 0.0))
+    {
+        for (i = 0; i < iOutputBlockSize; i++)
+        {
+            (*pvecOutputData)[i] = (*pvecOutputData)[i] * Conj(cCurExp);
+
+            /* Rotate exp-pointer on step further by complex multiplication
+               with precalculated rotation vector cExpStep. This saves us from
+               calling sin() and cos() functions all the time (iterative
+               calculation of these functions) */
+            cCurExp *= cExpStep;
+        }
+    }
+}
+
+void COFDMModulation::InitInternal(CParameter& Parameters)
+{
+    Parameters.Lock();
+    /* Get global parameters */
+    iDFTSize = Parameters.CellMappingTable.iFFTSizeN;
+    iGuardSize = Parameters.CellMappingTable.iGuardSize;
+    iShiftedKmin = Parameters.CellMappingTable.iShiftedKmin;
+
+    /* Last index */
+    iEndIndex = Parameters.CellMappingTable.iShiftedKmax + 1;
+
+    /* Normalized offset correction factor for IF shift. Subtract the
+       default IF frequency ("VIRTUAL_INTERMED_FREQ") */
+    const _REAL rNormCurFreqOffset = (_REAL) -2.0 * crPi *
+                                     (rDefCarOffset - VIRTUAL_INTERMED_FREQ) / Parameters.GetSigSampleRate();
+
+    /* Rotation vector for exp() calculation */
+    cExpStep = _COMPLEX(cos(rNormCurFreqOffset), sin(rNormCurFreqOffset));
+
+    /* Start with phase null (can be arbitrarily chosen) */
+    cCurExp = (_REAL) 1.0;
+
+    /* Init plans for FFT (faster processing of Fft and Ifft commands) */
+    FftPlan.Init(iDFTSize);
+
+    /* Allocate memory for intermediate result of fft. Zero out input vector
+       (because only a few bins are used, the rest has to be zero) */
+    veccFFTInput.Init(iDFTSize, (CReal) 0.0);
+    veccFFTOutput.Init(iDFTSize);
+
+    /* Define block-sizes for input and output */
+    iInputBlockSize = Parameters.CellMappingTable.iNumCarrier;
+    iOutputBlockSize = Parameters.CellMappingTable.iSymbolBlockSize;
+    Parameters.Unlock();
+}
+
+
+/******************************************************************************\
+* OFDM-demodulation                                                            *
+\******************************************************************************/
+void COFDMDemodulation::ProcessDataInternal(CParameter&)
+{
+    int i;
+
+    /* Copy data from CVector in CMatlib vector */
+    for (i = 0; i < iInputBlockSize; i++)
+        veccFFTInput[i] = (*pvecInputData)[i];
+
+    /* Calculate Fourier transformation (actual OFDM demodulation) */
+    veccFFTOutput = Fft(veccFFTInput, FftPlan);
+
+    /* Use only useful carriers and normalize with the block-size ("N"). Check
+       if spectrum can be cut in one step or two steps */
+    if (iShiftedKmin < 0)
+    {
+        /* Spectrum must be cut in two steps since some parts are on the left
+           side of the DC frequency */
+        for (i = iShiftedKmin; i < 0; i++)
+        {
+            (*pvecOutputData)[i - iShiftedKmin] =
+                veccFFTOutput[iDFTSize + i] / (CReal) iDFTSize;
+        }
+
+        for (i = 0; i < iShiftedKmax + 1; i++)
+        {
+            (*pvecOutputData)[i - iShiftedKmin] =
+                veccFFTOutput[i] / (CReal) iDFTSize;
+        }
+    }
+    else
+    {
+        /* DRM spectrum is completely on the right side of the DC carrier and
+           can be cut in one step */
+        for (i = iShiftedKmin; i < iShiftedKmax + 1; i++)
+        {
+            (*pvecOutputData)[i - iShiftedKmin] =
+                veccFFTOutput[i] / (CReal) iDFTSize;
+        }
+    }
+
+
+    /* Save averaged spectrum for plotting ---------------------------------- */
+    /* Average power (using power of this tap) (first order IIR filter) */
+    for (i = 0; i < iLenPowSpec; i++)
+        IIR1(vecrPowSpec[i], SqMag(veccFFTOutput[i]), rLamPSD);
+}
+
+void COFDMDemodulation::InitInternal(CParameter& Parameters)
+{
+    Parameters.Lock();
+    iSampleRate = Parameters.GetSigSampleRate();
+    iDFTSize = Parameters.CellMappingTable.iFFTSizeN;
+    iGuardSize = Parameters.CellMappingTable.iGuardSize;
+    iShiftedKmin = Parameters.CellMappingTable.iShiftedKmin;
+    iShiftedKmax = Parameters.CellMappingTable.iShiftedKmax;
+
+    /* Init plans for FFT (faster processing of Fft and Ifft commands) */
+    FftPlan.Init(iDFTSize);
+
+    /* Allocate memory for intermediate result of fftw */
+    veccFFTInput.Init(iDFTSize);
+    veccFFTOutput.Init(iDFTSize);
+
+    /* Vector for power density spectrum of input signal */
+    iLenPowSpec = iDFTSize / 2;
+    vecrPowSpec.Init(iLenPowSpec, (_REAL) 0.0);
+    rLamPSD = IIR1Lam(TICONST_PSD_EST_OFDM, (CReal) iSampleRate /
+                      Parameters.CellMappingTable.iSymbolBlockSize); /* Lambda for IIR filter */
+
+
+    /* Define block-sizes for input and output */
+    iInputBlockSize = iDFTSize;
+    iOutputBlockSize = Parameters.CellMappingTable.iNumCarrier;
+    Parameters.Unlock();
+}
+
+void COFDMDemodulation::GetPowDenSpec(CVector<_REAL>& vecrData,
+                                      CVector<_REAL>& vecrScale)
+{
+    /* Init output vectors */
+    vecrData.Init(iLenPowSpec, (_REAL) 0.0);
+    vecrScale.Init(iLenPowSpec, (_REAL) 0.0);
+
+    /* Do copying of data only if vector is of non-zero length which means that
+       the module was already initialized */
+    if (iLenPowSpec != 0)
+    {
+        /* Lock resources */
+        Lock();
+
+        /* Init the constants for scale and normalization */
+        const _REAL rNormData =
+            (_REAL) iDFTSize * iDFTSize * _MAXSHORT * _MAXSHORT;
+
+        const _REAL rFactorScale = _REAL(iSampleRate) / iLenPowSpec / 2000;
+
+        /* Apply the normalization (due to the FFT) */
+        for (int i = 0; i < iLenPowSpec; i++)
+        {
+            const _REAL rNormPowSpec = vecrPowSpec[i] / rNormData;
+
+            if (rNormPowSpec > 0)
+                vecrData[i] = (_REAL) 10.0 * log10(rNormPowSpec);
+            else
+                vecrData[i] = RET_VAL_LOG_0;
+
+            vecrScale[i] = (_REAL) i * rFactorScale;
+        }
+
+        /* Release resources */
+        Unlock();
+    }
+}
+
+
+/******************************************************************************\
+* OFDM-demodulation only for simulation purposes, with guard interval removal  *
+\******************************************************************************/
+void COFDMDemodSimulation::ProcessDataInternal(CParameter&)
+{
+    int i, j;
+    int iEndPointGuardRemov;
+
+    /* Guard-interval removal parameter */
+    iEndPointGuardRemov = iSymbolBlockSize - iGuardSize + iStartPointGuardRemov;
+
+
+    /* Regular signal *********************************************************/
+    /* Convert input vector in fft-vector type and cut out the guard-interval */
+    for (i = iStartPointGuardRemov; i < iEndPointGuardRemov; i++)
+        veccFFTInput[i - iStartPointGuardRemov] = (*pvecInputData)[i].tOut;
+
+    /* Actual OFDM demodulation */
+    /* Calculate Fourier transformation (actual OFDM demodulation) */
+    veccFFTOutput = Fft(veccFFTInput, FftPlan);
+
+    /* Use only useful carriers and normalize with the block-size ("N") */
+    for (i = iShiftedKmin; i < iShiftedKmax + 1; i++)
+    {
+        (*pvecOutputData2)[i - iShiftedKmin].tOut =
+            veccFFTOutput[i] / (CReal) iDFTSize;
+    }
+
+    /* We need the same information for channel estimation evaluation, too */
+    for (i = 0; i < iNumCarrier; i++)
+        (*pvecOutputData)[i] = (*pvecOutputData2)[i].tOut;
+
+
+    /* Channel-in signal ******************************************************/
+    /* Convert input vector in fft-vector type and cut out the guard-interval
+       We have to cut out the FFT window at the correct position, because the
+       channel estimation has information only about the original pilots
+       which are not phase shifted due to a timing-offset. To be able to
+       compare reference signal and channel estimation output we have to use
+       the synchronous reference signal for input */
+    for (i = iGuardSize; i < iSymbolBlockSize; i++)
+        veccFFTInput[i - iGuardSize] = (*pvecInputData)[i].tIn;
+
+    /* Actual OFDM demodulation */
+    /* Calculate Fourier transformation (actual OFDM demodulation) */
+    veccFFTOutput = Fft(veccFFTInput, FftPlan);
+
+    /* Use only useful carriers and normalize with the block-size ("N") */
+    for (i = iShiftedKmin; i < iShiftedKmax + 1; i++)
+    {
+        (*pvecOutputData2)[i - iShiftedKmin].tIn =
+            veccFFTOutput[i] / (CReal) iDFTSize;
+    }
+
+
+    /* Reference signal *******************************************************/
+    /* Convert input vector in fft-vector type and cut out the guard-interval */
+    for (i = iStartPointGuardRemov; i < iEndPointGuardRemov; i++)
+        veccFFTInput[i - iStartPointGuardRemov] = (*pvecInputData)[i].tRef;
+
+    /* Actual OFDM demodulation */
+    /* Calculate Fourier transformation (actual OFDM demodulation) */
+    veccFFTOutput = Fft(veccFFTInput, FftPlan);
+
+    /* Use only useful carriers and normalize with the block-size ("N") */
+    for (i = iShiftedKmin; i < iShiftedKmax + 1; i++)
+    {
+        (*pvecOutputData2)[i - iShiftedKmin].tRef =
+            veccFFTOutput[i] / (CReal) iDFTSize;
+    }
+
+
+    /* Channel tap gains ******************************************************/
+    /* Loop over all taps */
+    for (j = 0; j < iNumTapsChan; j++)
+    {
+        /* Convert input vector in fft-vector type and cut out the
+           guard-interval */
+        for (i = iStartPointGuardRemov; i < iEndPointGuardRemov; i++)
+            veccFFTInput[i - iStartPointGuardRemov] =
+                (*pvecInputData)[i].veccTap[j];
+
+        /* Actual OFDM demodulation */
+        /* Calculate Fourier transformation (actual OFDM demodulation) */
+        veccFFTOutput = Fft(veccFFTInput, FftPlan);
+
+        /* Use only useful carriers and normalize with the block-size ("N") */
+        for (i = 0; i < iNumCarrier; i++)
+        {
+            (*pvecOutputData2)[i].veccTap[j] =
+                veccFFTOutput[i] / (CReal) iDFTSize;
+        }
+
+        /* Store the end of the vector, too */
+        for (i = 0; i < iNumCarrier; i++)
+        {
+            (*pvecOutputData2)[i].veccTapBackw[j] =
+                veccFFTOutput[iDFTSize - i - 1] / (CReal) iDFTSize;
+        }
+    }
+
+
+    /* Take care of symbol IDs ---------------------------------------------- */
+    iSymbolCounterTiSy++;
+    if (iSymbolCounterTiSy == iNumSymPerFrame)
+        iSymbolCounterTiSy = 0;
+
+    /* Set current symbol ID in extended data of output vector */
+    (*pvecOutputData).GetExData().iSymbolID = iSymbolCounterTiSy;
+    (*pvecOutputData2).GetExData().iSymbolID = iSymbolCounterTiSy;
+
+    /* No timing corrections, timing is constant in this case */
+    (*pvecOutputData).GetExData().iCurTimeCorr = 0;
+    (*pvecOutputData2).GetExData().iCurTimeCorr = 0;
+
+    /* Symbol ID index is always ok */
+    (*pvecOutputData).GetExData().bSymbolIDHasChanged = FALSE;
+    (*pvecOutputData2).GetExData().bSymbolIDHasChanged = FALSE;
+}
+
+void COFDMDemodSimulation::InitInternal(CParameter& Parameters)
+{
+    Parameters.Lock();
+    /* Set internal parameters */
+    iDFTSize = Parameters.CellMappingTable.iFFTSizeN;
+    iGuardSize = Parameters.CellMappingTable.iGuardSize;
+    iNumCarrier = Parameters.CellMappingTable.iNumCarrier;
+    iShiftedKmin = Parameters.CellMappingTable.iShiftedKmin;
+    iShiftedKmax = Parameters.CellMappingTable.iShiftedKmax;
+    iSymbolBlockSize = Parameters.CellMappingTable.iSymbolBlockSize;
+    iNumSymPerFrame = Parameters.CellMappingTable.iNumSymPerFrame;
+
+    iNumTapsChan = Parameters.iNumTaps;
+
+    /* Init plans for FFT (faster processing of Fft and Ifft commands) */
+    FftPlan.Init(iDFTSize);
+
+    /* Allocate memory for intermediate result of fftw, init input signal with
+       zeros because imaginary part is not written */
+    veccFFTInput.Init(iDFTSize, (CReal) 0.0);
+    veccFFTOutput.Init(iDFTSize);
+
+    /* Init internal counter for symbol number. Set it to this value to get
+       a "0" for the first time */
+    iSymbolCounterTiSy = iNumSymPerFrame - 1;
+
+    /* Set guard-interval removal start index. Adapt this parameter to the
+       channel which was chosen. Place the delay spread centered in the
+       middle of the guard-interval */
+    iStartPointGuardRemov =
+        (iGuardSize + Parameters.iPathDelay[iNumTapsChan - 1]) / 2;
+
+    /* Check the case if impulse response is longer than guard-interval */
+    if (iStartPointGuardRemov > iGuardSize)
+        iStartPointGuardRemov = iGuardSize;
+
+    /* Set start point of useful part extraction in global struct */
+    Parameters.iOffUsfExtr = iGuardSize - iStartPointGuardRemov;
+
+    /* Define block-sizes for input and output */
+    iInputBlockSize = iSymbolBlockSize;
+    iOutputBlockSize = iNumCarrier;
+    iOutputBlockSize2 = iNumCarrier;
+
+    /* We need to store as many symbols in output buffer as long the channel
+       estimation delay is */
+    iMaxOutputBlockSize2 = iNumCarrier * Parameters.iChanEstDelay;
+    Parameters.Unlock();
+}
diff --git a/src/OFDM.h b/src/OFDM.h
new file mode 100644
index 0000000..53fb5a2
--- /dev/null
+++ b/src/OFDM.h
@@ -0,0 +1,135 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *	See OFDM.cpp
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#if !defined(OFDM_H__3B0BA660_CA63_4344_BB2B_23E7A0D31912__INCLUDED_)
+#define OFDM_H__3B0BA660_CA63_4344_BB2B_23E7A0D31912__INCLUDED_
+
+#include "Parameter.h"
+#include "util/Modul.h"
+#include "matlib/Matlib.h"
+
+
+/* Definitions ****************************************************************/
+/* Time constant for IIR averaging of PSD estimation */
+#define TICONST_PSD_EST_OFDM			((CReal) 1.0) /* sec */
+
+
+/* Classes ********************************************************************/
+class COFDMModulation : public CTransmitterModul<_COMPLEX, _COMPLEX>
+{
+public:
+    COFDMModulation() : rDefCarOffset((_REAL) VIRTUAL_INTERMED_FREQ) {}
+    virtual ~COFDMModulation() {}
+
+    void SetCarOffset(const _REAL rNewCarOffset)
+    {
+        rDefCarOffset = rNewCarOffset;
+    }
+
+protected:
+    CFftPlans				FftPlan;
+
+    CComplexVector			veccFFTInput;
+    CComplexVector			veccFFTOutput;
+
+    int						iShiftedKmin;
+    int						iEndIndex;
+    int						iDFTSize;
+    int						iGuardSize;
+
+    _COMPLEX				cCurExp;
+    _COMPLEX				cExpStep;
+    _REAL					rDefCarOffset;
+
+    virtual void InitInternal(CParameter& TransmParam);
+    virtual void ProcessDataInternal(CParameter& TransmParam);
+};
+
+class COFDMDemodulation : public CReceiverModul<_COMPLEX, _COMPLEX>
+{
+public:
+    /* bUseRecFilter shall be set the FALSE as default since in case of
+       BERIDEAL simulations, no filter shall be applied */
+    COFDMDemodulation() : iLenPowSpec(0) {}
+    virtual ~COFDMDemodulation() {}
+
+    void GetPowDenSpec(CVector<_REAL>& vecrData, CVector<_REAL>& vecrScale);
+
+protected:
+    CFftPlans				FftPlan;
+    CComplexVector			veccFFTInput;
+    CComplexVector			veccFFTOutput;
+
+    CVector<_REAL>			vecrPowSpec;
+    int						iSampleRate;
+    int						iLenPowSpec;
+
+    int						iShiftedKmin;
+    int						iShiftedKmax;
+    int						iDFTSize;
+    int						iGuardSize;
+    int						iNumCarrier;
+
+    CReal					rLamPSD;
+
+
+    virtual void InitInternal(CParameter& Parameters);
+    virtual void ProcessDataInternal(CParameter& Parameters);
+};
+
+class COFDMDemodSimulation :
+            public CSimulationModul<CChanSimDataMod, _COMPLEX, CChanSimDataDemod>
+{
+public:
+    COFDMDemodSimulation() {}
+    virtual ~COFDMDemodSimulation() {}
+
+protected:
+    CFftPlans				FftPlan;
+    CComplexVector			veccFFTInput;
+    CComplexVector			veccFFTOutput;
+
+    int						iStartPointGuardRemov;
+
+    int						iShiftedKmin;
+    int						iShiftedKmax;
+    int						iDFTSize;
+    int						iGuardSize;
+    int						iNumCarrier;
+    int						iSymbolBlockSize;
+    int						iSymbolCounterTiSy;
+    int						iNumSymPerFrame;
+
+    int						iNumTapsChan;
+
+    virtual void InitInternal(CParameter& Parameters);
+    virtual void ProcessDataInternal(CParameter& Parameters);
+};
+
+
+#endif // !defined(OFDM_H__3B0BA660_CA63_4344_BB2B_23E7A0D31912__INCLUDED_)
diff --git a/src/Parameter.cpp b/src/Parameter.cpp
new file mode 100644
index 0000000..ec7220c
--- /dev/null
+++ b/src/Parameter.cpp
@@ -0,0 +1,1377 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer, Andrew Murphy
+ *
+ * Description:
+ *	DRM Parameters
+ *
+ ******************************************************************************
+ *
+ * This program is free software(), you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation(), either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY(), without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program(), if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "Parameter.h"
+#include "DrmReceiver.h"
+#include "Version.h"
+#include <limits>
+#include <sstream>
+#include <iomanip>
+
+/* Implementation *************************************************************/
+CParameter::CParameter():
+    pDRMRec(NULL),
+    eSymbolInterlMode(),
+    eMSCCodingScheme(),
+    eSDCCodingScheme(),
+    iNumAudioService(0),
+    iNumDataService(0),
+    iAMSSCarrierMode(0),
+    sReceiverID("                "),
+    sSerialNumber(),
+    eTransmitCurrentTime(CT_OFF),
+    MSCPrLe(),bSDCCodeRateOneQuarter(false),
+    Stream(MAX_NUM_STREAMS), Service(MAX_NUM_SERVICES),
+	AudioComponentStatus(MAX_NUM_SERVICES),DataComponentStatus(MAX_NUM_SERVICES),
+    iNumBitsHierarchFrameTotal(0),
+    iNumDecodedBitsMSC(0),
+    iNumSDCBitsPerSFrame(0),
+    iNumFACBitsPerBlock(NUM_FAC_BITS_PER_BLOCK_DRM30), // assume DRM30
+    iNumAudioDecoderBits(0),
+    iNumDataDecoderBits(0),
+    iYear(0),
+    iMonth(0),
+    iDay(0),
+    iUTCHour(0),
+    iUTCMin(0),
+    iFrameIDTransm(0),
+    iFrameIDReceiv(0),
+    rFreqOffsetAcqui(0.0),
+    rFreqOffsetTrack(0.0),
+    rResampleOffset(0.0),
+    iTimingOffsTrack(0),
+    eReceiverMode(RM_NONE),
+    eAcquiState(AS_NO_SIGNAL),
+    iNumAudioFrames(0),
+    vecbiAudioFrameStatus(0),
+    bMeasurePSD(FALSE), bMeasurePSDAlways(FALSE),
+    vecrPSD(0),
+    matcReceivedPilotValues(),
+    RawSimDa(),
+    eSimType(ST_NONE),
+    iDRMChannelNum(0),
+    iSpecChDoppler(0),
+    rBitErrRate(0.0),
+    rSyncTestParam(0.0),
+    rSINR(0.0),
+    iNumBitErrors(0),
+    iChanEstDelay(0),
+    iNumTaps(0),
+    iPathDelay(MAX_NUM_TAPS_DRM_CHAN),
+    rGainCorr(0.0),
+    iOffUsfExtr(0),
+    ReceiveStatus(),
+    FrontEndParameters(),
+    AltFreqSign(),
+    rMER(0.0),
+    rWMERMSC(0.0),
+    rWMERFAC(0.0),
+    rSigmaEstimate(0.0),
+    rMinDelay(0.0),
+    rMaxDelay(0.0),
+    bMeasureDelay(),
+    vecrRdel(0),
+    vecrRdelThresholds(0),
+    vecrRdelIntervals(0),
+    bMeasureDoppler(0),
+    rRdop(0.0),
+    bMeasureInterference(FALSE),
+    rIntFreq(0.0),
+    rINR(0.0),
+    rICR(0.0),
+    rMaxPSDwrtSig(0.0),
+    rMaxPSDFreq(0.0),
+    rSigStrengthCorrection(0.0),
+    eRunState(STOPPED),
+    CellMappingTable(),
+    audioencoder(""),audiodecoder(""),
+    use_gpsd(0), restart_gpsd(false),
+    gps_host("localhost"), gps_port("2497"),
+    iAudSampleRate(DEFAULT_SOUNDCRD_SAMPLE_RATE),
+    iSigSampleRate(DEFAULT_SOUNDCRD_SAMPLE_RATE),
+    iSigUpscaleRatio(1),
+    iNewAudSampleRate(0),
+    iNewSigSampleRate(0),
+    iNewSigUpscaleRatio(0),
+    rSysSimSNRdB(0.0),
+    iFrequency(0),
+    bValidSignalStrength(FALSE),
+    rSigStr(0.0),
+    rIFSigStr(0.0),
+    iCurSelAudioService(0),
+    iCurSelDataService(0),
+    eRobustnessMode(RM_ROBUSTNESS_MODE_B),
+    eSpectOccup(SO_3),
+    LastAudioService(),
+    LastDataService(),
+    Mutex(), lenient_RSCI(false)
+{
+    GenerateRandomSerialNumber();
+    CellMappingTable.MakeTable(eRobustnessMode, eSpectOccup, iSigSampleRate);
+    gps_data.set=0;
+    gps_data.status=0;
+#ifdef HAVE_LIBGPS
+    gps_data.gps_fd = -1;
+#endif
+}
+
+CParameter::~CParameter()
+{
+}
+
+CParameter::CParameter(const CParameter& p):
+    pDRMRec(p.pDRMRec),
+    eSymbolInterlMode(p.eSymbolInterlMode),
+    eMSCCodingScheme(p.eMSCCodingScheme),
+    eSDCCodingScheme(p.eSDCCodingScheme),
+    iNumAudioService(p.iNumAudioService),
+    iNumDataService(p.iNumDataService),
+    iAMSSCarrierMode(p.iAMSSCarrierMode),
+    sReceiverID(p.sReceiverID),
+    sSerialNumber(p.sSerialNumber),
+    eTransmitCurrentTime(p.eTransmitCurrentTime),
+    MSCPrLe(p.MSCPrLe),bSDCCodeRateOneQuarter(p.bSDCCodeRateOneQuarter),
+    Stream(p.Stream), Service(p.Service),
+	AudioComponentStatus(p.AudioComponentStatus),DataComponentStatus(p.DataComponentStatus),
+	iNumBitsHierarchFrameTotal(p.iNumBitsHierarchFrameTotal),
+    iNumDecodedBitsMSC(p.iNumDecodedBitsMSC),
+    iNumFACBitsPerBlock(p.iNumFACBitsPerBlock),
+    iNumSDCBitsPerSFrame(p.iNumSDCBitsPerSFrame),
+    iNumAudioDecoderBits(p.iNumAudioDecoderBits),
+    iNumDataDecoderBits(p.iNumDataDecoderBits),
+    iYear(p.iYear),
+    iMonth(p.iMonth),
+    iDay(p.iDay),
+    iUTCHour(p.iUTCHour),
+    iUTCMin(p.iUTCMin),
+    iUTCOff(p.iUTCOff),
+    iUTCSense(p.iUTCSense),
+    bValidUTCOffsetAndSense(p.bValidUTCOffsetAndSense),
+    iFrameIDTransm(p.iFrameIDTransm),
+    iFrameIDReceiv(p.iFrameIDReceiv),
+    rFreqOffsetAcqui(p.rFreqOffsetAcqui),
+    rFreqOffsetTrack(p.rFreqOffsetTrack),
+    rResampleOffset(p.rResampleOffset),
+    iTimingOffsTrack(p.iTimingOffsTrack),
+    eReceiverMode(p.eReceiverMode),
+    eAcquiState(p.eAcquiState),
+    iNumAudioFrames(p.iNumAudioFrames),
+    vecbiAudioFrameStatus(p.vecbiAudioFrameStatus),
+    bMeasurePSD(p.bMeasurePSD), bMeasurePSDAlways(p.bMeasurePSDAlways),
+    vecrPSD(p.vecrPSD),
+//matcReceivedPilotValues(p.matcReceivedPilotValues),
+    matcReceivedPilotValues(), // OPH says copy constructor for CMatrix not safe yet
+    RawSimDa(p.RawSimDa),
+    eSimType(p.eSimType),
+    iDRMChannelNum(p.iDRMChannelNum),
+    iSpecChDoppler(p.iSpecChDoppler),
+    rBitErrRate(p.rBitErrRate),
+    rSyncTestParam	(p.rSyncTestParam),
+    rSINR(p.rSINR),
+    iNumBitErrors(p.iNumBitErrors),
+    iChanEstDelay(p.iChanEstDelay),
+    iNumTaps(p.iNumTaps),
+    iPathDelay(p.iPathDelay),
+    rGainCorr(p.rGainCorr),
+    iOffUsfExtr(p.iOffUsfExtr),
+    ReceiveStatus(p.ReceiveStatus),
+    FrontEndParameters(p.FrontEndParameters),
+    AltFreqSign(p.AltFreqSign),
+    rMER(p.rMER),
+    rWMERMSC(p.rWMERMSC),
+    rWMERFAC(p.rWMERFAC),
+    rSigmaEstimate(p.rSigmaEstimate),
+    rMinDelay(p.rMinDelay),
+    rMaxDelay(p.rMaxDelay),
+    bMeasureDelay(p.bMeasureDelay),
+    vecrRdel(p.vecrRdel),
+    vecrRdelThresholds(p.vecrRdelThresholds),
+    vecrRdelIntervals(p.vecrRdelIntervals),
+    bMeasureDoppler(p.bMeasureDoppler),
+    rRdop(p.rRdop),
+    bMeasureInterference(p.bMeasureInterference),
+    rIntFreq(p.rIntFreq),
+    rINR(p.rINR),
+    rICR(p.rICR),
+    rMaxPSDwrtSig(p.rMaxPSDwrtSig),
+    rMaxPSDFreq(p.rMaxPSDFreq),
+    rSigStrengthCorrection(p.rSigStrengthCorrection),
+    eRunState(p.eRunState),
+    CellMappingTable(), // jfbc CCellMappingTable uses a CMatrix :(
+    audioencoder(p.audioencoder),audiodecoder(p.audiodecoder),
+    use_gpsd(p.use_gpsd),restart_gpsd(p.restart_gpsd),
+    gps_host(p.gps_host),gps_port(p.gps_port),
+    iAudSampleRate(p.iAudSampleRate),
+    iSigSampleRate(p.iSigSampleRate),
+    iSigUpscaleRatio(p.iSigUpscaleRatio),
+    iNewAudSampleRate(p.iNewAudSampleRate),
+    iNewSigSampleRate(p.iNewSigSampleRate),
+    iNewSigUpscaleRatio(p.iNewSigUpscaleRatio),
+    rSysSimSNRdB(p.rSysSimSNRdB),
+    iFrequency(p.iFrequency),
+    bValidSignalStrength(p.bValidSignalStrength),
+    rSigStr(p.rSigStr),
+    rIFSigStr(p.rIFSigStr),
+    iCurSelAudioService(p.iCurSelAudioService),
+    iCurSelDataService(p.iCurSelDataService),
+    eRobustnessMode(p.eRobustnessMode),
+    eSpectOccup(p.eSpectOccup),
+    LastAudioService(p.LastAudioService),
+    LastDataService(p.LastDataService)
+//, Mutex() // jfbc: I don't think this state should be copied
+   ,lenient_RSCI(p.lenient_RSCI)
+{
+    CellMappingTable.MakeTable(eRobustnessMode, eSpectOccup, iSigSampleRate);
+    matcReceivedPilotValues = p.matcReceivedPilotValues; // TODO
+    gps_data = p.gps_data;
+}
+
+CParameter& CParameter::operator=(const CParameter& p)
+{
+    gps_data = p.gps_data;
+    pDRMRec = p.pDRMRec;
+    eSymbolInterlMode = p.eSymbolInterlMode;
+    eMSCCodingScheme = p.eMSCCodingScheme;
+    eSDCCodingScheme = p.eSDCCodingScheme;
+    iNumAudioService = p.iNumAudioService;
+    iNumDataService = p.iNumDataService;
+    iAMSSCarrierMode = p.iAMSSCarrierMode;
+    sReceiverID = p.sReceiverID;
+    sSerialNumber = p.sSerialNumber;
+    eTransmitCurrentTime = p.eTransmitCurrentTime;
+    MSCPrLe = p.MSCPrLe;
+    bSDCCodeRateOneQuarter = p.bSDCCodeRateOneQuarter;
+    Stream = p.Stream;
+    Service = p.Service;
+	AudioComponentStatus = p.AudioComponentStatus;
+	DataComponentStatus = p.DataComponentStatus;
+    iNumBitsHierarchFrameTotal = p.iNumBitsHierarchFrameTotal;
+    iNumDecodedBitsMSC = p.iNumDecodedBitsMSC;
+    iNumSDCBitsPerSFrame = p.iNumSDCBitsPerSFrame;
+    iNumFACBitsPerBlock = p.iNumFACBitsPerBlock;
+    iNumAudioDecoderBits = p.iNumAudioDecoderBits;
+    iNumDataDecoderBits = p.iNumDataDecoderBits;
+    iYear = p.iYear;
+    iMonth = p.iMonth;
+    iDay = p.iDay;
+    iUTCHour = p.iUTCHour;
+    iUTCMin = p.iUTCMin;
+    iFrameIDTransm = p.iFrameIDTransm;
+    iFrameIDReceiv = p.iFrameIDReceiv;
+    rFreqOffsetAcqui = p.rFreqOffsetAcqui;
+    rFreqOffsetTrack = p.rFreqOffsetTrack;
+    rResampleOffset = p.rResampleOffset;
+    iTimingOffsTrack = p.iTimingOffsTrack;
+    eReceiverMode = p.eReceiverMode;
+    eAcquiState = p.eAcquiState;
+    iNumAudioFrames = p.iNumAudioFrames;
+    vecbiAudioFrameStatus = p.vecbiAudioFrameStatus;
+    bMeasurePSD = p.bMeasurePSD;
+    bMeasurePSDAlways = p.bMeasurePSDAlways;
+    vecrPSD = p.vecrPSD;
+    matcReceivedPilotValues = p.matcReceivedPilotValues;
+    RawSimDa = p.RawSimDa;
+    eSimType = p.eSimType;
+    iDRMChannelNum = p.iDRMChannelNum;
+    iSpecChDoppler = p.iSpecChDoppler;
+    rBitErrRate = p.rBitErrRate;
+    rSyncTestParam	 = p.rSyncTestParam;
+    rSINR = p.rSINR;
+    iNumBitErrors = p.iNumBitErrors;
+    iChanEstDelay = p.iChanEstDelay;
+    iNumTaps = p.iNumTaps;
+    iPathDelay = p.iPathDelay;
+    rGainCorr = p.rGainCorr;
+    iOffUsfExtr = p.iOffUsfExtr;
+    ReceiveStatus = p.ReceiveStatus;
+    FrontEndParameters = p.FrontEndParameters;
+    AltFreqSign = p.AltFreqSign;
+    rMER = p.rMER;
+    rWMERMSC = p.rWMERMSC;
+    rWMERFAC = p.rWMERFAC;
+    rSigmaEstimate = p.rSigmaEstimate;
+    rMinDelay = p.rMinDelay;
+    rMaxDelay = p.rMaxDelay;
+    bMeasureDelay = p.bMeasureDelay;
+    vecrRdel = p.vecrRdel;
+    vecrRdelThresholds = p.vecrRdelThresholds;
+    vecrRdelIntervals = p.vecrRdelIntervals;
+    bMeasureDoppler = p.bMeasureDoppler;
+    rRdop = p.rRdop;
+    bMeasureInterference = p.bMeasureInterference;
+    rIntFreq = p.rIntFreq;
+    rINR = p.rINR;
+    rICR = p.rICR;
+    rMaxPSDwrtSig = p.rMaxPSDwrtSig;
+    rMaxPSDFreq = p.rMaxPSDFreq;
+    rSigStrengthCorrection = p.rSigStrengthCorrection;
+    eRunState = p.eRunState;
+    CellMappingTable.MakeTable(eRobustnessMode, eSpectOccup, iSigSampleRate); // don't copy CMatrix
+    audiodecoder =  p.audiodecoder;
+    audioencoder =  p.audioencoder;
+    use_gpsd = p.use_gpsd;
+    gps_host = p.gps_host;
+    gps_port = p.gps_port;
+    restart_gpsd = p.restart_gpsd;
+    iAudSampleRate = p.iAudSampleRate;
+    iSigSampleRate = p.iSigSampleRate;
+    iSigUpscaleRatio = p.iSigUpscaleRatio;
+    iNewAudSampleRate = p.iNewAudSampleRate;
+    iNewSigSampleRate = p.iNewSigSampleRate;
+    iNewSigUpscaleRatio = p.iNewSigUpscaleRatio;
+    rSysSimSNRdB = p.rSysSimSNRdB;
+    iFrequency = p.iFrequency;
+    bValidSignalStrength = p.bValidSignalStrength;
+    rSigStr = p.rSigStr;
+    rIFSigStr = p.rIFSigStr;
+    iCurSelAudioService = p.iCurSelAudioService;
+    iCurSelDataService = p.iCurSelDataService;
+    eRobustnessMode = p.eRobustnessMode;
+    eSpectOccup = p.eSpectOccup;
+    LastAudioService = p.LastAudioService;
+    LastDataService = p.LastDataService;
+    lenient_RSCI = p.lenient_RSCI;
+    return *this;
+}
+
+void CParameter::SetReceiver(CDRMReceiver* pDRMReceiver)
+{
+	pDRMRec = pDRMReceiver;
+    if (pDRMRec)
+        eReceiverMode = pDRMRec->GetReceiverMode();
+}
+
+void CParameter::ResetServicesStreams()
+{
+    int i;
+    if (GetReceiverMode() == RM_DRM)
+    {
+
+        /* Store informations about last service selected
+         * so the current service can be selected automatically after a resync */
+
+        if (iCurSelAudioService > 0)
+            LastAudioService.Save(iCurSelAudioService, Service[iCurSelAudioService].iServiceID);
+
+        if (iCurSelDataService > 0)
+            LastDataService.Save(iCurSelDataService, Service[iCurSelDataService].iServiceID);
+
+        /* Reset everything to possible start values */
+        for (i = 0; i < MAX_NUM_SERVICES; i++)
+        {
+            Service[i].AudioParam.strTextMessage = "";
+            Service[i].AudioParam.iStreamID = STREAM_ID_NOT_USED;
+            Service[i].AudioParam.eAudioCoding = CAudioParam::AC_NONE;
+            Service[i].AudioParam.eSBRFlag = CAudioParam::SB_NOT_USED;
+            Service[i].AudioParam.eAudioSamplRate = CAudioParam::AS_24KHZ;
+            Service[i].AudioParam.bTextflag = FALSE;
+            Service[i].AudioParam.bEnhanceFlag = FALSE;
+            Service[i].AudioParam.eAudioMode = CAudioParam::AM_MONO;
+            Service[i].AudioParam.iCELPIndex = 0;
+            Service[i].AudioParam.bCELPCRC = FALSE;
+            Service[i].AudioParam.eHVXCRate = CAudioParam::HR_2_KBIT;
+            Service[i].AudioParam.bHVXCCRC = FALSE;
+
+            Service[i].DataParam.iStreamID = STREAM_ID_NOT_USED;
+            Service[i].DataParam.ePacketModInd = CDataParam::PM_PACKET_MODE;
+            Service[i].DataParam.eDataUnitInd = CDataParam::DU_SINGLE_PACKETS;
+            Service[i].DataParam.iPacketID = 0;
+            Service[i].DataParam.iPacketLen = 0;
+            Service[i].DataParam.eAppDomain = CDataParam::AD_DRM_SPEC_APP;
+            Service[i].DataParam.iUserAppIdent = 0;
+
+            Service[i].iServiceID = SERV_ID_NOT_USED;
+            Service[i].eCAIndication = CService::CA_NOT_USED;
+            Service[i].iLanguage = 0;
+            Service[i].strCountryCode = "";
+            Service[i].strLanguageCode = "";
+            Service[i].eAudDataFlag = CService::SF_AUDIO;
+            Service[i].iServiceDescr = 0;
+            Service[i].strLabel = "";
+			AudioComponentStatus[i].SetStatus(NOT_PRESENT);
+			DataComponentStatus[i].SetStatus(NOT_PRESENT);
+        }
+
+        for (i = 0; i < MAX_NUM_STREAMS; i++)
+        {
+            Stream[i].iLenPartA = 0;
+            Stream[i].iLenPartB = 0;
+        }
+    }
+    else
+    {
+
+        // Set up encoded AM audio parameters
+        Service[0].AudioParam.strTextMessage = "";
+        Service[0].AudioParam.iStreamID = 0;
+        Service[0].AudioParam.eAudioCoding = CAudioParam::AC_AAC;
+        Service[0].AudioParam.eSBRFlag = CAudioParam::SB_NOT_USED;
+        Service[0].AudioParam.eAudioSamplRate = CAudioParam::AS_24KHZ;
+        Service[0].AudioParam.bTextflag = FALSE;
+        Service[0].AudioParam.bEnhanceFlag = FALSE;
+        Service[0].AudioParam.eAudioMode = CAudioParam::AM_MONO; // ? FM could be stereo
+        Service[0].AudioParam.iCELPIndex = 0;
+        Service[0].AudioParam.bCELPCRC = FALSE;
+        Service[0].AudioParam.eHVXCRate = CAudioParam::HR_2_KBIT;
+        Service[0].AudioParam.bHVXCCRC = FALSE;
+
+        Service[0].iServiceID = SERV_ID_NOT_USED;
+        Service[0].eCAIndication = CService::CA_NOT_USED;
+        Service[0].iLanguage = 0;
+        Service[0].strCountryCode = "";
+        Service[0].strLanguageCode = "";
+        Service[0].eAudDataFlag = CService::SF_AUDIO;
+        Service[0].iServiceDescr = 0;
+        Service[0].strLabel = "";
+
+        Stream[0].iLenPartA = 0;
+        Stream[0].iLenPartB = 1044;
+    }
+
+    /* Reset alternative frequencies */
+    AltFreqSign.Reset();
+
+    /* Date, time */
+    iDay = 0;
+    iMonth = 0;
+    iYear = 0;
+    iUTCHour = 0;
+    iUTCMin = 0;
+    iUTCOff = 0;
+    iUTCSense = 0;
+    bValidUTCOffsetAndSense = FALSE;
+}
+
+void CParameter::GetActiveServices(set<int>& actServ)
+{
+    /* Init return vector */
+    actServ.clear();
+
+    /* Get active services */
+    for (int i = 0; i < MAX_NUM_SERVICES; i++)
+    {
+        if (Service[i].IsActive())
+            /* A service is active, add ID to set */
+            actServ.insert(i);
+    }
+}
+
+/* using a set ensures each stream appears only once */
+void CParameter::GetActiveStreams(set<int>& actStr)
+{
+    actStr.clear();
+
+    /* Determine which streams are active */
+    for (int i = 0; i < MAX_NUM_SERVICES; i++)
+    {
+        if (Service[i].IsActive())
+        {
+            /* Audio stream */
+            if (Service[i].AudioParam.iStreamID != STREAM_ID_NOT_USED)
+                actStr.insert(Service[i].AudioParam.iStreamID);
+
+            /* Data stream */
+            if (Service[i].DataParam.iStreamID != STREAM_ID_NOT_USED)
+                actStr.insert(Service[i].DataParam.iStreamID);
+        }
+    }
+}
+
+_REAL CParameter::GetBitRateKbps(const int iShortID, const _BOOLEAN bAudData) const
+{
+    /* Init lengths to zero in case the stream is not yet assigned */
+    int iLen = 0;
+
+    /* First, check if audio or data service and get lengths */
+    if (Service[iShortID].eAudDataFlag == CService::SF_AUDIO)
+    {
+        /* Check if we want to get the data stream connected to an audio
+           stream */
+        if (bAudData == TRUE)
+        {
+            iLen = GetStreamLen( Service[iShortID].DataParam.iStreamID);
+        }
+        else
+        {
+            iLen = GetStreamLen( Service[iShortID].AudioParam.iStreamID);
+        }
+    }
+    else
+    {
+        iLen = GetStreamLen( Service[iShortID].DataParam.iStreamID);
+    }
+
+    /* We have 3 frames with time duration of 1.2 seconds. Bit rate should be
+       returned in kbps (/ 1000) */
+    return (_REAL) iLen * SIZEOF__BYTE * 3 / (_REAL) 1.2 / 1000;
+}
+
+_REAL CParameter::PartABLenRatio(const int iShortID) const
+{
+    int iLenA = 0;
+    int iLenB = 0;
+
+    /* Get the length of protection part A and B */
+    if (Service[iShortID].eAudDataFlag == CService::SF_AUDIO)
+    {
+        /* Audio service */
+        if (Service[iShortID].AudioParam.iStreamID != STREAM_ID_NOT_USED)
+        {
+            iLenA = Stream[Service[iShortID].AudioParam.iStreamID].iLenPartA;
+            iLenB = Stream[Service[iShortID].AudioParam.iStreamID].iLenPartB;
+        }
+    }
+    else
+    {
+        /* Data service */
+        if (Service[iShortID].DataParam.iStreamID != STREAM_ID_NOT_USED)
+        {
+            iLenA = Stream[Service[iShortID].DataParam.iStreamID].iLenPartA;
+            iLenB = Stream[Service[iShortID].DataParam.iStreamID].iLenPartB;
+        }
+    }
+
+    const int iTotLen = iLenA + iLenB;
+
+    if (iTotLen != 0)
+        return (_REAL) iLenA / iTotLen;
+    else
+        return (_REAL) 0.0;
+}
+
+void CParameter::InitCellMapTable(const ERobMode eNewWaveMode,
+                                  const ESpecOcc eNewSpecOcc)
+{
+    /* Set new values and make table */
+    eRobustnessMode = eNewWaveMode;
+    eSpectOccup = eNewSpecOcc;
+    CellMappingTable.MakeTable(eRobustnessMode, eSpectOccup, iSigSampleRate);
+}
+
+_BOOLEAN CParameter::SetWaveMode(const ERobMode eNewWaveMode)
+{
+    /* First check if spectrum occupancy and robustness mode pair is defined */
+    if ((
+                (eNewWaveMode == RM_ROBUSTNESS_MODE_C) ||
+                (eNewWaveMode == RM_ROBUSTNESS_MODE_D)
+            ) && !(
+                (eSpectOccup == SO_3) ||
+                (eSpectOccup == SO_5)
+            ))
+    {
+        /* Set spectrum occupance to a valid parameter */
+        eSpectOccup = SO_3;
+    }
+
+    /* Apply changes only if new paramter differs from old one */
+    if (eRobustnessMode != eNewWaveMode)
+    {
+        /* Set new value */
+        eRobustnessMode = eNewWaveMode;
+
+        /* This parameter change provokes update of table */
+        CellMappingTable.MakeTable(eRobustnessMode, eSpectOccup, iSigSampleRate);
+
+        /* Set init flags */
+        if (pDRMRec) pDRMRec->InitsForWaveMode();
+
+        /* Signal that parameter has changed */
+        return TRUE;
+    }
+    else
+        return FALSE;
+}
+
+void CParameter::SetSpectrumOccup(ESpecOcc eNewSpecOcc)
+{
+    /* First check if spectrum occupancy and robustness mode pair is defined */
+    if ((
+                (eRobustnessMode == RM_ROBUSTNESS_MODE_C) ||
+                (eRobustnessMode == RM_ROBUSTNESS_MODE_D)
+            ) && !(
+                (eNewSpecOcc == SO_3) ||
+                (eNewSpecOcc == SO_5)
+            ))
+    {
+        /* Set spectrum occupance to a valid parameter */
+        eNewSpecOcc = SO_3;
+    }
+
+    /* Apply changes only if new paramter differs from old one */
+    if (eSpectOccup != eNewSpecOcc)
+    {
+        /* Set new value */
+        eSpectOccup = eNewSpecOcc;
+
+        /* This parameter change provokes update of table */
+        CellMappingTable.MakeTable(eRobustnessMode, eSpectOccup, iSigSampleRate);
+
+        /* Set init flags */
+        if (pDRMRec) pDRMRec->InitsForSpectrumOccup();
+    }
+}
+
+void CParameter::SetStreamLen(const int iStreamID, const int iNewLenPartA,
+                              const int iNewLenPartB)
+{
+    /* Apply changes only if parameters have changed */
+    if ((Stream[iStreamID].iLenPartA != iNewLenPartA) ||
+            (Stream[iStreamID].iLenPartB != iNewLenPartB))
+    {
+        /* Use new parameters */
+        Stream[iStreamID].iLenPartA = iNewLenPartA;
+        Stream[iStreamID].iLenPartB = iNewLenPartB;
+
+        /* Set init flags */
+        if (pDRMRec) pDRMRec->InitsForMSC();
+    }
+}
+
+int CParameter::GetStreamLen(const int iStreamID) const
+{
+    if (iStreamID != STREAM_ID_NOT_USED)
+        return Stream[iStreamID].iLenPartA + Stream[iStreamID].iLenPartB;
+    else
+        return 0;
+}
+
+void CParameter::SetNumDecodedBitsMSC(const int iNewNumDecodedBitsMSC)
+{
+    /* Apply changes only if parameters have changed */
+    if (iNewNumDecodedBitsMSC != iNumDecodedBitsMSC)
+    {
+        iNumDecodedBitsMSC = iNewNumDecodedBitsMSC;
+
+        /* Set init flags */
+        if (pDRMRec) pDRMRec->InitsForMSCDemux();
+    }
+}
+
+void CParameter::SetNumDecodedBitsSDC(const int iNewNumDecodedBitsSDC)
+{
+    /* Apply changes only if parameters have changed */
+    if (iNewNumDecodedBitsSDC != iNumSDCBitsPerSFrame)
+    {
+        iNumSDCBitsPerSFrame = iNewNumDecodedBitsSDC;
+
+        /* Set init flags */
+        if (pDRMRec) pDRMRec->InitsForNoDecBitsSDC();
+    }
+}
+
+void CParameter::SetNumBitsHieraFrTot(const int iNewNumBitsHieraFrTot)
+{
+    /* Apply changes only if parameters have changed */
+    if (iNewNumBitsHieraFrTot != iNumBitsHierarchFrameTotal)
+    {
+        iNumBitsHierarchFrameTotal = iNewNumBitsHieraFrTot;
+
+        /* Set init flags */
+        if (pDRMRec) pDRMRec->InitsForMSCDemux();
+    }
+}
+
+void CParameter::SetNumAudioDecoderBits(const int iNewNumAudioDecoderBits)
+{
+    /* Apply changes only if parameters have changed */
+    if (iNewNumAudioDecoderBits != iNumAudioDecoderBits)
+    {
+        iNumAudioDecoderBits = iNewNumAudioDecoderBits;
+    }
+}
+
+void CParameter::SetNumDataDecoderBits(const int iNewNumDataDecoderBits)
+{
+    /* Apply changes only if parameters have changed */
+    if (iNewNumDataDecoderBits != iNumDataDecoderBits)
+    {
+        iNumDataDecoderBits = iNewNumDataDecoderBits;
+    }
+}
+
+void CParameter::SetMSCProtLev(const CMSCProtLev NewMSCPrLe,
+                               const _BOOLEAN bWithHierarch)
+{
+    _BOOLEAN bParamersHaveChanged = FALSE;
+
+    if ((NewMSCPrLe.iPartA != MSCPrLe.iPartA) ||
+            (NewMSCPrLe.iPartB != MSCPrLe.iPartB))
+    {
+        MSCPrLe.iPartA = NewMSCPrLe.iPartA;
+        MSCPrLe.iPartB = NewMSCPrLe.iPartB;
+
+        bParamersHaveChanged = TRUE;
+    }
+
+    /* Apply changes only if parameters have changed */
+    if (bWithHierarch == TRUE)
+    {
+        if (NewMSCPrLe.iHierarch != MSCPrLe.iHierarch)
+        {
+            MSCPrLe.iHierarch = NewMSCPrLe.iHierarch;
+
+            bParamersHaveChanged = TRUE;
+        }
+    }
+
+    /* In case parameters have changed, set init flags */
+    if (bParamersHaveChanged == TRUE)
+        if (pDRMRec) pDRMRec->InitsForMSC();
+}
+
+void CParameter::SetServiceParameters(int iShortID, const CService& newService)
+{
+    Service[iShortID] = newService;
+}
+
+void CParameter::SetAudioParam(const int iShortID, const CAudioParam& NewAudParam)
+{
+    /* Apply changes only if parameters have changed */
+    if (Service[iShortID].AudioParam != NewAudParam)
+    {
+        Service[iShortID].AudioParam = NewAudParam;
+
+        /* Set init flags */
+        if (pDRMRec) pDRMRec->InitsForAudParam();
+    }
+}
+
+CAudioParam CParameter::GetAudioParam(const int iShortID) const
+{
+    return Service[iShortID].AudioParam;
+}
+
+void CParameter::SetDataParam(const int iShortID, const CDataParam& NewDataParam)
+{
+    /* Apply changes only if parameters have changed */
+    if (Service[iShortID].DataParam != NewDataParam)
+    {
+        Service[iShortID].DataParam = NewDataParam;
+        /* Set init flags */
+        if (pDRMRec) pDRMRec->InitsForDataParam();
+    }
+}
+
+CDataParam CParameter::GetDataParam(const int iShortID) const
+{
+    return Service[iShortID].DataParam;
+}
+
+void CParameter::SetInterleaverDepth(const ESymIntMod eNewDepth)
+{
+    if (eSymbolInterlMode != eNewDepth)
+    {
+        eSymbolInterlMode = eNewDepth;
+
+        /* Set init flags */
+        if (pDRMRec) pDRMRec->InitsForInterlDepth();
+    }
+}
+
+void CParameter::SetMSCCodingScheme(const ECodScheme eNewScheme)
+{
+    if (eMSCCodingScheme != eNewScheme)
+    {
+        eMSCCodingScheme = eNewScheme;
+
+        /* Set init flags */
+        if (pDRMRec) pDRMRec->InitsForMSCCodSche();
+    }
+}
+
+void CParameter::SetSDCCodingScheme(const ECodScheme eNewScheme)
+{
+    if (eSDCCodingScheme != eNewScheme)
+    {
+        eSDCCodingScheme = eNewScheme;
+
+        /* Set init flags */
+        if (pDRMRec) pDRMRec->InitsForSDCCodSche();
+    }
+}
+
+void CParameter::SetCurSelAudioService(const int iNewService)
+{
+    /* Change the current selected audio service ID only if the new ID does
+       contain an audio service. If not, keep the old ID. In that case it is
+       possible to select a "data-only" service and still listen to the audio of
+       the last selected service */
+    if ((iCurSelAudioService != iNewService) &&
+            (Service[iNewService].AudioParam.iStreamID != STREAM_ID_NOT_USED))
+    {
+        iCurSelAudioService = iNewService;
+
+        LastAudioService.Reset();
+
+        /* Set init flags */
+        if (pDRMRec) pDRMRec->InitsForAudParam();
+    }
+}
+
+void CParameter::SetCurSelDataService(const int iNewService)
+{
+    /* Change the current selected data service ID only if the new ID does
+       contain a data service. If not, keep the old ID. In that case it is
+       possible to select a "data-only" service and click back to an audio
+       service to be able to decode data service and listen to audio at the
+       same time */
+    if ((iCurSelDataService != iNewService) &&
+            (Service[iNewService].DataParam.iStreamID != STREAM_ID_NOT_USED))
+    {
+        iCurSelDataService = iNewService;
+        LastDataService.Reset();
+
+        /* Set init flags */
+        if (pDRMRec) pDRMRec->InitsForDataParam();
+    }
+}
+
+void CParameter::SetNumOfServices(const size_t iNNumAuSe, const size_t iNNumDaSe)
+{
+    /* Check whether number of activated services is not greater than the
+       number of services signalled by the FAC because it can happen that
+       a false CRC check (it is only a 8 bit CRC) of the FAC block
+       initializes a wrong service */
+    set<int> actServ;
+
+    GetActiveServices(actServ);
+    if (actServ.size() > iNNumAuSe + iNNumDaSe)
+    {
+        /* Reset services and streams and set flag for init modules */
+        ResetServicesStreams();
+        if (pDRMRec) pDRMRec->InitsForMSCDemux();
+    }
+
+    if ((iNumAudioService != iNNumAuSe) || (iNumDataService != iNNumDaSe))
+    {
+        iNumAudioService = iNNumAuSe;
+        iNumDataService = iNNumDaSe;
+
+        /* Set init flags */
+        if (pDRMRec) pDRMRec->InitsForMSCDemux();
+    }
+}
+
+void CParameter::SetAudDataFlag(const int iShortID, const CService::ETyOServ iNewADaFl)
+{
+    if (Service[iShortID].eAudDataFlag != iNewADaFl)
+    {
+        Service[iShortID].eAudDataFlag = iNewADaFl;
+
+        /* Set init flags */
+        if (pDRMRec) pDRMRec->InitsForMSC();
+    }
+}
+
+void CParameter::SetServiceID(const int iShortID, const uint32_t iNewServiceID)
+{
+    if (Service[iShortID].iServiceID != iNewServiceID)
+    {
+        /* JFBC - what is this for? */
+        if ((iShortID == 0) && (Service[0].iServiceID > 0))
+            ResetServicesStreams();
+
+        Service[iShortID].iServiceID = iNewServiceID;
+
+        /* Set init flags */
+        if (pDRMRec) pDRMRec->InitsForMSC();
+
+
+        /* If the receiver has lost the sync automatically restore
+        	last current service selected */
+
+        if ((iShortID > 0) && (iNewServiceID > 0))
+        {
+            if (LastAudioService.iServiceID == iNewServiceID)
+            {
+                /* Restore last audio service selected */
+                iCurSelAudioService = LastAudioService.iService;
+
+                LastAudioService.Reset();
+
+                /* Set init flags */
+                if (pDRMRec) pDRMRec->InitsForAudParam();
+            }
+
+            if (LastDataService.iServiceID == iNewServiceID)
+            {
+                /* Restore last data service selected */
+                iCurSelDataService = LastDataService.iService;
+
+                LastDataService.Reset();
+
+                /* Set init flags */
+                if (pDRMRec) pDRMRec->InitsForDataParam();
+            }
+        }
+    }
+}
+
+/* Implementaions for simulation -------------------------------------------- */
+void CRawSimData::Add(uint32_t iNewSRS)
+{
+    /* Attention, function does not take care of overruns, data will be
+       lost if added to a filled shift register! */
+    if (iCurWritePos < ciMaxDelBlocks)
+        veciShRegSt[iCurWritePos++] = iNewSRS;
+}
+
+uint32_t CRawSimData::Get()
+{
+    /* We always use the first value of the array for reading and do a
+       shift of the other data by adding a arbitrary value (0) at the
+       end of the whole shift register */
+    uint32_t iRet = veciShRegSt[0];
+    veciShRegSt.AddEnd(0);
+    iCurWritePos--;
+
+    return iRet;
+}
+
+_REAL CParameter::GetSysSNRdBPilPos() const
+{
+    /*
+    	Get system SNR in dB for the pilot positions. Since the average power of
+    	the pilots is higher than the data cells, the SNR is also higher at these
+    	positions compared to the total SNR of the DRM signal.
+    */
+    return (_REAL) 10.0 * log10(pow((_REAL) 10.0, rSysSimSNRdB / 10) /
+                                CellMappingTable.rAvPowPerSymbol *
+				CellMappingTable.rAvScatPilPow *
+				(_REAL) CellMappingTable.iNumCarrier);
+}
+
+void
+CParameter::SetSNR(const _REAL iNewSNR)
+{
+    SNRstat.addSample(iNewSNR);
+}
+
+_REAL
+CParameter::GetSNR()
+{
+    return SNRstat.getCurrent();
+}
+
+_REAL CParameter::GetNominalSNRdB()
+{
+    /* Convert SNR from system bandwidth to nominal bandwidth */
+    return (_REAL) 10.0 * log10(pow((_REAL) 10.0, rSysSimSNRdB / 10) *
+                                GetSysToNomBWCorrFact());
+}
+
+void CParameter::SetNominalSNRdB(const _REAL rSNRdBNominal)
+{
+    /* Convert SNR from nominal bandwidth to system bandwidth */
+    rSysSimSNRdB = (_REAL) 10.0 * log10(pow((_REAL) 10.0, rSNRdBNominal / 10) /
+                                        GetSysToNomBWCorrFact());
+}
+
+_REAL CParameter::GetNominalBandwidth()
+{
+    _REAL rNomBW;
+
+    /* Nominal bandwidth as defined in the DRM standard */
+    switch (eSpectOccup)
+    {
+    case SO_0:
+        rNomBW = (_REAL) 4500.0; /* Hz */
+        break;
+
+    case SO_1:
+        rNomBW = (_REAL) 5000.0; /* Hz */
+        break;
+
+    case SO_2:
+        rNomBW = (_REAL) 9000.0; /* Hz */
+        break;
+
+    case SO_3:
+        rNomBW = (_REAL) 10000.0; /* Hz */
+        break;
+
+    case SO_4:
+        rNomBW = (_REAL) 18000.0; /* Hz */
+        break;
+
+    case SO_5:
+        rNomBW = (_REAL) 20000.0; /* Hz */
+        break;
+
+    default:
+        rNomBW = (_REAL) 10000.0; /* Hz */
+        break;
+    }
+
+    return rNomBW;
+}
+
+_REAL CParameter::GetSysToNomBWCorrFact()
+{
+    _REAL rNomBW = GetNominalBandwidth();
+
+    /* Calculate system bandwidth (N / T_u) */
+    const _REAL rSysBW = (_REAL) CellMappingTable.iNumCarrier / CellMappingTable.iFFTSizeN * iSigSampleRate;
+
+    return rSysBW / rNomBW;
+}
+
+
+void CParameter::SetIFSignalLevel(_REAL rNewSigStr)
+{
+    rIFSigStr = rNewSigStr;
+}
+
+_REAL CParameter::GetIFSignalLevel()
+{
+    return rIFSigStr;
+}
+
+void CRxStatus::SetStatus(const ETypeRxStatus OK)
+{
+    status = OK;
+    iNum++;
+    if (OK==RX_OK)
+        iNumOK++;
+}
+
+void CParameter::GenerateReceiverID()
+{
+    stringstream ssInfoVer;
+    ssInfoVer << setw(2) << setfill('0') << setw(2) << setfill('0') << dream_version_major << setw(2) << setfill('0') << dream_version_minor;
+
+    sReceiverID = string(dream_manufacturer)+string(dream_implementation)+ssInfoVer.str();
+
+    while (sSerialNumber.length() < 6)
+        sSerialNumber += "_";
+
+    if (sSerialNumber.length() > 6)
+        sSerialNumber.erase(6, sSerialNumber.length()-6);
+
+    sReceiverID += sSerialNumber;
+}
+
+void CParameter::GenerateRandomSerialNumber()
+{
+    //seed random number generator
+    srand((unsigned int)time(0));
+
+    char randomChars[36];
+
+    for (size_t q=0; q < 36; q++)
+    {
+        if (q < 26)
+            randomChars[q] = char(q)+97;
+        else
+            randomChars[q] = (char(q)-26)+48;
+    }
+
+    char serialNumTemp[7];
+
+    for (size_t i=0; i < 6; i++)
+#ifdef _WIN32
+        serialNumTemp[i] = randomChars[(int) 35.0*rand()/RAND_MAX]; /* integer overflow on linux, RAND_MAX=0x7FFFFFFF */
+#else
+        serialNumTemp[i] = randomChars[35ll * (long long)rand() / RAND_MAX];
+#endif
+
+    serialNumTemp[6] = '\0';
+
+    sSerialNumber = serialNumTemp;
+}
+
+CMinMaxMean::CMinMaxMean():rSum(0.0),rCur(0.0),
+    rMin(numeric_limits<_REAL>::max()),rMax(numeric_limits<_REAL>::min()),iNum(0)
+{
+}
+
+void
+CMinMaxMean::addSample(_REAL r)
+{
+    rCur = r;
+    rSum += r;
+    iNum++;
+    if (r>rMax)
+        rMax = r;
+    if (r<rMin)
+        rMin = r;
+}
+
+_REAL
+CMinMaxMean::getCurrent()
+{
+    return rCur;
+}
+
+_REAL
+CMinMaxMean::getMean()
+{
+    _REAL rMean = 0.0;
+    if (iNum>0)
+        rMean = rSum / iNum;
+    rSum = 0.0;
+    iNum = 0;
+    return rMean;
+}
+
+void
+CMinMaxMean::getMinMax(_REAL& rMinOut, _REAL& rMaxOut)
+{
+    if (rMin <= rMax)
+    {
+        rMinOut = rMin;
+        rMaxOut = rMax;
+    }
+    else
+    {
+        rMinOut = 0.0;
+        rMaxOut = 0.0;
+    }
+    rMin = numeric_limits<_REAL>::max();
+    rMax = numeric_limits<_REAL>::min();
+}
+
+string CServiceDefinition::Frequency(size_t n) const
+{
+    if (n>=veciFrequencies.size())
+        return ""; // not in the list
+
+    stringstream ss;
+    int iFrequency = veciFrequencies[n];
+
+    switch (iSystemID)
+    {
+    case 0:
+    case 1:
+    case 2:
+        /* AM or DRM */
+        ss << iFrequency;
+        break;
+
+    case 3:
+    case 4:
+    case 5:
+        /* 'FM1 frequency' - 87.5 to 107.9 MHz (100 kHz steps) */
+        ss << 87.5 + 0.1 * float(iFrequency);
+        break;
+
+    case 6:
+    case 7:
+    case 8:
+        /* 'FM2 frequency'- 76.0 to 90.0 MHz (100 kHz steps) */
+        ss << 76.0 + 0.1 * float(iFrequency);
+        break;
+
+    case 9:
+    case 10:
+    case 11:
+        if (iFrequency<=11) {
+            int chan = iFrequency / 4;
+            char subchan = 'A' + iFrequency % 4;
+            ss << "Band I channel " << (chan+2) << subchan;
+        } else if (64<= iFrequency && iFrequency <=95) {
+            int chan = iFrequency / 4;
+            char subchan = 'A' + iFrequency % 4;
+            ss << "Band III channel " << (chan-11) << subchan;
+        } else if (96<= iFrequency && iFrequency <=101) {
+            int chan = iFrequency / 6;
+            char subchan = 'A' + iFrequency % 6;
+            ss << "Band III+ channel " << (chan-3) << subchan;
+        } else if (128<= iFrequency && iFrequency <=143) {
+            char chan = iFrequency - 128;
+            double m = 1452.96+1.712*double(chan);
+            ss << "European L-Band channel L" << ('A'+chan) << ", " << m << " MHz";
+        } else if (160<= iFrequency && iFrequency <=182) {
+            int chan = iFrequency - 159;
+            double m = 1451.072+1.744*double(chan);
+            ss << "Canadian L-Band channel " << chan << ", " << m << " MHz";
+        } else {
+            ss << "unknown channel " << iFrequency;
+        }
+        break;
+    default:
+        break;
+    }
+    return ss.str();
+}
+
+string CServiceDefinition::FrequencyUnits() const
+{
+    switch (iSystemID)
+    {
+    case 0:
+    case 1:
+    case 2:
+        return "kHz";
+        break;
+
+    case 3:
+    case 4:
+    case 5:
+    case 6:
+    case 7:
+    case 8:
+        return "MHz";
+        break;
+
+    default:
+        return "";
+        break;
+    }
+}
+
+string CServiceDefinition::System() const
+{
+    switch (iSystemID)
+    {
+    case 0:
+        return "DRM";
+        break;
+
+    case 1:
+    case 2:
+        return "AM";
+        break;
+
+    case 3:
+    case 4:
+    case 5:
+    case 6:
+    case 7:
+    case 8:
+        return "FM";
+        break;
+    case 9:
+    case 10:
+    case 11:
+        return "DAB";
+        break;
+
+    default:
+        return "";
+        break;
+    }
+}
+
+string COtherService::ServiceID() const
+{
+    stringstream ss;
+    /*
+    switch (iSystemID)
+    {
+    case 0:
+    case 1:
+    	ss << "ID:" << hex << setw(6) << iServiceID;
+    	break;
+
+    case 3:
+    case 6:
+    	ss << "ECC+PI:" << hex << setw(6) << iServiceID;
+    	break;
+    case 4:
+    case 7:
+    	ss << "PI:" << hex << setw(4) << iServiceID;
+    	break;
+    case 9:
+    	ss << "ECC+aud:" << hex << setw(6) << iServiceID;
+    	break;
+    case 10:
+    	ss << "AUDIO:" << hex << setw(4) << iServiceID;
+    	break;
+    case 11:
+    	ss << "DATA:" << hex << setw(8) << iServiceID;
+    	break;
+    	break;
+
+    default:
+    	break;
+    }
+    */
+    return ss.str();
+}
+
+/* See ETSI ES 201 980 v2.1.1 Annex O */
+_BOOLEAN
+CAltFreqSched::IsActive(const time_t ltime)
+{
+    int iScheduleStart;
+    int iScheduleEnd;
+    int iWeekDay;
+
+    /* Empty schedule is always active */
+    if (iDuration == 0)
+        return true;
+
+    /* Calculate time in UTC */
+    struct tm *gmtCur = gmtime(&ltime);
+
+    /* Check day
+       tm_wday: day of week (0 - 6; Sunday = 0)
+       I must normalize so Monday = 0   */
+
+    if (gmtCur->tm_wday == 0)
+        iWeekDay = 6;
+    else
+        iWeekDay = gmtCur->tm_wday - 1;
+
+    /* iTimeWeek minutes since last Monday 00:00 in UTC */
+    /* the value is in the range 0 <= iTimeWeek < 60 * 24 * 7)   */
+
+    const int iTimeWeek =
+        (iWeekDay * 24 * 60) + (gmtCur->tm_hour * 60) + gmtCur->tm_min;
+
+    /* Day Code: this field indicates which days the frequency schedule
+     * (the following Start Time and Duration) applies to.
+     * The msb indicates Monday, the lsb Sunday. Between one and seven bits may be set to 1.
+     */
+    for (int i = 0; i < 7; i++)
+    {
+        /* Check if day is active */
+        if ((1 << (6 - i)) & iDayCode)
+        {
+            /* Tuesday -> 1 * 24 * 60 = 1440 */
+            iScheduleStart = (i * 24 * 60) + iStartTime;
+            iScheduleEnd = iScheduleStart + iDuration;
+
+            /* the normal check (are we inside start and end?) */
+            if ((iTimeWeek >= iScheduleStart) && (iTimeWeek <= iScheduleEnd))
+                return true;
+
+            /* the wrap-around check */
+            const int iMinutesPerWeek = 7 * 24 * 60;
+
+            if (iScheduleEnd > iMinutesPerWeek)
+            {
+                /* our duration wraps into next Monday (or even later) */
+                if (iTimeWeek < (iScheduleEnd - iMinutesPerWeek))
+                    return true;
+            }
+        }
+    }
+    return false;
+}
diff --git a/src/Parameter.h b/src/Parameter.h
new file mode 100644
index 0000000..46f30a1
--- /dev/null
+++ b/src/Parameter.h
@@ -0,0 +1,1307 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer, Andrew Murphy, Andrea Russo
+ *
+ * Description:
+ *	See Parameter.cpp
+ *
+ * 10/01/2001-2014 Andrew Murphy, BBC Research & Development, 2005
+ *	- Additions to include additional RSCI related fields
+ *
+ * 11/21/2005 Andrew Murphy, BBC Research & Development, 2005
+ *	- Additions to include AMSS demodulation (Added class
+ *    CAltFreqOtherServicesSign)
+ *
+ * 11/28/2005 Andrea Russo
+ *	- Added classes for store alternative frequencies schedules and regions
+ *
+ *******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#if !defined(PARAMETER_H__3B0BA660_CA63_4344_BB2B_23E7A0D31912__INCLUDED_)
+#define PARAMETER_H__3B0BA660_CA63_4344_BB2B_23E7A0D31912__INCLUDED_
+
+#include "GlobalDefinitions.h"
+#include "ofdmcellmapping/CellMappingTable.h"
+#include "matlib/Matlib.h"
+#include <time.h>
+#include "ServiceInformation.h"
+#include <map>
+#include <iostream>
+#ifdef HAVE_LIBGPS
+# include <gps.h>
+#else
+    struct gps_fix_t {
+	double time;
+	double latitude;
+	double longitude;
+	double altitude;
+	double speed;
+	double track;
+    };
+    struct gps_data_t {
+	uint32_t set;
+#define TIME_SET        0x00000002u
+#define LATLON_SET      0x00000008u
+#define ALTITUDE_SET    0x00000010u
+#define SPEED_SET       0x00000020u
+#define TRACK_SET       0x00000040u
+#define STATUS_SET      0x00000100u
+#define SATELLITE_SET   0x00010000u
+	gps_fix_t fix;
+	int    status; 
+	int satellites_used;
+    };
+#endif
+
+class CDRMReceiver;
+class CDataDecoder;
+
+/* SI: Symbol Interleaver */
+enum ESymIntMod { SI_LONG, SI_SHORT, SI_MODE_E };
+
+/* CS: Coding Scheme */
+enum ECodScheme { CS_1_SM, CS_2_SM, CS_3_SM, CS_3_HMSYM, CS_3_HMMIX };
+
+/* CT: Channel Type */
+enum EChanType { CT_MSC, CT_SDC, CT_FAC };
+
+enum ETypeIntFreq
+{ FLINEAR, FDFTFILTER, FWIENER };
+enum ETypeIntTime
+{ TLINEAR, TWIENER };
+enum ETypeSNREst
+{ SNR_FAC, SNR_PIL };
+enum ETypeRxStatus
+{ NOT_PRESENT, CRC_ERROR, DATA_ERROR, RX_OK };
+/* RM: Receiver mode (analog or digital demodulation) */
+
+enum ERecMode
+{ RM_DRM, RM_AM, RM_FM, RM_NONE };
+
+/* Acquisition state of receiver */
+enum EAcqStat {AS_NO_SIGNAL, AS_WITH_SIGNAL};
+
+/* Receiver state */
+enum ERecState {RS_TRACKING, RS_ACQUISITION};
+
+/* Classes ********************************************************************/
+
+class CAudioParam
+{
+public:
+
+    /* AC: Audio Coding */
+    enum EAudCod { AC_NONE, AC_AAC, AC_CELP, AC_HVXC, AC_xHE_AAC, AC_OPUS };
+
+    /* SB: SBR */
+    enum ESBRFlag { SB_NOT_USED, SB_USED };
+
+    /* AM: Audio Mode */
+    enum EAudMode { AM_MONO, AM_P_STEREO, AM_STEREO };
+
+    /* HR: HVXC Rate */
+    enum EHVXCRate { HR_2_KBIT, HR_4_KBIT };
+
+    /* AS: Audio Sampling rate */
+    enum EAudSamRat { AS_8_KHZ, AS_12KHZ, AS_16KHZ, AS_24KHZ, AS_48KHZ,
+                      AS_9_6_KHZ, AS_19_2KHZ, AS_32KHZ, AS_38_4KHZ,
+                      AS_RESERVED
+                    };
+
+    /* OB: Opus Audio Bandwidth, coded in audio data stream */
+    enum EOPUSBandwidth { OB_NB, OB_MB, OB_WB, OB_SWB, OB_FB };
+
+    /* OS: Opus Audio Sub Codec, coded in audio data stream */
+    enum EOPUSSubCod { OS_SILK, OS_HYBRID, OS_CELT };
+
+    /* OC: Opus Audio Channels, coded in audio data stream */
+    enum EOPUSChan { OC_MONO, OC_STEREO };
+
+    /* OG: Opus encoder signal type, for encoder only */
+    enum EOPUSSignal { OG_VOICE, OG_MUSIC };
+
+    /* OA: Opus encoder intended application, for encoder only */
+    enum EOPUSApplication { OA_VOIP, OA_AUDIO };
+
+    CAudioParam(): strTextMessage(), iStreamID(STREAM_ID_NOT_USED),
+            eAudioCoding(AC_NONE), eSBRFlag(SB_NOT_USED), eAudioSamplRate(AS_24KHZ),
+            bTextflag(FALSE), bEnhanceFlag(FALSE), eAudioMode(AM_MONO),
+            iCELPIndex(0), bCELPCRC(FALSE), eHVXCRate(HR_2_KBIT), bHVXCCRC(FALSE),
+            eOPUSBandwidth(OB_FB), eOPUSSubCod(OS_SILK), eOPUSChan(OC_STEREO),
+            eOPUSSignal(OG_MUSIC), eOPUSApplication(OA_AUDIO),
+            bOPUSForwardErrorCorrection(FALSE), bOPUSRequestReset(FALSE),
+            bParamChanged(FALSE),
+            rBitRate(0.0),bCanDecode(false)
+    {
+    }
+
+    /* Text-message */
+    string strTextMessage;	/* Max length is (8 * 16 Bytes) */
+
+    int iStreamID;			/* Stream Id of the stream which carries the audio service */
+
+    EAudCod eAudioCoding;	/* This field indicated the source coding system */
+    ESBRFlag eSBRFlag;		/* SBR flag */
+    EAudSamRat eAudioSamplRate;	/* Audio sampling rate */
+    _BOOLEAN bTextflag;		/* Indicates whether a text message is present or not */
+    _BOOLEAN bEnhanceFlag;	/* Enhancement flag */
+    bool bCA;               /* Conditional Access */
+
+    /* For AAC: Mono, LC Stereo, Stereo --------------------------------- */
+    EAudMode eAudioMode;	/* Audio mode */
+
+    /* For CELP --------------------------------------------------------- */
+    int iCELPIndex;			/* This field indicates the CELP bit rate index */
+    _BOOLEAN bCELPCRC;		/* This field indicates whether the CRC is used or not */
+
+    /* For HVXC --------------------------------------------------------- */
+    EHVXCRate eHVXCRate;	/* This field indicates the rate of the HVXC */
+    _BOOLEAN bHVXCCRC;		/* This field indicates whether the CRC is used or not */
+
+    /* For OPUS --------------------------------------------------------- */
+    EOPUSBandwidth eOPUSBandwidth; /* Audio bandwidth */
+    EOPUSSubCod eOPUSSubCod; /* Audio sub codec */
+    EOPUSChan eOPUSChan;	/* Audio channels */
+    EOPUSSignal eOPUSSignal; /* Encoder signal type */
+    EOPUSApplication eOPUSApplication; /* Encoder intended application */
+    _BOOLEAN bOPUSForwardErrorCorrection; /* Encoder Forward Error Correction enabled */
+    _BOOLEAN bOPUSRequestReset; /* Request encoder reset */
+
+    /* CAudioParam has changed */
+    _BOOLEAN bParamChanged;
+    double rBitRate;
+    bool bCanDecode;
+
+    /* This function is needed for detection changes in the class */
+    _BOOLEAN operator!=(const CAudioParam AudioParam)
+    {
+        if (iStreamID != AudioParam.iStreamID)
+            return TRUE;
+        if (eAudioCoding != AudioParam.eAudioCoding)
+            return TRUE;
+        if (eSBRFlag != AudioParam.eSBRFlag)
+            return TRUE;
+        if (eAudioSamplRate != AudioParam.eAudioSamplRate)
+            return TRUE;
+        if (bTextflag != AudioParam.bTextflag)
+            return TRUE;
+        if (bEnhanceFlag != AudioParam.bEnhanceFlag)
+            return TRUE;
+
+        switch (AudioParam.eAudioCoding)
+        {
+        case AC_AAC:
+            if (eAudioMode != AudioParam.eAudioMode)
+                return TRUE;
+            break;
+
+        case AC_CELP:
+            if (bCELPCRC != AudioParam.bCELPCRC)
+                return TRUE;
+            if (iCELPIndex != AudioParam.iCELPIndex)
+                return TRUE;
+            break;
+
+        case AC_HVXC:
+            if (eHVXCRate != AudioParam.eHVXCRate)
+                return TRUE;
+            if (bHVXCCRC != AudioParam.bHVXCCRC)
+                return TRUE;
+            break;
+
+        case AC_NONE:
+        case AC_OPUS:
+        case AC_xHE_AAC: // TODO
+            break;
+        }
+        return FALSE;
+    }
+};
+
+class CDataParam
+{
+public:
+
+    /* PM: Packet Mode */
+    enum EPackMod { PM_SYNCHRON_STR_MODE, PM_PACKET_MODE };
+
+    /* DU: Data Unit */
+    enum EDatUnit { DU_SINGLE_PACKETS, DU_DATA_UNITS };
+
+    /* AD: Application Domain */
+    enum EApplDomain { AD_DRM_SPEC_APP, AD_DAB_SPEC_APP, AD_OTHER_SPEC_APP };
+
+    int iStreamID;			/* Stream Id of the stream which carries the data service */
+
+    EPackMod ePacketModInd;	/* Packet mode indicator */
+
+    /* In case of packet mode ------------------------------------------- */
+    EDatUnit eDataUnitInd;	/* Data unit indicator */
+    int iPacketID;			/* Packet Id (2 bits) */
+    int iPacketLen;			/* Packet length */
+
+    // "DAB specified application" not yet implemented!!!
+    EApplDomain eAppDomain;	/* Application domain */
+    int iUserAppIdent;		/* User application identifier, only DAB */
+    double rBitRate;
+    bool bCanDecode;
+    CDataDecoder* pDecoder;
+
+    CDataParam():
+            iStreamID(STREAM_ID_NOT_USED),
+            ePacketModInd(PM_PACKET_MODE),
+            eDataUnitInd(DU_DATA_UNITS),
+            iPacketID(0),
+            iPacketLen(0),
+            eAppDomain(AD_DAB_SPEC_APP),
+            iUserAppIdent(0),
+            rBitRate(0.0),bCanDecode(false),
+            pDecoder(NULL)
+    {
+    }
+
+    /* This function is needed to detect changes in the data service */
+    _BOOLEAN operator!=(const CDataParam DataParam)
+    {
+        if (iStreamID != DataParam.iStreamID)
+            return TRUE;
+        if (ePacketModInd != DataParam.ePacketModInd)
+            return TRUE;
+        if (DataParam.ePacketModInd == PM_PACKET_MODE)
+        {
+            if (eDataUnitInd != DataParam.eDataUnitInd)
+                return TRUE;
+            if (iPacketID != DataParam.iPacketID)
+                return TRUE;
+            if (iPacketLen != DataParam.iPacketLen)
+                return TRUE;
+            if (eAppDomain != DataParam.eAppDomain)
+                return TRUE;
+            if (DataParam.eAppDomain == AD_DAB_SPEC_APP)
+                if (iUserAppIdent != DataParam.iUserAppIdent)
+                    return TRUE;
+        }
+        return FALSE;
+    }
+};
+
+class CService
+{
+public:
+
+    /* CA: CA system */
+    enum ECACond { CA_USED, CA_NOT_USED };
+
+    /* SF: Service Flag */
+    enum ETyOServ { SF_AUDIO, SF_DATA };
+
+    CService():
+            iServiceID(SERV_ID_NOT_USED), eCAIndication(CA_NOT_USED),
+            iLanguage(0), eAudDataFlag(SF_AUDIO), iServiceDescr(0),
+            strCountryCode(), strLanguageCode(), strLabel(),
+            AudioParam(), DataParam()
+    {
+    }
+
+    _BOOLEAN IsActive() const
+    {
+        return iServiceID != SERV_ID_NOT_USED;
+    }
+
+    uint32_t iServiceID;
+    ECACond eCAIndication;
+    int iLanguage;
+    ETyOServ eAudDataFlag;
+    int iServiceDescr;
+    string strCountryCode;
+    string strLanguageCode;
+
+    /* Label of the service */
+    string strLabel;
+
+    /* Audio parameters */
+    CAudioParam AudioParam;
+
+    /* Data parameters */
+    CDataParam DataParam;
+};
+
+class CStream
+{
+public:
+
+    CStream():iLenPartA(0), iLenPartB(0)
+    {
+    }
+    CStream(const CStream& s):iLenPartA(s.iLenPartA), iLenPartB(s.iLenPartB)
+    {
+    }
+    CStream& operator=(const CStream& Stream)
+    {
+        iLenPartA=Stream.iLenPartA;
+        iLenPartB=Stream.iLenPartB;
+        return *this;
+    }
+
+    bool operator==(const CStream Stream)
+    {
+        if (iLenPartA != Stream.iLenPartA)
+            return false;
+        if (iLenPartB != Stream.iLenPartB)
+            return false;
+        return true;
+    }
+
+    int iLenPartA;			/* Data length for part A */
+    int iLenPartB;			/* Data length for part B */
+};
+
+class CMSCProtLev
+{
+public:
+
+    CMSCProtLev():iPartA(0),iPartB(0),iHierarch(0) {}
+    CMSCProtLev(const CMSCProtLev& p):iPartA(p.iPartA),iPartB(p.iPartB),iHierarch(p.iHierarch) {}
+    CMSCProtLev& operator=(const CMSCProtLev& NewMSCProtLev)
+    {
+        iPartA = NewMSCProtLev.iPartA;
+        iPartB = NewMSCProtLev.iPartB;
+        iHierarch = NewMSCProtLev.iHierarch;
+        return *this;
+    }
+
+    int iPartA;				/* MSC protection level for part A */
+    int iPartB;				/* MSC protection level for part B */
+    int iHierarch;			/* MSC protection level for hierachical frame */
+};
+
+/* Alternative Frequency Signalling ************************************** */
+/* Alternative frequency signalling Schedules informations class */
+class CAltFreqSched
+{
+public:
+    CAltFreqSched():iDayCode(0),iStartTime(0),iDuration(0)
+    {
+    }
+    CAltFreqSched(const CAltFreqSched& nAFS):
+            iDayCode(nAFS.iDayCode), iStartTime(nAFS.iStartTime),
+            iDuration(nAFS.iDuration)
+    {
+    }
+
+    CAltFreqSched& operator=(const CAltFreqSched& nAFS)
+    {
+        iDayCode = nAFS.iDayCode;
+        iStartTime = nAFS.iStartTime;
+        iDuration = nAFS.iDuration;
+
+        return *this;
+    }
+
+    _BOOLEAN operator==(const CAltFreqSched& nAFS)
+    {
+        if (iDayCode != nAFS.iDayCode)
+            return FALSE;
+        if (iStartTime != nAFS.iStartTime)
+            return FALSE;
+        if (iDuration != nAFS.iDuration)
+            return FALSE;
+
+        return TRUE;
+    }
+
+    _BOOLEAN IsActive(const time_t ltime);
+
+    int iDayCode;
+    int iStartTime;
+    int iDuration;
+};
+
+/* Alternative frequency signalling Regions informations class */
+class CAltFreqRegion
+{
+public:
+    CAltFreqRegion():veciCIRAFZones(),
+            iLatitude(0), iLongitude(0),
+            iLatitudeEx(0), iLongitudeEx(0)
+    {
+    }
+    CAltFreqRegion(const CAltFreqRegion& nAFR):
+            veciCIRAFZones(nAFR.veciCIRAFZones),
+            iLatitude(nAFR.iLatitude),
+            iLongitude(nAFR.iLongitude),
+            iLatitudeEx(nAFR.iLatitudeEx), iLongitudeEx(nAFR.iLongitudeEx)
+    {
+    }
+
+    CAltFreqRegion& operator=(const CAltFreqRegion& nAFR)
+    {
+        iLatitude = nAFR.iLatitude;
+        iLongitude = nAFR.iLongitude;
+        iLatitudeEx = nAFR.iLatitudeEx;
+        iLongitudeEx = nAFR.iLongitudeEx;
+
+        veciCIRAFZones = nAFR.veciCIRAFZones;
+
+        return *this;
+    }
+
+    _BOOLEAN operator==(const CAltFreqRegion& nAFR)
+    {
+        if (iLatitude != nAFR.iLatitude)
+            return FALSE;
+        if (iLongitude != nAFR.iLongitude)
+            return FALSE;
+        if (iLatitudeEx != nAFR.iLatitudeEx)
+            return FALSE;
+        if (iLongitudeEx != nAFR.iLongitudeEx)
+            return FALSE;
+
+        /* Vector sizes */
+        if (veciCIRAFZones.size() != nAFR.veciCIRAFZones.size())
+            return FALSE;
+
+        /* Vector contents */
+        for (size_t i = 0; i < veciCIRAFZones.size(); i++)
+            if (veciCIRAFZones[i] != nAFR.veciCIRAFZones[i])
+                return FALSE;
+
+        return TRUE;
+    }
+
+    vector<int> veciCIRAFZones;
+    int iLatitude;
+    int iLongitude;
+    int iLatitudeEx;
+    int iLongitudeEx;
+};
+
+class CServiceDefinition
+{
+public:
+    CServiceDefinition():veciFrequencies(), iRegionID(0), iScheduleID(0),iSystemID(0)
+    {
+    }
+
+    CServiceDefinition(const CServiceDefinition& nAF):
+            veciFrequencies(nAF.veciFrequencies),
+            iRegionID(nAF.iRegionID), iScheduleID(nAF.iScheduleID),
+            iSystemID(nAF.iSystemID)
+    {
+    }
+
+    CServiceDefinition& operator=(const CServiceDefinition& nAF)
+    {
+        veciFrequencies = nAF.veciFrequencies;
+        iRegionID = nAF.iRegionID;
+        iScheduleID = nAF.iScheduleID;
+        iSystemID = nAF.iSystemID;
+        return *this;
+    }
+
+    bool operator==(const CServiceDefinition& sd) const
+    {
+        size_t i;
+
+        /* Vector sizes */
+        if (veciFrequencies.size() != sd.veciFrequencies.size())
+            return FALSE;
+
+        /* Vector contents */
+        for (i = 0; i < veciFrequencies.size(); i++)
+            if (veciFrequencies[i] != sd.veciFrequencies[i])
+                return FALSE;
+
+        if (iRegionID != sd.iRegionID)
+            return FALSE;
+
+        if (iScheduleID != sd.iScheduleID)
+            return FALSE;
+
+        if (iSystemID != sd.iSystemID)
+            return FALSE;
+
+        return TRUE;
+    }
+    bool operator!=(const CServiceDefinition& sd) const {
+        return !(*this==sd);
+    }
+
+    string Frequency(size_t) const;
+    string FrequencyUnits() const;
+    string System() const;
+
+    vector<int> veciFrequencies;
+    int iRegionID;
+    int iScheduleID;
+    int iSystemID;
+};
+
+class CMultiplexDefinition: public CServiceDefinition
+{
+public:
+    CMultiplexDefinition():CServiceDefinition(), veciServRestrict(4), bIsSyncMultplx(FALSE)
+    {
+    }
+
+    CMultiplexDefinition(const CMultiplexDefinition& nAF):CServiceDefinition(nAF),
+            veciServRestrict(nAF.veciServRestrict),
+            bIsSyncMultplx(nAF.bIsSyncMultplx)
+    {
+    }
+
+    CMultiplexDefinition& operator=(const CMultiplexDefinition& nAF)
+    {
+        CServiceDefinition(*this) = nAF;
+        veciServRestrict = nAF.veciServRestrict;
+        bIsSyncMultplx = nAF.bIsSyncMultplx;
+        return *this;
+    }
+
+    bool operator==(const CMultiplexDefinition& md) const
+    {
+        if (CServiceDefinition(*this) != md)
+            return FALSE;
+
+        /* Vector sizes */
+        if (veciServRestrict.size() != md.veciServRestrict.size())
+            return FALSE;
+
+        /* Vector contents */
+        for (size_t i = 0; i < veciServRestrict.size(); i++)
+            if (veciServRestrict[i] != md.veciServRestrict[i])
+                return FALSE;
+
+        if (bIsSyncMultplx != md.bIsSyncMultplx)
+            return FALSE;
+
+        return TRUE;
+    }
+
+    vector<int> veciServRestrict;
+    _BOOLEAN bIsSyncMultplx;
+};
+
+class COtherService: public CServiceDefinition
+{
+public:
+    COtherService(): CServiceDefinition(), bSameService(TRUE),
+            iShortID(0), iServiceID(SERV_ID_NOT_USED)
+    {
+    }
+
+    COtherService(const COtherService& nAF):
+            CServiceDefinition(nAF), bSameService(nAF.bSameService),
+            iShortID(nAF.iShortID), iServiceID(nAF.iServiceID)
+    {
+    }
+
+    COtherService& operator=(const COtherService& nAF)
+    {
+        CServiceDefinition(*this) = nAF;
+
+        bSameService = nAF.bSameService;
+        iShortID = nAF.iShortID;
+        iServiceID = nAF.iServiceID;
+
+        return *this;
+    }
+
+    bool operator==(const COtherService& nAF)
+    {
+        if (CServiceDefinition(*this) != nAF)
+            return FALSE;
+
+        if (bSameService != nAF.bSameService)
+            return FALSE;
+
+        if (iShortID != nAF.iShortID)
+            return FALSE;
+
+        if (iServiceID != nAF.iServiceID)
+            return FALSE;
+
+        return TRUE;
+    }
+
+    string ServiceID() const;
+
+    _BOOLEAN bSameService;
+    int iShortID;
+    uint32_t iServiceID;
+};
+
+/* Alternative frequency signalling class */
+class CAltFreqSign
+{
+public:
+
+    CAltFreqSign():vecRegions(16),vecSchedules(16),vecMultiplexes(),vecOtherServices(),
+            bRegionVersionFlag(FALSE),bScheduleVersionFlag(FALSE),
+            bMultiplexVersionFlag(FALSE),bOtherServicesVersionFlag(FALSE)
+    {
+    }
+
+    CAltFreqSign(const CAltFreqSign& a):vecRegions(a.vecRegions),
+            vecSchedules(a.vecSchedules), vecMultiplexes(a.vecMultiplexes),
+            bRegionVersionFlag(a.bRegionVersionFlag),
+            bScheduleVersionFlag(a.bScheduleVersionFlag),
+            bMultiplexVersionFlag(a.bMultiplexVersionFlag),
+            bOtherServicesVersionFlag(a.bOtherServicesVersionFlag)
+    {
+    }
+
+    CAltFreqSign& operator=(const CAltFreqSign& a)
+    {
+        vecRegions = a.vecRegions;
+        vecSchedules = a.vecSchedules;
+        vecMultiplexes = a.vecMultiplexes;
+        bRegionVersionFlag = a.bRegionVersionFlag;
+        bScheduleVersionFlag = a.bScheduleVersionFlag;
+        bMultiplexVersionFlag = a.bMultiplexVersionFlag;
+        bOtherServicesVersionFlag = a.bOtherServicesVersionFlag;
+        return *this;
+    }
+
+    void ResetRegions(_BOOLEAN b)
+    {
+        vecRegions.clear();
+        vecRegions.resize(16);
+        bRegionVersionFlag=b;
+    }
+
+    void ResetSchedules(_BOOLEAN b)
+    {
+        vecSchedules.clear();
+        vecSchedules.resize(16);
+        bScheduleVersionFlag=b;
+    }
+
+    void ResetMultiplexes(_BOOLEAN b)
+    {
+        vecMultiplexes.clear();
+        bMultiplexVersionFlag=b;
+    }
+
+    void ResetOtherServices(_BOOLEAN b)
+    {
+        vecOtherServices.clear();
+        bOtherServicesVersionFlag=b;
+    }
+
+    void Reset()
+    {
+        ResetRegions(FALSE);
+        ResetSchedules(FALSE);
+        ResetMultiplexes(FALSE);
+        ResetOtherServices(FALSE);
+    }
+
+    vector < vector<CAltFreqRegion> > vecRegions; // outer vector indexed by regionID
+    vector < vector<CAltFreqSched> > vecSchedules; // outer vector indexed by scheduleID
+    vector < CMultiplexDefinition > vecMultiplexes;
+    vector < COtherService > vecOtherServices;
+    _BOOLEAN bRegionVersionFlag;
+    _BOOLEAN bScheduleVersionFlag;
+    _BOOLEAN bMultiplexVersionFlag;
+    _BOOLEAN bOtherServicesVersionFlag;
+};
+
+/* Class to store information about the last service selected ------------- */
+
+class CLastService
+{
+public:
+    CLastService():iService(0), iServiceID(SERV_ID_NOT_USED)
+    {
+    }
+    CLastService(const CLastService& l):iService(l.iService), iServiceID(l.iServiceID)
+    {
+    }
+    CLastService& operator=(const CLastService& l)
+    {
+        iService = l.iService;
+        iServiceID = l.iServiceID;
+        return *this;
+    }
+
+    void Reset()
+    {
+        iService = 0;
+        iServiceID = SERV_ID_NOT_USED;
+    };
+
+    void Save(const int iCurSel, const int iCurServiceID)
+    {
+        if (iCurServiceID != SERV_ID_NOT_USED)
+        {
+            iService = iCurSel;
+            iServiceID = iCurServiceID;
+        }
+    };
+
+    /* store only fac parameters */
+    int iService;
+    uint32_t iServiceID;
+};
+
+/* Classes to keep track of status flags for RSCI rsta tag and log file */
+class CRxStatus
+{
+public:
+    CRxStatus():status(NOT_PRESENT),iNum(0),iNumOK(0) {}
+    CRxStatus(const CRxStatus& s):status(s.status),iNum(s.iNum),iNumOK(s.iNumOK) {}
+    CRxStatus& operator=(const CRxStatus& s)
+    {
+        status = s.status;
+        iNum = s.iNum;
+        iNumOK = s.iNumOK;
+        return *this;
+    }
+    void SetStatus(const ETypeRxStatus);
+    ETypeRxStatus GetStatus() {
+        return status;
+    }
+    int GetCount() {
+        return iNum;
+    }
+    int GetOKCount() {
+        return iNumOK;
+    }
+    void ResetCounts() {
+        iNum=0;
+        iNumOK = 0;
+    }
+private:
+    ETypeRxStatus status;
+    int iNum, iNumOK;
+};
+
+class CReceiveStatus
+{
+public:
+    CReceiveStatus():FSync(),TSync(),InterfaceI(),InterfaceO(),
+            FAC(),SDC(),SLAudio(),LLAudio()
+    {
+    }
+    CReceiveStatus(const CReceiveStatus& s):FSync(s.FSync), TSync(s.TSync),
+            InterfaceI(s.InterfaceI), InterfaceO(s.InterfaceO), FAC(s.FAC), SDC(s.SDC),
+            SLAudio(s.SLAudio),LLAudio(s.LLAudio)
+    {
+    }
+    CReceiveStatus& operator=(const CReceiveStatus& s)
+    {
+        FSync = s.FSync;
+        TSync = s.TSync;
+        InterfaceI = s.InterfaceI;
+        InterfaceO = s.InterfaceO;
+        FAC = s.FAC;
+        SDC = s.SDC;
+        SLAudio = s.SLAudio;
+        LLAudio = s.LLAudio;
+        return *this;
+    }
+
+    CRxStatus FSync;
+    CRxStatus TSync;
+    CRxStatus InterfaceI;
+    CRxStatus InterfaceO;
+    CRxStatus FAC;
+    CRxStatus SDC;
+    CRxStatus SLAudio;
+    CRxStatus LLAudio;
+};
+
+
+/* Simulation raw-data management. We have to implement a shift register
+   with varying size. We do that by adding a variable for storing the
+   current write position. */
+class CRawSimData
+{
+    /* We have to implement a shift register with varying size. We do that
+       by adding a variable for storing the current write position. We use
+       always the first value of the array for reading and do a shift of the
+       other data by adding a arbitrary value (0) at the end of the whole
+       shift register */
+public:
+    /* Here, the maximal size of the shift register is set */
+    CRawSimData():ciMaxDelBlocks(50), iCurWritePos(0)
+    {
+        veciShRegSt.Init(ciMaxDelBlocks);
+    }
+
+    void Add(uint32_t iNewSRS);
+    uint32_t Get();
+
+    void Reset()
+    {
+        iCurWritePos = 0;
+    }
+
+protected:
+    /* Max number of delayed blocks */
+    int ciMaxDelBlocks;
+    CShiftRegister < uint32_t > veciShRegSt;
+    int iCurWritePos;
+};
+
+class CFrontEndParameters
+{
+public:
+    enum ESMeterCorrectionType {S_METER_CORRECTION_TYPE_CAL_FACTOR_ONLY, S_METER_CORRECTION_TYPE_AGC_ONLY, S_METER_CORRECTION_TYPE_AGC_RSSI};
+
+    // Constructor
+    CFrontEndParameters():
+            eSMeterCorrectionType(S_METER_CORRECTION_TYPE_CAL_FACTOR_ONLY), rSMeterBandwidth(10000.0),
+            rDefaultMeasurementBandwidth(10000.0), bAutoMeasurementBandwidth(TRUE), rCalFactorAM(0.0),
+            rCalFactorDRM(0.0), rIFCentreFreq(12000.0)
+    {}
+    CFrontEndParameters(const CFrontEndParameters& p):
+            eSMeterCorrectionType(p.eSMeterCorrectionType), rSMeterBandwidth(p.rSMeterBandwidth),
+            rDefaultMeasurementBandwidth(p.rDefaultMeasurementBandwidth),
+            bAutoMeasurementBandwidth(p.bAutoMeasurementBandwidth),
+            rCalFactorAM(p.rCalFactorAM), rCalFactorDRM(p.rCalFactorDRM),
+            rIFCentreFreq(p.rIFCentreFreq)
+    {}
+    CFrontEndParameters& operator=(const CFrontEndParameters& p)
+    {
+        eSMeterCorrectionType = p.eSMeterCorrectionType;
+        rSMeterBandwidth = p.rSMeterBandwidth;
+        rDefaultMeasurementBandwidth = p.rDefaultMeasurementBandwidth;
+        bAutoMeasurementBandwidth = p.bAutoMeasurementBandwidth;
+        rCalFactorAM = p.rCalFactorAM;
+        rCalFactorDRM = p.rCalFactorDRM;
+        rIFCentreFreq = p.rIFCentreFreq;
+        return *this;
+    }
+
+    ESMeterCorrectionType eSMeterCorrectionType;
+    _REAL rSMeterBandwidth; // The bandwidth the S-meter uses to do the measurement
+
+    _REAL rDefaultMeasurementBandwidth; // Bandwidth to do measurement if not synchronised
+    _BOOLEAN bAutoMeasurementBandwidth; // TRUE: use the current FAC bandwidth if locked, FALSE: use default bandwidth always
+    _REAL rCalFactorAM;
+    _REAL rCalFactorDRM;
+    _REAL rIFCentreFreq;
+
+};
+
+
+class CMinMaxMean
+{
+public:
+    CMinMaxMean();
+
+    void addSample(_REAL);
+    _REAL getCurrent();
+    _REAL getMean();
+    void getMinMax(_REAL&, _REAL&);
+protected:
+    _REAL rSum, rCur, rMin, rMax;
+    int iNum;
+};
+
+class CParameter
+{
+public:
+    CParameter();
+    CParameter(const CParameter&);
+    virtual ~CParameter();
+    CParameter& operator=(const CParameter&);
+
+    /* Enumerations --------------------------------------------------------- */
+    /* AS: AFS in SDC is valid or not */
+    enum EAFSVali { AS_VALID, AS_NOT_VALID };
+
+    /* CT: Current Time */
+    enum ECurTime { CT_OFF, CT_LOCAL, CT_UTC, CT_UTC_OFFSET };
+
+    /* ST: Simulation Type */
+    enum ESimType
+    { ST_NONE, ST_BITERROR, ST_MSECHANEST, ST_BER_IDEALCHAN,
+      ST_SYNC_PARAM, ST_SINR
+    };
+
+    /* Misc. Functions ------------------------------------------------------ */
+    void SetReceiver(CDRMReceiver *pDRMReceiver);
+    void GenerateRandomSerialNumber();
+    void GenerateReceiverID();
+    void ResetServicesStreams();
+    void GetActiveServices(set<int>& actServ);
+    void GetActiveStreams(set<int>& actStr);
+    void InitCellMapTable(const ERobMode eNewWaveMode,
+                          const ESpecOcc eNewSpecOcc);
+
+    void SetNumDecodedBitsMSC(const int iNewNumDecodedBitsMSC);
+    void SetNumDecodedBitsSDC(const int iNewNumDecodedBitsSDC);
+    void SetNumBitsHieraFrTot(const int iNewNumBitsHieraFrTot);
+    void SetNumAudioDecoderBits(const int iNewNumAudioDecoderBits);
+    void SetNumDataDecoderBits(const int iNewNumDataDecoderBits);
+
+    _BOOLEAN SetWaveMode(const ERobMode eNewWaveMode);
+    ERobMode GetWaveMode() const {
+        return eRobustnessMode;
+    }
+
+    void SetFrequency(int iNewFrequency) {
+        iFrequency = iNewFrequency;
+    }
+    int GetFrequency() {
+        return iFrequency;
+    }
+
+    void SetServiceParameters(int iShortID, const CService& newService);
+
+    void SetCurSelAudioService(const int iNewService);
+    int GetCurSelAudioService() const {
+        return iCurSelAudioService;
+    }
+    void SetCurSelDataService(const int iNewService);
+    int GetCurSelDataService() const {
+        return iCurSelDataService;
+    }
+
+    void ResetCurSelAudDatServ()
+    {
+        iCurSelAudioService = 0;
+        iCurSelDataService = 0;
+    }
+
+    /*
+       Sample rate related getters/setters
+    */
+    int GetAudSampleRate() const
+    {
+        return iAudSampleRate;
+    }
+    int GetSigSampleRate() const
+    {
+        return iSigSampleRate;
+    }
+    int GetSigUpscaleRatio() const
+    {
+        return iSigUpscaleRatio;
+    }
+    int GetSoundCardSigSampleRate() const
+    {
+        return iSigSampleRate / iSigUpscaleRatio;
+    }
+    void SetSoundCardSigSampleRate(int sr)
+    {
+        iSigSampleRate = sr * iSigUpscaleRatio;
+    }
+    void SetNewAudSampleRate(int sr)
+    {
+        /* Perform range check */
+        if      (sr < 22050)  sr = 22050;
+        else if (sr > 192000) sr = 192000;
+        /* Audio sample rate must be a multiple of 50,
+           set to the nearest multiple of 50,
+           a limitation from buffering system */
+        sr = (sr + 25) / 50 * 50;
+        iNewAudSampleRate = sr;
+    }
+    void SetNewSigSampleRate(int sr)
+    {
+        /* Set to the nearest supported sample rate */
+        if      (sr < 36000)  sr = 24000;
+        else if (sr < 72000)  sr = 48000;
+        else if (sr < 144000) sr = 96000;
+        else                  sr = 192000;
+        iNewSigSampleRate = sr;
+    }
+    void SetNewSigUpscaleRatio(int ratio)
+    {
+        iNewSigUpscaleRatio = ratio < 2 ? 1 : 2;
+    }
+    /* New sample rate are fetched at init and restart */
+    void FetchNewSampleRate()
+    {
+        if (iNewSigUpscaleRatio != 0)
+        {
+            iSigUpscaleRatio = iNewSigUpscaleRatio;
+            iNewSigUpscaleRatio = 0;
+        }
+        if (iNewAudSampleRate != 0)
+        {
+            iAudSampleRate = iNewAudSampleRate;
+            iNewAudSampleRate = 0;
+        }
+        if (iNewSigSampleRate != 0)
+        {
+            iSigSampleRate = iNewSigSampleRate * iSigUpscaleRatio;
+            iNewSigSampleRate = 0;
+        }
+    }
+
+    _REAL GetDCFrequency() const
+    {
+        return iSigSampleRate * (rFreqOffsetAcqui + rFreqOffsetTrack);
+    }
+
+    _REAL GetBitRateKbps(const int iShortID, const _BOOLEAN bAudData) const;
+    _REAL PartABLenRatio(const int iShortID) const;
+
+    /* Parameters controlled by FAC ----------------------------------------- */
+    void SetInterleaverDepth(const ESymIntMod eNewDepth);
+    ESymIntMod GetInterleaverDepth() const
+    {
+        return eSymbolInterlMode;
+    }
+
+    void SetMSCCodingScheme(const ECodScheme eNewScheme);
+    void SetSDCCodingScheme(const ECodScheme eNewScheme);
+
+    void SetSpectrumOccup(ESpecOcc eNewSpecOcc);
+    ESpecOcc GetSpectrumOccup() const
+    {
+        return eSpectOccup;
+    }
+
+    void SetNumOfServices(const size_t iNNumAuSe, const size_t iNNumDaSe);
+    size_t GetTotNumServices() const
+    {
+        return iNumAudioService + iNumDataService;
+    }
+
+    void SetAudDataFlag(const int iShortID, const CService::ETyOServ iNewADaFl);
+    void SetServiceID(const int iShortID, const uint32_t iNewServiceID);
+
+    CDRMReceiver* pDRMRec;
+
+    /* Symbol interleaver mode (long or short interleaving) */
+    ESymIntMod eSymbolInterlMode;
+
+    ECodScheme eMSCCodingScheme;	/* MSC coding scheme */
+    ECodScheme eSDCCodingScheme;	/* SDC coding scheme */
+
+    size_t iNumAudioService;
+    size_t iNumDataService;
+
+    /* AMSS */
+    int iAMSSCarrierMode;
+
+    /* Serial number and received ID */
+    string sReceiverID;
+    string sSerialNumber;
+
+public:
+
+    /* Parameters controlled by SDC ----------------------------------------- */
+    void SetAudioParam(const int iShortID, const CAudioParam& NewAudParam);
+    CAudioParam GetAudioParam(const int iShortID) const;
+    CDataParam GetDataParam(const int iShortID) const;
+    void SetDataParam(const int iShortID, const CDataParam& NewDataParam);
+
+    void SetMSCProtLev(const CMSCProtLev NewMSCPrLe, const _BOOLEAN bWithHierarch);
+    void SetStreamLen(const int iStreamID, const int iNewLenPartA, const int iNewLenPartB);
+    void GetStreamLen(const int iStreamID, int& iLenPartA, int& iLenPartB) const;
+    int GetStreamLen(const int iStreamID) const;
+    ECurTime eTransmitCurrentTime;
+
+    /* Protection levels for MSC */
+    CMSCProtLev MSCPrLe;
+    /* Protection levels for SDC */
+    bool bSDCCodeRateOneQuarter;
+
+    vector<CStream> Stream;
+    vector<CService> Service;
+    vector<CRxStatus> AudioComponentStatus;
+    vector<CRxStatus> DataComponentStatus;
+
+    /* information about services gathered from SDC, EPG and web schedules */
+    map<uint32_t,CServiceInformation> ServiceInformation;
+
+    /* These values are used to set input and output block sizes of some modules */
+    int iNumBitsHierarchFrameTotal;
+    int iNumDecodedBitsMSC;
+    int iNumSDCBitsPerSFrame;	/* Number of SDC bits per super-frame */
+    int iNumFACBitsPerBlock;	/* Number of FAC bits per block 72 for DRM30 120 for DRM+ */
+    int iNumAudioDecoderBits;	/* Number of input bits for audio module */
+    int iNumDataDecoderBits;	/* Number of input bits for data decoder module */
+
+    /* Date */
+    int iYear;
+    int iMonth;
+    int iDay;
+
+    /* UTC (hours and minutes) */
+    int iUTCHour;
+    int iUTCMin;
+    int iUTCOff;
+    int iUTCSense;
+    _BOOLEAN bValidUTCOffsetAndSense;
+
+    /* Identifies the current frame. This parameter is set by FAC */
+    int iFrameIDTransm;
+    int iFrameIDReceiv;
+
+    /* Synchronization ------------------------------------------------------ */
+    _REAL rFreqOffsetAcqui;
+    _REAL rFreqOffsetTrack;
+
+    _REAL rResampleOffset;
+
+    int iTimingOffsTrack;
+
+    ERecMode GetReceiverMode() {
+        return eReceiverMode;
+    }
+    ERecMode eReceiverMode;
+    EAcqStat GetAcquiState() {
+        return eAcquiState;
+    }
+    EAcqStat eAcquiState;
+    int iNumAudioFrames;
+
+    CVector <_BINARY> vecbiAudioFrameStatus;
+    _BOOLEAN bMeasurePSD, bMeasurePSDAlways;
+    _REAL rPIRStart;
+    _REAL rPIREnd;
+
+    /* vector to hold the PSD values for the rpsd tag. */
+    CVector <_REAL> vecrPSD;
+
+    // vector to hold impulse response values for (proposed) rpir tag
+    CVector <_REAL> vecrPIR;
+
+    CMatrix <_COMPLEX> matcReceivedPilotValues;
+
+    /* Simulation ----------------------------------------------------------- */
+    CRawSimData RawSimDa;
+    ESimType eSimType;
+
+    int iDRMChannelNum;
+    int iSpecChDoppler;
+    _REAL rBitErrRate;
+    _REAL rSyncTestParam;		/* For any other simulations, used
+								   with "ST_SYNC_PARAM" type */
+    _REAL rSINR;
+    int iNumBitErrors;
+    int iChanEstDelay;
+
+    int iNumTaps;
+    vector<int> iPathDelay;
+    _REAL rGainCorr;
+    int iOffUsfExtr;
+
+    void SetSNR(const _REAL);
+    _REAL GetSNR();
+    void SetNominalSNRdB(const _REAL rSNRdBNominal);
+    _REAL GetNominalSNRdB();
+    void SetSystemSNRdB(const _REAL rSNRdBSystem)
+    {
+        rSysSimSNRdB = rSNRdBSystem;
+    }
+    _REAL GetSystemSNRdB() const
+    {
+        return rSysSimSNRdB;
+    }
+    _REAL GetSysSNRdBPilPos() const;
+
+    CReceiveStatus ReceiveStatus;
+    CFrontEndParameters FrontEndParameters;
+    CAltFreqSign AltFreqSign;
+
+    void Lock()
+    {
+        Mutex.Lock();
+    }
+    void Unlock()
+    {
+        Mutex.Unlock();
+    }
+    /* Channel Estimation */
+    _REAL rMER;
+    _REAL rWMERMSC;
+    _REAL rWMERFAC;
+    _REAL rSigmaEstimate;
+    _REAL rMinDelay;
+    _REAL rMaxDelay;
+
+    _BOOLEAN bMeasureDelay;
+    CRealVector vecrRdel;
+    CRealVector vecrRdelThresholds;
+    CRealVector vecrRdelIntervals;
+    _BOOLEAN bMeasureDoppler;
+    _REAL rRdop;
+    /* interference (constellation-based measurement rnic)*/
+    _BOOLEAN bMeasureInterference;
+    _REAL rIntFreq, rINR, rICR;
+
+    /* peak of PSD - for PSD-based interference measurement rnip */
+    _REAL rMaxPSDwrtSig;
+    _REAL rMaxPSDFreq;
+
+    /* the signal level as measured at IF by dream */
+    void SetIFSignalLevel(_REAL);
+    _REAL GetIFSignalLevel();
+    _REAL rSigStrengthCorrection;
+
+    /* General -------------------------------------------------------------- */
+    _REAL GetNominalBandwidth();
+    _REAL GetSysToNomBWCorrFact();
+    volatile enum { STOPPED, RUNNING, STOP_REQUESTED, RESTART } eRunState;
+
+    CCellMappingTable CellMappingTable;
+
+    CMinMaxMean SNRstat, SigStrstat;
+
+    string audioencoder, audiodecoder;
+    gps_data_t gps_data;
+    bool use_gpsd;
+    bool restart_gpsd;
+    string gps_host; string gps_port;
+
+protected:
+
+    int iAudSampleRate;
+    int iSigSampleRate;
+    int iSigUpscaleRatio;
+    int iNewAudSampleRate;
+    int iNewSigSampleRate;
+    int iNewSigUpscaleRatio;
+
+    _REAL rSysSimSNRdB;
+
+    int iFrequency;
+    _BOOLEAN bValidSignalStrength;
+    _REAL rSigStr;
+    _REAL rIFSigStr;
+
+    /* Current selected audio service for processing */
+    int iCurSelAudioService;
+    int iCurSelDataService;
+
+    ERobMode eRobustnessMode;	/* E.g.: Mode A, B, C or D */
+    ESpecOcc eSpectOccup;
+
+    /* For resync to last service------------------------------------------- */
+    CLastService LastAudioService;
+    CLastService LastDataService;
+
+    CMutex Mutex;
+public:
+    bool lenient_RSCI;
+};
+
+#endif // !defined(PARAMETER_H__3B0BA660_CA63_4344_BB2B_23E7A0D31912__INCLUDED_)
diff --git a/src/PlotManager.cpp b/src/PlotManager.cpp
new file mode 100644
index 0000000..c9d8cd0
--- /dev/null
+++ b/src/PlotManager.cpp
@@ -0,0 +1,358 @@
+/******************************************************************************\
+ * British Broadcasting Corporation
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer, Andrew Murphy, Andrea Russo, Oliver Haffenden
+ *
+ * Description:
+ *	This class takes care of keeping the history plots as well as interfacing to the
+ *  relevant module in the case of the other plots, including getting data either from
+ *  the RSCI input or the demodulator
+ *
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "PlotManager.h"
+#include "DrmReceiver.h"
+#include <iostream>
+
+CPlotManager::CPlotManager() :
+        pReceiver(0),
+        vecrFreqSyncValHist(LEN_HIST_PLOT_SYNC_PARMS),
+        vecrSamOffsValHist(LEN_HIST_PLOT_SYNC_PARMS),
+        vecrLenIRHist(LEN_HIST_PLOT_SYNC_PARMS),
+        vecrDopplerHist(LEN_HIST_PLOT_SYNC_PARMS),
+        vecrSNRHist(LEN_HIST_PLOT_SYNC_PARMS),
+        veciCDAudHist(LEN_HIST_PLOT_SYNC_PARMS), iSymbolCount(0),
+        rSumDopplerHist((_REAL) 0.0), rSumSNRHist((_REAL) 0.0), iCurrentCDAud(0)
+{
+}
+
+/* Parameter histories for plot --------------------------------------------- */
+
+void CPlotManager::Init()
+{
+    iSymbolCount = 0;
+    rSumDopplerHist = (_REAL) 0.0;
+    rSumSNRHist = (_REAL) 0.0;
+}
+
+void
+CPlotManager::UpdateParamHistories(ERecState eReceiverState)
+{
+    CParameter& Parameters = *pReceiver->GetParameters();
+
+    /* TODO: do not use the shift register class, build a new
+       one which just increments a pointer in a buffer and put
+       the new value at the position of the pointer instead of
+       moving the total data all the time -> special care has
+       to be taken when reading out the data */
+
+    /* Only update histories if the receiver is in tracking mode */
+    if (eReceiverState == RS_TRACKING)
+    {
+        Parameters.Lock();
+        _REAL rFreqOffsetTrack = Parameters.rFreqOffsetTrack;
+        _REAL rResampleOffset = Parameters.rResampleOffset;
+        _REAL rSNR = Parameters.GetSNR();
+        _REAL rSigmaEstimate = Parameters.rSigmaEstimate;
+        _REAL iNumSymPerFrame = Parameters.CellMappingTable.iNumSymPerFrame;
+        _REAL rMeanDelay = (Parameters.rMinDelay +	Parameters.rMaxDelay) / 2.0;
+        Parameters.Unlock();
+
+        MutexHist.Lock();
+
+        /* Frequency offset tracking values */
+        vecrFreqSyncValHist.AddEnd(rFreqOffsetTrack * Parameters.GetSigSampleRate());
+
+        /* Sample rate offset estimation */
+        vecrSamOffsValHist.AddEnd(rResampleOffset);
+        /* Signal to Noise ratio estimates */
+        rSumSNRHist += rSNR;
+
+        /* TODO - reconcile this with Ollies RSCI Doppler code in ChannelEstimation */
+        /* Average Doppler estimate */
+        rSumDopplerHist += rSigmaEstimate;
+
+        /* Only evaluate Doppler and delay once in one DRM frame */
+        iSymbolCount++;
+        if (iSymbolCount == iNumSymPerFrame)
+        {
+            /* Apply averaged values to the history vectors */
+            vecrLenIRHist.AddEnd(rMeanDelay);
+
+            vecrSNRHist.AddEnd(rSumSNRHist / iNumSymPerFrame);
+
+            vecrDopplerHist.AddEnd(rSumDopplerHist / iNumSymPerFrame);
+
+            /* At the same time, add number of correctly decoded audio blocks.
+               This number is updated once a DRM frame. Since the other
+               parameters like SNR is also updated once a DRM frame, the two
+               values are synchronized by one DRM frame */
+            veciCDAudHist.AddEnd(iCurrentCDAud);
+
+            /* Reset parameters used for averaging */
+            iSymbolCount = 0;
+            rSumDopplerHist = (_REAL) 0.0;
+            rSumSNRHist = (_REAL) 0.0;
+        }
+
+        MutexHist.Unlock();
+    }
+}
+
+void
+CPlotManager::UpdateParamHistoriesRSIIn()
+{
+    /* This function is only called once per RSI frame, so process every time */
+
+    CParameter& Parameters = *pReceiver->GetParameters();
+
+    Parameters.Lock();
+    _REAL rDelay = _REAL(0.0);
+    if (Parameters.vecrRdelIntervals.GetSize() > 0)
+        rDelay = Parameters.vecrRdelIntervals[0];
+    _REAL rMER = Parameters.rMER;
+    _REAL rRdop = Parameters.rRdop;
+    Parameters.Unlock();
+
+    MutexHist.Lock();
+
+    /* Apply averaged values to the history vectors */
+    vecrLenIRHist.AddEnd(rDelay);
+    vecrSNRHist.AddEnd(rMER);
+    vecrDopplerHist.AddEnd(rRdop);
+
+    /* At the same time, add number of correctly decoded audio blocks.
+       This number is updated once a DRM frame. Since the other
+       parameters like SNR is also updated once a DRM frame, the two
+       values are synchronized by one DRM frame */
+    veciCDAudHist.AddEnd(iCurrentCDAud);
+    /* Reset parameters used for averaging */
+    iSymbolCount = 0;
+    rSumDopplerHist = (_REAL) 0.0;
+    rSumSNRHist = (_REAL) 0.0;
+
+    MutexHist.Unlock();
+}
+
+void
+CPlotManager::GetFreqSamOffsHist(CVector < _REAL > &vecrFreqOffs,
+                                 CVector < _REAL > &vecrSamOffs,
+                                 CVector < _REAL > &vecrScale,
+                                 _REAL & rFreqAquVal)
+{
+    CParameter& Parameters = *pReceiver->GetParameters();
+
+    Parameters.Lock();
+    /* Duration of OFDM symbol */
+    const _REAL rTs = (CReal) (Parameters.CellMappingTable.iFFTSizeN + Parameters.CellMappingTable.iGuardSize) / Parameters.GetSigSampleRate();
+    /* Value from frequency acquisition */
+    rFreqAquVal = Parameters.rFreqOffsetAcqui * Parameters.GetSigSampleRate();
+    Parameters.Unlock();
+
+    /* Init output vectors */
+    vecrFreqOffs.Init(LEN_HIST_PLOT_SYNC_PARMS, (_REAL) 0.0);
+    vecrSamOffs.Init(LEN_HIST_PLOT_SYNC_PARMS, (_REAL) 0.0);
+    vecrScale.Init(LEN_HIST_PLOT_SYNC_PARMS, (_REAL) 0.0);
+
+    /* Lock resources */
+    MutexHist.Lock();
+
+    /* Simply copy history buffers in output buffers */
+    vecrFreqOffs = vecrFreqSyncValHist;
+    vecrSamOffs = vecrSamOffsValHist;
+
+    /* Calculate time scale */
+    for (int i = 0; i < LEN_HIST_PLOT_SYNC_PARMS; i++)
+        vecrScale[i] = (i - LEN_HIST_PLOT_SYNC_PARMS + 1) * rTs;
+
+    /* Release resources */
+    MutexHist.Unlock();
+}
+
+void
+CPlotManager::GetDopplerDelHist(CVector < _REAL > &vecrLenIR,
+                                CVector < _REAL > &vecrDoppler,
+                                CVector < _REAL > &vecrScale)
+{
+    CParameter& Parameters = *pReceiver->GetParameters();
+
+    /* Init output vectors */
+    vecrLenIR.Init(LEN_HIST_PLOT_SYNC_PARMS, (_REAL) 0.0);
+    vecrDoppler.Init(LEN_HIST_PLOT_SYNC_PARMS, (_REAL) 0.0);
+    vecrScale.Init(LEN_HIST_PLOT_SYNC_PARMS, (_REAL) 0.0);
+
+    Parameters.Lock();
+    /* Duration of DRM frame */
+    const _REAL rDRMFrameDur = (CReal) (Parameters.CellMappingTable.iFFTSizeN
+                                        + Parameters.CellMappingTable.iGuardSize) /
+                               Parameters.GetSigSampleRate() * Parameters.CellMappingTable.iNumSymPerFrame;
+    Parameters.Unlock();
+
+    /* Lock resources */
+    MutexHist.Lock();
+
+    /* Simply copy history buffers in output buffers */
+    vecrLenIR = vecrLenIRHist;
+    vecrDoppler = vecrDopplerHist;
+
+
+    /* Calculate time scale in minutes */
+    for (int i = 0; i < LEN_HIST_PLOT_SYNC_PARMS; i++)
+        vecrScale[i] = (i - LEN_HIST_PLOT_SYNC_PARMS + 1) * rDRMFrameDur / 60;
+
+    /* Release resources */
+    MutexHist.Unlock();
+}
+
+void
+CPlotManager::GetSNRHist(CVector < _REAL > &vecrSNR,
+                         CVector < _REAL > &vecrCDAud,
+                         CVector < _REAL > &vecrScale)
+{
+    CParameter& Parameters = *pReceiver->GetParameters();
+    /* Duration of DRM frame */
+    Parameters.Lock();
+    /* Duration of DRM frame */
+    const _REAL rDRMFrameDur = (CReal) (Parameters.CellMappingTable.iFFTSizeN + Parameters.CellMappingTable.iGuardSize) /
+                               Parameters.GetSigSampleRate() * Parameters.CellMappingTable.iNumSymPerFrame;
+    Parameters.Unlock();
+
+    /* Init output vectors */
+    vecrSNR.Init(LEN_HIST_PLOT_SYNC_PARMS, (_REAL) 0.0);
+    vecrCDAud.Init(LEN_HIST_PLOT_SYNC_PARMS, (_REAL) 0.0);
+    vecrScale.Init(LEN_HIST_PLOT_SYNC_PARMS, (_REAL) 0.0);
+
+    /* Lock resources */
+    MutexHist.Lock();
+
+    /* Simply copy history buffer in output buffer */
+    vecrSNR = vecrSNRHist;
+
+    /* Calculate time scale. Copy correctly decoded audio blocks history (must
+       be transformed from "int" to "real", therefore we need a for-loop */
+    for (int i = 0; i < LEN_HIST_PLOT_SYNC_PARMS; i++)
+    {
+        /* Scale in minutes */
+        vecrScale[i] = (i - LEN_HIST_PLOT_SYNC_PARMS + 1) * rDRMFrameDur / 60;
+
+        /* Correctly decoded audio blocks */
+        vecrCDAud[i] = (_REAL) veciCDAudHist[i];
+    }
+
+    /* Release resources */
+    MutexHist.Unlock();
+}
+
+void
+CPlotManager::GetInputPSD(CVector<_REAL>& vecrData, CVector<_REAL>& vecrScale)
+{
+    CParameter& Parameters = *pReceiver->GetParameters();
+
+    if (pReceiver->GetRSIIn()->GetInEnabled())
+    {
+        // read it from the parameter structure
+        Parameters.Lock();
+        CVector<_REAL>& vecrPSD = Parameters.vecrPSD;
+        Parameters.Unlock();
+
+        int iVectorLen = vecrPSD.Size();
+        vecrData.Init(iVectorLen);
+        vecrScale.Init(iVectorLen);
+
+        // starting frequency and frequency step as defined in TS 102 349
+        // plot expects the scale values in kHz
+        _REAL f = _REAL(-7.875) + VIRTUAL_INTERMED_FREQ/_REAL(1000.0);
+        const _REAL fstep =_REAL(0.1875);
+
+        for (int i=0; i<iVectorLen; i++)
+        {
+            vecrData[i] = vecrPSD[i];
+            vecrScale[i] = f;
+            f += fstep;
+        }
+
+    }
+    else
+    {
+        pReceiver->GetReceiveData()->GetInputPSD(vecrData, vecrScale);
+    }
+}
+
+void CPlotManager::GetTransferFunction(CVector<_REAL>& vecrData,
+                                       CVector<_REAL>& vecrGrpDly,	CVector<_REAL>& vecrScale)
+{
+    pReceiver->GetChannelEstimation()->GetTransferFunction(vecrData, vecrGrpDly, vecrScale);
+}
+
+
+void CPlotManager::GetAvPoDeSp(CVector<_REAL>& vecrData, CVector<_REAL>& vecrScale,
+                               _REAL& rLowerBound, _REAL& rHigherBound,
+                               _REAL& rStartGuard, _REAL& rEndGuard, _REAL& rPDSBegin,
+                               _REAL& rPDSEnd)
+{
+    CParameter& Parameters = *pReceiver->GetParameters();
+
+    if (pReceiver->GetRSIIn()->GetInEnabled())
+    {
+        // read it from the parameter structure
+        Parameters.Lock();
+        CVector<_REAL>& vecrPIR = Parameters.vecrPIR;
+        _REAL rPIRStart = Parameters.rPIRStart;
+        _REAL rPIREnd = Parameters.rPIREnd;
+        Parameters.Unlock();
+
+        int iVectorLen = vecrPIR.Size();
+        vecrData.Init(iVectorLen);
+        vecrScale.Init(iVectorLen);
+
+        // starting frequency and frequency step as defined in TS 102 349
+        // plot expects the scale values in kHz
+        _REAL t = rPIRStart;
+        const _REAL tstep = (rPIREnd-rPIRStart)/(_REAL(iVectorLen)-1);
+
+        for (int i=0; i<iVectorLen; i++)
+        {
+            vecrData[i] = vecrPIR[i];
+            vecrScale[i] = t;
+            t += tstep;
+        }
+
+        rLowerBound = _REAL(0);
+        rHigherBound = _REAL(0);
+        rStartGuard = _REAL(0);
+        rEndGuard = _REAL(0);
+        rPDSBegin = _REAL(0);
+        rPDSEnd = _REAL(0);
+
+    }
+    else
+    {
+        pReceiver->GetChannelEstimation()->GetAvPoDeSp(vecrData, vecrScale, rLowerBound, rHigherBound,
+                rStartGuard, rEndGuard, rPDSBegin, rPDSEnd);
+    }
+}
+
+void CPlotManager::GetSNRProfile(CVector<_REAL>& vecrData, CVector<_REAL>& vecrScale)
+{
+    pReceiver->GetChannelEstimation()->GetSNRProfile(vecrData, vecrScale);
+}
+
diff --git a/src/PlotManager.h b/src/PlotManager.h
new file mode 100644
index 0000000..87fc8db
--- /dev/null
+++ b/src/PlotManager.h
@@ -0,0 +1,108 @@
+/******************************************************************************\
+ * British Broadcasting Corporation
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer, Andrew Murphy, Andrea Russo, Oliver Haffenden
+ *
+ * Description:
+ *	See PlotManager.cpp
+ *
+ *
+ *
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#if !defined(PLOT_MANAGER_H_INCLUDED)
+#define PLOT_MANAGER_H_INCLUDED
+
+#include "GlobalDefinitions.h"
+#include "Parameter.h"
+
+/* Definitions ****************************************************************/
+
+/* Length of the history for synchronization parameters (used for the plot) */
+#define LEN_HIST_PLOT_SYNC_PARMS		2250
+
+
+
+class CPlotManager
+{
+public:
+
+    CPlotManager();
+
+    void SetReceiver(CDRMReceiver *pRx) {
+        pReceiver = pRx;
+    }
+
+    void Init();
+
+    void SetCurrentCDAud(int iN) {
+        iCurrentCDAud = iN;
+    }
+
+    void UpdateParamHistories(ERecState eReceiverState);
+
+    void UpdateParamHistoriesRSIIn();
+
+    void GetTransferFunction(CVector<_REAL>& vecrData,
+                             CVector<_REAL>& vecrGrpDly,	CVector<_REAL>& vecrScale);
+
+    void GetAvPoDeSp(CVector<_REAL>& vecrData, CVector<_REAL>& vecrScale,
+                     _REAL& rLowerBound, _REAL& rHigherBound,
+                     _REAL& rStartGuard, _REAL& rEndGuard, _REAL& rPDSBegin,
+                     _REAL& rPDSEnd);
+
+    void GetSNRProfile(CVector<_REAL>& vecrData, CVector<_REAL>& vecrScale);
+
+    void GetInputPSD(CVector<_REAL>& vecrData, CVector<_REAL>& vecrScale);
+
+    /* Interfaces to internal parameters/vectors used for the plot */
+    void GetFreqSamOffsHist(CVector<_REAL>& vecrFreqOffs,
+                            CVector<_REAL>& vecrSamOffs, CVector<_REAL>& vecrScale,
+                            _REAL& rFreqAquVal);
+
+    void GetDopplerDelHist(CVector<_REAL>& vecrLenIR,
+                           CVector<_REAL>& vecrDoppler, CVector<_REAL>& vecrScale);
+
+    void GetSNRHist(CVector<_REAL>& vecrSNR, CVector<_REAL>& vecrCDAud,
+                    CVector<_REAL>& vecrScale);
+
+
+
+
+private:
+    CDRMReceiver			*pReceiver;
+    /* Storing parameters for plot */
+    CShiftRegister<_REAL>	vecrFreqSyncValHist;
+    CShiftRegister<_REAL>	vecrSamOffsValHist;
+    CShiftRegister<_REAL>	vecrLenIRHist;
+    CShiftRegister<_REAL>	vecrDopplerHist;
+    CShiftRegister<_REAL>	vecrSNRHist;
+    CShiftRegister<int>		veciCDAudHist;
+    int						iSymbolCount;
+    _REAL					rSumDopplerHist;
+    _REAL					rSumSNRHist;
+    int						iCurrentCDAud;
+    CMutex					MutexHist;
+
+};
+
+#endif
diff --git a/src/ReceptLog.cpp b/src/ReceptLog.cpp
new file mode 100644
index 0000000..9fbcdda
--- /dev/null
+++ b/src/ReceptLog.cpp
@@ -0,0 +1,526 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer, Andrew Murphy, Julian Cable
+ *
+ * Description:
+ *	see ReceptLog.h
+ *
+ ******************************************************************************
+ *
+ * This program is free software(), you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation(), either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY(), without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program(), if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "Version.h"
+#include "ReceptLog.h"
+#include <iomanip>
+#include <iostream>
+
+/* implementation --------------------------------------------- */
+
+CReceptLog::CReceptLog(CParameter & p):Parameters(p), File(), bLogActivated(FALSE),
+    bRxlEnabled(FALSE), bPositionEnabled(FALSE),
+    iSecDelLogStart(0)
+{
+    iFrequency = Parameters.GetFrequency();
+    latitude = Parameters.gps_data.fix.latitude;
+    longitude = Parameters.gps_data.fix.longitude;
+}
+
+void
+CReceptLog::Start(const string & filename)
+{
+    File.open(filename.c_str(), ios::app);
+    if (File.is_open())
+    {
+        bLogActivated = TRUE;
+        writeHeader();
+    }
+    init();
+}
+
+void
+CReceptLog::Stop()
+{
+    if (!bLogActivated)
+        return;
+    writeTrailer();
+    File.close();
+    bLogActivated = FALSE;
+}
+
+void
+CReceptLog::Update()
+{
+    if (!bLogActivated)
+        return;
+    writeParameters();
+}
+
+bool CReceptLog::restartNeeded()
+{
+    int iCurrentFrequency = Parameters.GetFrequency();
+    double currentLatitude = Parameters.gps_data.fix.latitude;
+    double currentLongitude = Parameters.gps_data.fix.longitude;
+    if((iCurrentFrequency != iFrequency)
+            || (bPositionEnabled && int(currentLatitude) != int(latitude))
+            || (bPositionEnabled && int(currentLongitude) != int(longitude))
+      )
+    {
+        iFrequency = iCurrentFrequency;
+        latitude = currentLatitude;
+        longitude = currentLongitude;
+        return true;
+    }
+    return false;
+}
+
+/* Get robustness mode string */
+char
+CReceptLog::GetRobModeStr()
+{
+    char chRobMode = 'X';
+    switch (Parameters.GetWaveMode())
+    {
+    case RM_ROBUSTNESS_MODE_A:
+        chRobMode = 'A';
+        break;
+
+    case RM_ROBUSTNESS_MODE_B:
+        chRobMode = 'B';
+        break;
+
+    case RM_ROBUSTNESS_MODE_C:
+        chRobMode = 'C';
+        break;
+
+    case RM_ROBUSTNESS_MODE_D:
+        chRobMode = 'D';
+        break;
+
+    case RM_ROBUSTNESS_MODE_E:
+        chRobMode = 'E';
+        break;
+
+    case RM_NO_MODE_DETECTED:
+        chRobMode = 'X';
+        break;
+    }
+    return chRobMode;
+}
+
+void
+CShortLog::init()
+{
+    Parameters.Lock();
+    Parameters.ReceiveStatus.FAC.ResetCounts();
+    Parameters.ReceiveStatus.SLAudio.ResetCounts();
+    Parameters.Unlock();
+    /* initialise the minute count */
+    iCount = 0;
+}
+
+void
+CShortLog::writeHeader()
+{
+    string latitude, longitude, label, RobMode;
+    ESpecOcc SpecOcc=SO_5;
+    _REAL bitrate = 0.0;
+
+    Parameters.Lock();
+    iFrequency = Parameters.GetFrequency();
+
+    if (Parameters.gps_data.set & LATLON_SET)
+    {
+        asDM(latitude, Parameters.gps_data.fix.latitude, 'S', 'N');
+        asDM(longitude, Parameters.gps_data.fix.longitude, 'W', 'E');
+    }
+    int iCurSelServ = Parameters.GetCurSelAudioService();
+
+    if (Parameters.Service[iCurSelServ].IsActive())
+    {
+        /* Service label (UTF-8 encoded string -> convert ? TODO locale) */
+        label = Parameters.Service[iCurSelServ].strLabel;
+        bitrate = Parameters.GetBitRateKbps(iCurSelServ, FALSE);
+        RobMode = GetRobModeStr();
+        SpecOcc = Parameters.GetSpectrumOccup();
+    }
+
+    Parameters.Unlock();
+
+    if (!File.is_open())
+        return; /* allow updates when file closed */
+
+    /* Beginning of new table (similar to DW DRM log file) */
+    File << endl << ">>>>" << endl << "Dream" << endl << "Software Version ";
+    if (dream_version_patch == 0)
+        File << dream_version_major << "." << dream_version_minor << dream_version_build << endl;
+    else
+        File << dream_version_major << "." << dream_version_minor << "." << dream_version_patch << dream_version_build << endl;
+
+    time_t now;
+    (void) time(&now);
+    File << "Starttime (UTC)  " << strdate(now) << " " << strtime(now) << endl;
+
+    File << "Frequency        ";
+    if (iFrequency != 0)
+        File << iFrequency << " kHz";
+    File << endl;
+
+    if (latitude != "")
+    {
+        File << "Latitude         " << latitude << endl;
+        File << "Longitude        " << longitude << endl;
+    }
+
+    /* Write additional text */
+
+    /* First get current selected audio service */
+
+    /* Check whether service parameters were not transmitted yet */
+    if (RobMode != "")
+    {
+        /* Service label (UTF-8 encoded string -> convert ? TODO locale) */
+        File << fixed << setprecision(2);
+        File << "Label            " << label << endl;
+        File << "Bitrate          " << setw(4) << bitrate << " kbps" << endl;
+        File << "Mode             " << RobMode << endl;
+        File << "Bandwidth        ";
+        switch (SpecOcc)
+        {
+        case SO_0:
+            File << "4,5 kHz";
+            break;
+
+        case SO_1:
+            File << "5 kHz";
+            break;
+
+        case SO_2:
+            File << "9 kHz";
+            break;
+
+        case SO_3:
+            File << "10 kHz";
+            break;
+
+        case SO_4:
+            File << "18 kHz";
+            break;
+
+        case SO_5:
+            File << "20 kHz";
+            break;
+
+        default:
+            File << "10 kHz";
+        }
+        File << endl;
+    }
+
+    File << endl << "MINUTE  SNR     SYNC    AUDIO     TYPE";
+    if (bRxlEnabled)
+        File << "      RXL";
+    File << endl;
+
+    iCount = 0; // start count each time a new header is put
+}
+
+void
+CShortLog::writeParameters()
+{
+    Parameters.Lock();
+
+    int iAverageSNR = (int) Round(Parameters.SNRstat.getMean());
+    int iNumCRCOkFAC = Parameters.ReceiveStatus.FAC.GetOKCount();
+    int iNumCRCOkMSC = Parameters.ReceiveStatus.SLAudio.GetOKCount();
+
+    Parameters.ReceiveStatus.FAC.ResetCounts();
+    Parameters.ReceiveStatus.SLAudio.ResetCounts();
+
+    int iTmpNumAAC=0, iRXL=0;
+
+    /* If no sync, do not print number of AAC frames.
+     * If the number of correct FAC CRCs is lower than 10%,
+     * we assume that receiver is not synchronized */
+    if (iNumCRCOkFAC >= 15)
+        iTmpNumAAC = Parameters.iNumAudioFrames;
+
+    if (bRxlEnabled)
+        iRXL = (int)Round(Parameters.SigStrstat.getMean()+S9_DBUV);
+
+    Parameters.Unlock();
+
+    int count = iCount++;
+
+    if (!File.is_open())
+        return; /* allow updates when file closed */
+
+    try
+    {
+        File << "  " << fixed << setw(4) << setfill('0') << count
+             << setfill(' ') << setw(5) << iAverageSNR
+             << setw(9) << iNumCRCOkFAC
+             << setw(6) << iNumCRCOkMSC << "/" << setw(2) << setfill('0') << iTmpNumAAC
+             << setfill(' ') << "      0";
+        if (bRxlEnabled)
+        {
+            File << setw(10) << setprecision(2) << iRXL;
+        }
+        File << endl;
+        File.flush();
+    }
+    catch (...)
+    {
+        /* To prevent errors if user views the file during reception */
+    }
+}
+
+void
+CShortLog::writeTrailer()
+{
+
+    _REAL rMaxSNR, rMinSNR;
+    _REAL rMaxSigStr=0.0, rMinSigStr=0.0;
+
+    Parameters.Lock();
+    Parameters.SNRstat.getMinMax(rMinSNR, rMaxSNR);
+    if (bRxlEnabled)
+    {
+        Parameters.SigStrstat.getMinMax(rMinSigStr, rMaxSigStr);
+        rMinSigStr+=S9_DBUV;
+        rMaxSigStr+=S9_DBUV;
+    }
+    Parameters.Unlock();
+
+    if (!File.is_open())
+        return; /* allow updates when file closed */
+
+    File << fixed << setprecision(1);
+    File << endl << "SNR min: " << setw(4) << rMinSNR << ", max: " << setw(4) << rMaxSNR << endl;
+
+    if (bRxlEnabled)
+    {
+        File << "RXL min: " << setw(4) << rMinSigStr << ", max: " << setw(4) << rMaxSigStr << endl;
+    }
+
+    /* Short log file ending */
+    File << "CRC: " << endl << "<<<<" << endl << endl;
+}
+
+void
+CLongLog::writeHeader()
+{
+    if (!File.is_open())
+        return; /* allow updates when file closed */
+
+    File <<
+         "FREQ/MODE/QAM PL:ABH,       DATE,       TIME,    SNR, SYNC, FAC, MSC, AUDIO, AUDIOOK, DOPPLER, DELAY";
+    if (bRxlEnabled)
+        File << ",     RXL";
+    if (bPositionEnabled)
+        File << ",  LATITUDE, LONGITUDE";
+#ifdef _DEBUG_
+    /* In case of debug mode, use more parameters */
+    File << ",    DC-FREQ, SAMRATEOFFS";
+#endif
+    File << endl;
+}
+
+void
+CLongLog::init()
+{
+    Parameters.Lock();
+    Parameters.ReceiveStatus.LLAudio.ResetCounts();
+    Parameters.Unlock();
+}
+
+void
+CLongLog::writeParameters()
+{
+
+    Parameters.Lock();
+    iFrequency = Parameters.GetFrequency();
+
+    /* Get parameters for delay and Doppler. In case the receiver is
+       not synchronized, set parameters to zero */
+    _REAL rDelay = (_REAL) 0.0;
+    _REAL rDoppler = (_REAL) 0.0;
+    if (Parameters.GetAcquiState() == AS_WITH_SIGNAL)
+    {
+        rDelay = Parameters.rMinDelay;
+        rDoppler = Parameters.rSigmaEstimate;
+    }
+
+    /* Only show mode if FAC CRC was ok */
+    int iCurProtLevPartA = 0;
+    int iCurProtLevPartB = 0;
+    int iCurProtLevPartH = 0;
+    int iCurMSCSc = 0;
+
+    if (Parameters.ReceiveStatus.FAC.GetStatus() == RX_OK)
+    {
+        /* Copy protection levels */
+        iCurProtLevPartA = Parameters.MSCPrLe.iPartA;
+        iCurProtLevPartB = Parameters.MSCPrLe.iPartB;
+        iCurProtLevPartH = Parameters.MSCPrLe.iHierarch;
+        switch (Parameters.eMSCCodingScheme)
+        {
+        case CS_3_SM:
+            iCurMSCSc = 0;
+            break;
+
+        case CS_3_HMMIX:
+            iCurMSCSc = 1;
+            break;
+
+        case CS_3_HMSYM:
+            iCurMSCSc = 2;
+            break;
+
+        case CS_2_SM:
+            iCurMSCSc = 3;
+            break;
+
+        case CS_1_SM:			/* TODO */
+            break;
+        }
+    }
+
+    char cRobMode = GetRobModeStr();
+
+    _REAL rSNR = Parameters.SNRstat.getCurrent();
+    int iFrameSyncStatus = (Parameters.ReceiveStatus.FSync.GetStatus()==RX_OK)?1:0;
+    int iFACStatus = (Parameters.ReceiveStatus.FAC.GetStatus()==RX_OK)?1:0;
+    int iAudioStatus = (Parameters.ReceiveStatus.LLAudio.GetStatus()==RX_OK)?1:0;
+    int iNumCRCMSC = Parameters.ReceiveStatus.LLAudio.GetCount();
+    int iNumCRCOkMSC = Parameters.ReceiveStatus.LLAudio.GetOKCount();
+
+    Parameters.ReceiveStatus.LLAudio.ResetCounts();
+
+    double latitude=0.0, longitude=0.0;
+    if (bPositionEnabled && (Parameters.gps_data.set & LATLON_SET))
+    {
+        latitude = Parameters.gps_data.fix.latitude;
+        longitude = Parameters.gps_data.fix.longitude;
+    }
+
+    Parameters.Unlock();
+
+    if (!File.is_open())
+        return; /* allow updates when file closed */
+
+    try
+    {
+        time_t now;
+        (void) time(&now);
+        File << fixed << setprecision(2)
+             << setw(5) << iFrequency << '/' << setw(1) << cRobMode
+             << iCurMSCSc << iCurProtLevPartA << iCurProtLevPartB << iCurProtLevPartH << "         ,"
+             << " " << strdate(now) << ", "
+             << strtime(now) << ".0" << ","
+             << setw(7) << rSNR << ","
+             << setw(5) << iFrameSyncStatus << ","
+             << setw(4) << iFACStatus << ","
+             << setw(4) << iAudioStatus << ","
+             << setw(6) << iNumCRCMSC << ","
+             << setw(8) << iNumCRCOkMSC << ","
+             << "  " << setw(6) << rDoppler << ','
+             << setw(6) << rDelay;
+
+        if (bRxlEnabled)
+            File << ',' << setprecision(2) << setw(8) << Parameters.SigStrstat.getCurrent()+S9_DBUV;
+
+        if (bPositionEnabled)
+            File << ',' << setprecision(4) << setw(10) << latitude << ',' << setw(10) << longitude;
+
+#ifdef _DEBUG_
+        /* Some more parameters in debug mode */
+        Parameters.Lock();
+        File << Parameters.GetDCFrequency() << ',' << Parameters.GetSampFreqEst();
+        Parameters.Unlock();
+#endif
+        File << endl;
+        File.flush();
+    }
+
+    catch (...)
+    {
+        /* To prevent errors if user views the file during reception */
+    }
+
+}
+
+void
+CLongLog::writeTrailer()
+{
+    if (!File.is_open())
+        return; /* allow updates when file closed */
+
+    File << endl << endl;
+}
+
+string CReceptLog::strdate(time_t t)
+{
+    struct tm * today;
+    stringstream s;
+
+    today = gmtime(&t);		/* Always UTC */
+
+    s << setfill('0')
+      << setw(4) << today->tm_year + 1900 << "-"
+      << setw(2) << today->tm_mon + 1 << "-" << setw(2) << today->tm_mday;
+    return s.str();
+}
+
+string CReceptLog::strtime(time_t t)
+{
+    struct tm * today;
+    stringstream s;
+
+    today = gmtime(&t);		/* Always UTC */
+
+    s << setfill('0')
+      << setw(2) << today->tm_hour << ":" << setw(2) << today-> tm_min << ":" << setw(2) << today->tm_sec;
+    return s.str();
+}
+
+void
+CReceptLog::asDM(string& pos, double d, char n, char p) const
+{
+    stringstream s;
+    char np;
+    int ideg;
+    double dmin;
+    if (d<0.0)
+    {
+        np = n;
+        ideg = 0 - int(d);
+        dmin = 0.0 - d;
+    }
+    else
+    {
+        np = p;
+        ideg = int(d);
+        dmin = d;
+    }
+    int degrees = (unsigned int) dmin;
+    uint16_t minutes = (unsigned int) (((floor((dmin - degrees) * 1000000) / 1000000) + 0.00005) * 60.0);
+    s << ideg << '\xb0' << setw(2) << setfill('0') << minutes << "'" << np;
+    pos = s.str();
+}
diff --git a/src/ReceptLog.h b/src/ReceptLog.h
new file mode 100644
index 0000000..b81e838
--- /dev/null
+++ b/src/ReceptLog.h
@@ -0,0 +1,118 @@
+/******************************************************************************\
+* Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+* Copyright (c) 2001-2001-2014
+*
+* Author(s):
+* Volker Fischer, Andrew Murphy, Andrea Russo
+*
+* Description:
+* Logging to a file
+*
+*******************************************************************************
+*
+* This program is free software; you can redistribute it and/or modify it under
+* the terms of the GNU General Public License as published by the Free Software
+* Foundation; either version 2 of the License, or (at your option) any later
+* version.
+*
+* This program is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+* details.
+*
+* You should have received a copy of the GNU General Public License along with
+* this program; if not, write to the Free Software Foundation, Inc.,
+* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*
+\******************************************************************************/
+
+#ifndef _RECEPTLOG_H
+#define _RECEPTLOG_H
+
+#include "Parameter.h"
+#include <fstream>
+
+class CReceptLog
+{
+public:
+    CReceptLog(CParameter & p);
+    virtual ~CReceptLog()
+    {
+    }
+    void Start(const string & filename);
+    void Stop();
+    void Update();
+    bool restartNeeded();
+
+    void SetRxlEnabled(const _BOOLEAN b) {
+        bRxlEnabled = b;
+    }
+    _BOOLEAN GetRxlEnabled() {
+        return bRxlEnabled;
+    }
+
+    void SetPositionEnabled(const _BOOLEAN b) {
+        bPositionEnabled = b;
+    }
+    _BOOLEAN GetPositionEnabled() {
+        return bPositionEnabled;
+    }
+    _BOOLEAN GetLoggingActivated() {
+        return bLogActivated;
+    }
+
+    void SetDelLogStart(const int iSecDel) {
+        iSecDelLogStart = iSecDel;
+    }
+
+    int GetDelLogStart() {
+        return iSecDelLogStart;
+    }
+
+protected:
+    virtual void init() = 0;
+    virtual void writeParameters() = 0;
+    virtual void writeHeader() = 0;
+    virtual void writeTrailer() = 0;
+    char GetRobModeStr();
+    void asDM(string& pos, double d, char n, char p) const;
+
+
+    string strdate(time_t);
+    string strtime(time_t);
+
+    CParameter & Parameters;
+    ofstream File;
+    _BOOLEAN bLogActivated;
+    _BOOLEAN bLogEnabled;
+    _BOOLEAN bRxlEnabled;
+    _BOOLEAN bPositionEnabled;
+    int iSecDelLogStart;
+    int iFrequency;
+    double latitude,longitude;
+};
+
+class CShortLog: public CReceptLog
+{
+public:
+    CShortLog(CParameter& p):CReceptLog(p) {}
+protected:
+    virtual void init();
+    virtual void writeParameters();
+    virtual void writeHeader();
+    virtual void writeTrailer();
+    int iCount;
+};
+
+class CLongLog: public CReceptLog
+{
+public:
+    CLongLog(CParameter& p):CReceptLog(p) {}
+protected:
+    virtual void init();
+    virtual void writeParameters();
+    virtual void writeHeader();
+    virtual void writeTrailer();
+};
+
+#endif
diff --git a/src/SDC/SDC.h b/src/SDC/SDC.h
new file mode 100644
index 0000000..ff57a01
--- /dev/null
+++ b/src/SDC/SDC.h
@@ -0,0 +1,129 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer, Andrew Murphy, David Flamand
+ *
+ * Description:
+ *	See SDC.cpp
+ *
+ * 11/30/2001-2014 David Flamand, added transmit data entity type 8
+ *
+ * 11/21/2005 Andrew Murphy, BBC Research & Development, 2005
+ *	- AMSS data entity groups (no AFS index), added eSDCType, data type 11
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#if !defined(SDC_H__3B0BA660_CA63SDBOJKEWROBNER89NE877A0D312__INCLUDED_)
+#define SDC_H__3B0BA660_CA63SDBOJKEWROBNER89NE877A0D312__INCLUDED_
+
+#include "../GlobalDefinitions.h"
+#include "../Parameter.h"
+#include "../util/CRC.h"
+#include "../util/Vector.h"
+#include "../util/Utilities.h"
+
+/* Definitions ****************************************************************/
+/* Number of bits of header of SDC block */
+#define NUM_BITS_HEADER_SDC			12
+
+
+/* Classes ********************************************************************/
+class CSDCTransmit
+{
+public:
+    CSDCTransmit() {}
+    virtual ~CSDCTransmit() {}
+
+    void SDCParam(CVector<_BINARY>* pbiData, CParameter& Parameter);
+
+protected:
+    void CommitEnter(CVector<_BINARY>* pbiData, CParameter& Parameter);
+    void CommitFlush();
+    void CommitLeave();
+
+    _BOOLEAN CanTransmitCurrentTime(CParameter& Parameter);
+
+    void DataEntityType0(CVector<_BINARY>& vecbiData, CParameter& Parameter);
+    void DataEntityType1(CVector<_BINARY>& vecbiData, int ServiceID,
+                         CParameter& Parameter);
+// ...
+    void DataEntityType5(CVector<_BINARY>& vecbiData, int ServiceID,
+                         CParameter& Parameter);
+// ...
+    void DataEntityType8(CVector<_BINARY>& vecbiData, int ServiceID,
+                         CParameter& Parameter);
+    void DataEntityType9(CVector<_BINARY>& vecbiData, int ServiceID,
+                         CParameter& Parameter);
+
+    CCRC CRCObject;
+    CVector<_BINARY>* pbiData;
+    CVector<_BINARY> vecbiData;
+    int iNumUsedBits;
+    int iMaxNumBitsDataBlocks;
+    int iLengthDataFieldBytes;
+    int iUsefulBitsSDC;
+    int iLastMinuteTransmitted;
+};
+
+class CSDCReceive
+{
+public:
+    enum ERetStatus {SR_OK, SR_BAD_CRC, SR_BAD_DATA};
+    enum ESDCType {SDC_DRM, SDC_AMSS};
+    CSDCReceive() : eSDCType(SDC_DRM) {}
+    virtual ~CSDCReceive() {}
+
+    ERetStatus SDCParam(CVector<_BINARY>* pbiData, CParameter& Parameter);
+    void SetSDCType(ESDCType sdcType) {
+        eSDCType = sdcType;
+    }
+
+protected:
+    _BOOLEAN DataEntityType0(CVector<_BINARY>* pbiData, const int iLengthOfBody,
+                             CParameter& Parameter, const _BOOLEAN bVersion);
+    _BOOLEAN DataEntityType1(CVector<_BINARY>* pbiData, const int iLengthOfBody,
+                             CParameter& Parameter);
+// ...
+    _BOOLEAN DataEntityType3(CVector<_BINARY>* pbiData, const int iLengthOfBody,
+                             CParameter& Parameter, const _BOOLEAN bVersion);
+    _BOOLEAN DataEntityType4(CVector<_BINARY>* pbiData, const int iLengthOfBody,
+                             CParameter& Parameter, const _BOOLEAN bVersion);
+    _BOOLEAN DataEntityType5(CVector<_BINARY>* pbiData, const int iLengthOfBody,
+                             CParameter& Parameter, const _BOOLEAN bVersion);
+// ...
+    _BOOLEAN DataEntityType7(CVector<_BINARY>* pbiData, const int iLengthOfBody,
+                             CParameter& Parameter, const _BOOLEAN bVersion);
+    _BOOLEAN DataEntityType8(CVector<_BINARY>* pbiData, const int iLengthOfBody,
+                             CParameter& Parameter);
+    _BOOLEAN DataEntityType9(CVector<_BINARY>* pbiData, const int iLengthOfBody,
+                             CParameter& Parameter, const _BOOLEAN bVersion);
+// ...
+    _BOOLEAN DataEntityType11(CVector<_BINARY>* pbiData, const int iLengthOfBody,
+                              CParameter& Parameter, const _BOOLEAN bVersion);
+    _BOOLEAN DataEntityType12(CVector<_BINARY>* pbiData, const int iLengthOfBody,
+                              CParameter& Parameter);
+
+    CCRC		CRCObject;
+    ESDCType	eSDCType;
+};
+
+
+#endif // !defined(SDC_H__3B0BA660_CA63SDBOJKEWROBNER89NE877A0D312__INCLUDED_)
diff --git a/src/SDC/SDCReceive.cpp b/src/SDC/SDCReceive.cpp
new file mode 100644
index 0000000..3df173e
--- /dev/null
+++ b/src/SDC/SDCReceive.cpp
@@ -0,0 +1,1388 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer, Andrew Murphy
+ *
+ * Description:
+ *	SDC data stream decoding (receiver)
+ *
+ *
+ * 11/21/2005 Andrew Murphy, BBC Research & Development, 2005
+ *	- AMSS data entity groups (no AFS index), added eSDCType, data type 11
+ *
+ * 11/28/2005 Andrea Russo
+ *	- Added code for store alternative frequencies informations about Regions
+ *      and Schedules.
+ *
+ ******************************************************************************
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "SDC.h"
+
+
+/* Implementation *************************************************************/
+CSDCReceive::ERetStatus CSDCReceive::SDCParam(CVector<_BINARY>* pbiData,
+        CParameter& Parameter)
+{
+    /* Calculate length of data field in bytes
+       (consistant to table 61 in (6.4.1)) */
+    int iLengthDataFieldBytes;
+    int iUsefulBitsSDC;
+    int iNumBytesForCRCCheck;
+    int iBitsConsumed;
+
+    Parameter.Lock();
+    if (eSDCType == SDC_DRM)
+    {
+        iLengthDataFieldBytes =
+            (int) ((_REAL) (Parameter.iNumSDCBitsPerSFrame - 20) / 8);
+
+        /* 20 bits from AFS index and CRC */
+        iUsefulBitsSDC= 20 + iLengthDataFieldBytes * 8;
+    }
+    else	// SDC_AMSS
+    {
+        iLengthDataFieldBytes =
+            (int) ((_REAL) (Parameter.iNumSDCBitsPerSFrame - 16) / 8);
+
+        /* 16 bits from CRC */
+        iUsefulBitsSDC = 16 + iLengthDataFieldBytes * 8;
+    }
+    Parameter.Unlock();
+
+    /* CRC ------------------------------------------------------------------ */
+    /* Check the CRC of this data block */
+    CRCObject.Reset(16);
+
+    (*pbiData).ResetBitAccess();
+
+    /* Special treatment of SDC data stream: The CRC (Cyclic Redundancy
+    Check) field shall contain a 16-bit CRC calculated over the AFS
+    index coded in an 8-bit field (4 msbs are 0) and the data field.
+    4 MSBs from AFS-index. Insert four "0" in the data-stream */
+    if (eSDCType == SDC_DRM) /* Skip for AMSS */
+    {
+        const _BYTE byFirstByte = (_BYTE) (*pbiData).Separate(4);
+        CRCObject.AddByte(byFirstByte);
+    }
+
+    if (eSDCType == SDC_DRM)
+    {
+        /* "- 4": Four bits already used, "/ SIZEOF__BYTE": We add bytes, not
+           bits, "- 2": 16 bits for CRC at the end */
+        iNumBytesForCRCCheck = (iUsefulBitsSDC - 4) / SIZEOF__BYTE - 2;
+    }
+    else
+    {
+        /* Consider 2 bytes for CRC ("- 2") */
+        iNumBytesForCRCCheck = iUsefulBitsSDC / SIZEOF__BYTE - 2;
+    }
+
+    for (int i = 0; i < iNumBytesForCRCCheck; i++)
+        CRCObject.AddByte((_BYTE) (*pbiData).Separate(SIZEOF__BYTE));
+
+    bool permissive = Parameter.lenient_RSCI;
+
+    if (permissive || CRCObject.CheckCRC((*pbiData).Separate(16)) == TRUE)
+    {
+        /* CRC-check successful, extract data from SDC-stream --------------- */
+        int			iLengthOfBody;
+        _BOOLEAN	bError = FALSE;
+
+        /* Reset separation function */
+        (*pbiData).ResetBitAccess();
+
+        /* AFS index */
+        /* Reconfiguration index (not used by this application) */
+        if (eSDCType == SDC_DRM) /* Skip for AMSS */
+            (*pbiData).Separate(4);
+
+        /* Init bit count and total number of bits for body */
+        if (eSDCType == SDC_DRM)
+            iBitsConsumed = 4; /* 4 bits for AFS index */
+        else
+            iBitsConsumed = 0; /* 0 for AMSS, no AFS index */
+
+        const int iTotNumBitsWithoutCRC = iUsefulBitsSDC - 16;
+
+        /* Length of the body, excluding the initial 4 bits ("- 4"),
+           measured in bytes ("/ 8").
+           With this condition also the error code of the "Separate" function
+           is checked! (implicitly)
+           Check for: -end tag, -error, -no more data available */
+        while (((iLengthOfBody = (*pbiData).Separate(7)) != 0) &&
+                (bError == FALSE) && (iBitsConsumed < iTotNumBitsWithoutCRC))
+        {
+            /* Version flag */
+            _BOOLEAN bVersionFlag;
+            if ((*pbiData).Separate(1) == 0)
+                bVersionFlag = FALSE;
+            else
+                bVersionFlag = TRUE;
+
+            /* Data entity type */
+            /* First calculate number of bits for this entity ("+ 4" because of:
+               "The body of the data entities shall be at least 4 bits long. The
+               length of the body, excluding the initial 4 bits, shall be
+               signalled by the header") */
+            const int iNumBitsEntity = iLengthOfBody * 8 + 4;
+
+            /* Call the routine for the signalled type */
+            switch ((*pbiData).Separate(4))
+            {
+            case 0: /* Type 0 */
+                bError = DataEntityType0(pbiData, iLengthOfBody, Parameter, bVersionFlag);
+                break;
+
+            case 1: /* Type 1 */
+                bError = DataEntityType1(pbiData, iLengthOfBody, Parameter);
+                break;
+
+            case 3: /* Type 3 */
+                bError = DataEntityType3(pbiData, iLengthOfBody, Parameter, bVersionFlag);
+                break;
+
+            case 4: /* Type 4 */
+                bError = DataEntityType4(pbiData, iLengthOfBody, Parameter, bVersionFlag);
+                break;
+
+            case 5: /* Type 5 */
+                bError = DataEntityType5(pbiData, iLengthOfBody, Parameter, bVersionFlag);
+                break;
+
+            case 7: /* Type 7 */
+                bError = DataEntityType7(pbiData, iLengthOfBody, Parameter, bVersionFlag);
+                break;
+
+            case 8: /* Type 8 */
+                bError = DataEntityType8(pbiData, iLengthOfBody, Parameter);
+                break;
+
+            case 9: /* Type 9 */
+                bError = DataEntityType9(pbiData, iLengthOfBody, Parameter, bVersionFlag);
+                break;
+
+            case 11: /* Type 11 */
+                bError = DataEntityType11(pbiData, iLengthOfBody, Parameter, bVersionFlag);
+                break;
+
+            case 12: /* Type 12 */
+                bError = DataEntityType12(pbiData, iLengthOfBody, Parameter);
+                break;
+
+            default:
+                /* This type is not supported, delete all bits of this entity
+                   from the queue */
+                (*pbiData).Separate(iNumBitsEntity);
+            }
+
+            /* Count number of bits consumed (7 for length, 1 for version flag,
+               4 for type = 12 plus actual entitiy body data) */
+            iBitsConsumed += 12 + iNumBitsEntity;
+        }
+
+        /* If error was detected, return proper error code */
+        if (bError == TRUE)
+            return SR_BAD_DATA;
+        else
+            return SR_OK; /* everything was ok */
+    }
+    else
+    {
+        /* Data is corrupted, do not use it. Return error code */
+        return SR_BAD_CRC;
+    }
+}
+
+
+/******************************************************************************\
+* Data entity Type 0 (Multiplex description data entity)					   *
+\******************************************************************************/
+_BOOLEAN CSDCReceive::DataEntityType0(CVector<_BINARY>* pbiData,
+                                      const int iLengthOfBody,
+                                      CParameter& Parameter,
+                                      const _BOOLEAN)
+{
+    CMSCProtLev				MSCPrLe;
+    int						iLenPartA;
+    int						iLenPartB;
+
+    /* The receiver may determine the number of streams present in the multiplex
+       by dividing the length field of the header by three (6.4.3.1) */
+    const int iNumStreams = iLengthOfBody / 3;
+
+    /* Check number of streams for overflow */
+    if (iNumStreams > MAX_NUM_STREAMS)
+        return TRUE;
+
+    /* Get protection levels */
+    /* Protection level for part A */
+    MSCPrLe.iPartA = (*pbiData).Separate(2);
+
+    /* Protection level for part B */
+    MSCPrLe.iPartB = (*pbiData).Separate(2);
+
+    /* Reset hierarchical flag (hierarchical present or not) */
+    _BOOLEAN bWithHierarch = FALSE;
+
+    Parameter.Lock();
+    /* Get stream parameters */
+    for (int i = 0; i < iNumStreams; i++)
+    {
+        /* In case of hirachical modulation stream 0 describes the protection
+           level and length of hierarchical data */
+        if ((i == 0) &&
+                ((Parameter.eMSCCodingScheme == CS_3_HMSYM) ||
+                 (Parameter.eMSCCodingScheme == CS_3_HMMIX)))
+        {
+            /* Protection level for hierarchical */
+            MSCPrLe.iHierarch = (*pbiData).Separate(2);
+            bWithHierarch = TRUE;
+
+            /* rfu: these 10 bits shall be reserved for future use by the stream
+               description field and shall be set to zero until they are
+               defined */
+            if ((*pbiData).Separate(10) != 0)
+                return TRUE;
+
+            /* Data length for hierarchical */
+            iLenPartB = (*pbiData).Separate(12);
+
+            /* Set new parameters in global struct. Length of part A is zero
+               with hierarchical modulation */
+            Parameter.SetStreamLen(i, 0, iLenPartB);
+        }
+        else
+        {
+            /* Data length for part A */
+            iLenPartA = (*pbiData).Separate(12);
+
+            /* Data length for part B */
+            iLenPartB = (*pbiData).Separate(12);
+
+            /* Set new parameters in global struct */
+            Parameter.SetStreamLen(i, iLenPartA, iLenPartB);
+        }
+    }
+
+    /* Set new parameters in global struct */
+    Parameter.SetMSCProtLev(MSCPrLe, bWithHierarch);
+    Parameter.Unlock();
+
+    return FALSE;
+}
+
+
+/******************************************************************************\
+* Data entity Type 1 (Label data entity)									   *
+* Uses the unique flavour of the version flag so it is not needed here		   *
+\******************************************************************************/
+_BOOLEAN CSDCReceive::DataEntityType1(CVector<_BINARY>* pbiData,
+                                      const int iLengthOfBody,
+                                      CParameter& Parameter)
+{
+    /* Short ID (the short ID is the index of the service-array) */
+    const int iTempShortID = (*pbiData).Separate(2);
+
+    /* rfu: these 2 bits are reserved for future use and shall be set to zero
+       until they are defined */
+    if ((*pbiData).Separate(2) != 0)
+        return TRUE;
+
+
+    /* Get label string ----------------------------------------------------- */
+    string strLabel(iLengthOfBody, 0);
+    /* Check the following restriction to the length of label: "label: this is a
+       variable length field of up to 64 bytes defining the label" */
+    if (iLengthOfBody <= 64)
+    {
+
+        /* Get all characters from SDC-stream */
+        for (int i = 0; i < iLengthOfBody; i++)
+        {
+            /* Get character */
+            strLabel[i] = char((*pbiData).Separate(8));
+        }
+
+        /* store label string in the current service structure */
+        Parameter.Lock();
+        Parameter.Service[iTempShortID].strLabel = strLabel;
+        /* and keep it in the persistent service information store.
+         * But only if the FAC has already seen the sid. */
+        uint32_t sid = Parameter.Service[iTempShortID].iServiceID;
+        if (sid != SERV_ID_NOT_USED)
+        {
+            (void)Parameter.ServiceInformation[sid].label.insert(strLabel);
+            Parameter.ServiceInformation[sid].id = sid;
+        }
+        Parameter.Unlock();
+
+        return FALSE;
+    }
+    else
+        return TRUE; /* error */
+}
+
+
+/******************************************************************************\
+* Data entity Type 3 (Alternative frequency signalling)                        *
+\******************************************************************************/
+_BOOLEAN CSDCReceive::DataEntityType3(CVector<_BINARY>* pbiData,
+                                      const int iLengthOfBody,
+                                      CParameter& Parameter,
+                                      const _BOOLEAN bVersion)
+{
+    int			i;
+    _BOOLEAN	bEnhanceFlag = FALSE;
+    _BOOLEAN	bServRestrFlag = FALSE;
+    int			iServRestr = 0x0f;
+    CMultiplexDefinition AltFreq;
+
+    /* Init number of frequency count */
+    int iNumFreqTmp = iLengthOfBody;
+
+    /* Init region ID and schedule ID with "not used" parameters */
+    AltFreq.iRegionID = 0;
+    AltFreq.iScheduleID = 0;
+
+    /* Synchronous Multiplex flag: this flag indicates whether the multiplex is
+       broadcast synchronously */
+    switch ((*pbiData).Separate(1))
+    {
+    case 0: /* 0 */
+        /* Multiplex is not synchronous (different content and/or channel
+           parameters and/or multiplex parameters and/or signal timing in target
+           area) */
+        AltFreq.bIsSyncMultplx = FALSE;
+        break;
+
+    case 1: /* 1 */
+        /* Multiplex is synchronous (identical content and channel parameters
+           and multiplex parameters and signal timing in target area) */
+        AltFreq.bIsSyncMultplx = TRUE;
+        break;
+    }
+
+    /* Layer flag: this flag indicates whether the frequencies given apply to
+       the base layer of the DRM multiplex or to the enhancement layer */
+    switch ((*pbiData).Separate(1))
+    {
+    case 0: /* 0 */
+        /* Base layer */
+        bEnhanceFlag = FALSE;
+        break;
+
+    case 1: /* 1 */
+        /* Enhancement layer */
+        bEnhanceFlag = TRUE;
+        break;
+    }
+
+    /* Service Restriction flag: this flag indicates whether all or just some of
+       the services of the tuned multiplex are available in the DRM multiplex on
+       the frequencies */
+    switch ((*pbiData).Separate(1))
+    {
+    case 0: /* 0 */
+        /* All services in the tuned multiplex are available on the frequencies
+           given */
+        bServRestrFlag = FALSE;
+        break;
+
+    case 1: /* 1 */
+        /* A restricted set of services are available on the frequencies
+           given */
+        bServRestrFlag = TRUE;
+        break;
+    }
+
+    /* Region/Schedule flag: this field indicates whether the list of
+       frequencies is restricted by region and/or schedule or not */
+    _BOOLEAN bRegionSchedFlag = FALSE;
+    switch ((*pbiData).Separate(1))
+    {
+    case 0: /* 0 */
+        /* No restriction */
+        bRegionSchedFlag = FALSE;
+        break;
+
+    case 1: /* 1 */
+        /* Region and/or schedule applies to this list of frequencies */
+        bRegionSchedFlag = TRUE;
+        break;
+    }
+
+    /* Service Restriction field: this 8 bit field is only present if the
+       Service Restriction flag is set to 1 */
+    if (bServRestrFlag == TRUE)
+    {
+        /* Short Id flags 4 bits. This field indicates, which services
+           (identified by their Short Id) of the tuned DRM multiplex are carried
+           in the DRM multiplex on the alternative frequencies by setting the
+           corresponding bit to 1 */
+        iServRestr = (*pbiData).Separate(4);
+
+        /* rfa 4 bits. This field (if present) is reserved for future additions
+           and shall be set to zero until it is defined */
+        if ((*pbiData).Separate(4) != 0)
+            return TRUE;
+
+        /* Remove one byte from frequency count */
+        iNumFreqTmp--;
+    }
+    else
+    {
+        iServRestr = 0x0f; /* all services are included */
+    }
+
+    /* Region/Schedule field: this 8 bit field is only present if the
+       Region/Schedule flag is set to 1 */
+    if (bRegionSchedFlag == TRUE)
+    {
+        /* Region Id 4 bits. This field indicates whether the region is
+           unspecified (value 0) or whether the alternative frequencies are
+           valid just in certain geographic areas, in which case it carries
+           the Region Id (value 1 to 15). The region may be described by one or
+           more "Alternative frequency signalling: Region definition data entity
+           - type 7" with this Region Id */
+        AltFreq.iRegionID = (*pbiData).Separate(4);
+
+        /* Schedule Id 4 bits. This field indicates whether the schedule is
+           unspecified (value 0) or whether the alternative frequencies are
+           valid just at certain times, in which case it carries the Schedule Id
+           (value 1 to 15). The schedule is described by one or more
+           "Alternative frequency signalling: Schedule definition data entity
+           - type 4" with this Schedule Id */
+        AltFreq.iScheduleID = (*pbiData).Separate(4);
+
+        /* Remove one byte from frequency count */
+        iNumFreqTmp--;
+    }
+
+    /* Check for error (length of body must be so long to include Service
+       Restriction field and Region/Schedule field, also check that
+       remaining number of bytes is devidable by 2 since we read 16 bits) */
+    if ((iNumFreqTmp < 0) || (iNumFreqTmp % 2 != 0))
+        return TRUE;
+
+    /* n frequencies: this field carries n 16 bit fields. n is in the
+       range 0 to 16. The number of frequencies, n, is determined from the
+       length field of the header and the value of the Service Restriction flag
+       and the Region/Schedule flag */
+    const int iNumFreq = iNumFreqTmp / 2; /* 16 bits are read */
+
+    AltFreq.veciFrequencies.resize(iNumFreq);
+
+    for (i = 0; i < iNumFreq; i++)
+    {
+        /* rfu 1 bit. This field is reserved for future use of the frequency
+           value field and shall be set to zero until defined */
+        if ((*pbiData).Separate(1) != 0)
+            return TRUE;
+
+        /* Frequency value 15 bits. This field is coded as an unsigned integer
+           and gives the frequency in kHz */
+        AltFreq.veciFrequencies[i] = (*pbiData).Separate(15);
+    }
+
+    /* Now, set data in global struct */
+    Parameter.Lock();
+
+    /* Check the version flag */
+    if (bVersion != Parameter.AltFreqSign.bMultiplexVersionFlag)
+    {
+        /* If version flag has changed, delete all data for this entity type and save flag */
+        Parameter.AltFreqSign.ResetMultiplexes(bVersion);
+    }
+    /* Enhancement layer is not supported */
+    if (bEnhanceFlag == FALSE)
+    {
+
+        /* Set some parameters */
+
+        /* Set Service Restriction
+         * The first bit (msb) refers to Short Id 3,
+         * while the last bit (lsb) refers to Short Id 0 of the tuned DRM multiplex
+         * We made iServRestr valid whether the flag was there or not.
+         */
+        for (i = 0; i < MAX_NUM_SERVICES; i++)
+        {
+            /* Mask last bit (lsb) */
+            AltFreq.veciServRestrict[i] = iServRestr & 1;
+
+            /* Shift by one bit to get information for next service */
+            iServRestr >>= 1;
+        }
+
+        /* Now apply temporary object to global struct (first check if new object is not already there) */
+        int iCurNumAltFreq = Parameter.AltFreqSign.vecMultiplexes.size();
+
+        _BOOLEAN bAltFreqIsAlreadyThere = FALSE;
+        for (i = 0; i < iCurNumAltFreq; i++)
+        {
+            if (Parameter.AltFreqSign.vecMultiplexes[i] == AltFreq)
+                bAltFreqIsAlreadyThere = TRUE;
+        }
+
+        if (bAltFreqIsAlreadyThere == FALSE)
+            Parameter.AltFreqSign.vecMultiplexes.push_back(AltFreq);
+    }
+    Parameter.Unlock();
+
+    return FALSE;
+}
+
+
+/******************************************************************************\
+* Data entity Type 4 (Alternative frequency signalling: Schedule definition)   *
+\******************************************************************************/
+_BOOLEAN CSDCReceive::DataEntityType4(CVector<_BINARY>* pbiData,
+                                      const int iLengthOfBody,
+                                      CParameter& Parameter,
+                                      const _BOOLEAN bVersion)
+{
+    /* Check length -> must be 4 bytes */
+    if (iLengthOfBody != 4)
+        return TRUE;
+
+    int iScheduleID = 0;
+    CAltFreqSched Sched;
+
+    /* Schedule Id: this field indicates the Schedule Id for the defined
+       schedule. Up to 15 different schedules with an individual Schedule Id
+       (values 1 to 15) can be defined; the value 0 shall not be used, since it
+       indicates "unspecified schedule" in data entity type 3 and 11 */
+    iScheduleID = (*pbiData).Separate(4);
+
+    /* Day Code: this field indicates which days the frequency schedule (the
+       following Start Time and Duration) applies to. The msb indicates Monday,
+       the lsb Sunday. Between one and seven bits may be set to 1 */
+    Sched.iDayCode = (*pbiData).Separate(7);
+
+    /* Start Time: this field indicates the time from when the frequency is
+       valid. The time is expressed in minutes since midnight UTC. Valid values
+       range from 0 to 1439 (representing 00:00 to 23:59) */
+    Sched.iStartTime = (*pbiData).Separate(11);
+
+    /* Duration: this field indicates how long the frequency is valid starting
+       from the indicated Start Time. The time is expressed in minutes. Valid
+       values range from 1 to 16383 */
+    Sched.iDuration = (*pbiData).Separate(14);
+
+    /* Error checking */
+    if ((iScheduleID == 0) || (Sched.iDayCode == 0) || (Sched.iDayCode > 127) ||
+            (Sched.iStartTime > 1439) || (Sched.iDuration > 16383) || (Sched.iDuration == 0))
+    {
+        return TRUE;
+    }
+
+
+    /* Now apply temporary object to global struct */
+    Parameter.Lock();
+    /* Check the version flag */
+    if (bVersion != Parameter.AltFreqSign.bScheduleVersionFlag)
+    {
+        /* If version flag has changed, delete all data for this entity type and save flag */
+        Parameter.AltFreqSign.ResetSchedules(bVersion);
+    }
+
+    vector<CAltFreqSched>& vecSchedules =
+        Parameter.AltFreqSign.vecSchedules[iScheduleID];
+
+    /*(first check if new object is not already there) */
+
+    _BOOLEAN bAltFreqSchedIsAlreadyThere = FALSE;
+    for (size_t i = 0; i < vecSchedules.size(); i++)
+    {
+        if (vecSchedules[i] == Sched)
+            bAltFreqSchedIsAlreadyThere = TRUE;
+    }
+
+    if (bAltFreqSchedIsAlreadyThere == FALSE)
+        vecSchedules.push_back(Sched);
+
+    Parameter.Unlock();
+
+    return FALSE;
+}
+
+/******************************************************************************\
+* Data entity Type 5 (Application information data entity)					   *
+\******************************************************************************/
+_BOOLEAN CSDCReceive::DataEntityType5(CVector<_BINARY>* pbiData,
+                                      const int iLengthOfBody,
+                                      CParameter& Parameter,
+                                      const _BOOLEAN)
+{
+    /* Short ID (the short ID is the index of the service-array) */
+    const int iTempShortID = (*pbiData).Separate(2);
+
+    /* Load data parameters class with current parameters */
+    Parameter.Lock();
+    CDataParam DataParam = Parameter.GetDataParam(iTempShortID);
+    Parameter.Unlock();
+
+    /* Stream Id */
+    DataParam.iStreamID = (*pbiData).Separate(2);
+
+    /* Packet mode indicator */
+    switch ((*pbiData).Separate(1))
+    {
+    case 0: /* 0 */
+        DataParam.ePacketModInd = CDataParam::PM_SYNCHRON_STR_MODE;
+
+        /* Descriptor (not used) */
+        (*pbiData).Separate(7);
+        break;
+
+    case 1: /* 1 */
+        DataParam.ePacketModInd = CDataParam::PM_PACKET_MODE;
+
+        /* Descriptor */
+        /* Data unit indicator */
+        switch ((*pbiData).Separate(1))
+        {
+        case 0: /* 0 */
+            DataParam.eDataUnitInd = CDataParam::DU_SINGLE_PACKETS;
+            break;
+
+        case 1: /* 1 */
+            DataParam.eDataUnitInd = CDataParam::DU_DATA_UNITS;
+            break;
+        }
+
+        /* Packet Id */
+        DataParam.iPacketID = (*pbiData).Separate(2);
+
+        /* Application domain */
+        switch ((*pbiData).Separate(4))
+        {
+        case 0: /* 0000 */
+            DataParam.eAppDomain = CDataParam::AD_DRM_SPEC_APP;
+            break;
+
+        case 1: /* 0001 */
+            DataParam.eAppDomain = CDataParam::AD_DAB_SPEC_APP;
+            break;
+
+        default: /* 2 - 15 reserved */
+            DataParam.eAppDomain = CDataParam::AD_OTHER_SPEC_APP;
+            break;
+        }
+
+        /* Packet length */
+        DataParam.iPacketLen = (*pbiData).Separate(8);
+        break;
+    }
+
+    /* Application data */
+    if (DataParam.ePacketModInd == CDataParam::PM_SYNCHRON_STR_MODE)
+    {
+        /* Not used */
+        (*pbiData).Separate(iLengthOfBody * 8 - 8);
+    }
+    else if (DataParam.eAppDomain == CDataParam::AD_DAB_SPEC_APP)
+    {
+        /* rfu */
+        (*pbiData).Separate(5);
+
+        /* User application identifier */
+        DataParam.iUserAppIdent = (*pbiData).Separate(11);
+
+        /* Data fields as required by DAB application specification, not used */
+        (*pbiData).Separate(iLengthOfBody * 8 - 32);
+    }
+    else
+    {
+        /* AppIdent */
+        DataParam.iUserAppIdent = (*pbiData).Separate(iLengthOfBody * 8 - 16);
+    }
+
+    /* Set new parameters in global struct */
+    Parameter.Lock();
+    Parameter.SetDataParam(iTempShortID, DataParam);
+    Parameter.Unlock();
+
+    return FALSE;
+}
+
+/******************************************************************************\
+* Data entity Type 7 (Alternative frequency signalling: Region definition)     *
+\******************************************************************************/
+_BOOLEAN CSDCReceive::DataEntityType7(CVector<_BINARY>* pbiData,
+                                      const int iLengthOfBody,
+                                      CParameter& Parameter,
+                                      const _BOOLEAN bVersion)
+{
+    size_t i;
+    CAltFreqRegion Region;
+
+    /* Region Id: this field indicates the identifier for this region
+       definition. Up to 15 different geographic regions with an individual
+       Region Id (values 1 to 15) can be defined; the value 0 shall not be used,
+       since it indicates "unspecified geographic area" in data entity
+       type 3 and 11 */
+    const int iRegionID = (*pbiData).Separate(4);
+
+    /* Latitude: this field specifies the southerly point of the area in
+       degrees, as a 2's complement number between -90 (south pole) and
+       +90 (north pole) */
+
+
+    Region.iLatitude = Complement2toInt(8, pbiData);
+
+    /* Longitude: this field specifies the westerly point of the area in
+       degrees, as a 2's complement number between -180 (west) and
+       +179 (east) */
+
+    Region.iLongitude = Complement2toInt(9, pbiData);
+
+    /* Latitude Extent: this field specifies the size of the area to the north,
+       in 1 degree steps; the value of Latitude plus the value of Latitude
+       Extent shall be equal or less than 90 */
+    Region.iLatitudeEx = (*pbiData).Separate(7);
+
+    /* Longitude Extent: this field specifies the size of the area to the east,
+       in 1 degree steps; the value of Longitude plus the value of Longitude
+       Extent may exceed the value +179 (i.e. wrap into the region of negative
+       longitude values) */
+    Region.iLongitudeEx = (*pbiData).Separate(8);
+
+    /* n CIRAF Zones: this field carries n CIRAF zones (n in the range 0 to 16).
+       The number of CIRAF zones, n, is determined from the length field of the
+       header - 4 */
+    for (i = 0; i < size_t(iLengthOfBody - 4); i++)
+    {
+        /* Each CIRAF zone is coded as an 8 bit unsigned binary number in the
+           range 1 to 85 */
+        const int iCIRAFZone = (*pbiData).Separate(8);
+
+        if ((iCIRAFZone == 0) || (iCIRAFZone > 85))
+            return TRUE; /* Error */
+        else
+            Region.veciCIRAFZones.push_back(iCIRAFZone);
+
+        /*
+        	TODO: To check whether a certain longitude value is inside the specified
+        	longitude range, the following formula in pseudo program code shall be used
+        	(with my_longitude in the range -180 to +179):
+        	inside_area = ( (my_longitude >= longitude) AND
+        		(my_longitude <= (longitude + longitude_extent) ) OR
+        		( ((longitude + longitude_extent) >= +180) AND
+        		(my_longitude <= (longitude + longitude_extent - 360)) )
+        */
+    }
+
+    /* Error checking */
+    if ((iRegionID == 0)
+            || (Region.iLatitude + Region.iLatitudeEx > 90)
+            || (Region.iLongitude < -180) || (Region.iLongitude > 179)
+            || (Region.iLatitude < -90) || (Region.iLatitude > 90))
+    {
+        return TRUE; /* Error */
+    }
+
+
+    /* Now apply temporary object to global struct */
+    Parameter.Lock();
+    /* Check the version flag */
+    if (bVersion != Parameter.AltFreqSign.bRegionVersionFlag)
+    {
+        /* If version flag has changed, delete all data for this entity type and save flag */
+        Parameter.AltFreqSign.ResetRegions(bVersion);
+    }
+
+    vector<CAltFreqRegion>& vecRegions = Parameter.AltFreqSign.vecRegions[iRegionID];
+
+    /*(first check if new object is not already there) */
+
+    _BOOLEAN bAltFreqRegionIsAlreadyThere = FALSE;
+    for (i = 0; i < vecRegions.size(); i++)
+    {
+        if (vecRegions[i] == Region)
+            bAltFreqRegionIsAlreadyThere = TRUE;
+    }
+
+    if (bAltFreqRegionIsAlreadyThere == FALSE)
+        vecRegions.push_back(Region);
+
+    Parameter.Unlock();
+
+    return FALSE;
+}
+
+
+/******************************************************************************\
+* Data entity Type 8 (Time and date information data entity)				   *
+\******************************************************************************/
+_BOOLEAN CSDCReceive::DataEntityType8(CVector<_BINARY>* pbiData,
+                                      const int iLengthOfBody,
+                                      CParameter& Parameter)
+{
+    /* Check length -> must be 3 or 4 bytes */
+    if (iLengthOfBody < 3)
+        return FALSE;
+
+    if (iLengthOfBody > 4)
+        return FALSE;
+
+	if (iLengthOfBody == 3)
+    {
+    /* Decode date */
+    CModJulDate ModJulDate((*pbiData).Separate(17));
+
+    Parameter.Lock();
+    Parameter.iDay = ModJulDate.GetDay();
+    Parameter.iMonth = ModJulDate.GetMonth();
+    Parameter.iYear = ModJulDate.GetYear();
+
+    /* UTC (hours and minutes) */
+    Parameter.iUTCHour = (*pbiData).Separate(5);
+    Parameter.iUTCMin = (*pbiData).Separate(6);
+
+    Parameter.bValidUTCOffsetAndSense = FALSE;
+    }
+
+    if (iLengthOfBody == 4)
+    {
+    /* Decode date */
+    CModJulDate ModJulDate((*pbiData).Separate(17));
+
+    Parameter.Lock();
+    Parameter.iDay = ModJulDate.GetDay();
+    Parameter.iMonth = ModJulDate.GetMonth();
+    Parameter.iYear = ModJulDate.GetYear();
+
+    /* UTC (hours and minutes) */
+    Parameter.iUTCHour = (*pbiData).Separate(5);
+    Parameter.iUTCMin = (*pbiData).Separate(6);
+
+    /* rfu */
+    const int rfu = (*pbiData).Separate(2);
+
+    /* UTC Sense */
+    Parameter.iUTCSense = (*pbiData).Separate(1); 
+
+    /* UTC Offset (local time offset) */
+    Parameter.iUTCOff = ((*pbiData).Separate(5));
+
+    Parameter.bValidUTCOffsetAndSense = TRUE;
+
+    if (rfu)
+    {
+        /* rfu is set, reset all */
+        Parameter.iDay = 0;
+        Parameter.iMonth = 0;
+        Parameter.iYear = 0;
+        Parameter.iUTCSense = 0; 
+        Parameter.iUTCOff = 0;
+        Parameter.bValidUTCOffsetAndSense = FALSE;
+    }
+    }
+	
+    Parameter.Unlock();
+
+    return FALSE;
+}
+
+
+/******************************************************************************\
+* Data entity Type 9 (Audio information data entity)						   *
+\******************************************************************************/
+_BOOLEAN CSDCReceive::DataEntityType9(CVector<_BINARY>* pbiData,
+                                      const int iLengthOfBody,
+                                      CParameter& Parameter,
+                                      const _BOOLEAN)
+{
+    /* Check length -> must be at least 2 bytes */
+    if (iLengthOfBody < 2)
+        return TRUE;
+
+    /* Init error flag with "no error" */
+    _BOOLEAN bError = FALSE;
+
+    /* Short ID (the short ID is the index of the service-array) */
+    const int iTempShortID = (*pbiData).Separate(2);
+
+    /* Load audio parameters class with current parameters */
+    Parameter.Lock();
+    CAudioParam AudParam = Parameter.GetAudioParam(iTempShortID);
+    Parameter.Unlock();
+
+    /* Stream Id */
+    AudParam.iStreamID = (*pbiData).Separate(2);
+
+    /* Audio coding */
+    switch ((*pbiData).Separate(2))
+    {
+    case 0: /* 00 */
+        AudParam.eAudioCoding = CAudioParam::AC_AAC;
+        break;
+
+    case 1: /* 01 */
+        AudParam.eAudioCoding = CAudioParam::AC_CELP;
+        break;
+
+    case 2: /* 10 */
+        AudParam.eAudioCoding = CAudioParam::AC_HVXC;
+        break;
+
+    default: /* 11 */
+        AudParam.eAudioCoding = CAudioParam::AC_xHE_AAC;
+        break;
+    }
+
+    /* SBR flag */
+    switch ((*pbiData).Separate(1))
+    {
+    case 0: /* 0 */
+        AudParam.eSBRFlag = CAudioParam::SB_NOT_USED;
+        break;
+
+    case 1: /* 1 */
+        AudParam.eSBRFlag = CAudioParam::SB_USED;
+        break;
+    }
+
+    /* Audio mode */
+    switch (AudParam.eAudioCoding)
+    {
+    case CAudioParam::AC_AAC:
+        /* Channel type */
+        switch ((*pbiData).Separate(2))
+        {
+        case 0: /* 00 */
+            AudParam.eAudioMode = CAudioParam::AM_MONO;
+            break;
+
+        case 1: /* 01 */
+            AudParam.eAudioMode = CAudioParam::AM_P_STEREO;
+            break;
+
+        case 2: /* 10 */
+            AudParam.eAudioMode = CAudioParam::AM_STEREO;
+            break;
+
+        default: /* reserved */
+            AudParam.eAudioMode = CAudioParam::AM_STEREO;
+            bError = TRUE;
+            break;
+        }
+        break;
+
+    case CAudioParam::AC_CELP:
+        /* rfa */
+        (*pbiData).Separate(1);
+
+        /* CELP_CRC */
+        switch ((*pbiData).Separate(1))
+        {
+        case 0: /* 0 */
+            AudParam.bCELPCRC = FALSE;
+            break;
+
+        case 1: /* 1 */
+            AudParam.bCELPCRC = TRUE;
+            break;
+        }
+        break;
+
+    case CAudioParam::AC_HVXC:
+        /* HVXC_rate */
+        switch ((*pbiData).Separate(1))
+        {
+        case 0: /* 0 */
+            AudParam.eHVXCRate = CAudioParam::HR_2_KBIT;
+            break;
+
+        case 1: /* 1 */
+            AudParam.eHVXCRate = CAudioParam::HR_4_KBIT;
+            break;
+        }
+
+        /* HVXC CRC */
+        switch ((*pbiData).Separate(1))
+        {
+        case 0: /* 0 */
+            AudParam.bHVXCCRC = FALSE;
+            break;
+
+        case 1: /* 1 */
+            AudParam.bHVXCCRC = TRUE;
+            break;
+        }
+        break;
+
+    case CAudioParam::AC_xHE_AAC:
+        /* Channel type */
+        switch ((*pbiData).Separate(2))
+        {
+        case 0: /* 00 */
+            AudParam.eAudioMode = CAudioParam::AM_MONO;
+            break;
+
+        case 1: /* 01 reserved */
+            AudParam.eAudioMode = CAudioParam::AM_STEREO;
+            bError = TRUE;
+            break;
+
+        case 2: /* 10 */
+            AudParam.eAudioMode = CAudioParam::AM_STEREO;
+            break;
+
+        case 3: /* 11 reserved */
+            AudParam.eAudioMode = CAudioParam::AM_STEREO;
+            bError = TRUE;
+            break;
+        }
+        break;
+    case CAudioParam::AC_NONE: // can't happen
+    case CAudioParam::AC_OPUS: // can't happen
+	;
+    }
+
+    /* Audio sampling rate */
+    if(AudParam.eAudioCoding!=CAudioParam::AC_xHE_AAC)
+    {
+        CAudioParam::EAudSamRat sr[] = {
+            CAudioParam::AS_8_KHZ,
+            CAudioParam::AS_12KHZ,
+            CAudioParam::AS_16KHZ,
+            CAudioParam::AS_24KHZ,
+            CAudioParam::AS_48KHZ,
+            CAudioParam::AS_RESERVED,
+            CAudioParam::AS_RESERVED,
+            CAudioParam::AS_RESERVED
+        };
+        AudParam.eAudioSamplRate = sr[(*pbiData).Separate(3)];
+    }
+    else
+    {
+        CAudioParam::EAudSamRat sr[] = {
+            CAudioParam::AS_9_6_KHZ,
+            CAudioParam::AS_12KHZ,
+            CAudioParam::AS_16KHZ,
+            CAudioParam::AS_19_2KHZ,
+            CAudioParam::AS_48KHZ,
+            CAudioParam::AS_32KHZ,
+            CAudioParam::AS_38_4KHZ,
+            CAudioParam::AS_48KHZ
+        };
+        AudParam.eAudioSamplRate = sr[(*pbiData).Separate(3)];
+    }
+
+    /* XXX EXPERIMENTAL THIS IS NOT PART OF DRM STANDARD XXX */
+    if (AudParam.eAudioSamplRate ==  CAudioParam::AS_RESERVED
+            && AudParam.eAudioCoding == CAudioParam::AC_AAC) {
+        bError = AudParam.eSBRFlag != CAudioParam::SB_NOT_USED || AudParam.eAudioMode != CAudioParam::AM_MONO;
+        AudParam.eAudioCoding = CAudioParam::AC_OPUS;
+        AudParam.eAudioMode = CAudioParam::AM_STEREO;
+        AudParam.eAudioSamplRate = CAudioParam::AS_48KHZ;
+        AudParam.eSBRFlag = CAudioParam::SB_NOT_USED;
+    }
+
+    /* Text flag */
+    switch ((*pbiData).Separate(1))
+    {
+    case 0: /* 0 */
+        AudParam.bTextflag = FALSE;
+        break;
+
+    case 1: /* 1 */
+        AudParam.bTextflag = TRUE;
+        break;
+    }
+
+    /* Enhancement flag */
+    switch ((*pbiData).Separate(1))
+    {
+    case 0: /* 0 */
+        AudParam.bEnhanceFlag = FALSE;
+        break;
+
+    case 1: /* 1 */
+        AudParam.bEnhanceFlag = TRUE;
+        break;
+    }
+
+    /* Coder field */
+    if (AudParam.eAudioCoding == CAudioParam::AC_CELP)
+    {
+        /* CELP index */
+        AudParam.iCELPIndex = (*pbiData).Separate(5);
+    }
+    else
+    {
+        /* rfa 5 bit */
+        (*pbiData).Separate(5);
+    }
+
+    /* rfa 1 bit */
+    (*pbiData).Separate(1);
+
+    /* n bytes codec specific */
+    (*pbiData).Separate((iLengthOfBody-2)*SIZEOF__BYTE);
+
+    /* Set new parameters in global struct */
+    if (bError == FALSE)
+    {
+        Parameter.Lock();
+        Parameter.SetAudioParam(iTempShortID, AudParam);
+        Parameter.Unlock();
+        return FALSE;
+    }
+    else
+        return TRUE;
+}
+
+/******************************************************************************\
+* Data entity Type 11 (Alternative frequency signalling - other services)      *
+\******************************************************************************/
+_BOOLEAN CSDCReceive::DataEntityType11(CVector<_BINARY>* pbiData,
+                                       const int iLengthOfBody,
+                                       CParameter& Parameter,
+                                       const _BOOLEAN bVersion)
+{
+    size_t i;
+    _BOOLEAN		bRegionSchedFlag = FALSE;
+    int				iFrequencyEntryLength;
+    COtherService	OtherService;
+
+    /* Init number of frequency count */
+    int iNumFreqTmp = iLengthOfBody;
+
+    /* Short ID/Announcement flag: specifies
+     * whether this data entity is an AFS or an Announcement
+     * type entity. We only support AFS
+     */
+    const int iShortIDAnnounceFlag = pbiData->Separate(1);
+
+    /* Short Id / announcement field */
+    OtherService.iShortID = (*pbiData).Separate(2);
+
+    /* Region/Schedule flag: this field indicates whether the list of
+       frequencies is restricted by region and/or schedule or not */
+    switch ((*pbiData).Separate(1))
+    {
+    case 0: /* 0 */
+        /* No restriction */
+        bRegionSchedFlag = FALSE;
+        break;
+
+    case 1: /* 1 */
+        /* Region and/or schedule applies to this list of frequencies */
+        bRegionSchedFlag = TRUE;
+        break;
+    }
+
+    /* Same service ID flag: this field indicates whether the specified
+       other service carries the same audio programme or not */
+    switch ((*pbiData).Separate(1))
+    {
+    case 0: /* 0 */
+        /* No restriction */
+        OtherService.bSameService = FALSE;
+        break;
+
+    case 1: /* 1 */
+        OtherService.bSameService = TRUE;
+        break;
+    }
+
+    /* RFA - 2 bits */
+    (*pbiData).Separate(2);
+
+    /* Other system ID */
+    OtherService.iSystemID = (*pbiData).Separate(5);
+
+    /* Remove one byte from frequency count */
+    iNumFreqTmp--;
+
+    /* Optional Region/schedule ID */
+    if (bRegionSchedFlag == TRUE)
+    {
+        OtherService.iRegionID = (*pbiData).Separate(4);
+        OtherService.iScheduleID = (*pbiData).Separate(4);
+
+        /* Remove one byte from frequency count */
+        iNumFreqTmp--;
+    }
+
+    switch (OtherService.iSystemID)
+    {
+    case 0:
+    case 1:
+    case 3:
+    case 6:
+    case 9:
+        /* DRM, FM-RDS (European & North American grid, PI+ECC),
+           FM-RDS (Asia grid, PI+ECC), DAB (ECC + audio service ID) */
+        OtherService.iServiceID = (*pbiData).Separate(24);
+
+        /* Remove three bytes from frequency count */
+        iNumFreqTmp -= 3;
+        break;
+
+    case 4:
+    case 7:
+    case 10:
+        /* FM RDS (European & North American grid, PI only),
+           FM-RDS (Asia grid, PI only), DAB (audio service ID only) */
+        OtherService.iServiceID = (*pbiData).Separate(16);
+
+        /* Remove two bytes from frequency count */
+        iNumFreqTmp -= 2;
+        break;
+
+    case 11:
+        /* DAB (data service ID) */
+        OtherService.iServiceID = (*pbiData).Separate(32);
+
+        /* Remove four bytes from frequency count */
+        iNumFreqTmp -= 4;
+        break;
+
+    default:
+        OtherService.iServiceID = SERV_ID_NOT_USED;
+    }
+
+    /* n frequencies: this field carries n, variable length bit fields. n is in
+       the range 0 to 16. The number of frequencies, n, is determined from the
+       length field of the header and the value of the Service Restriction flag
+       and the Region/Schedule flag */
+    switch (OtherService.iSystemID)
+    {
+    case 0:
+    case 1:
+    case 2:
+        /* 16 bit frequency value for DRM/AM frequency */
+        iFrequencyEntryLength = 2;
+        break;
+
+    default:
+        /* 8 bit frequency value for all other broadcast systems currently
+           defined */
+        iFrequencyEntryLength = 1;
+    }
+
+    /* Check for error (length of body must be so long to include Service
+       Restriction field and Region/Schedule field, also check that
+       remaining number of bytes is devisible by iFrequencyEntryLength since
+       we read iFrequencyEntryLength * 8 bits) */
+    if ( (iNumFreqTmp < 0) || ((iNumFreqTmp % iFrequencyEntryLength) != 0) )
+        return TRUE;
+
+    /* 16 bits are read */
+    const size_t iNumFreq = iNumFreqTmp / iFrequencyEntryLength;
+
+    OtherService.veciFrequencies.resize(iNumFreq);
+
+    for (i = 0; i < iNumFreq; i++)
+    {
+        /* Frequency value iFrequencyEntryLength*8 bits. This field is coded as
+           an unsigned integer and gives the frequency in kHz */
+        int iFrequency = (*pbiData).Separate(iFrequencyEntryLength*8);
+
+        if (iFrequencyEntryLength == 2) // mask off top bit, undefined
+            iFrequency &= (unsigned short) 0x7fff;
+        OtherService.veciFrequencies[i] = iFrequency;
+    }
+
+    if (iShortIDAnnounceFlag != 0)
+        return FALSE; // no error, but we don't support announcements
+
+    /* Now, set data in global struct */
+    Parameter.Lock();
+    /* Check the version flag */
+    if (bVersion != Parameter.AltFreqSign.bOtherServicesVersionFlag)
+    {
+        /* If version flag has changed, delete all data for this entity type and save flag */
+        Parameter.AltFreqSign.ResetOtherServices(bVersion);
+    }
+
+    /* (first check if new object is not already there) */
+    const size_t iCurNumAltFreqOtherServices = Parameter.AltFreqSign.vecOtherServices.size();
+
+    _BOOLEAN bAltFreqIsAlreadyThere = FALSE;
+    for (i = 0; i < iCurNumAltFreqOtherServices; i++)
+    {
+        if (Parameter.AltFreqSign.vecOtherServices[i] == OtherService)
+            bAltFreqIsAlreadyThere = TRUE;
+    }
+    if (bAltFreqIsAlreadyThere == FALSE)
+        Parameter.AltFreqSign.vecOtherServices.push_back(OtherService);
+    Parameter.Unlock();
+
+    return FALSE;
+}
+
+
+/******************************************************************************\
+* Data entity Type 12 (Language and country data entity)                       *
+\******************************************************************************/
+_BOOLEAN CSDCReceive::DataEntityType12(CVector<_BINARY>* pbiData,
+                                       const int iLengthOfBody,
+                                       CParameter& Parameter)
+{
+    int i;
+
+    /* Check length -> must be 5 bytes */
+    if (iLengthOfBody != 5)
+        return TRUE;
+
+    /* Short Id: this field indicates the short Id for the service concerned */
+    const int iShortID = (*pbiData).Separate(2);
+
+    /* rfu: these 2 bits are reserved for future use and shall be set to zero
+       until they are defined */
+    if ((*pbiData).Separate(2) != 0)
+        return TRUE;
+
+    Parameter.Lock();
+    /* Language code: this 24-bit field identifies the language of the target
+       audience of the service according to ISO 639-2 using three lower case
+       characters as specified by ISO 8859-1. If the language is not specified,
+       the field shall contain three "-" characters */
+    Parameter.Service[iShortID].strLanguageCode = "";
+    for (i = 0; i < 3; i++)
+    {
+        /* Get character */
+        const char cNewChar = char((*pbiData).Separate(8));
+
+        /* Append new character */
+        Parameter.Service[iShortID].strLanguageCode.append(&cNewChar, 1);
+    }
+
+    /* Country code: this 16-bit field identifies the country of origin of the
+       service (the site of the studio) according to ISO 3166 using two lower
+       case characters as specified by ISO 8859-1. If the country code is not
+       specified, the field shall contain two "-" characters */
+    Parameter.Service[iShortID].strCountryCode = "";
+    for (i = 0; i < 2; i++)
+    {
+        /* Get character */
+        const char cNewChar = char((*pbiData).Separate(8));
+
+        /* Append new character */
+        Parameter.Service[iShortID].strCountryCode.append(&cNewChar, 1);
+    }
+    Parameter.Unlock();
+
+    return FALSE;
+}
diff --git a/src/SDC/SDCTransmit.cpp b/src/SDC/SDCTransmit.cpp
new file mode 100644
index 0000000..03aacaa
--- /dev/null
+++ b/src/SDC/SDCTransmit.cpp
@@ -0,0 +1,698 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *	SDC
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "SDC.h"
+
+
+/* Implementation *************************************************************/
+void CSDCTransmit::SDCParam(CVector<_BINARY>* pbiData, CParameter& Parameter)
+{
+    CommitEnter(pbiData, Parameter);
+
+        /* Type 0 */
+        DataEntityType0(vecbiData, Parameter);
+        CommitFlush();
+
+        // Only working for either one audio or data service!
+        if (Parameter.iNumAudioService == 1)
+        {
+            /* Type 9 */
+            DataEntityType9(vecbiData, 0, Parameter);
+            CommitFlush();
+        }
+        else
+        {
+            /* Type 5 */
+            DataEntityType5(vecbiData, 0, Parameter);
+            CommitFlush();
+        }
+
+        /* Type 1 */
+        DataEntityType1(vecbiData, 0, Parameter);
+        CommitFlush();
+
+        /* Check if the current time can be transmitted */
+        if (CanTransmitCurrentTime(Parameter))
+        {
+            /* Type 8 */
+            DataEntityType8(vecbiData, 0, Parameter);
+            CommitFlush();
+        }
+
+    CommitLeave();
+}
+
+
+void CSDCTransmit::CommitEnter(CVector<_BINARY>* pbiData, CParameter& Parameter)
+{
+    CSDCTransmit::pbiData = pbiData;
+
+    /* Calculate length of data field in bytes
+       (consistant to table 61 in (6.4.1)) */
+    iLengthDataFieldBytes =
+        (int) ((_REAL) (Parameter.iNumSDCBitsPerSFrame - 20) / 8);
+
+    /* 20 bits from AFS index and CRC */
+    iUsefulBitsSDC = 20 + iLengthDataFieldBytes * 8;
+
+    /* "- 20" for the AFS-index and CRC! */
+    iMaxNumBitsDataBlocks = iUsefulBitsSDC - 20;
+
+    /* Reset enqueue function */
+    (*pbiData).ResetBitAccess();
+
+    /* SDC Header ----------------------------------------------------------- */
+    /* AFS index (not used by this application, insert a "1" */
+    (*pbiData).Enqueue((uint32_t) 1, 4);
+
+    /* Reset number of bits used */
+    iNumUsedBits = 0;
+}
+
+void CSDCTransmit::CommitFlush()
+{
+    // TODO: nicer solution
+    /* Copy all bit of vecbiData to pbiData if enough room */
+    int iSize = vecbiData.Size();
+    if (iNumUsedBits + iSize < iMaxNumBitsDataBlocks)
+    {
+        iNumUsedBits += iSize;
+        vecbiData.ResetBitAccess();
+        /* Optimized bit transfer: by 32, 16, 8, 4, 2 or 1 */
+        int i, bits, size, numtrans;
+        for (bits = 5; iSize > 0; bits--)
+        {
+            numtrans = iSize >> bits;
+            if (!numtrans)
+                continue;
+            size = 1 << bits;
+            for (i = 0; i < numtrans; i++, iSize -= size)
+                (*pbiData).Enqueue(vecbiData.Separate(size), size);
+        }
+    }
+}
+
+void CSDCTransmit::CommitLeave()
+{
+    int i;
+
+    /* Zero-pad the unused bits in this SDC-block */
+    for (i = 0; i < iMaxNumBitsDataBlocks - iNumUsedBits; i++)
+        (*pbiData).Enqueue((uint32_t) 0, 1);
+
+    /* CRC ------------------------------------------------------------------ */
+    /* Calculate the CRC and put it at the end of the stream */
+    CRCObject.Reset(16);
+
+    (*pbiData).ResetBitAccess();
+
+    /* Special treatment of SDC data stream: The CRC (Cyclic Redundancy
+    Check) field shall contain a 16-bit CRC calculated over the AFS
+    index coded in an 8-bit field (4 msbs are 0) and the data field.
+    4 MSBs from AFS-index. Insert four "0" in the data-stream */
+    const _BYTE byFirstByte = (_BYTE) (*pbiData).Separate(4);
+    CRCObject.AddByte(byFirstByte);
+
+    for (i = 0; i < (iUsefulBitsSDC - 4) / SIZEOF__BYTE - 2; i++)
+        CRCObject.AddByte((_BYTE) (*pbiData).Separate(SIZEOF__BYTE));
+
+    /* Now, pointer in "enqueue"-function is back at the same place,
+       add CRC */
+    (*pbiData).Enqueue(CRCObject.GetCRC(), 16);
+}
+
+
+_BOOLEAN CSDCTransmit::CanTransmitCurrentTime(CParameter& Parameter)
+{
+    if (Parameter.eTransmitCurrentTime != CParameter::CT_OFF)
+    {
+        /* Get current UTC time */
+        time_t t = time(NULL);
+        if (t != ((time_t)-1))
+        {
+            struct tm *gtm, *ltm = localtime(&t);
+            switch (Parameter.eTransmitCurrentTime)
+            {
+            case CParameter::CT_UTC_OFFSET:
+#ifndef _WIN32
+				/* Extract time zone info */
+                if (ltm != NULL)
+                {
+                    const int iTimeZone = ltm->tm_gmtoff; /* offset in seconds */
+                    /* Set local time offset in half hour */
+                    Parameter.iUTCOff = (abs(iTimeZone) + 15 * 60) / (30 * 60);
+                    /* Set the sense of the offset: 0 = positive, 1 = negative */
+                    Parameter.iUTCSense = iTimeZone < 0;
+                    /* Set UTC offset and sense valid flag */
+                    Parameter.bValidUTCOffsetAndSense = Parameter.iUTCOff >= 0 && Parameter.iUTCOff <= 31;
+                }
+#else
+// TODO
+#endif
+			case CParameter::CT_LOCAL:
+            case CParameter::CT_UTC:
+                /* Extract time components */
+                if (Parameter.eTransmitCurrentTime == CParameter::CT_LOCAL)
+                    gtm = ltm;
+                else
+                    gtm = gmtime(&t);
+                if (gtm != NULL)
+                {
+                    /* Time info is only transmitted at minute edge see 6.4.3.9 */
+                    if (iLastMinuteTransmitted != gtm->tm_min)
+                    {
+                        iLastMinuteTransmitted = gtm->tm_min;
+                        Parameter.Lock();
+                        Parameter.iDay = (int)gtm->tm_mday;
+                        Parameter.iMonth = (int)gtm->tm_mon + 1;
+                        Parameter.iYear = (int)gtm->tm_year + 1900;
+                        Parameter.iUTCHour = (int)gtm->tm_hour;
+                        Parameter.iUTCMin = (int)gtm->tm_min;
+                        Parameter.Unlock();
+                        return TRUE;
+                    }
+                }
+                break;
+            case CParameter::CT_OFF:
+                break;
+            }
+        }
+    }
+    return FALSE;
+}
+
+
+/******************************************************************************\
+* Data entity Type 0 (Multiplex description data entity)					   *
+\******************************************************************************/
+void CSDCTransmit::DataEntityType0(CVector<_BINARY>& vecbiData,
+                                   CParameter& Parameter)
+{
+    /* 24 bits for each stream description + 4 bits for protection levels */
+    const int iNumBitsTotal = 4 + Parameter.GetTotNumServices() * 24;
+
+    /* Init return vector (storing this data block) */
+    vecbiData.Init(iNumBitsTotal + NUM_BITS_HEADER_SDC);
+    vecbiData.ResetBitAccess();
+
+    /* Length of the body, excluding the initial 4 bits ("- 4"),
+       measured in bytes ("/ 8") */
+    uint32_t iLengthInBytes = (iNumBitsTotal - 4) / 8;
+    vecbiData.Enqueue(iLengthInBytes, 7);
+
+    /* Version flag (not used in this implementation) */
+    vecbiData.Enqueue((uint32_t) 0, 1);
+
+    /* Data entity type */
+    vecbiData.Enqueue((uint32_t) 00, 4); /* Type 00 */
+
+
+    /* Actual body ---------------------------------------------------------- */
+    /* Protection level for part A */
+    vecbiData.Enqueue((uint32_t) Parameter.MSCPrLe.iPartA, 2);
+
+    /* Protection level for part B */
+    vecbiData.Enqueue((uint32_t) Parameter.MSCPrLe.iPartB, 2);
+
+    for (size_t i = 0; i < Parameter.GetTotNumServices(); i++)
+    {
+        /* In case of hirachical modulation stream 0 describes the protection
+           level and length of hirarchical data */
+        if ((i == 0) &&
+                ((Parameter.eMSCCodingScheme == CS_3_HMSYM) ||
+                 (Parameter.eMSCCodingScheme == CS_3_HMMIX)))
+        {
+            /* Protection level for hierarchical */
+            vecbiData.Enqueue((uint32_t) Parameter.MSCPrLe.iHierarch, 2);
+
+            /* rfu */
+            vecbiData.Enqueue((uint32_t) 0, 10);
+
+            /* Data length for hierarchical */
+            vecbiData.Enqueue((uint32_t) Parameter.Stream[i].iLenPartB, 12);
+        }
+        else
+        {
+            /* Data length for part A */
+            vecbiData.Enqueue((uint32_t) Parameter.Stream[i].iLenPartA, 12);
+
+            /* Data length for part B */
+            vecbiData.Enqueue((uint32_t) Parameter.Stream[i].iLenPartB, 12);
+        }
+    }
+}
+
+
+/******************************************************************************\
+* Data entity Type 1 (Label data entity)									   *
+\******************************************************************************/
+void CSDCTransmit::DataEntityType1(CVector<_BINARY>& vecbiData, int ServiceID,
+                                   CParameter& Parameter)
+{
+    int	iLenLabel;
+
+    /* Length of label. Label is a variable length field of up to 16 bytes
+       defining the label using UTF-8 coding */
+    const int iLenLabelTmp = Parameter.Service[ServiceID].strLabel.length();
+    if (iLenLabelTmp > 16)
+        iLenLabel = 16;
+    else
+        iLenLabel = iLenLabelTmp;
+
+    /* Number in bits (* 8) plus initial 4 bits (+ 4) */
+    const int iNumBitsTotal = iLenLabel * 8 + 4;
+
+    /* Init return vector (storing this data block) */
+    vecbiData.Init(iNumBitsTotal + NUM_BITS_HEADER_SDC);
+    vecbiData.ResetBitAccess();
+
+
+    /**** Multiplex description data entity - type 1 ****/
+    /* Length of the body, excluding the initial 4 bits,
+       measured in bytes -> only number bytes of label */
+    vecbiData.Enqueue((uint32_t) iLenLabel, 7);
+
+    /* Version flag (not used in this implementation) */
+    vecbiData.Enqueue((uint32_t) 0, 1);
+
+    /* Data entity type */
+    vecbiData.Enqueue((uint32_t) 01, 4); /* Type 01 */
+
+
+    /* Actual body ---------------------------------------------------------- */
+    /* Short Id */
+    vecbiData.Enqueue((uint32_t) ServiceID, 2);
+
+    /* rfu */
+    vecbiData.Enqueue((uint32_t) 0, 2);
+
+    /* Set all characters of label string */
+    for (int i = 0; i < iLenLabel; i++)
+    {
+        const char cNewChar = Parameter.Service[ServiceID].strLabel[i];
+
+        /* Set character */
+        vecbiData.Enqueue((uint32_t) cNewChar, 8);
+    }
+}
+
+
+/******************************************************************************\
+* Data entity Type 5 (Application information data entity)					   *
+\******************************************************************************/
+void CSDCTransmit::DataEntityType5(CVector<_BINARY>& vecbiData, int ServiceID,
+                                   CParameter& Parameter)
+{
+    int	iNumBitsTotal = 0;
+
+    /* Set total number of bits */
+    switch (Parameter.Service[ServiceID].DataParam.ePacketModInd)
+    {
+    case CDataParam::PM_SYNCHRON_STR_MODE:
+        iNumBitsTotal = 12 + 16 /* TEST */ /* + application data TODO! */;
+        break;
+
+    case CDataParam::PM_PACKET_MODE:
+        iNumBitsTotal = 20 + 16 /* TEST */ /* + application data TODO! */;
+        break;
+    }
+
+    /* Init return vector (storing this data block) */
+    vecbiData.Init(iNumBitsTotal + NUM_BITS_HEADER_SDC);
+    vecbiData.ResetBitAccess();
+
+    /* Length of the body, excluding the initial 4 bits ("- 4"),
+       measured in bytes ("/ 8") */
+    vecbiData.Enqueue((uint32_t) (iNumBitsTotal - 4) / 8, 7);
+
+    /* Version flag (not used in this implementation) */
+    vecbiData.Enqueue((uint32_t) 0, 1);
+
+    /* Data entity type */
+    vecbiData.Enqueue((uint32_t) 05, 4); /* Type 05 */
+
+
+    /* Actual body ---------------------------------------------------------- */
+    /* Short Id */
+    vecbiData.Enqueue((uint32_t) ServiceID, 2);
+
+    /* Stream Id */
+    vecbiData.Enqueue((uint32_t) Parameter.Service[ServiceID].DataParam.
+                      iStreamID, 2);
+
+    /* Packet mode indicator */
+    switch (Parameter.Service[ServiceID].DataParam.ePacketModInd)
+    {
+    case CDataParam::PM_SYNCHRON_STR_MODE:
+        vecbiData.Enqueue(0 /* 0 */, 1);
+
+        /* Descriptor */
+        vecbiData.Enqueue((uint32_t) 0, 7);
+        break;
+
+    case CDataParam::PM_PACKET_MODE:
+        vecbiData.Enqueue(1 /* 1 */, 1);
+
+        /* Descriptor */
+        /* Data unit indicator */
+        switch (Parameter.Service[ServiceID].DataParam.eDataUnitInd)
+        {
+        case CDataParam::DU_SINGLE_PACKETS:
+            vecbiData.Enqueue(0 /* 0 */, 1);
+            break;
+
+        case CDataParam::DU_DATA_UNITS:
+            vecbiData.Enqueue(1 /* 1 */, 1);
+            break;
+        }
+
+        /* Packet Id */
+        vecbiData.Enqueue(
+            (uint32_t) Parameter.Service[ServiceID].DataParam.iPacketID, 2);
+
+        /* Application domain */
+        switch (Parameter.Service[ServiceID].DataParam.eAppDomain)
+        {
+        case CDataParam::AD_DRM_SPEC_APP:
+            vecbiData.Enqueue(0 /* 0000 */, 4);
+            break;
+
+        case CDataParam::AD_DAB_SPEC_APP:
+            vecbiData.Enqueue(1 /* 0001 */, 4);
+            break;
+        default:
+            throw CGenErr("bad application domain in SDC preparation");
+        }
+
+        /* Packet length */
+        vecbiData.Enqueue(
+            (uint32_t) Parameter.Service[ServiceID].DataParam.iPacketLen, 8);
+
+        break;
+    }
+
+    /* Application data */
+// Not used
+
+// TEST
+    /* Fixed implementation for MOTSlideshow application which is the one and
+       only supported application right now. TODO */
+    /* rfu */
+    vecbiData.Enqueue((uint32_t) 0, 5);
+
+    /* User application identifier. SlideShow = 2 */
+    vecbiData.Enqueue((uint32_t) 2, 11);
+}
+
+
+/******************************************************************************\
+* Data entity Type 8 (Time and date information data entity)				   *
+\******************************************************************************/
+void CSDCTransmit::DataEntityType8(CVector<_BINARY>& vecbiData, int ServiceID,
+                                      CParameter& Parameter)
+{
+    (void)ServiceID;
+    const _BOOLEAN bTransmitOffset =
+        Parameter.bValidUTCOffsetAndSense &&
+        Parameter.eTransmitCurrentTime == CParameter::CT_UTC_OFFSET;
+    const int iNumBitsTotal = 28 + (bTransmitOffset ? 8 : 0);
+
+    /* Init return vector (storing this data block) */
+    vecbiData.Init(iNumBitsTotal + NUM_BITS_HEADER_SDC);
+    vecbiData.ResetBitAccess();
+
+    /* Length of the body, excluding the initial 4 bits ("- 4"),
+       measured in bytes ("/ 8") */
+    vecbiData.Enqueue((uint32_t) (iNumBitsTotal - 4) / 8, 7);
+
+    /* Version flag (not used in this implementation) */
+    vecbiData.Enqueue((uint32_t) 0, 1);
+
+    /* Data entity type */
+    vecbiData.Enqueue((uint32_t) 8, 4); /* Type 08 */
+
+
+    /* Actual body ---------------------------------------------------------- */
+    /* Date */
+    CModJulDate ModJulDate(Parameter.iYear, Parameter.iMonth, Parameter.iDay);
+    vecbiData.Enqueue((uint32_t) ModJulDate.GetModJulDate(), 17);
+
+    /* UTC (hours and minutes) */
+    vecbiData.Enqueue((uint32_t) Parameter.iUTCHour, 5);
+    vecbiData.Enqueue((uint32_t) Parameter.iUTCMin, 6);
+
+    /* UTC offset */
+    if (bTransmitOffset)
+    {
+        /* rfu */
+        vecbiData.Enqueue((uint32_t) 0, 2);
+
+        /* UTC Sense */
+        vecbiData.Enqueue((uint32_t) Parameter.iUTCSense, 1);
+
+        /* UTC Offset */
+        vecbiData.Enqueue((uint32_t) Parameter.iUTCOff, 5);
+    }
+}
+
+
+/******************************************************************************\
+* Data entity Type 9 (Audio information data entity)						   *
+\******************************************************************************/
+void CSDCTransmit::DataEntityType9(CVector<_BINARY>& vecbiData, int ServiceID,
+                                   CParameter& Parameter)
+{
+    /* Set total number of bits */
+    const int iNumBitsTotal = 20;
+
+    /* Init return vector (storing this data block) */
+    vecbiData.Init(iNumBitsTotal + NUM_BITS_HEADER_SDC);
+    vecbiData.ResetBitAccess();
+
+    /* Length of the body, excluding the initial 4 bits ("- 4"),
+       measured in bytes ("/ 8") */
+    vecbiData.Enqueue((uint32_t) (iNumBitsTotal - 4) / 8, 7);
+
+    /* Version flag (not used in this implementation) */
+    vecbiData.Enqueue((uint32_t) 0, 1);
+
+    /* Data entity type */
+    vecbiData.Enqueue((uint32_t) 9, 4); /* Type 09 */
+
+    /* Actual body ---------------------------------------------------------- */
+    /* Short Id */
+    vecbiData.Enqueue((uint32_t) ServiceID, 2);
+
+    /* Stream Id */
+    vecbiData.Enqueue((uint32_t) Parameter.Service[ServiceID].AudioParam.
+                      iStreamID, 2);
+
+    /* Audio coding */
+    switch (Parameter.Service[ServiceID].AudioParam.eAudioCoding)
+    {
+    case CAudioParam::AC_AAC:
+    case CAudioParam::AC_OPUS:
+        vecbiData.Enqueue(0 /* 00 */, 2);
+        break;
+
+    case CAudioParam::AC_CELP:
+        vecbiData.Enqueue(1 /* 01 */, 2);
+        break;
+
+    case CAudioParam::AC_HVXC:
+        vecbiData.Enqueue(2 /* 10 */, 2);
+        break;
+
+    default:
+        vecbiData.Enqueue(2 /* 11 */, 2);
+        break;
+    }
+
+    if (Parameter.Service[ServiceID].AudioParam.eAudioCoding == CAudioParam::AC_OPUS)
+    {
+        /* XXX EXPERIMENTAL THIS IS NOT PART OF DRM STANDARD XXX */
+        /* SBR flag, Audio mode */
+        vecbiData.Enqueue(0 /* 000 */, 3); /* set to zero, rfa for OPUS */
+        /* Audio sampling rate */
+        vecbiData.Enqueue(7 /* 111 */, 3); /* set to seven, reserved value for AAC */
+    }
+    else
+    {
+        /* SBR flag */
+        switch (Parameter.Service[ServiceID].AudioParam.eSBRFlag)
+        {
+        case CAudioParam::SB_NOT_USED:
+            vecbiData.Enqueue(0 /* 0 */, 1);
+            break;
+
+        case CAudioParam::SB_USED:
+            vecbiData.Enqueue(1 /* 1 */, 1);
+            break;
+        }
+
+        /* Audio mode */
+        switch (Parameter.Service[ServiceID].AudioParam.eAudioCoding)
+        {
+        case CAudioParam::AC_AAC:
+            /* Channel type */
+            switch (Parameter.Service[ServiceID].AudioParam.eAudioMode)
+            {
+            case CAudioParam::AM_MONO:
+                vecbiData.Enqueue(0 /* 00 */, 2);
+                break;
+
+            case CAudioParam::AM_P_STEREO:
+                vecbiData.Enqueue(1 /* 01 */, 2);
+                break;
+
+            case CAudioParam::AM_STEREO:
+                vecbiData.Enqueue(2 /* 10 */, 2);
+                break;
+            }
+            break;
+
+        case CAudioParam::AC_CELP:
+            /* rfa */
+            vecbiData.Enqueue((uint32_t) 0, 1);
+
+            /* CELP_CRC */
+            switch (Parameter.Service[ServiceID].AudioParam.bCELPCRC)
+            {
+            case FALSE:
+                vecbiData.Enqueue(0 /* 0 */, 1);
+                break;
+
+            case TRUE:
+                vecbiData.Enqueue(1 /* 1 */, 1);
+                break;
+            }
+            break;
+
+        case CAudioParam::AC_HVXC:
+            /* HVXC_rate */
+            switch (Parameter.Service[ServiceID].AudioParam.eHVXCRate)
+            {
+            case CAudioParam::HR_2_KBIT:
+                vecbiData.Enqueue(0 /* 0 */, 1);
+                break;
+
+            case CAudioParam::HR_4_KBIT:
+                vecbiData.Enqueue(1 /* 1 */, 1);
+                break;
+            }
+
+            /* HVXC CRC */
+            switch (Parameter.Service[ServiceID].AudioParam.bHVXCCRC)
+            {
+            case FALSE:
+                vecbiData.Enqueue(0 /* 0 */, 1);
+                break;
+
+            case TRUE:
+                vecbiData.Enqueue(1 /* 1 */, 1);
+                break;
+            }
+            break;
+
+        default:
+            vecbiData.Enqueue(0 /* 00 */, 2);
+            break;
+        }
+
+        /* Audio sampling rate */
+        switch (Parameter.Service[ServiceID].AudioParam.eAudioSamplRate)
+        {
+        case CAudioParam::AS_8_KHZ:
+            vecbiData.Enqueue(0 /* 000 */, 3);
+            break;
+
+        case CAudioParam::AS_12KHZ:
+            vecbiData.Enqueue(1 /* 001 */, 3);
+            break;
+
+        case CAudioParam::AS_16KHZ:
+            vecbiData.Enqueue(2 /* 010 */, 3);
+            break;
+
+        case CAudioParam::AS_24KHZ:
+            vecbiData.Enqueue(3 /* 011 */, 3);
+            break;
+
+        case CAudioParam::AS_48KHZ:
+            vecbiData.Enqueue(5 /* 101 */, 3);
+            break;
+        case CAudioParam::AS_19_2KHZ: // TODO
+        case CAudioParam::AS_32KHZ: // TODO
+        case CAudioParam::AS_38_4KHZ: // TODO
+        case CAudioParam::AS_9_6_KHZ: // TODO
+        case CAudioParam::AS_RESERVED: // can't happen
+	    ;
+        }
+    }
+
+    /* Text flag */
+    switch (Parameter.Service[ServiceID].AudioParam.bTextflag)
+    {
+    case FALSE:
+        vecbiData.Enqueue(0 /* 0 */, 1);
+        break;
+
+    case TRUE:
+        vecbiData.Enqueue(1 /* 1 */, 1);
+        break;
+    }
+
+    /* Enhancement flag */
+    switch (Parameter.Service[ServiceID].AudioParam.bEnhanceFlag)
+    {
+    case FALSE:
+        vecbiData.Enqueue(0 /* 0 */, 1);
+        break;
+
+    case TRUE:
+        vecbiData.Enqueue(1 /* 1 */, 1);
+        break;
+    }
+
+    /* Coder field */
+    if (Parameter.Service[ServiceID].AudioParam.
+            eAudioCoding == CAudioParam::AC_CELP)
+    {
+        /* CELP index */
+        vecbiData.Enqueue(
+            (uint32_t) Parameter.Service[ServiceID].AudioParam.iCELPIndex, 5);
+    }
+    else
+    {
+        /* rfa 5 bit */
+        vecbiData.Enqueue((uint32_t) 0, 5);
+    }
+
+    /* rfa 1 bit */
+    vecbiData.Enqueue((uint32_t) 0, 1);
+}
diff --git a/src/Scheduler.cpp b/src/Scheduler.cpp
new file mode 100644
index 0000000..0cc3743
--- /dev/null
+++ b/src/Scheduler.cpp
@@ -0,0 +1,168 @@
+/******************************************************************************\
+ * British Broadcasting Corporation
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *      Julian Cable
+ *
+ * Description:
+ *
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "Scheduler.h"
+#include <iostream>
+#include <sstream>
+#include <cstdlib>
+#include <ctime>
+#ifdef _WIN32
+# include <windows.h>
+#endif
+
+#ifdef _WIN32
+# include "windows/platform_util.h"
+#endif
+#ifdef __ANDROID_API__
+# include "android/platform_util.h"
+#endif
+
+// get next event
+CScheduler::SEvent CScheduler::front()
+{
+	if(events.empty())
+	{
+		fill();
+	}
+	if(testMode)
+		cerr << format(events.front().time) << " " << events.front().frequency << endl;
+	return events.front();
+}
+
+// remove first event from queue and return the front
+CScheduler::SEvent CScheduler::pop()
+{
+	events.pop();
+	return front();
+}
+
+bool CScheduler::empty() const
+{
+	return events.empty();
+}
+
+bool CScheduler::LoadSchedule(const string& filename)
+{
+	bool ok = iniFile.LoadIni(filename.c_str());
+	if(!ok)
+		return false;
+
+	if(testMode)
+		before();
+	for(int i=1; i<99; i++)
+	{
+		ostringstream ss;
+		ss << "Freq" << i;
+		string f = iniFile.GetIniSetting("Settings", ss.str());
+		ss.str("");
+		ss << "StartTime" << i;
+		string starttime = iniFile.GetIniSetting("Settings", ss.str());
+		ss.str("");
+		ss << "EndTime" << i;
+		string endtime = iniFile.GetIniSetting("Settings", ss.str());
+		if(starttime == endtime)
+			break;
+		time_t start = parse(starttime);
+		time_t end = parse(endtime);
+		schedule[start] = int(atol(f.c_str()));
+		schedule[end] = -1;
+	}
+	fill();
+	return true;
+}
+
+void CScheduler::fill()
+{
+	time_t dt = time(NULL); // daytime
+	struct tm dts;
+	dts = *gmtime(&dt);
+	dts.tm_hour = 0;
+	dts.tm_min = 0;
+	dts.tm_sec = 0;
+	time_t sod = timegm(&dts); // start of daytime
+	// resolve schedule to absolute time
+	map<time_t,int> abs_sched;
+	map<time_t,int>::const_iterator i;
+	for(i = schedule.begin(); i != schedule.end(); i++)
+	{
+		time_t st = sod + i->first;
+		if (st < dt)
+			st += 24 * 60 * 60; // want tomorrow's.
+		abs_sched[st] = i->second;
+	}
+	for (i = abs_sched.begin(); i != abs_sched.end(); i++)
+	{
+		SEvent e;
+		e.time = i->first;
+		e.frequency = i->second;
+		events.push(e);
+	}
+}
+
+int CScheduler::parse(string s)
+{
+	int hh,mm,ss;
+	char c;
+	istringstream iss(s);
+	iss >> hh >> c >> mm >> c >> ss;
+	return 60*(mm + 60*hh)+ss;
+}
+
+string CScheduler::format(time_t t)
+{
+	struct tm g = *gmtime(&t);
+	return format(g);
+}
+
+string CScheduler::format(const struct tm& g)
+{
+	ostringstream ss;
+	if(g.tm_hour < 10)
+		ss << '0';
+	ss << g.tm_hour << ":";
+	if(g.tm_min < 10)
+		ss << '0';
+	ss << g.tm_min << ":" ;
+	if(g.tm_sec < 10)
+		ss << '0';
+	ss << g.tm_sec;
+	return ss.str();
+}
+
+void CScheduler::before()
+{
+	time_t t = time(NULL);
+	t += 10;
+	iniFile.PutIniSetting("Settings", "StartTime1", format(t));
+	t += 30;
+	iniFile.PutIniSetting("Settings", "EndTime1", format(t));
+	iniFile.PutIniSetting("Settings", "StartTime2", format(t));
+	t += 30;
+	iniFile.PutIniSetting("Settings", "EndTime2", format(t));
+	cerr << "CScheduler::before()" << endl;
+}
diff --git a/src/Scheduler.h b/src/Scheduler.h
new file mode 100644
index 0000000..3874b3d
--- /dev/null
+++ b/src/Scheduler.h
@@ -0,0 +1,64 @@
+/******************************************************************************\
+ * British Broadcasting Corporation
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *      Julian Cable
+ *
+ * Description:
+ *
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#ifndef __SCHEDULER_H
+#define __SCHEDULER_H
+
+#include <string>
+#include <map>
+#include <queue>
+#include "util/Settings.h"
+
+using namespace std;
+
+class CScheduler
+{
+public:
+	struct SEvent { time_t time; int frequency; };
+	CScheduler(bool test=false):schedule(),events(),iniFile(),testMode(test){}
+	bool LoadSchedule(const string& filename);
+	bool empty() const;
+	SEvent front(); // get next event 
+	SEvent pop(); // remove first event from queue
+private:
+	map<time_t,int> schedule; // map seconds from start of day to schedule event, frequency or -1 for off
+	queue<SEvent> events;
+	CIniFile iniFile;
+	bool testMode;
+	void fill();
+	void before();
+	int parse(string);
+	string format(time_t);
+	string format(const struct tm&);
+};
+
+#if 0
+int dprintf(const char *format, ...);
+#endif
+
+#endif
diff --git a/src/ServiceInformation.cpp b/src/ServiceInformation.cpp
new file mode 100644
index 0000000..9f14f47
--- /dev/null
+++ b/src/ServiceInformation.cpp
@@ -0,0 +1,31 @@
+/******************************************************************************\
+ * British Broadcasting Corporation
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Julian Cable
+ *
+ * Description:
+ *  see ServiceInformation.h
+ *
+ *
+ *******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "ServiceInformation.h"
+
diff --git a/src/ServiceInformation.h b/src/ServiceInformation.h
new file mode 100644
index 0000000..ef09b63
--- /dev/null
+++ b/src/ServiceInformation.h
@@ -0,0 +1,43 @@
+/******************************************************************************\
+ * British Broadcasting Corporation
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Julian Cable
+ *
+ * Description:
+ *  Information about services gathered from SDC, EPG and web schedules.
+ *
+ *
+ *******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#ifndef _SERVICE_INFORMATION_H
+#define _SERVICE_INFORMATION_H
+
+#include "GlobalDefinitions.h"
+#include <set>
+
+class CServiceInformation
+{
+public:
+    uint32_t		id;    /* this is the primary key but we keep it inside too for completeness */
+    set<string>		label; /* gathered from the SDC. Normally the label is static and is the station name, but
+							  it is officially dynamic so we collect all that we see. */
+};
+#endif
diff --git a/src/SimulationParameters.cpp b/src/SimulationParameters.cpp
new file mode 100644
index 0000000..6cc41c8
--- /dev/null
+++ b/src/SimulationParameters.cpp
@@ -0,0 +1,477 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *	DRM simulation script
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "DrmSimulation.h"
+
+#ifdef _WIN32
+#include <windows.h>
+#else
+# ifdef HAVE_UNISTD_H
+#  include <unistd.h>
+# endif
+#endif
+
+/* Implementation *************************************************************/
+void CDRMSimulation::SimScript()
+{
+    int									i;
+    int									iNumItMLC;
+    _REAL								rSNRCnt;
+    FILE*								pFileSimRes;
+    CVector<_REAL>						vecrMSE;
+    string								strSimFile;
+    string								strSpecialRemark;
+    CChannelEstimation::ETypeIntFreq	eChanEstFreqIntType;
+    CChannelEstimation::ETypeIntTime	eChanEstTimIntType;
+
+
+    /**************************************************************************\
+    * Simulation settings vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*
+    \**************************************************************************/
+    /* Choose which type of simulation, if you choose "ST_NONE", the regular
+       application will be started
+       For ease of use, all possible types are plotted below. To enable a
+       certain type, just cut and past it at the end of the list
+       There are  different types of simulations available:
+       ST_BITERROR: BER simulation using actual channel estimation algorithms
+    		(either Wiener, linear or DFT method, can be set by
+    		eChanEstFreqIntType and eChanEstTimIntType)
+       ST_SYNC_PARAM: testing synchronization units (requires modifications in
+    		the actual synchronization code to make it work)
+       ST_MSECHANEST: MSE versus carrier for channel estimation algorithms
+       ST_BER_IDEALCHAN: BER assuming ideal channel estimation
+
+       Make sure the /drm/[linux, windows]/test directory exists since all the
+       simulation results are stored there. Together with the actual simulation
+       results, a file called x__SIMTIME.dat is also created and updated very
+       frequently, showing the remaining time.
+       By using the skript "plotsimres.m" in Matlab, a nice plot of the results
+       is generated automatically (this script reads all available simulation
+       results) */
+    Parameters.eSimType = CParameter::ST_BITERROR;
+    Parameters.eSimType = CParameter::ST_SYNC_PARAM; /* Check "SetSyncInput()"s! */
+    Parameters.eSimType = CParameter::ST_BER_IDEALCHAN;
+    Parameters.eSimType = CParameter::ST_MSECHANEST;
+    Parameters.eSimType = CParameter::ST_NONE; /* No simulation, regular GUI */
+
+
+    if (Parameters.eSimType != CParameter::ST_NONE)
+    {
+        /* Choose channel model. The channel numbers are according to the
+           numbers in the DRM-standard (e.g., channel number 1 is AWGN) plus
+           some additional channel profiles defined by the author */
+        Parameters.iDRMChannelNum = 1;
+
+        /* This parameter is only needed for the non-standard special channels 8, 10, 11, 12 */
+        Parameters.iSpecChDoppler = 2; /* Hz (integer value!) */
+
+        /* Defines the SNR range for the simulation. A start, stop and step
+           value can be set here */
+        rStartSNR = (_REAL) 14;
+        rEndSNR = (_REAL) 15.2;
+        rStepSNR = (_REAL) 0.3;
+
+        /* A string which is appended to the result files */
+        strSpecialRemark = "AWGNtest";
+
+        /* Define length of simulation. Only one of the following methods can
+           be used: time or number of bit errors:
+           iSimTime: simulation time in seconds of the virtual DRM stream (which
+           is not the simulation time)
+           iSimNumErrors: number of bit errors */
+        iSimTime = 100;
+//		iSimNumErrors = 100000;
+
+
+        /* Number of iterations for MLC */
+        iNumItMLC = 1;
+
+        /* The associated code rate is R = 0,6 and the modulation is 64-QAM */
+        Parameters.MSCPrLe.iPartB = 1;
+        Parameters.eMSCCodingScheme = CS_3_SM;
+
+
+        /* Choose the type of channel estimation algorithms used for simlation */
+        eChanEstFreqIntType = CChannelEstimation::FWIENER;//FDFTFILTER;//FLINEAR;
+        eChanEstTimIntType = CChannelEstimation::TWIENER;//TLINEAR;
+
+
+        /* Define which synchronization algorithms we want to use */
+        /* In case of bit error simulations, a synchronized DRM data stream is
+           used. Set corresponding modules to synchronized mode */
+        InputResample.SetSyncInput(TRUE);
+        FreqSyncAcq.SetSyncInput(TRUE);
+        SyncUsingPil.SetSyncInput(TRUE);
+        TimeSync.SetSyncInput(TRUE);
+
+
+        if (Parameters.iDRMChannelNum < 3)
+        {
+            Parameters.InitCellMapTable(RM_ROBUSTNESS_MODE_A, SO_2);
+            Parameters.eSymbolInterlMode = SI_SHORT;
+        }
+        else if ((Parameters.iDRMChannelNum == 8) || (Parameters.iDRMChannelNum == 10))
+        {
+            /* Special setting for channel 8 */
+            Parameters.InitCellMapTable(RM_ROBUSTNESS_MODE_B, SO_0);
+            Parameters.eSymbolInterlMode = SI_LONG;
+        }
+        else
+        {
+            Parameters.InitCellMapTable(RM_ROBUSTNESS_MODE_B, SO_3);
+            Parameters.eSymbolInterlMode = SI_LONG;
+        }
+
+
+        /**************************************************************************\
+        * Simulation settings ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*
+        \**************************************************************************/
+
+
+        /* Apply settings --------------------------------------------------- */
+        /* Set channel estimation interpolation type */
+        ChannelEstimation.SetFreqInt(eChanEstFreqIntType);
+        ChannelEstimation.SetTimeInt(eChanEstTimIntType);
+
+        /* Number of iterations for MLC */
+        MSCMLCDecoder.SetNumIterations(iNumItMLC);
+
+
+        /* Set the simulation priority to lowest possible value */
+#ifdef _WIN32
+        SetPriorityClass(GetCurrentProcess(), IDLE_PRIORITY_CLASS);
+#else
+# ifdef HAVE_UNISTD_H
+        /* re-nice the process to highest possible value -> 19 */
+        int n = nice(19); (void)n;
+
+        /* Try to get hostname */
+        char chHostName[255];
+        if (gethostname(chHostName, size_t(255)) == 0)
+        {
+            /* Append it to the file name of simulation output */
+            strSpecialRemark += "_";
+            strSpecialRemark += chHostName;
+        }
+# endif
+#endif
+
+        /* Set simulation time or number of errors. Slighty different convention
+           for __SIMTIME file name */
+        if (iSimTime != 0)
+        {
+            GenSimData.SetSimTime(iSimTime,
+                                  SimFileName(Parameters, strSpecialRemark, TRUE));
+        }
+        else
+        {
+            GenSimData.SetNumErrors(iSimNumErrors,
+                                    SimFileName(Parameters, strSpecialRemark, TRUE));
+        }
+
+        /* Set file name for simulation results output (in case of MSE, plot
+           SNR range, too) */
+        strSimFile = string(SIM_OUT_FILES_PATH) +
+                     SimFileName(Parameters, strSpecialRemark,
+                                 Parameters.eSimType == CParameter::ST_MSECHANEST) + string(".dat");
+
+        /* Open file for storing simulation results */
+        pFileSimRes = fopen(strSimFile.c_str(), "w");
+
+        /* If opening of file was not successful, exit simulation */
+        if (pFileSimRes == NULL)
+            exit(1);
+
+        /* Show name as console output */
+        fprintf(stderr, "%s\n", strSimFile.c_str());
+
+        /* Main SNR loop */
+        for (rSNRCnt = rStartSNR; rSNRCnt <= rEndSNR; rSNRCnt += rStepSNR)
+        {
+            /* Set SNR in global struct and run simulation */
+            Parameters.SetNominalSNRdB(rSNRCnt);
+            Run();
+
+            /* Store results in file */
+            switch (Parameters.eSimType)
+            {
+            case CParameter::ST_MSECHANEST:
+                /* After the simulation get results */
+                IdealChanEst.GetResults(vecrMSE);
+
+                /* Store results in a file */
+                for (i = 0; i < vecrMSE.Size(); i++)
+                    fprintf(pFileSimRes, "%e ", vecrMSE[i]);
+                fprintf(pFileSimRes, "\n"); /* New line */
+                break;
+
+            case CParameter::ST_SYNC_PARAM:
+                /* Save results in the file */
+                fprintf(pFileSimRes, "%e %e\n", rSNRCnt, Parameters.rSyncTestParam);
+                break;
+
+            default:
+                /* Save results in the file */
+                fprintf(pFileSimRes, "%e %e\n", rSNRCnt, Parameters.rBitErrRate);
+                break;
+            }
+
+            /* Make sure results are actually written in the file. In case the
+               simulation machine crashes, at least the last results are
+               preserved */
+            fflush(pFileSimRes);
+        }
+
+        /* Close simulation results file afterwards */
+        fclose(pFileSimRes);
+
+        /* At the end of the simulation, exit the application */
+        exit(1);
+    }
+}
+
+string CDRMSimulation::SimFileName(CParameter& SaveParam, string strAddInf,
+                                   _BOOLEAN bWithSNR)
+{
+    /*
+    	File naming convention:
+    	BER: Bit error rate simulation
+    	MSE: MSE for channel estimation
+    	BERIDEAL: Bit error rate simulation with ideal channel estimation
+    	SYNC: Simulation for a synchronization paramter (usually variance)
+
+    	B3: Robustness mode and spectrum occupancy
+    	CH5: Channel number
+    	It: Number of iterations in MLC decoder
+    	PL: Protection level of channel code
+    	"64SM": Modulation
+    	"T50": Length of simulation
+
+    	example: BERIDEAL_CH8_B0_It1_PL1_64SM_T50_MyRemark
+    */
+    char chNumTmpLong[256];
+    string strFileName = "";
+
+    /* What type of simulation ---------------------------------------------- */
+    switch (SaveParam.eSimType)
+    {
+    case CParameter::ST_BITERROR:
+        strFileName += "BER_";
+        break;
+    case CParameter::ST_MSECHANEST:
+        strFileName += "MSE_";
+        break;
+    case CParameter::ST_BER_IDEALCHAN:
+        strFileName += "BERIDEAL_";
+        break;
+    case CParameter::ST_SYNC_PARAM:
+        strFileName += "SYNC_";
+        break;
+    case CParameter::ST_NONE:
+    case CParameter::ST_SINR:
+        break;
+    }
+
+
+    /* Channel -------------------------------------------------------------- */
+    /* In case of channels 8 / 10 also write Doppler frequency in file name */
+    if ((SaveParam.iDRMChannelNum == 8) || (SaveParam.iDRMChannelNum == 10))
+    {
+        sprintf(chNumTmpLong, "CH%d_%dHz_",
+                SaveParam.iDRMChannelNum, SaveParam.iSpecChDoppler);
+    }
+    else
+        sprintf(chNumTmpLong, "CH%d_", SaveParam.iDRMChannelNum);
+
+    strFileName += chNumTmpLong;
+
+
+    /* Robustness mode and spectrum occupancy ------------------------------- */
+    switch (SaveParam.GetWaveMode())
+    {
+    case RM_ROBUSTNESS_MODE_A:
+        strFileName += "A";
+        break;
+    case RM_ROBUSTNESS_MODE_B:
+        strFileName += "B";
+        break;
+    case RM_ROBUSTNESS_MODE_C:
+        strFileName += "C";
+        break;
+    case RM_ROBUSTNESS_MODE_D:
+        strFileName += "D";
+        break;
+    case RM_ROBUSTNESS_MODE_E:
+        strFileName += "E";
+        break;
+    case RM_NO_MODE_DETECTED:
+        break;
+    }
+    switch (SaveParam.GetSpectrumOccup())
+    {
+    case SO_0:
+        strFileName += "0_";
+        break;
+    case SO_1:
+        strFileName += "1_";
+        break;
+    case SO_2:
+        strFileName += "2_";
+        break;
+    case SO_3:
+        strFileName += "3_";
+        break;
+    case SO_4:
+        strFileName += "4_";
+        break;
+    case SO_5:
+        strFileName += "5_";
+        break;
+    case SO_6:
+        strFileName += "6_";
+        break;
+    }
+
+
+    /* Channel estimation method -------------------------------------------- */
+    /* In case of BER simulation, print out channel estimation methods used */
+    if (SaveParam.eSimType == CParameter::ST_BITERROR)
+    {
+        /* Time direction */
+        switch (ChannelEstimation.GetTimeInt())
+        {
+        case CChannelEstimation::TLINEAR:
+            strFileName += "Tl";
+            break;
+
+        case CChannelEstimation::TWIENER:
+            strFileName += "Tw";
+            break;
+        }
+
+        /* Frequency direction */
+        switch (ChannelEstimation.GetFreqInt())
+        {
+        case CChannelEstimation::FLINEAR:
+            strFileName += "Fl_";
+            break;
+
+        case CChannelEstimation::FDFTFILTER:
+            strFileName += "Fd_";
+            break;
+
+        case CChannelEstimation::FWIENER:
+            strFileName += "Fw_";
+            break;
+        }
+    }
+
+
+    /* Number of iterations in MLC decoder ---------------------------------- */
+    sprintf(chNumTmpLong, "It%d_", MSCMLCDecoder.GetInitNumIterations());
+    strFileName += chNumTmpLong;
+
+
+    /* Protection level part B ---------------------------------------------- */
+    sprintf(chNumTmpLong, "PL%d_", SaveParam.MSCPrLe.iPartB);
+    strFileName += chNumTmpLong;
+
+
+    /* MSC coding scheme ---------------------------------------------------- */
+    switch (SaveParam.eMSCCodingScheme)
+    {
+    case CS_1_SM:
+        break;
+
+    case CS_2_SM:
+        strFileName += "16SM_";
+        break;
+
+    case CS_3_SM:
+        strFileName += "64SM_";
+        break;
+
+    case CS_3_HMMIX:
+        strFileName += "64MIX_";
+        break;
+
+    case CS_3_HMSYM:
+        strFileName += "64SYM_";
+        break;
+    }
+
+
+    /* Number of error events or simulation time ---------------------------- */
+    int iCurNum;
+    string strMultPl = "_";
+    if (iSimTime != 0)
+    {
+        strFileName += "T"; /* T -> time */
+        iCurNum = iSimTime;
+    }
+    else
+    {
+        strFileName += "E"; /* E -> errors */
+        iCurNum = iSimNumErrors;
+    }
+
+    if (iCurNum / 1000 > 0)
+    {
+        strMultPl = "K_";
+        iCurNum /= 1000;
+
+        if (iCurNum / 1000 > 0)
+        {
+            strMultPl = "M_";
+            iCurNum /= 1000;
+        }
+    }
+
+    sprintf(chNumTmpLong, "%d", iCurNum);
+    strFileName += chNumTmpLong;
+    strFileName += strMultPl;
+
+
+    /* SNR range (optional) ------------------------------------------------- */
+    if (bWithSNR == TRUE)
+    {
+        strFileName += "SNR";
+        sprintf(chNumTmpLong, "%.1f-", rStartSNR);
+        strFileName += chNumTmpLong;
+        sprintf(chNumTmpLong, "%.1f-", rStepSNR);
+        strFileName += chNumTmpLong;
+        sprintf(chNumTmpLong, "%.1f_", rEndSNR);
+        strFileName += chNumTmpLong;
+    }
+
+    /* Special remark */
+    if (!strAddInf.empty())
+        strFileName += strAddInf;
+
+    return strFileName;
+}
diff --git a/src/TextMessage.cpp b/src/TextMessage.cpp
new file mode 100644
index 0000000..fe6d955
--- /dev/null
+++ b/src/TextMessage.cpp
@@ -0,0 +1,539 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ * Implementation of the text message application of section 6.5
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "TextMessage.h"
+
+
+/* Implementation *************************************************************/
+/******************************************************************************\
+* Text message encoder (for transmitter)                                       *
+\******************************************************************************/
+void CTextMessageEncoder::Encode(CVector<_BINARY>& pData)
+{
+    int j;
+
+    /* Set data for this piece from segment data */
+    for (int i = 0; i < NUM_BYTES_TEXT_MESS_IN_AUD_STR; i++)
+    {
+        if (iByteCnt < CurTextMessage.GetSegSize(iSegCnt))
+        {
+            for (j = 0; j < SIZEOF__BYTE; j++)
+                pData[i * SIZEOF__BYTE + j] =
+                    (_BINARY) CurTextMessage[iSegCnt].Separate(1);
+        }
+        else
+        {
+            /* If the length of the last segment is not a multiple of four then
+               the incomplete frame shall be padded with 0x00 bytes */
+            for (j = 0; j < SIZEOF__BYTE; j++)
+                pData[i * SIZEOF__BYTE + j] = 0;
+        }
+
+        iByteCnt++;
+    }
+
+
+    /* Take care of byte count, segment count and message count ------------- */
+    /* Check if current segment is completely done */
+    if (iByteCnt >=	CurTextMessage.GetSegSize(iSegCnt))
+    {
+        iByteCnt = 0;
+
+        /* Next segment (test for wrap around) */
+        iSegCnt++;
+        if (iSegCnt == CurTextMessage.GetNumSeg())
+        {
+            iSegCnt = 0;
+
+
+            /* Use next message --------------------------------------------- */
+            iMessCnt++;
+            if (iMessCnt == iNumMess)
+                iMessCnt = 0;
+
+            /* Take care of toggle bit. If only one message is sent, toggle bit
+               must not be changed */
+            if (iNumMess != 1)
+                biToggleBit = !biToggleBit;
+
+            CurTextMessage.SetText(vecstrText[iMessCnt], biToggleBit);
+        }
+
+        /* Reset bit access of segment which is used next */
+        CurTextMessage[iSegCnt].ResetBitAccess();
+    }
+}
+
+void CTextMessageEncoder::SetMessage(const string& strMessage)
+{
+    /* Allocate memory for new text message, store text and increment counter */
+    vecstrText.Add(strMessage);
+    iNumMess++;
+
+    /* Init first message. TODO: this is always done when an additional text
+       is set but can only be done once. But for that we need an initialization
+       routine */
+    /* Reset counter for encoder function */
+    iSegCnt = 0; /* Segment counter */
+    iByteCnt = 0; /* Byte counter */
+    iMessCnt = 0; /* Message counter */
+
+    biToggleBit = 0;
+    CurTextMessage.SetText(vecstrText[0], biToggleBit);
+}
+
+void CTextMessageEncoder::ClearAllText()
+{
+    vecstrText.Init(0);
+    iNumMess = 0;
+    iSegCnt = 0; /* Segment counter */
+    iByteCnt = 0; /* Byte counter */
+    iMessCnt = 0; /* Message counter */
+    biToggleBit = 0;
+}
+
+void CTextMessage::SetText(const string& strMessage, const _BINARY biToggleBit)
+{
+    int		i, j;
+    int		iNumBodyBytes;
+    _BINARY	biFirstFlag;
+    _BINARY	biLastFlag;
+    CCRC	CRCObject;
+
+    /* Get length of text message.
+       TODO: take care of multiple byte characters (UTF-8 coding)! */
+    int iLenBytesOfText = strMessage.length();
+
+    /* Calculate required number of segments. The body shall contain 16 bytes
+       of character data */
+    iNumSeg = (int) ceil((_REAL) iLenBytesOfText / BYTES_PER_SEG_TEXT_MESS);
+
+    /* The text message may comprise up to 8 segments. Check the number of
+       segments, if number is larger, cut message */
+    if (iNumSeg > 8)
+    {
+        iNumSeg = 8;
+        iLenBytesOfText = iNumSeg * BYTES_PER_SEG_TEXT_MESS;
+    }
+
+    /* Allocate memory for segment pointer */
+    vvbiSegment.Init(iNumSeg);
+
+
+    /* Generate segments ---------------------------------------------------- */
+    /* Reset position in string */
+    int iPosInStr = 0;
+
+    for (i = 0; i < iNumSeg; i++)
+    {
+        /* Calculate number of bytes for body */
+        const int iRemainingBytes = iLenBytesOfText - iPosInStr;
+
+        /* All segments should have the maximum number of bytes per segment
+           except the last one which takes the remaining bytes */
+        if (iRemainingBytes > BYTES_PER_SEG_TEXT_MESS)
+            iNumBodyBytes = BYTES_PER_SEG_TEXT_MESS;
+        else
+            iNumBodyBytes = iRemainingBytes;
+
+        /* Init segment vector: "Beginning of segment" 4 * 8 bits,
+           Header 16 bits, body n * 8 bits, CRC 16 bits */
+        vvbiSegment[i].Init(4 * 8 + 16 + iNumBodyBytes * 8 + 16);
+
+        /* Reset enqueue function */
+        vvbiSegment[i].ResetBitAccess();
+
+
+        /* Generate "beginning of segment" identification by "all 0xFF" ----- */
+        for (j = 0; j < NUM_BYTES_TEXT_MESS_IN_AUD_STR; j++)
+            vvbiSegment[i].Enqueue((uint32_t) 0xFF, SIZEOF__BYTE);
+
+
+        /* Header ----------------------------------------------------------- */
+        /* Toggle bit */
+        vvbiSegment[i].Enqueue((uint32_t) biToggleBit, 1);
+
+        /* Determine position of segment */
+        if (i == 0)
+            biFirstFlag = 1;
+        else
+            biFirstFlag = 0;
+
+        if (iLenBytesOfText - iPosInStr <= BYTES_PER_SEG_TEXT_MESS)
+            biLastFlag = 1;
+        else
+            biLastFlag = 0;
+
+        /* Enqueue first flag */
+        vvbiSegment[i].Enqueue((uint32_t) biFirstFlag, 1);
+
+        /* Enqueue last flag */
+        vvbiSegment[i].Enqueue((uint32_t) biLastFlag, 1);
+
+        /* Command flag. This is a data block -> command flag = 0 */
+        vvbiSegment[i].Enqueue((uint32_t) 0, 1);
+
+        /* Field 1: specify the number of bytes in the body minus 1 (It
+           shall normally take the value 15 except in the last segment) */
+        vvbiSegment[i].Enqueue((uint32_t) iNumBodyBytes - 1, 4);
+
+        /* Field 2. If First flag = "1", this field shall contain the
+           value "1111" */
+        if (biFirstFlag == 1)
+            vvbiSegment[i].Enqueue((uint32_t) 15 /* 1111 */, 4);
+        else
+        {
+            /* Rfa. The bit shall be set to zero until it is defined */
+            vvbiSegment[i].Enqueue((uint32_t) 0, 1);
+
+            /* SegNum: specify the sequence number of the current segment
+               minus 1. The value 0 is reserved for future use */
+            vvbiSegment[i].Enqueue((uint32_t) i, 3);
+        }
+
+        /* Rfa. These bits shall be set to zero until they are defined */
+        vvbiSegment[i].Enqueue((uint32_t) 0, 4);
+
+
+        /* Body ------------------------------------------------------------- */
+        /* Set body bytes */
+        for (j = 0; j < iNumBodyBytes; j++)
+        {
+            vvbiSegment[i].Enqueue((uint32_t) strMessage.at(iPosInStr),
+                                   SIZEOF__BYTE);
+
+            iPosInStr++;
+        }
+
+
+        /* CRC -------------------------------------------------------------- */
+        /* Reset bit access and skip segment beginning piece (all 0xFFs) */
+        vvbiSegment[i].ResetBitAccess();
+        vvbiSegment[i].Separate(SIZEOF__BYTE * NUM_BYTES_TEXT_MESS_IN_AUD_STR);
+
+        /* Calculate the CRC and put it at the end of the segment */
+        CRCObject.Reset(16);
+
+        /* "byLengthBody" was defined in the header */
+        for (j = 0; j < iNumBodyBytes + 2 /* Header */; j++)
+            CRCObject.AddByte((_BYTE) vvbiSegment[i].Separate(SIZEOF__BYTE));
+
+        /* Now, pointer in "enqueue"-function is back at the same place,
+           add CRC */
+        vvbiSegment[i].Enqueue(CRCObject.GetCRC(), 16);
+
+
+        /* Reset bit access for using segment in encoder function */
+        vvbiSegment[i].ResetBitAccess();
+    }
+}
+
+
+/******************************************************************************\
+* Text message decoder (for receiver)                                          *
+\******************************************************************************/
+void CTextMessageDecoder::Decode(CVector<_BINARY>& pData)
+{
+    int			i, j;
+    _BOOLEAN	bBeginningFound;
+
+    /* Reset binary vector function. Always four bytes of data */
+    pData.ResetBitAccess();
+
+    /* Identify the beginning of a segment, all four bytes are 0xFF, otherwise
+       store total new buffer in internal intermediate buffer. This buffer is
+       read, when a beginning was found */
+    bBeginningFound = TRUE;
+    for (i = 0; i < NUM_BYTES_TEXT_MESS_IN_AUD_STR; i++)
+    {
+        if (pData.Separate(SIZEOF__BYTE) != 0xFF)
+            bBeginningFound = FALSE;
+    }
+
+    if (bBeginningFound)
+    {
+        /* Analyse old stream buffer, which should be completed now --------- */
+        /* Get header information. This function separates 16 bits from
+           stream */
+        biStreamBuffer.ResetBitAccess();
+        ReadHeader();
+
+        /* Check CRC */
+        biStreamBuffer.ResetBitAccess();
+        CRCObject.Reset(16);
+
+        /* "byLengthBody" was defined in the header */
+        for (i = 0; i < byLengthBody + 2 /* Header */; i++)
+            CRCObject.AddByte(_BYTE(biStreamBuffer.Separate(SIZEOF__BYTE)));
+
+        if (CRCObject.CheckCRC(biStreamBuffer.Separate(16)) == TRUE)
+        {
+            if (biCommandFlag == 1)
+            {
+                switch (byCommand)
+                {
+                case 1: /* 0001 */
+                    /* The message shall be removed from the display */
+                    ClearText();
+                    break;
+                }
+            }
+            else
+            {
+                /* Body ----------------------------------------------------- */
+                /* Evaluate toggle bit */
+                if (biToggleBit != biOldToggleBit)
+                {
+                    /* A new message is sent, clear all old segments */
+                    ResetSegments();
+
+                    biOldToggleBit = biToggleBit;
+                }
+
+
+                /* Read all bytes in stream buffer -------------------------- */
+                /* First, check if segment was already OK and if new data has
+                   the same content or not. If the content is different, a new
+                   message is being send, clear all other segments */
+                if (Segment[bySegmentID].bIsOK == TRUE)
+                {
+                    /* Reset bit access and skip header bits to go directly to
+                       the body bytes */
+                    biStreamBuffer.ResetBitAccess();
+                    biStreamBuffer.Separate(16);
+
+                    _BOOLEAN bIsSame = TRUE;
+                    for (i = 0; i < byLengthBody; i++)
+                    {
+                        if (Segment[bySegmentID].byData[i] !=
+                                biStreamBuffer.Separate(SIZEOF__BYTE))
+                        {
+                            bIsSame = FALSE;
+                        }
+                    }
+
+                    /* If a new message is sent, clear all old segments */
+                    if (bIsSame == FALSE)
+                        ResetSegments();
+                }
+
+                /* Reset bit access and skip header bits to go directly to the
+                   body bytes */
+                biStreamBuffer.ResetBitAccess();
+                biStreamBuffer.Separate(16);
+
+                /* Get all body bytes */
+                for (i = 0; i < byLengthBody; i++)
+                {
+                    Segment[bySegmentID].byData[i] =
+                        _BINARY(biStreamBuffer.Separate(SIZEOF__BYTE));
+                }
+
+                /* Set length of this segment and OK flag */
+                Segment[bySegmentID].iNumBytes = byLengthBody;
+                Segment[bySegmentID].bIsOK = TRUE;
+
+                /* Check length of text message */
+                if (biLastFlag == 1)
+                    iNumSegments = bySegmentID + 1;
+
+                /* Set text to display */
+                SetText();
+            }
+        }
+
+        /* Reset bit count */
+        iBitCount = 0;
+    }
+    else
+    {
+        for (i = 0; i < NUM_BYTES_TEXT_MESS_IN_AUD_STR; i++)
+        {
+            /* Check, if number of bytes is not too big */
+            if (iBitCount < TOT_NUM_BITS_PER_PIECE)
+            {
+                for (j = 0; j < SIZEOF__BYTE; j++)
+                    biStreamBuffer[iBitCount + j] = pData[i * SIZEOF__BYTE + j];
+
+                iBitCount += SIZEOF__BYTE;
+            }
+        }
+    }
+}
+
+void CTextMessageDecoder::ReadHeader()
+{
+    /* Toggle bit */
+    biToggleBit = (_BINARY) biStreamBuffer.Separate(1);
+
+    /* First flag */
+    biFirstFlag = (_BINARY) biStreamBuffer.Separate(1);
+
+    /* Last flag */
+    biLastFlag = (_BINARY) biStreamBuffer.Separate(1);
+
+    /* Command flag */
+    biCommandFlag = _BINARY(biStreamBuffer.Separate(1));
+
+    if (biCommandFlag == 1)
+    {
+        /* Command */
+        /* Field 1 */
+        byCommand = (_BYTE) biStreamBuffer.Separate(4);
+
+        /* 0001: the message shall be removed from the display */
+
+        /* Field 2: This field shall contain the value "1111", not
+           tested here */
+        biStreamBuffer.Separate(4);
+
+        /* When a command ist send, no body is present */
+        byLengthBody = 0;
+    }
+    else
+    {
+        /* Field 1: specify the number of bytes in the body minus 1 */
+        byLengthBody = (_BYTE) biStreamBuffer.Separate(4) + 1;
+
+        /* Field 2, Rfa */
+        biStreamBuffer.Separate(1);
+
+        /* SegNum: specify the sequence number of the current segment
+           minus 1. The value 0 is reserved for future use */
+        bySegmentID = (_BYTE) biStreamBuffer.Separate(3);
+
+        if (biFirstFlag == 1)
+            bySegmentID = 0;
+    }
+
+    /* Rfa */
+    biStreamBuffer.Separate(4);
+}
+
+void CTextMessageDecoder::Init(string* pstrNewPText)
+{
+    pstrText = pstrNewPText;
+    biOldToggleBit = 0;
+    iBitCount = 0;
+
+    /* Init segments */
+    ResetSegments();
+
+    /* Init and reset stream buffer */
+    biStreamBuffer.Init(TOT_NUM_BITS_PER_PIECE, 0);
+}
+
+void CTextMessageDecoder::SetText()
+{
+    int i;
+
+#ifndef _DEBUG_
+    if (iNumSegments != 0)
+#endif
+    {
+#ifndef _DEBUG_
+        /* Check, if all segments are ready */
+        _BOOLEAN bTextMessageReady = TRUE;
+        for (i = 0; i < iNumSegments; i++)
+        {
+            if (Segment[i].bIsOK == FALSE)
+                bTextMessageReady = FALSE;
+        }
+
+        if (bTextMessageReady == TRUE)
+#endif
+        {
+            /* Clear text */
+            *pstrText = "";
+
+            for (i = 0; i < MAX_NUM_SEG_TEXT_MESSAGE; i++)
+            {
+                if (Segment[i].bIsOK == TRUE)
+                {
+                    for (int j = 0; j < Segment[i].iNumBytes; j++)
+                    {
+                        /* Get character */
+                        char cNewChar = Segment[i].byData[j];
+
+                        if(decodeSpecial)
+                        {
+                            switch (cNewChar)
+                            {
+                            case 0x0A:
+                                /* Code 0x0A may be inserted to indicate a preferred
+                                   line break */
+                            case 0x1F:
+                                /* Code 0x1F (hex) may be inserted to indicate a
+                                   preferred word break. This code may be used to
+                                   display long words comprehensibly */
+
+                                (*pstrText).append("\r\n", 2);
+                                break;
+
+                            case 0x0B:
+                                /* End of a headline */
+
+                                /* Two line-breaks */
+                                (*pstrText).append("\r\n\r\n", 4);
+                                cNewChar = 0x0A;
+                                break;
+
+                            default:
+                                /* Append new character */
+                                (*pstrText).append(&cNewChar, 1);
+                                break;
+                            }
+                        }
+                        else
+                        {
+                            /* Append new character */
+                            (*pstrText).append(&cNewChar, 1);
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
+
+void CTextMessageDecoder::ClearText()
+{
+    /* Reset segments */
+    ResetSegments();
+
+    /* Clear text */
+    *pstrText = "";
+}
+
+void CTextMessageDecoder::ResetSegments()
+{
+    for (int i = 0; i < MAX_NUM_SEG_TEXT_MESSAGE; i++)
+        Segment[i].bIsOK = FALSE;
+
+    iNumSegments = 0;
+}
diff --git a/src/TextMessage.h b/src/TextMessage.h
new file mode 100644
index 0000000..6f47731
--- /dev/null
+++ b/src/TextMessage.h
@@ -0,0 +1,147 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *	See TextMessage.cpp
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#if !defined(TEXT_MESSAGE_H__3B00_CA63_4344_BB2B_23E7A0D31912__INCLUDED_)
+#define TEXT_MESSAGE_H__3B00_CA63_4344_BB2B_23E7A0D31912__INCLUDED_
+
+#include "GlobalDefinitions.h"
+#include "util/CRC.h"
+#include "util/Vector.h"
+
+
+/* Definitions ****************************************************************/
+/* The text message may comprise up to 8 segments ... The body shall contain
+   16 bytes of character data ...
+   We add "+ 1" since the entry "0" is not used */
+#define MAX_NUM_SEG_TEXT_MESSAGE		(8 + 1)
+#define BYTES_PER_SEG_TEXT_MESS			16
+
+#define TOT_NUM_BITS_PER_PIECE			((BYTES_PER_SEG_TEXT_MESS /* Max body */ \
+										+ 2 /* Header */ + 2 /* CRC */) * SIZEOF__BYTE)
+
+
+/* Classes ********************************************************************/
+/* Encoder ------------------------------------------------------------------ */
+class CTextMessage
+{
+public:
+    CTextMessage() : iNumSeg(0) {}
+    virtual ~CTextMessage() {}
+
+    CVector<_BINARY>&	operator[](const int iI) {
+        return vvbiSegment[iI];
+    }
+
+    void				SetText(const string& strMessage, const _BINARY biToggleBit);
+    inline int			GetNumSeg() const {
+        return iNumSeg;
+    }
+    inline int			GetSegSize(const int iSegID) const
+    {
+        return vvbiSegment[iSegID].Size() / SIZEOF__BYTE;
+    }
+
+protected:
+    CVector<CVector<_BINARY> >	vvbiSegment;
+    int							iNumSeg;
+};
+
+class CTextMessageEncoder
+{
+public:
+    CTextMessageEncoder() : vecstrText(0), iNumMess(0) {}
+    virtual ~CTextMessageEncoder() {}
+
+    void Encode(CVector<_BINARY>& pData);
+    void SetMessage(const string& strMessage);
+    void ClearAllText();
+
+protected:
+    CTextMessage	CurTextMessage;
+    CVector<string>	vecstrText;
+    int				iSegCnt;
+    int				iByteCnt;
+    int				iNumMess;
+    int				iMessCnt;
+    _BINARY			biToggleBit;
+};
+
+
+/* Decoder ------------------------------------------------------------------ */
+class CTextMessSegment
+{
+public:
+    CTextMessSegment() : byData(BYTES_PER_SEG_TEXT_MESS), bIsOK(FALSE),
+            iNumBytes(0) {}
+
+    CVector<_BYTE>	byData;
+    _BOOLEAN		bIsOK;
+    int				iNumBytes;
+};
+
+class CTextMessageDecoder
+{
+public:
+    CTextMessageDecoder(bool b):decodeSpecial(b) {}
+    virtual ~CTextMessageDecoder() {}
+
+    void Decode(CVector<_BINARY>& pData);
+    void Init(string* pstrNewPText);
+
+protected:
+    void ReadHeader();
+    void ClearText();
+    void SetText();
+    void ResetSegments();
+
+    CVector<_BINARY>	biStreamBuffer;
+
+    bool		decodeSpecial;
+
+    string*		pstrText;
+
+    _BINARY		biCommandFlag;
+
+    _BINARY		biFirstFlag;
+    _BINARY		biLastFlag;
+    _BYTE		byCommand;
+    _BYTE		bySegmentID;
+    _BINARY		biToggleBit;
+    _BYTE		byLengthBody;
+    int			iBitCount;
+    int			iNumSegments;
+
+    _BINARY		biOldToggleBit;
+
+    CTextMessSegment	Segment[MAX_NUM_SEG_TEXT_MESSAGE];
+
+    CCRC		CRCObject;
+};
+
+
+#endif // !defined(TEXT_MESSAGE_H__3B00_CA63_4344_BB2B_23E7A0D31912__INCLUDED_)
diff --git a/src/UpsampleFilter.h b/src/UpsampleFilter.h
new file mode 100644
index 0000000..1c44228
--- /dev/null
+++ b/src/UpsampleFilter.h
@@ -0,0 +1,318 @@
+/* Automatically generated file with GNU Octave */
+
+/* File name: "UpsampleFilter.octave" */
+/* Filter taps in time-domain */
+
+#ifndef _UPSAMPLEFILTER_H_
+#define _UPSAMPLEFILTER_H_
+
+#define NUM_TAPS_UPSAMPLE_FILT 303
+
+static const double dUpsampleFilt[NUM_TAPS_UPSAMPLE_FILT] =
+{
+	2.751996864053556761e-05,
+	9.218065509768166919e-05,
+	1.261559360350616630e-04,
+	1.648054055632974078e-05,
+	-2.237537428491481988e-04,
+	-3.815881221435321927e-04,
+	-2.723853673993414611e-04,
+	-1.947440724805229442e-05,
+	6.899947172471374230e-05,
+	-6.986320696674203534e-05,
+	-1.618818222183037814e-04,
+	-3.336255588917188934e-05,
+	1.054814601699522619e-04,
+	2.176347128557998040e-05,
+	-1.273718309271914032e-04,
+	-6.228962880295759190e-05,
+	1.123216887517165596e-04,
+	7.770469560686708334e-05,
+	-1.145014804796180271e-04,
+	-1.083538498992689473e-04,
+	1.044234377549441910e-04,
+	1.346968558277973150e-04,
+	-9.427767369476469368e-05,
+	-1.655625761837682436e-04,
+	7.651523160477260034e-05,
+	1.957139805363162057e-04,
+	-5.314962076644850087e-05,
+	-2.259022268739692028e-04,
+	2.231654509650029728e-05,
+	2.539970277787277240e-04,
+	1.587237780719335679e-05,
+	-2.787354112577792491e-04,
+	-6.150045405618378275e-05,
+	2.987500539032328134e-04,
+	1.147057894132901283e-04,
+	-3.120169886206589451e-04,
+	-1.745826168559310571e-04,
+	3.173508046984695771e-04,
+	2.407814060458014175e-04,
+	-3.127987822396973154e-04,
+	-3.120089459711855107e-04,
+	2.969225947660614619e-04,
+	3.869182106855122605e-04,
+	-2.682877496189162310e-04,
+	-4.638166266125248131e-04,
+	2.256055667052327953e-04,
+	5.406485062781422575e-04,
+	-1.678955555041303162e-04,
+	-6.151620616498615834e-04,
+	9.433922510286000976e-05,
+	6.846196893784361982e-04,
+	-4.852340934820595089e-06,
+	-7.466662909708113522e-04,
+	-1.010791326059708672e-04,
+	7.977390582292878196e-04,
+	2.222996998662563593e-04,
+	-8.355237314512333662e-04,
+	-3.585928595261100881e-04,
+	8.562669828031126053e-04,
+	5.079518974507890063e-04,
+	-8.573346991152585922e-04,
+	-6.686899981552816077e-04,
+	8.356123757804900668e-04,
+	8.382591787128835202e-04,
+	-7.882154847940520039e-04,
+	-1.013345767861847805e-03,
+	7.129941026609097187e-04,
+	1.190754270782738060e-03,
+	-6.073580697812347266e-04,
+	-1.365855075952519034e-03,
+	4.701957542234735184e-04,
+	1.534624945737060337e-03,
+	-2.998522075919117340e-04,
+	-1.691573245451375405e-03,
+	9.628546469572301324e-05,
+	1.831760310883087921e-03,
+	1.406301875750112557e-04,
+	-1.949331941128691148e-03,
+	-4.097704508932830531e-04,
+	2.038561549741572509e-03,
+	7.093111541454933658e-04,
+	-2.093700119885259694e-03,
+	-1.036806965618407208e-03,
+	2.108579725123998355e-03,
+	1.388271117273558218e-03,
+	-2.077982868435441100e-03,
+	-1.759730421152113332e-03,
+	1.995938210061983051e-03,
+	2.145248398638312237e-03,
+	-1.857839422126203802e-03,
+	-2.538813131164377110e-03,
+	1.658971261781380180e-03,
+	2.933198703887086346e-03,
+	-1.395240537826762574e-03,
+	-3.320004367868830113e-03,
+	1.063905953599462171e-03,
+	3.690873392118769643e-03,
+	-6.620939717131116590e-04,
+	-4.035731353743081569e-03,
+	1.887321305786974265e-04,
+	4.344477994230309427e-03,
+	3.565728621975029419e-04,
+	-4.606436269794938337e-03,
+	-9.734972823126291459e-04,
+	4.809735796069409056e-03,
+	1.659667791052220126e-03,
+	-4.943129714369473397e-03,
+	-2.412658431621823169e-03,
+	4.993973811089596170e-03,
+	3.228093332062952677e-03,
+	-4.949761627076211708e-03,
+	-4.100635476476820716e-03,
+	4.797789368508094052e-03,
+	5.024423682392547066e-03,
+	-4.523961550330355894e-03,
+	-5.991378631026889924e-03,
+	4.114860540130080985e-03,
+	6.993777527485181035e-03,
+	-3.554929665525276457e-03,
+	-8.022008694945799434e-03,
+	2.827923418364394325e-03,
+	9.065921694892125834e-03,
+	-1.915782147841799121e-03,
+	-1.011536779392369599e-02,
+	7.964189136577040900e-04,
+	1.115867945037955604e-02,
+	5.559874462161183912e-04,
+	-1.218478585550160191e-02,
+	-2.175216032920724088e-03,
+	1.318235483761330366e-02,
+	4.106842782961189244e-03,
+	-1.413958546485700671e-02,
+	-6.414163379277711304e-03,
+	1.504545944614148201e-02,
+	9.190770524869986899e-03,
+	-1.588939457771746180e-02,
+	-1.258164066898782678e-02,
+	1.666047166484150091e-02,
+	1.682174628371814820e-02,
+	-1.734957525748768992e-02,
+	-2.232200342598941040e-02,
+	1.794823606327803842e-02,
+	2.986487086638505220e-02,
+	-1.844843838651967147e-02,
+	-4.113534660696490514e-02,
+	1.884472213482938849e-02,
+	6.053263593121212260e-02,
+	-1.913178231772779542e-02,
+	-1.042136486879898377e-01,
+	1.930487923966702976e-02,
+	3.176781311579163214e-01,
+	4.806374931887292812e-01,
+	3.176781311579163214e-01,
+	1.930487923966702976e-02,
+	-1.042136486879898377e-01,
+	-1.913178231772779542e-02,
+	6.053263593121212260e-02,
+	1.884472213482938849e-02,
+	-4.113534660696490514e-02,
+	-1.844843838651967147e-02,
+	2.986487086638505220e-02,
+	1.794823606327803842e-02,
+	-2.232200342598941040e-02,
+	-1.734957525748768992e-02,
+	1.682174628371814820e-02,
+	1.666047166484150091e-02,
+	-1.258164066898782678e-02,
+	-1.588939457771746180e-02,
+	9.190770524869986899e-03,
+	1.504545944614148201e-02,
+	-6.414163379277711304e-03,
+	-1.413958546485700671e-02,
+	4.106842782961189244e-03,
+	1.318235483761330366e-02,
+	-2.175216032920724088e-03,
+	-1.218478585550160191e-02,
+	5.559874462161183912e-04,
+	1.115867945037955604e-02,
+	7.964189136577040900e-04,
+	-1.011536779392369599e-02,
+	-1.915782147841799121e-03,
+	9.065921694892125834e-03,
+	2.827923418364394325e-03,
+	-8.022008694945799434e-03,
+	-3.554929665525276457e-03,
+	6.993777527485181035e-03,
+	4.114860540130080985e-03,
+	-5.991378631026889924e-03,
+	-4.523961550330355894e-03,
+	5.024423682392547066e-03,
+	4.797789368508094052e-03,
+	-4.100635476476820716e-03,
+	-4.949761627076211708e-03,
+	3.228093332062952677e-03,
+	4.993973811089596170e-03,
+	-2.412658431621823169e-03,
+	-4.943129714369473397e-03,
+	1.659667791052220126e-03,
+	4.809735796069409056e-03,
+	-9.734972823126291459e-04,
+	-4.606436269794938337e-03,
+	3.565728621975029419e-04,
+	4.344477994230309427e-03,
+	1.887321305786974265e-04,
+	-4.035731353743081569e-03,
+	-6.620939717131116590e-04,
+	3.690873392118769643e-03,
+	1.063905953599462171e-03,
+	-3.320004367868830113e-03,
+	-1.395240537826762574e-03,
+	2.933198703887086346e-03,
+	1.658971261781380180e-03,
+	-2.538813131164377110e-03,
+	-1.857839422126203802e-03,
+	2.145248398638312237e-03,
+	1.995938210061983051e-03,
+	-1.759730421152113332e-03,
+	-2.077982868435441100e-03,
+	1.388271117273558218e-03,
+	2.108579725123998355e-03,
+	-1.036806965618407208e-03,
+	-2.093700119885259694e-03,
+	7.093111541454933658e-04,
+	2.038561549741572509e-03,
+	-4.097704508932830531e-04,
+	-1.949331941128691148e-03,
+	1.406301875750112557e-04,
+	1.831760310883087921e-03,
+	9.628546469572301324e-05,
+	-1.691573245451375405e-03,
+	-2.998522075919117340e-04,
+	1.534624945737060337e-03,
+	4.701957542234735184e-04,
+	-1.365855075952519034e-03,
+	-6.073580697812347266e-04,
+	1.190754270782738060e-03,
+	7.129941026609097187e-04,
+	-1.013345767861847805e-03,
+	-7.882154847940520039e-04,
+	8.382591787128835202e-04,
+	8.356123757804900668e-04,
+	-6.686899981552816077e-04,
+	-8.573346991152585922e-04,
+	5.079518974507890063e-04,
+	8.562669828031126053e-04,
+	-3.585928595261100881e-04,
+	-8.355237314512333662e-04,
+	2.222996998662563593e-04,
+	7.977390582292878196e-04,
+	-1.010791326059708672e-04,
+	-7.466662909708113522e-04,
+	-4.852340934820595089e-06,
+	6.846196893784361982e-04,
+	9.433922510286000976e-05,
+	-6.151620616498615834e-04,
+	-1.678955555041303162e-04,
+	5.406485062781422575e-04,
+	2.256055667052327953e-04,
+	-4.638166266125248131e-04,
+	-2.682877496189162310e-04,
+	3.869182106855122605e-04,
+	2.969225947660614619e-04,
+	-3.120089459711855107e-04,
+	-3.127987822396973154e-04,
+	2.407814060458014175e-04,
+	3.173508046984695771e-04,
+	-1.745826168559310571e-04,
+	-3.120169886206589451e-04,
+	1.147057894132901283e-04,
+	2.987500539032328134e-04,
+	-6.150045405618378275e-05,
+	-2.787354112577792491e-04,
+	1.587237780719335679e-05,
+	2.539970277787277240e-04,
+	2.231654509650029728e-05,
+	-2.259022268739692028e-04,
+	-5.314962076644850087e-05,
+	1.957139805363162057e-04,
+	7.651523160477260034e-05,
+	-1.655625761837682436e-04,
+	-9.427767369476469368e-05,
+	1.346968558277973150e-04,
+	1.044234377549441910e-04,
+	-1.083538498992689473e-04,
+	-1.145014804796180271e-04,
+	7.770469560686708334e-05,
+	1.123216887517165596e-04,
+	-6.228962880295759190e-05,
+	-1.273718309271914032e-04,
+	2.176347128557998040e-05,
+	1.054814601699522619e-04,
+	-3.336255588917188934e-05,
+	-1.618818222183037814e-04,
+	-6.986320696674203534e-05,
+	6.899947172471374230e-05,
+	-1.947440724805229442e-05,
+	-2.723853673993414611e-04,
+	-3.815881221435321927e-04,
+	-2.237537428491481988e-04,
+	1.648054055632974078e-05,
+	1.261559360350616630e-04,
+	9.218065509768166919e-05,
+	2.751996864053556761e-05
+};
+
+#endif /* _UPSAMPLEFILTER_H_ */
diff --git a/src/UpsampleFilter.octave b/src/UpsampleFilter.octave
new file mode 100644
index 0000000..9098030
--- /dev/null
+++ b/src/UpsampleFilter.octave
@@ -0,0 +1,68 @@
+%******************************************************************************\
+%*
+%* Copyright (c) 2001-2014
+%*
+%* Author:
+%*	David Flamand
+%*
+%* Description:
+%* 	Lowpass Filter for Upsampling
+%*
+%******************************************************************************
+%*
+%* This program is free software; you can redistribute it and/or modify it under
+%* the terms of the GNU General Public License as published by the Free Software
+%* Foundation; either version 2 of the License, or (at your option) any later 
+%* version.
+%*
+%* This program is distributed in the hope that it will be useful, but WITHOUT 
+%* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+%* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 
+%* details.
+%*
+%* You should have received a copy of the GNU General Public License along with
+%* this program; if not, write to the Free Software Foundation, Inc., 
+%* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+%*
+%******************************************************************************/
+
+n = 303;
+ripple_dB = 0.05;
+att_dB = 100;
+
+f = [0 (1/2-1/32) (1/2) 1];
+m = [1 1 0 0];
+w = [(1/(1 - 10 ^ (-ripple_dB / 20))) (1/(10 ^ (-att_dB / 20)))];
+b = remez(n - 1, f, m, w, 'bandpass');
+
+PLOT = 1;
+if (PLOT == 1)
+    close all;
+    freqz(b);
+    plot(b);
+    figure;
+end
+
+fid = fopen('UpsampleFilter.h', 'w');
+fprintf(fid, '/* Automatically generated file with GNU Octave */\n');
+fprintf(fid, '\n');
+fprintf(fid, '/* File name: "UpsampleFilter.octave" */\n');
+fprintf(fid, '/* Filter taps in time-domain */\n');
+fprintf(fid, '\n');
+fprintf(fid, '#ifndef _UPSAMPLEFILTER_H_\n');
+fprintf(fid, '#define _UPSAMPLEFILTER_H_\n');
+fprintf(fid, '\n');
+fprintf(fid, '#define NUM_TAPS_UPSAMPLE_FILT %i\n', n);
+fprintf(fid, '\n');
+fprintf(fid, 'static const double dUpsampleFilt[NUM_TAPS_UPSAMPLE_FILT] =\n');
+fprintf(fid, '{\n');
+fprintf(fid, '	%.18e,\n', b(1:end - 1));
+fprintf(fid, '	%.18e\n', b(end));
+fprintf(fid, '};\n');
+fprintf(fid, '\n');
+fprintf(fid, '#endif /* _UPSAMPLEFILTER_H_ */\n');
+fclose(fid);
+
+if (PLOT == 1)
+    input("press enter to exit ");
+end
diff --git a/src/Version.cpp b/src/Version.cpp
new file mode 100644
index 0000000..50a5146
--- /dev/null
+++ b/src/Version.cpp
@@ -0,0 +1,47 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Andrea Russo, Julian Cable
+ *
+ * Description:
+ *	Dream program version number
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+#include "Version.h"
+#include "GlobalDefinitions.h"
+
+const char dream_manufacturer[] = "drea";
+#ifdef QT_CORE_LIB
+# if QT_VERSION >= 0x050000
+const char dream_implementation[] = "Q5";
+# elif QT_VERSION >= 0x040000
+const char dream_implementation[] = "Q4";
+# else
+const char dream_implementation[] = "QT";
+# endif
+#else
+const char dream_implementation[] = "CL";
+#endif
+const int dream_version_major = 2;
+const int dream_version_minor = 2;
+const int dream_version_patch = 0;
+const char dream_version_build[] = "-svn924";
+
diff --git a/src/Version.h b/src/Version.h
new file mode 100644
index 0000000..23c9b1d
--- /dev/null
+++ b/src/Version.h
@@ -0,0 +1,39 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Andrea Russo, Julian Cable
+ *
+ * Description:
+ *	Dream program version number
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#ifndef _VERSION_H
+#define _VERSION_H
+
+extern const char dream_manufacturer[];
+extern const char dream_implementation[];
+extern const int dream_version_major;
+extern const int dream_version_minor;
+extern const int dream_version_patch;
+extern const char dream_version_build[];
+
+#endif
diff --git a/src/android/platform_util.cpp b/src/android/platform_util.cpp
new file mode 100644
index 0000000..7ebd3f1
--- /dev/null
+++ b/src/android/platform_util.cpp
@@ -0,0 +1,14 @@
+
+#include "platform_util.h"
+#include <time64.h>
+#include <limits.h>
+
+time_t timegm(const struct tm* const t) {
+  // time_t is signed on Android.
+  static const time_t kTimeMax = ~(1 << (sizeof(time_t) * CHAR_BIT - 1));
+  static const time_t kTimeMin = (1 << (sizeof(time_t) * CHAR_BIT - 1));
+  time64_t result = timegm64(t);
+  if (result < kTimeMin || result > kTimeMax)
+    return -1;
+  return time_t(result);
+}
diff --git a/src/android/platform_util.h b/src/android/platform_util.h
new file mode 100644
index 0000000..eb1f02d
--- /dev/null
+++ b/src/android/platform_util.h
@@ -0,0 +1,8 @@
+#ifndef UTIL_H
+#define UTIL_H
+
+#include <time.h>
+
+time_t timegm(const struct tm* const);
+
+#endif // UTIL_H
diff --git a/src/android/soundin.cpp b/src/android/soundin.cpp
new file mode 100644
index 0000000..28b00ae
--- /dev/null
+++ b/src/android/soundin.cpp
@@ -0,0 +1,1235 @@
+#include "soundin.h"
+#include <SLES/OpenSLES.h>
+
+extern SLObjectItf engineObject;
+
+const int MAX_NUMBER_INPUT_DEVICES = 10;
+
+static const char* SLESErrorToString(SLresult result)
+{
+    switch (result)
+    {
+    case SL_RESULT_SUCCESS: return "SUCCESS";
+    case SL_RESULT_PRECONDITIONS_VIOLATED: return
+    "SL_RESULT_PRECONDITIONS_VIOLATED";
+    case SL_RESULT_PARAMETER_INVALID: return "SL_RESULT_PARAMETER_INVALID";
+    case SL_RESULT_MEMORY_FAILURE: return "SL_RESULT_MEMORY_FAILURE";
+    case SL_RESULT_RESOURCE_ERROR: return "SL_RESULT_RESOURCE_ERROR";
+    case SL_RESULT_RESOURCE_LOST: return "SL_RESULT_RESOURCE_LOST";
+    case SL_RESULT_IO_ERROR: return "SL_RESULT_IO_ERROR";
+    case SL_RESULT_BUFFER_INSUFFICIENT: return "SL_RESULT_BUFFER_INSUFFICIENT";
+    case SL_RESULT_CONTENT_CORRUPTED: return "SL_RESULT_CONTENT_CORRUPTED";
+    case SL_RESULT_CONTENT_UNSUPPORTED: return "SL_RESULT_CONTENT_UNSUPPORTED";
+    case SL_RESULT_CONTENT_NOT_FOUND: return "SL_RESULT_CONTENT_NOT_FOUND";
+    case SL_RESULT_PERMISSION_DENIED: return "SL_RESULT_PERMISSION_DENIED";
+    case SL_RESULT_FEATURE_UNSUPPORTED: return
+    "SL_RESULT_FEATURE_UNSUPPORTED";
+    case SL_RESULT_INTERNAL_ERROR: return "SL_RESULT_INTERNAL_ERROR";
+    case SL_RESULT_UNKNOWN_ERROR: return "SL_RESULT_UNKNOWN_ERROR";
+    case SL_RESULT_OPERATION_ABORTED: return "SL_RESULT_OPERATION_ABORTED";
+    case SL_RESULT_CONTROL_LOST: return "SL_RESULT_CONTROL_LOST";
+    default: return "Unknown";
+    }
+}
+
+
+
+COpenSLESIn::COpenSLESIn():currentDevice("")
+{
+}
+
+COpenSLESIn::~COpenSLESIn()
+{
+
+}
+
+void COpenSLESIn::Enumerate(vector<string>& names, vector<string>& descriptions)
+{
+    SLuint32 InputDeviceIDs[MAX_NUMBER_INPUT_DEVICES];
+    SLint32 numInputs = 0;
+    //(*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine);
+    /* Get the Audio IO DEVICE CAPABILITIES interface */
+    SLAudioIODeviceCapabilitiesItf AudioIODeviceCapabilitiesItf;
+    SLresult res = (*engineObject)->GetInterface(engineObject, SL_IID_AUDIOIODEVICECAPABILITIES, (void*)&AudioIODeviceCapabilitiesItf);
+    if(res!=SL_RESULT_SUCCESS) {
+        string em = "Can't get audio input device capabilities ";
+        em += SLESErrorToString(res);
+        qDebug(em.c_str());
+        return;
+    }
+    numInputs = MAX_NUMBER_INPUT_DEVICES;
+    res = (*AudioIODeviceCapabilitiesItf)->GetAvailableAudioInputs( AudioIODeviceCapabilitiesItf, &numInputs, InputDeviceIDs);
+    if(res!=SL_RESULT_SUCCESS) {
+        string em = "Can't enumerate audio input devices ";
+        em += SLESErrorToString(res);
+        qDebug(em.c_str());
+        return;
+    }
+    for (SLint32 i=0;i<numInputs; i++)
+    {
+        SLAudioInputDescriptor AudioInputDescriptor;
+        res = (*AudioIODeviceCapabilitiesItf)->QueryAudioInputCapabilities(
+                    AudioIODeviceCapabilitiesItf, InputDeviceIDs[i], &AudioInputDescriptor
+              );
+        //CheckErr(res);
+        names.push_back((char*)AudioInputDescriptor.deviceName);
+        descriptions.push_back("(tbd)");
+    }
+
+}
+
+void COpenSLESIn::SetDev(string sNewDevice)
+{
+    currentDevice = sNewDevice;
+
+}
+
+string COpenSLESIn::GetDev()
+{
+    return currentDevice;
+}
+
+int COpenSLESIn::GetSampleRate()
+{
+    return 48000;
+}
+
+_BOOLEAN COpenSLESIn::Init(int iNewSampleRate, int iNewBufferSize, _BOOLEAN bNewBlocking)
+{
+    (void)iNewSampleRate;
+    (void)iNewBufferSize;
+    (void)bNewBlocking;
+    return FALSE;
+}
+
+_BOOLEAN COpenSLESIn::Read(CVector<short>& psData)
+{
+    (void)psData;
+    return FALSE;
+}
+
+void COpenSLESIn::Close()
+{
+
+}
+/*
+
+Grokbase › Groups › Android › android-ndk › August 2012FAQ
+Groups
+ Users
+ Badges
+
+[android-ndk] Errors with OpenSLES recording and the emulator
+  Brendon Costa
+Aug 25, 2012 at 2:12 pm
+
+Hi all,
+
+I have been playing with OpenSLES on Android and all seems to be fine
+except that I have a problem where the emulator fails to record audio. I
+have a small test app based on the native-audio sample (I have cut down to
+relevant portions and pasted below) which works fine on my Android device
+(X10 Mini Pro rooted and re-rom'ed with Cyanogen) but no matter what I do I
+cant get it to work on an emulator.
+
+I have tried creating emulators of different versions, and explicitly
+enabling the audio recording option. Basically when I run the app on the
+emulator I get the following errors from a logcat:
+
+W/libOpenSLES( 459): class Engine interface 0 requested but unavailable
+MPH=9
+E/AudioRecord( 459): Could not get audio input for record source 1
+E/libOpenSLES( 459): android_audioRecorder_realize(0x52438) error creating
+AudioRecord object
+
+I am not using JNI for the moment (though did write a small JNI app that
+used this code to test if there was some permissions thing requiring a
+manifest but had the same problem). Instead I am basically executing the
+binary directly under a root shell on the device using adb.
+
+When running the app I get the following output (error happens when
+realizing the recorder object):
+
+Running: ./clienttest
+result: 9 : SL_RESULT_CONTENT_UNSUPPORTED
+assertion "SL_RESULT_SUCCESS == result" failed: file
+"jni/../../../../AxonCore/make/android/jni/../../../../AxonCore/src/clienttest.cpp",
+line 122, function "int main()"
+[1] Segmentation fault ./clienttest
+
+I figures the problem was an unsupported sample rate or format, but I have
+tried all defined sample rates, and a bunch of other format specifiers for
+the buffer queue and nothing seems to fix the problem.
+
+Any thoughts?
+
+
+
+// for native audio
+#include <SLES/OpenSLES.h>
+#include <SLES/OpenSLES_Android.h>
+
+#include <assert.h>
+#include <iostream>
+#include <math.h>
+#include <limits>
+#include <vector>
+
+static const int CHANNELS = 1; // If not 1 need to set the SLDataFormat_PCM
+channel mask correctly
+static const int SAMPLE_RATE = SL_SAMPLINGRATE_16 / 1000;
+static const int TOTAL_BUFFERS = 2;
+static const unsigned int BUFFER_SIZE = SAMPLE_RATE * CHANNELS * 20 / 1000;
+
+std::vector<std::vector<short> > record_buffers;
+unsigned int next_record_buffer_index = 0;
+
+void bqRecorderCallback(SLAndroidSimpleBufferQueueItf bq, void *context)
+{
+std::vector<short>& buffer(record_buffers[next_record_buffer_index %
+TOTAL_BUFFERS]);
+++next_record_buffer_index;
+
+
+SLresult result;
+result = (*bq)->Enqueue(bq, &buffer[0], buffer.size()*sizeof(short));
+if (SL_RESULT_SUCCESS != result)
+{
+std::cerr << "Failed to enqueue record buffer: " <<
+next_record_buffer_index << std::endl;
+}
+}
+
+static const char* SLESErrorToString(SLresult result)
+{
+switch (result)
+{
+case SL_RESULT_SUCCESS: return "SUCCESS";
+case SL_RESULT_PRECONDITIONS_VIOLATED: return
+"SL_RESULT_PRECONDITIONS_VIOLATED";
+case SL_RESULT_PARAMETER_INVALID: return "SL_RESULT_PARAMETER_INVALID";
+case SL_RESULT_MEMORY_FAILURE: return "SL_RESULT_MEMORY_FAILURE";
+case SL_RESULT_RESOURCE_ERROR: return "SL_RESULT_RESOURCE_ERROR";
+case SL_RESULT_RESOURCE_LOST: return "SL_RESULT_RESOURCE_LOST";
+case SL_RESULT_IO_ERROR: return "SL_RESULT_IO_ERROR";
+case SL_RESULT_BUFFER_INSUFFICIENT: return "SL_RESULT_BUFFER_INSUFFICIENT";
+case SL_RESULT_CONTENT_CORRUPTED: return "SL_RESULT_CONTENT_CORRUPTED";
+case SL_RESULT_CONTENT_UNSUPPORTED: return "SL_RESULT_CONTENT_UNSUPPORTED";
+case SL_RESULT_CONTENT_NOT_FOUND: return "SL_RESULT_CONTENT_NOT_FOUND";
+case SL_RESULT_PERMISSION_DENIED: return "SL_RESULT_PERMISSION_DENIED";
+case SL_RESULT_FEATURE_UNSUPPORTED: return "SL_RESULT_FEATURE_UNSUPPORTED";
+case SL_RESULT_INTERNAL_ERROR: return "SL_RESULT_INTERNAL_ERROR";
+case SL_RESULT_UNKNOWN_ERROR: return "SL_RESULT_UNKNOWN_ERROR";
+case SL_RESULT_OPERATION_ABORTED: return "SL_RESULT_OPERATION_ABORTED";
+case SL_RESULT_CONTROL_LOST: return "SL_RESULT_CONTROL_LOST";
+default: return "Unknown";
+}
+}
+
+int main()
+{
+record_buffers.resize(TOTAL_BUFFERS);
+for (size_t i = 0; i < record_buffers.size(); ++i)
+{
+record_buffers[i].resize(BUFFER_SIZE, 0);
+}
+next_record_buffer_index = 0;
+
+
+SLresult result;
+
+const SLInterfaceID engine_ids[] = {SL_IID_AUDIOIODEVICECAPABILITIES};
+const SLboolean engine_req[] = {SL_BOOLEAN_FALSE};
+// create engine
+SLObjectItf engineObject = NULL;
+result = slCreateEngine(&engineObject, 0, NULL, 1, engine_ids, engine_req);
+assert(SL_RESULT_SUCCESS == result);
+
+// realize the engine
+result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
+assert(SL_RESULT_SUCCESS == result);
+
+// get the engine interface, which is needed in order to create other
+objects
+SLEngineItf engineEngine;
+result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE,
+&engineEngine);
+assert(SL_RESULT_SUCCESS == result);
+
+// recorder interfaces
+SLObjectItf recorderObject = NULL;
+SLRecordItf recorderRecord;
+SLAndroidSimpleBufferQueueItf recorderBufferQueue;
+SLDataFormat_PCM rec_format_pcm =
+{
+SL_DATAFORMAT_PCM // Format type
+, CHANNELS // Channels
+, SL_SAMPLINGRATE_16 // (in millihertz apparently)
+, SL_PCMSAMPLEFORMAT_FIXED_16 // bits per sample
+, SL_PCMSAMPLEFORMAT_FIXED_16 // container size
+, SL_SPEAKER_FRONT_CENTER // channel mask
+, SL_BYTEORDER_LITTLEENDIAN // endianess
+};
+
+// configure audio source
+SLDataLocator_IODevice rec_loc_dev = {SL_DATALOCATOR_IODEVICE,
+SL_IODEVICE_AUDIOINPUT, SL_DEFAULTDEVICEID_AUDIOINPUT, NULL};
+SLDataSource rec_audioSrc = {&rec_loc_dev, NULL};
+
+// configure audio sink
+SLDataLocator_AndroidSimpleBufferQueue rec_loc_bq =
+{SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, TOTAL_BUFFERS};
+SLDataSink rec_audioSnk = {&rec_loc_bq, &rec_format_pcm};
+
+// create audio recorder
+// (requires the RECORD_AUDIO permission)
+const SLInterfaceID rec_id[] = {SL_IID_ANDROIDSIMPLEBUFFERQUEUE};
+const SLboolean rec_req[] = {SL_BOOLEAN_TRUE};
+result = (*engineEngine)->CreateAudioRecorder(engineEngine,
+&recorderObject, &rec_audioSrc, &rec_audioSnk, 1, rec_id, rec_req);
+assert(SL_RESULT_SUCCESS == result);
+
+// realize the audio recorder
+result = (*recorderObject)->Realize(recorderObject, SL_BOOLEAN_FALSE);
+std::cerr << "result: " << result << " : " << SLESErrorToString(result) <<
+std::endl;
+assert(SL_RESULT_SUCCESS == result);
+
+// get the record interface
+result = (*recorderObject)->GetInterface(recorderObject, SL_IID_RECORD,
+&recorderRecord);
+assert(SL_RESULT_SUCCESS == result);
+
+// get the buffer queue interface
+result = (*recorderObject)->GetInterface(recorderObject,
+SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &recorderBufferQueue);
+assert(SL_RESULT_SUCCESS == result);
+
+// register callback on the buffer queue
+result = (*recorderBufferQueue)->RegisterCallback(recorderBufferQueue,
+bqRecorderCallback, NULL);
+assert(SL_RESULT_SUCCESS == result);
+// in case already recording, stop recording and clear buffer queue
+result = (*recorderRecord)->SetRecordState(recorderRecord,
+SL_RECORDSTATE_STOPPED);
+assert(SL_RESULT_SUCCESS == result);
+result = (*recorderBufferQueue)->Clear(recorderBufferQueue);
+assert(SL_RESULT_SUCCESS == result);
+
+
+for (size_t i = 0; i < TOTAL_BUFFERS; ++i)
+{
+// @todo bcost : Enqueue should have size * sizeof(short) BUT DOES NOT
+//result = (*recorderBufferQueue)->Enqueue(recorderBufferQueue,
+recorderBuffer, RECORDER_FRAMES * sizeof(short));
+result = (*recorderBufferQueue)->Enqueue(recorderBufferQueue,
+&record_buffers[i][0], record_buffers[i].size()*sizeof(short));
+assert(SL_RESULT_SUCCESS == result);
+}
+
+// start recording
+result = (*recorderRecord)->SetRecordState(recorderRecord,
+SL_RECORDSTATE_RECORDING);
+assert(SL_RESULT_SUCCESS == result);
+// Start main loop
+std::cerr << "Starting main loop" << std::endl;
+while (true)
+{
+usleep(100000);
+}
+// @todo : Test app need to add cleanup and proper exit
+return 0;
+}
+
+
+--
+You received this message because you are subscribed to the Google Groups "android-ndk" group.
+To post to this group, send email to android-ndk at googlegroups.com.
+To unsubscribe from this group, send email to android-ndk+unsubscribe at googlegroups.com.
+For more options, visit this group at http://groups.google.com/group/android-ndk?hl=en.
+reply
+
+
+Search Discussions
+
+ All Groups  Android  android-ndk
+5 responsesNested Oldest
+  Doug Emulators have never done well with recording audio. Best stick with your device. Or mock your audio recording source if you want to use the emulator. Doug -- You received this message because you are subscribed to the Google Groups "android-ndk" group. To view this discussion on the web visit https://groups.google.com/d/msg/android-ndk/-/OrFmZ47xNAwJ. To post to this group, send email to android-ndk at googlegroups.com. To unsubscribe from this group, send email to
+  Doug  at Aug 26, 2012 at 5:15 pm  ⇧
+
+Emulators have never done well with recording audio. Best stick with your
+device. Or mock your audio recording source if you want to use the
+emulator.
+
+Doug
+
+On Friday, August 24, 2012 9:09:45 PM UTC-7, Brendon Costa wrote:
+
+Hi all,
+
+I have been playing with OpenSLES on Android and all seems to be fine
+except that I have a problem where the emulator fails to record audio. I
+have a small test app based on the native-audio sample (I have cut down to
+relevant portions and pasted below) which works fine on my Android device
+(X10 Mini Pro rooted and re-rom'ed with Cyanogen) but no matter what I do I
+cant get it to work on an emulator.
+
+I have tried creating emulators of different versions, and explicitly
+enabling the audio recording option. Basically when I run the app on the
+emulator I get the following errors from a logcat:
+
+W/libOpenSLES( 459): class Engine interface 0 requested but unavailable
+MPH=9
+E/AudioRecord( 459): Could not get audio input for record source 1
+E/libOpenSLES( 459): android_audioRecorder_realize(0x52438) error
+creating AudioRecord object
+
+I am not using JNI for the moment (though did write a small JNI app that
+used this code to test if there was some permissions thing requiring a
+manifest but had the same problem). Instead I am basically executing the
+binary directly under a root shell on the device using adb.
+
+When running the app I get the following output (error happens when
+realizing the recorder object):
+
+Running: ./clienttest
+result: 9 : SL_RESULT_CONTENT_UNSUPPORTED
+assertion "SL_RESULT_SUCCESS == result" failed: file
+"jni/../../../../AxonCore/make/android/jni/../../../../AxonCore/src/clienttest.cpp",
+line 122, function "int main()"
+[1] Segmentation fault ./clienttest
+
+I figures the problem was an unsupported sample rate or format, but I have
+tried all defined sample rates, and a bunch of other format specifiers for
+the buffer queue and nothing seems to fix the problem.
+
+Any thoughts?
+
+
+
+// for native audio
+#include <SLES/OpenSLES.h>
+#include <SLES/OpenSLES_Android.h>
+
+#include <assert.h>
+#include <iostream>
+#include <math.h>
+#include <limits>
+#include <vector>
+
+static const int CHANNELS = 1; // If not 1 need to set the
+SLDataFormat_PCM channel mask correctly
+static const int SAMPLE_RATE = SL_SAMPLINGRATE_16 / 1000;
+static const int TOTAL_BUFFERS = 2;
+static const unsigned int BUFFER_SIZE = SAMPLE_RATE * CHANNELS * 20 / 1000;
+
+std::vector<std::vector<short> > record_buffers;
+unsigned int next_record_buffer_index = 0;
+
+void bqRecorderCallback(SLAndroidSimpleBufferQueueItf bq, void *context)
+{
+std::vector<short>& buffer(record_buffers[next_record_buffer_index %
+TOTAL_BUFFERS]);
+++next_record_buffer_index;
+
+
+SLresult result;
+result = (*bq)->Enqueue(bq, &buffer[0], buffer.size()*sizeof(short));
+if (SL_RESULT_SUCCESS != result)
+{
+std::cerr << "Failed to enqueue record buffer: " <<
+next_record_buffer_index << std::endl;
+}
+}
+
+static const char* SLESErrorToString(SLresult result)
+{
+switch (result)
+{
+case SL_RESULT_SUCCESS: return "SUCCESS";
+case SL_RESULT_PRECONDITIONS_VIOLATED: return
+"SL_RESULT_PRECONDITIONS_VIOLATED";
+case SL_RESULT_PARAMETER_INVALID: return "SL_RESULT_PARAMETER_INVALID";
+case SL_RESULT_MEMORY_FAILURE: return "SL_RESULT_MEMORY_FAILURE";
+case SL_RESULT_RESOURCE_ERROR: return "SL_RESULT_RESOURCE_ERROR";
+case SL_RESULT_RESOURCE_LOST: return "SL_RESULT_RESOURCE_LOST";
+case SL_RESULT_IO_ERROR: return "SL_RESULT_IO_ERROR";
+case SL_RESULT_BUFFER_INSUFFICIENT: return "SL_RESULT_BUFFER_INSUFFICIENT";
+case SL_RESULT_CONTENT_CORRUPTED: return "SL_RESULT_CONTENT_CORRUPTED";
+case SL_RESULT_CONTENT_UNSUPPORTED: return "SL_RESULT_CONTENT_UNSUPPORTED";
+case SL_RESULT_CONTENT_NOT_FOUND: return "SL_RESULT_CONTENT_NOT_FOUND";
+case SL_RESULT_PERMISSION_DENIED: return "SL_RESULT_PERMISSION_DENIED";
+case SL_RESULT_FEATURE_UNSUPPORTED: return
+"SL_RESULT_FEATURE_UNSUPPORTED";
+case SL_RESULT_INTERNAL_ERROR: return "SL_RESULT_INTERNAL_ERROR";
+case SL_RESULT_UNKNOWN_ERROR: return "SL_RESULT_UNKNOWN_ERROR";
+case SL_RESULT_OPERATION_ABORTED: return "SL_RESULT_OPERATION_ABORTED";
+case SL_RESULT_CONTROL_LOST: return "SL_RESULT_CONTROL_LOST";
+default: return "Unknown";
+}
+}
+
+int main()
+{
+record_buffers.resize(TOTAL_BUFFERS);
+for (size_t i = 0; i < record_buffers.size(); ++i)
+{
+record_buffers[i].resize(BUFFER_SIZE, 0);
+}
+next_record_buffer_index = 0;
+
+
+SLresult result;
+
+const SLInterfaceID engine_ids[] = {SL_IID_AUDIOIODEVICECAPABILITIES};
+const SLboolean engine_req[] = {SL_BOOLEAN_FALSE};
+// create engine
+SLObjectItf engineObject = NULL;
+result = slCreateEngine(&engineObject, 0, NULL, 1, engine_ids,
+engine_req);
+assert(SL_RESULT_SUCCESS == result);
+
+// realize the engine
+result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
+assert(SL_RESULT_SUCCESS == result);
+
+// get the engine interface, which is needed in order to create other
+objects
+SLEngineItf engineEngine;
+result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE,
+&engineEngine);
+assert(SL_RESULT_SUCCESS == result);
+
+// recorder interfaces
+SLObjectItf recorderObject = NULL;
+SLRecordItf recorderRecord;
+SLAndroidSimpleBufferQueueItf recorderBufferQueue;
+SLDataFormat_PCM rec_format_pcm =
+{
+SL_DATAFORMAT_PCM // Format type
+, CHANNELS // Channels
+, SL_SAMPLINGRATE_16 // (in millihertz apparently)
+, SL_PCMSAMPLEFORMAT_FIXED_16 // bits per sample
+, SL_PCMSAMPLEFORMAT_FIXED_16 // container size
+, SL_SPEAKER_FRONT_CENTER // channel mask
+, SL_BYTEORDER_LITTLEENDIAN // endianess
+};
+
+// configure audio source
+SLDataLocator_IODevice rec_loc_dev = {SL_DATALOCATOR_IODEVICE,
+SL_IODEVICE_AUDIOINPUT, SL_DEFAULTDEVICEID_AUDIOINPUT, NULL};
+SLDataSource rec_audioSrc = {&rec_loc_dev, NULL};
+
+// configure audio sink
+SLDataLocator_AndroidSimpleBufferQueue rec_loc_bq =
+{SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, TOTAL_BUFFERS};
+SLDataSink rec_audioSnk = {&rec_loc_bq, &rec_format_pcm};
+
+// create audio recorder
+// (requires the RECORD_AUDIO permission)
+const SLInterfaceID rec_id[] = {SL_IID_ANDROIDSIMPLEBUFFERQUEUE};
+const SLboolean rec_req[] = {SL_BOOLEAN_TRUE};
+result = (*engineEngine)->CreateAudioRecorder(engineEngine,
+&recorderObject, &rec_audioSrc, &rec_audioSnk, 1, rec_id, rec_req);
+assert(SL_RESULT_SUCCESS == result);
+
+// realize the audio recorder
+result = (*recorderObject)->Realize(recorderObject, SL_BOOLEAN_FALSE);
+std::cerr << "result: " << result << " : " << SLESErrorToString(result) <<
+std::endl;
+assert(SL_RESULT_SUCCESS == result);
+
+// get the record interface
+result = (*recorderObject)->GetInterface(recorderObject, SL_IID_RECORD,
+&recorderRecord);
+assert(SL_RESULT_SUCCESS == result);
+
+// get the buffer queue interface
+result = (*recorderObject)->GetInterface(recorderObject,
+SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &recorderBufferQueue);
+assert(SL_RESULT_SUCCESS == result);
+
+// register callback on the buffer queue
+result = (*recorderBufferQueue)->RegisterCallback(recorderBufferQueue,
+bqRecorderCallback, NULL);
+assert(SL_RESULT_SUCCESS == result);
+// in case already recording, stop recording and clear buffer queue
+result = (*recorderRecord)->SetRecordState(recorderRecord,
+SL_RECORDSTATE_STOPPED);
+assert(SL_RESULT_SUCCESS == result);
+result = (*recorderBufferQueue)->Clear(recorderBufferQueue);
+assert(SL_RESULT_SUCCESS == result);
+
+
+for (size_t i = 0; i < TOTAL_BUFFERS; ++i)
+{
+// @todo bcost : Enqueue should have size * sizeof(short) BUT DOES NOT
+//result = (*recorderBufferQueue)->Enqueue(recorderBufferQueue,
+recorderBuffer, RECORDER_FRAMES * sizeof(short));
+result = (*recorderBufferQueue)->Enqueue(recorderBufferQueue,
+&record_buffers[i][0], record_buffers[i].size()*sizeof(short));
+assert(SL_RESULT_SUCCESS == result);
+}
+
+// start recording
+result = (*recorderRecord)->SetRecordState(recorderRecord,
+SL_RECORDSTATE_RECORDING);
+assert(SL_RESULT_SUCCESS == result);
+// Start main loop
+std::cerr << "Starting main loop" << std::endl;
+while (true)
+{
+usleep(100000);
+}
+// @todo : Test app need to add cleanup and proper exit
+return 0;
+}
+
+
+
+--
+You received this message because you are subscribed to the Google Groups "android-ndk" group.
+To view this discussion on the web visit https://groups.google.com/d/msg/android-ndk/-/OrFmZ47xNAwJ.
+To post to this group, send email to android-ndk at googlegroups.com.
+To unsubscribe from this group, send email to android-ndk+unsubscribe at googlegroups.com.
+For more options, visit this group at http://groups.google.com/group/android-ndk?hl=en.
+reply | permalink
+  Saeed Abbassi Hi Brendon I've tested this example on OpenSL-ES and it works fine, Android audio streaming with OpenSL ES and the NDK Pay attention to getting audio permission before recording, good luck saeed Le samedi 25 août 2012 08:39:45 UTC+4:30, Brendon Costa a écrit : -- You received this message because you are subscribed to the Google Groups "android-ndk" group. To view this discussion on the web visit https://groups.google.com/d/msg/android-ndk/-/svHQumNGJ04J. To post to this  [...]
+  Saeed Abbassi  at Sep 6, 2012 at 6:35 am  ⇧
+
+Hi Brendon
+
+I've tested this example on OpenSL-ES and it works fine,
+
+Android audio streaming with OpenSL ES and the NDK
+
+Pay attention to getting audio permission before recording,
+
+good luck
+saeed
+
+
+Le samedi 25 août 2012 08:39:45 UTC+4:30, Brendon Costa a écrit :
+
+Hi all,
+
+I have been playing with OpenSLES on Android and all seems to be fine
+except that I have a problem where the emulator fails to record audio. I
+have a small test app based on the native-audio sample (I have cut down to
+relevant portions and pasted below) which works fine on my Android device
+(X10 Mini Pro rooted and re-rom'ed with Cyanogen) but no matter what I do I
+cant get it to work on an emulator.
+
+I have tried creating emulators of different versions, and explicitly
+enabling the audio recording option. Basically when I run the app on the
+emulator I get the following errors from a logcat:
+
+W/libOpenSLES( 459): class Engine interface 0 requested but unavailable
+MPH=9
+E/AudioRecord( 459): Could not get audio input for record source 1
+E/libOpenSLES( 459): android_audioRecorder_realize(0x52438) error
+creating AudioRecord object
+
+I am not using JNI for the moment (though did write a small JNI app that
+used this code to test if there was some permissions thing requiring a
+manifest but had the same problem). Instead I am basically executing the
+binary directly under a root shell on the device using adb.
+
+When running the app I get the following output (error happens when
+realizing the recorder object):
+
+Running: ./clienttest
+result: 9 : SL_RESULT_CONTENT_UNSUPPORTED
+assertion "SL_RESULT_SUCCESS == result" failed: file
+"jni/../../../../AxonCore/make/android/jni/../../../../AxonCore/src/clienttest.cpp",
+line 122, function "int main()"
+[1] Segmentation fault ./clienttest
+
+I figures the problem was an unsupported sample rate or format, but I have
+tried all defined sample rates, and a bunch of other format specifiers for
+the buffer queue and nothing seems to fix the problem.
+
+Any thoughts?
+
+
+
+// for native audio
+#include <SLES/OpenSLES.h>
+#include <SLES/OpenSLES_Android.h>
+
+#include <assert.h>
+#include <iostream>
+#include <math.h>
+#include <limits>
+#include <vector>
+
+static const int CHANNELS = 1; // If not 1 need to set the
+SLDataFormat_PCM channel mask correctly
+static const int SAMPLE_RATE = SL_SAMPLINGRATE_16 / 1000;
+static const int TOTAL_BUFFERS = 2;
+static const unsigned int BUFFER_SIZE = SAMPLE_RATE * CHANNELS * 20 / 1000;
+
+std::vector<std::vector<short> > record_buffers;
+unsigned int next_record_buffer_index = 0;
+
+void bqRecorderCallback(SLAndroidSimpleBufferQueueItf bq, void *context)
+{
+std::vector<short>& buffer(record_buffers[next_record_buffer_index %
+TOTAL_BUFFERS]);
+++next_record_buffer_index;
+
+
+SLresult result;
+result = (*bq)->Enqueue(bq, &buffer[0], buffer.size()*sizeof(short));
+if (SL_RESULT_SUCCESS != result)
+{
+std::cerr << "Failed to enqueue record buffer: " <<
+next_record_buffer_index << std::endl;
+}
+}
+
+int main()
+{
+record_buffers.resize(TOTAL_BUFFERS);
+for (size_t i = 0; i < record_buffers.size(); ++i)
+{
+record_buffers[i].resize(BUFFER_SIZE, 0);
+}
+next_record_buffer_index = 0;
+
+
+SLresult result;
+
+const SLInterfaceID engine_ids[] = {SL_IID_AUDIOIODEVICECAPABILITIES};
+const SLboolean engine_req[] = {SL_BOOLEAN_FALSE};
+// create engine
+SLObjectItf engineObject = NULL;
+result = slCreateEngine(&engineObject, 0, NULL, 1, engine_ids,
+engine_req);
+assert(SL_RESULT_SUCCESS == result);
+
+// realize the engine
+result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
+assert(SL_RESULT_SUCCESS == result);
+
+// get the engine interface, which is needed in order to create other
+objects
+SLEngineItf engineEngine;
+result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE,
+&engineEngine);
+assert(SL_RESULT_SUCCESS == result);
+
+// recorder interfaces
+SLObjectItf recorderObject = NULL;
+SLRecordItf recorderRecord;
+SLAndroidSimpleBufferQueueItf recorderBufferQueue;
+SLDataFormat_PCM rec_format_pcm =
+{
+SL_DATAFORMAT_PCM // Format type
+, CHANNELS // Channels
+, SL_SAMPLINGRATE_16 // (in millihertz apparently)
+, SL_PCMSAMPLEFORMAT_FIXED_16 // bits per sample
+, SL_PCMSAMPLEFORMAT_FIXED_16 // container size
+, SL_SPEAKER_FRONT_CENTER // channel mask
+, SL_BYTEORDER_LITTLEENDIAN // endianess
+};
+
+// configure audio source
+SLDataLocator_IODevice rec_loc_dev = {SL_DATALOCATOR_IODEVICE,
+SL_IODEVICE_AUDIOINPUT, SL_DEFAULTDEVICEID_AUDIOINPUT, NULL};
+SLDataSource rec_audioSrc = {&rec_loc_dev, NULL};
+
+// configure audio sink
+SLDataLocator_AndroidSimpleBufferQueue rec_loc_bq =
+{SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, TOTAL_BUFFERS};
+SLDataSink rec_audioSnk = {&rec_loc_bq, &rec_format_pcm};
+
+// create audio recorder
+// (requires the RECORD_AUDIO permission)
+const SLInterfaceID rec_id[] = {SL_IID_ANDROIDSIMPLEBUFFERQUEUE};
+const SLboolean rec_req[] = {SL_BOOLEAN_TRUE};
+result = (*engineEngine)->CreateAudioRecorder(engineEngine,
+&recorderObject, &rec_audioSrc, &rec_audioSnk, 1, rec_id, rec_req);
+assert(SL_RESULT_SUCCESS == result);
+
+// realize the audio recorder
+result = (*recorderObject)->Realize(recorderObject, SL_BOOLEAN_FALSE);
+std::cerr << "result: " << result << " : " << SLESErrorToString(result) <<
+std::endl;
+assert(SL_RESULT_SUCCESS == result);
+
+// get the record interface
+result = (*recorderObject)->GetInterface(recorderObject, SL_IID_RECORD,
+&recorderRecord);
+assert(SL_RESULT_SUCCESS == result);
+
+// get the buffer queue interface
+result = (*recorderObject)->GetInterface(recorderObject,
+SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &recorderBufferQueue);
+assert(SL_RESULT_SUCCESS == result);
+
+// register callback on the buffer queue
+result = (*recorderBufferQueue)->RegisterCallback(recorderBufferQueue,
+bqRecorderCallback, NULL);
+assert(SL_RESULT_SUCCESS == result);
+// in case already recording, stop recording and clear buffer queue
+result = (*recorderRecord)->SetRecordState(recorderRecord,
+SL_RECORDSTATE_STOPPED);
+assert(SL_RESULT_SUCCESS == result);
+result = (*recorderBufferQueue)->Clear(recorderBufferQueue);
+assert(SL_RESULT_SUCCESS == result);
+
+
+for (size_t i = 0; i < TOTAL_BUFFERS; ++i)
+{
+// @todo bcost : Enqueue should have size * sizeof(short) BUT DOES NOT
+//result = (*recorderBufferQueue)->Enqueue(recorderBufferQueue,
+recorderBuffer, RECORDER_FRAMES * sizeof(short));
+result = (*recorderBufferQueue)->Enqueue(recorderBufferQueue,
+&record_buffers[i][0], record_buffers[i].size()*sizeof(short));
+assert(SL_RESULT_SUCCESS == result);
+}
+
+// start recording
+result = (*recorderRecord)->SetRecordState(recorderRecord,
+SL_RECORDSTATE_RECORDING);
+assert(SL_RESULT_SUCCESS == result);
+// Start main loop
+std::cerr << "Starting main loop" << std::endl;
+while (true)
+{
+usleep(100000);
+}
+// @todo : Test app need to add cleanup and proper exit
+return 0;
+}
+
+
+
+--
+You received this message because you are subscribed to the Google Groups "android-ndk" group.
+To view this discussion on the web visit https://groups.google.com/d/msg/android-ndk/-/svHQumNGJ04J.
+To post to this group, send email to android-ndk at googlegroups.com.
+To unsubscribe from this group, send email to android-ndk+unsubscribe at googlegroups.com.
+For more options, visit this group at http://groups.google.com/group/android-ndk?hl=en.
+reply | permalink
+  Saeed Abbassi When running the executable on android, debugging using gdbserver could help a lot to back trace your program and debug give it a try 2012/9/5 Saeed Abbassi < [email protected] > -- You received this message because you are subscribed to the Google Groups "android-ndk" group. To post to this group, send email to android-ndk at googlegroups.com. To unsubscribe from this group, send email to android-ndk+unsubscribe at googlegroups.com. For more options, visit this group at
+  Saeed Abbassi  at Sep 7, 2012 at 1:59 am  ⇧
+
+When running the executable on android,
+debugging using gdbserver could help a lot to back trace your program and
+debug
+
+give it a try
+
+2012/9/5 Saeed Abbassi <sae... at ...com>
+
+When running the a
+--
+You received this message because you are subscribed to the Google Groups "android-ndk" group.
+To post to this group, send email to android-ndk at googlegroups.com.
+To unsubscribe from this group, send email to android-ndk+unsubscribe at googlegroups.com.
+For more options, visit this group at http://groups.google.com/group/android-ndk?hl=en.
+reply | permalink
+  Brendon Costa Hi Saeed, Thanks for the response. You mentioned permissions. I did try to create a JNI layer that wrapped the code above and call it from a Java app in which I gave the recording permissions in the manifest and it still didn't work for me. I used: "" Unless there is a way to request the permissions from within the NDK, I am not sure what else I am missing. Would you be willing to provide a tarball or something of the project you got this working in? So you got this to wo [...]
+  Brendon Costa  at Sep 7, 2012 at 2:00 am  ⇧
+
+Hi Saeed,
+
+Thanks for the response.
+
+You mentioned permissions. I did try to create a JNI layer that wrapped the
+code above and call it from a Java app in which I gave the recording
+permissions in the manifest and it still didn't work for me. I used:
+"<uses-permission
+android:name="android.permission.RECORD_AUDIO"></uses-permission>"
+
+Unless there is a way to request the permissions from within the NDK, I am
+not sure what else I am missing.
+
+Would you be willing to provide a tarball or something of the project you
+got this working in?
+
+So you got this to work with the emulator? What platform was the emulator
+running on and how was it configured, maybe that has an effect (I am using
+windows with a emulator at API Level 10, Audio recording support set to
+yes)?
+
+Thanks,
+Brendon.
+
+On Wednesday, 5 September 2012, Saeed Abbassi wrote:
+
+Hi Brendon
+
+I've tested this example on OpenSL-ES and it works fine,
+
+Android audio streaming with OpenSL ES and the NDK
+
+Pay attention to getting audio permission before recording,
+
+good luck
+saeed
+
+
+Le samedi 25 août 2012 08:39:45 UTC+4:30, Brendon Costa a écrit :
+
+Hi all,
+
+I have been playing with OpenSLES on Android and all seems to be fine
+except that I have a problem where the emulator fails to record audio. I
+have a small test app based on the native-audio sample (I have cut down to
+relevant portions and pasted below) which works fine on my Android device
+(X10 Mini Pro rooted and re-rom'ed with Cyanogen) but no matter what I do I
+cant get it to work on an emulator.
+
+I have tried creating emulators of different versions, and explicitly
+enabling the audio recording option. Basically when I run the app on the
+emulator I get the following errors from a logcat:
+
+W/libOpenSLES( 459): class Engine interface 0 requested but unavailable
+MPH=9
+E/AudioRecord( 459): Could not get audio input for record source 1
+E/libOpenSLES( 459): android_audioRecorder_realize(**0x52438) error
+creating AudioRecord object
+
+I am not using JNI for the moment (though did write a small JNI app that
+used this code to test if there was some permissions thing requiring a
+manifest but had the same problem). Instead I am basically executing the
+binary directly under a root shell on the device using adb.
+
+When running the app I get the following output (error happens when
+realizing the recorder object):
+
+Running: ./clienttest
+result: 9 : SL_RESULT_CONTENT_UNSUPPORTED
+assertion "SL_RESULT_SUCCESS == result" failed: file
+line 122, function "int main()"
+[1] Segmentation fault ./clienttest
+
+I figures the problem was an unsupported sample rate or format, but I have
+tried all defined sample rates, and a bunch of other format specifiers for
+the buffer queue and nothing seems to fix the problem.
+
+Any thoughts?
+
+
+
+// for native audio
+#include <SLES/OpenSLES.h>
+#include <SLES/OpenSLES_Android.h>
+
+#include <assert.h>
+#include <iostream>
+#include <math.h>
+#include <limits>
+#include <vector>
+
+static const int CHANNELS = 1; // If not 1 need to set the
+SLDataFormat_PCM channel mask correctly
+static const int SAMPLE_RATE = SL_SAMPLINGRATE_16 / 1000;
+static const int TOTAL_BUFFERS = 2;
+static const unsigned int BUFFER_SIZE = SAMPLE_RATE * CHANNELS * 20 / 1000;
+
+std::vector<std::vector<short> > record_buffers;
+unsigned int next_record_buffer_index = 0;
+
+void bqRecorderCallback(**SLAndroidSimpleBufferQueueItf bq, void *context)
+{
+std::vector<short>& buffer(record_buffers[next_**record_buffer_index %
+TOTAL_BUFFERS]);
+++next_record_buffer_index;
+
+
+SLresult result;
+result = (*bq)->Enqueue(bq, &buffer[0], buffer.size()*sizeof(short));
+if (SL_RESULT_SUCCESS != result)
+{
+std::cerr << "Failed to enqueue record buffer: " <<
+next_record_buffer_index << std::endl;
+}
+}
+
+static const char* SLESErrorToString(SLresult result)
+{
+switch (result)
+{
+case SL_RESULT_SUCCESS: return "SUCCESS";
+case SL_RESULT_PRECONDITIONS_**VIOLATED: return "SL_RESULT_PRECONDITIONS_*
+*VIOLATED";
+case SL_RESULT_PARAMETER_INVALID: return "SL_RESULT_PARAMETER_INVALID";
+case SL_RESULT_MEMORY_FAILURE: return "SL_RESULT_MEMORY_FAILURE";
+case SL_RESULT_RESOURCE_ERROR: return "SL_RESULT_RESOURCE_ERROR";
+case SL_RESULT_RESOURCE_LOST: return "SL_RESULT_RESOURCE_LOST";
+case SL_RESULT_IO_ERROR: return "SL_RESULT_IO_ERROR";
+
+--
+You received this message because you are subscribed to the Google Groups
+"android-ndk" group.
+To view this discussion on the web visit
+https://groups.google.com/d/msg/android-ndk/-/svHQumNGJ04J.
+To post to this group, send email to android-ndk at googlegroups.com<javascript:_e({}, 'cvml', 'android-ndk at googlegroups.com');>
+.
+To unsubscribe from this group, send email to
+android-ndk+unsubscribe at googlegroups.com <javascript:_e({}, 'cvml',
+'android-ndk%2Bunsubscribe at googlegroups.com');>.
+For more options, visit this group at
+http://groups.google.com/group/android-ndk?hl=en.
+--
+You received this message because you are subscribed to the Google Groups "android-ndk" group.
+To post to this group, send email to android-ndk at googlegroups.com.
+To unsubscribe from this group, send email to android-ndk+unsubscribe at googlegroups.com.
+For more options, visit this group at http://groups.google.com/group/android-ndk?hl=en.
+reply | permalink
+  Sylvain Hi Brendon, I thought I made a reply with a suggestion to your issue but apparently I did not. What I experienced is that you can create a recorder in the AVD, but it must be using a 8kHz sample rate. And the tricky part is that you should not attempt to initialize it with another sample rate before, otherwise you will never been able to initialize it successfully. So the way I ended up implementing it is by using __system_property_get to detect whether the kernel is the one us [...]
+  Sylvain  at Sep 7, 2012 at 1:26 pm  ⇧
+
+Hi Brendon,
+
+I thought I made a reply with a suggestion to your issue but apparently I
+did not.
+
+What I experienced is that you can create a recorder in the AVD, but it
+must be using a 8kHz sample rate. And the tricky part is that you should
+not attempt to initialize it with another sample rate before, otherwise you
+will never been able to initialize it successfully. So the way I ended up
+implementing it is by using __system_property_get to detect whether the
+kernel is the one used by qemu, and if yes, I use 8kHz:
+
+#include <sys/system_properties.h>
+...
+char outProperty[PROP_VALUE_MAX];
+__system_property_get("ro.hardware", outProperty);
+SLDataFormat_PCM format_pcm = {SL_DATAFORMAT_PCM, 1, SL_SAMPLINGRATE_16,
+SL_PCMSAMPLEFORMAT_FIXED_16, SL_PCMSAMPLEFORMAT_FIXED_16,
+SL_SPEAKER_FRONT_CENTER, SL_BYTEORDER_LITTLEENDIAN};
+if (strcmp(outProperty,"goldfish") == 0)
+{
+format_pcm.samplesPerSec = SL_SAMPLINGRATE_8;
+}
+
+I hope that helps
+
+On Saturday, August 25, 2012 12:09:45 PM UTC+8, Brendon Costa wrote:
+
+Hi all,
+
+I have been playing with OpenSLES on Android and all seems to be fine
+except that I have a problem where the emulator fails to record audio. I
+have a small test app based on the native-audio sample (I have cut down to
+relevant portions and pasted below) which works fine on my Android device
+(X10 Mini Pro rooted and re-rom'ed with Cyanogen) but no matter what I do I
+cant get it to work on an emulator.
+
+I have tried creating emulators of different versions, and explicitly
+enabling the audio recording option. Basically when I run the app on the
+emulator I get the following errors from a logcat:
+
+W/libOpenSLES( 459): class Engine interface 0 requested but unavailable
+MPH=9
+E/AudioRecord( 459): Could not get audio input for record source 1
+E/libOpenSLES( 459): android_audioRecorder_realize(0x52438) error
+creating AudioRecord object
+
+I am not using JNI for the moment (though did write a small JNI app that
+used this code to test if there was some permissions thing requiring a
+manifest but had the same problem). Instead I am basically executing the
+binary directly under a root shell on the device using adb.
+
+When running the app I get the following output (error happens when
+realizing the recorder object):
+
+Running: ./clienttest
+result: 9 : SL_RESULT_CONTENT_UNSUPPORTED
+assertion "SL_RESULT_SUCCESS == result" failed: file
+"jni/../../../../AxonCore/make/android/jni/../../../../AxonCore/src/clienttest.cpp",
+line 122, function "int main()"
+[1] Segmentation fault ./clienttest
+
+I figures the problem was an unsupported sample rate or format, but I have
+tried all defined sample rates, and a bunch of other format specifiers for
+the buffer queue and nothing seems to fix the problem.
+
+Any thoughts?
+
+
+
+// for native audio
+#include <SLES/OpenSLES.h>
+#include <SLES/OpenSLES_Android.h>
+
+#include <assert.h>
+#include <iostream>
+#include <math.h>
+#include <limits>
+#include <vector>
+
+static const int CHANNELS = 1; // If not 1 need to set the
+SLDataFormat_PCM channel mask correctly
+static const int SAMPLE_RATE = SL_SAMPLINGRATE_16 / 1000;
+static const int TOTAL_BUFFERS = 2;
+static const unsigned int BUFFER_SIZE = SAMPLE_RATE * CHANNELS * 20 / 1000;
+
+std::vector<std::vector<short> > record_buffers;
+unsigned int next_record_buffer_index = 0;
+
+void bqRecorderCallback(SLAndroidSimpleBufferQueueItf bq, void *context)
+{
+std::vector<short>& buffer(record_buffers[next_record_buffer_index %
+TOTAL_BUFFERS]);
+++next_record_buffer_index;
+
+
+SLresult result;
+result = (*bq)->Enqueue(bq, &buffer[0], buffer.size()*sizeof(short));
+if (SL_RESULT_SUCCESS != result)
+{
+std::cerr << "Failed to enqueue record buffer: " <<
+next_record_buffer_index << std::endl;
+}
+}
+
+static const char* SLESErrorToString(SLresult result)
+{
+switch (result)
+{
+case SL_RESULT_SUCCESS: return "SUCCESS";
+case SL_RESULT_PRECONDITIONS_VIOLATED: return
+"SL_RESULT_PRECONDITIONS_VIOLATED";
+case SL_RESULT_PARAMETER_INVALID: return "SL_RESULT_PARAMETER_INVALID";
+case SL_RESULT_MEMORY_FAILURE: return "SL_RESULT_MEMORY_FAILURE";
+case SL_RESULT_RESOURCE_ERROR: return "SL_RESULT_RESOURCE_ERROR";
+case SL_RESULT_RESOURCE_LOST: return "SL_RESULT_RESOURCE_LOST";
+case SL_RESULT_IO_ERROR: return "SL_RESULT_IO_ERROR";
+case SL_RESULT_BUFFER_INSUFFICIENT: return "SL_RESULT_BUFFER_INSUFFICIENT";
+case SL_RESULT_CONTENT_CORRUPTED: return "SL_RESULT_CONTENT_CORRUPTED";
+case SL_RESULT_CONTENT_UNSUPPORTED: return "SL_RESULT_CONTENT_UNSUPPORTED";
+case SL_RESULT_CONTENT_NOT_FOUND: return "SL_RESULT_CONTENT_NOT_FOUND";
+case SL_RESULT_PERMISSION_DENIED: return "SL_RESULT_PERMISSION_DENIED";
+case SL_RESULT_FEATURE_UNSUPPORTED: return
+"SL_RESULT_FEATURE_UNSUPPORTED";
+case SL_RESULT_INTERNAL_ERROR: return "SL_RESULT_INTERNAL_ERROR";
+case SL_RESULT_UNKNOWN_ERROR: return "SL_RESULT_UNKNOWN_ERROR";
+case SL_RESULT_OPERATION_ABORTED: return "SL_RESULT_OPERATION_ABORTED";
+case SL_RESULT_CONTROL_LOST: return "SL_RESULT_CONTROL_LOST";
+default: return "Unknown";
+}
+}
+
+int main()
+{
+record_buffers.resize(TOTAL_BUFFERS);
+for (size_t i = 0; i < record_buffers.size(); ++i)
+{
+record_buffers[i].resize(BUFFER_SIZE, 0);
+}
+next_record_buffer_index = 0;
+
+
+SLresult result;
+
+const SLInterfaceID engine_ids[] = {SL_IID_AUDIOIODEVICECAPABILITIES};
+const SLboolean engine_req[] = {SL_BOOLEAN_FALSE};
+// create engine
+SLObjectItf engineObject = NULL;
+result = slCreateEngine(&engineObject, 0, NULL, 1, engine_ids,
+engine_req);
+assert(SL_RESULT_SUCCESS == result);
+
+// realize the engine
+result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
+assert(SL_RESULT_SUCCESS == result);
+
+// get the engine interface, which is needed in order to create other
+objects
+SLEngineItf engineEngine;
+result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE,
+&engineEngine);
+assert(SL_RESULT_SUCCESS == result);
+
+// recorder interfaces
+SLObjectItf recorderObject = NULL;
+SLRecordItf recorderRecord;
+SLAndroidSimpleBufferQueueItf recorderBufferQueue;
+SLDataFormat_PCM rec_format_pcm =
+{
+SL_DATAFORMAT_PCM // Format type
+, CHANNELS // Channels
+, SL_SAMPLINGRATE_16 // (in millihertz apparently)
+, SL_PCMSAMPLEFORMAT_FIXED_16 // bits per sample
+, SL_PCMSAMPLEFORMAT_FIXED_16 // container size
+, SL_SPEAKER_FRONT_CENTER // channel mask
+, SL_BYTEORDER_LITTLEENDIAN // endianess
+};
+
+// configure audio source
+SLDataLocator_IODevice rec_loc_dev = {SL_DATALOCATOR_IODEVICE,
+SL_IODEVICE_AUDIOINPUT, SL_DEFAULTDEVICEID_AUDIOINPUT, NULL};
+SLDataSource rec_audioSrc = {&rec_loc_dev, NULL};
+
+// configure audio sink
+SLDataLocator_AndroidSimpleBufferQueue rec_loc_bq =
+{SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, TOTAL_BUFFERS};
+SLDataSink rec_audioSnk = {&rec_loc_bq, &rec_format_pcm};
+
+// create audio recorder
+// (requires the RECORD_AUDIO permission)
+const SLInterfaceID rec_id[] = {SL_IID_ANDROIDSIMPLEBUFFERQUEUE};
+const SLboolean rec_req[] = {SL_BOOLEAN_TRUE};
+result = (*engineEngine)->CreateAudioRecorder(engineEngine,
+&recorderObject, &rec_audioSrc, &rec_audioSnk, 1, rec_id, rec_req);
+assert(SL_RESULT_SUCCESS == result);
+
+// realize the audio recorder
+result = (*recorderObject)->Realize(recorderObject, SL_BOOLEAN_FALSE);
+std::cerr << "result: " << result << " : " << SLESErrorToString(result) <<
+std::endl;
+assert(SL_RESULT_SUCCESS == result);
+
+// get the record interface
+result = (*recorderObject)->GetInterface(recorderObject, SL_IID_RECORD,
+&recorderRecord);
+assert(SL_RESULT_SUCCESS == result);
+
+// get the buffer queue interface
+result = (*recorderObject)->GetInterface(recorderObject,
+SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &recorderBufferQueue);
+assert(SL_RESULT_SUCCESS == result);
+
+// register callback on the buffer queue
+result = (*recorderBufferQueue)->RegisterCallback(recorderBufferQueue,
+bqRecorderCallback, NULL);
+assert(SL_RESULT_SUCCESS == result);
+// in case already recording, stop recording and clear buffer queue
+result = (*recorderRecord)->SetRecordState(recorderRecord,
+SL_RECORDSTATE_STOPPED);
+assert(SL_RESULT_SUCCESS == result);
+result = (*recorderBufferQueue)->Clear(recorderBufferQueue);
+assert(SL_RESULT_SUCCESS == result);
+
+
+for (size_t i = 0; i < TOTAL_BUFFERS; ++i)
+{
+// @todo bcost : Enqueue should have size * sizeof(short) BUT DOES NOT
+//result = (*recorderBufferQueue)->Enqueue(recorderBufferQueue,
+recorderBuffer, RECORDER_FRAMES * sizeof(short));
+result = (*recorderBufferQueue)->Enqueue(recorderBufferQueue,
+&record_buffers[i][0], record_buffers[i].size()*sizeof(short));
+assert(SL_RESULT_SUCCESS == result);
+}
+
+// start recording
+result = (*recorderRecord)->SetRecordState(recorderRecord,
+SL_RECORDSTATE_RECORDING);
+assert(SL_RESULT_SUCCESS == result);
+// Start main loop
+std::cerr << "Starting main loop" << std::endl;
+while (true)
+{
+usleep(100000);
+}
+// @todo : Test app need to add cleanup and proper exit
+return 0;
+}
+
+ */
diff --git a/src/android/soundin.h b/src/android/soundin.h
new file mode 100644
index 0000000..95c7376
--- /dev/null
+++ b/src/android/soundin.h
@@ -0,0 +1,26 @@
+#ifndef SOUNDIN_H
+#define SOUNDIN_H
+
+#include "../sound/soundinterface.h"
+
+/* Classes ********************************************************************/
+class COpenSLESIn : public CSoundInInterface
+{
+public:
+    COpenSLESIn();
+    virtual ~COpenSLESIn();
+
+    virtual void		Enumerate(vector<string>&, vector<string>&);
+    virtual void		SetDev(string sNewDevice);
+    virtual string		GetDev();
+    virtual int			GetSampleRate();
+
+    virtual _BOOLEAN	Init(int iNewSampleRate, int iNewBufferSize, _BOOLEAN bNewBlocking);
+    virtual _BOOLEAN 	Read(CVector<short>& psData);
+    virtual void 		Close();
+
+protected:
+    string currentDevice;
+};
+
+#endif // SOUNDIN_H
diff --git a/src/android/soundout.cpp b/src/android/soundout.cpp
new file mode 100644
index 0000000..f2063af
--- /dev/null
+++ b/src/android/soundout.cpp
@@ -0,0 +1,79 @@
+#include "soundout.h"
+#include <SLES/OpenSLES.h>
+
+extern SLObjectItf engineObject;
+
+const int MAX_NUMBER_OUTPUT_DEVICES = 10;
+
+COpenSLESOut::COpenSLESOut():currentDevice("")
+{
+}
+
+COpenSLESOut::~COpenSLESOut()
+{
+
+}
+
+void COpenSLESOut::Enumerate(vector<string>& names, vector<string>& descriptions)
+{
+    SLuint32 OutputDeviceIDs[MAX_NUMBER_OUTPUT_DEVICES];
+    SLint32 numOutputs = 0;
+
+    //(*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine);
+    /* Get the Audio IO DEVICE CAPABILITIES interface */
+    SLAudioIODeviceCapabilitiesItf AudioIODeviceCapabilitiesItf;
+    SLresult res = (*engineObject)->GetInterface(engineObject, SL_IID_AUDIOIODEVICECAPABILITIES, (void*)&AudioIODeviceCapabilitiesItf);
+    if(res!=SL_RESULT_SUCCESS) {
+        string em = "Can't get audio output device capabilities";
+        //em += SLESErrorToString(res);
+        qDebug(em.c_str());
+        return;
+    }
+    numOutputs = MAX_NUMBER_OUTPUT_DEVICES;
+    res = (*AudioIODeviceCapabilitiesItf)->GetAvailableAudioOutputs( AudioIODeviceCapabilitiesItf, &numOutputs, OutputDeviceIDs);
+    /* Search for phone earpiece output and phone speaker device */
+    for (SLint32 i=0;i<numOutputs; i++)
+    {
+        SLAudioOutputDescriptor AudioOutputDescriptor;
+        res = (*AudioIODeviceCapabilitiesItf)->QueryAudioOutputCapabilities(
+                    AudioIODeviceCapabilitiesItf, OutputDeviceIDs[i], &AudioOutputDescriptor
+              );
+        //CheckErr(res);
+        names.push_back((char*)AudioOutputDescriptor.pDeviceName);
+        descriptions.push_back("(tbd)");
+    }
+}
+
+void COpenSLESOut::SetDev(string sNewDevice)
+{
+    currentDevice = sNewDevice;
+}
+
+string COpenSLESOut::GetDev()
+{
+    return currentDevice;
+}
+
+int COpenSLESOut::GetSampleRate()
+{
+    return 48000;
+}
+
+_BOOLEAN COpenSLESOut::Init(int iNewSampleRate, int iNewBufferSize, _BOOLEAN bNewBlocking)
+{
+    (void)iNewSampleRate;
+    (void)iNewBufferSize;
+    (void)bNewBlocking;
+    return TRUE;
+}
+
+_BOOLEAN COpenSLESOut::Write(CVector<short>& psData)
+{
+    (void)psData;
+    return TRUE;
+}
+
+void COpenSLESOut::Close()
+{
+
+}
diff --git a/src/android/soundout.h b/src/android/soundout.h
new file mode 100644
index 0000000..5fbb564
--- /dev/null
+++ b/src/android/soundout.h
@@ -0,0 +1,26 @@
+#ifndef SOUNDOUT_H
+#define SOUNDOUT_H
+
+#include "../sound/soundinterface.h"
+
+/* Classes ********************************************************************/
+class COpenSLESOut : public CSoundOutInterface
+{
+public:
+    COpenSLESOut();
+    virtual ~COpenSLESOut();
+
+    virtual void		Enumerate(vector<string>&, vector<string>&);
+    virtual void		SetDev(string sNewDevice);
+    virtual string		GetDev();
+    virtual int			GetSampleRate();
+
+    virtual _BOOLEAN	Init(int iNewSampleRate, int iNewBufferSize, _BOOLEAN bNewBlocking);
+    virtual _BOOLEAN 	Write(CVector<short>& psData);
+    virtual void 		Close();
+
+protected:
+    string currentDevice;
+};
+
+#endif // SOUNDOUT_H
diff --git a/src/chanest/ChanEstTime.cpp b/src/chanest/ChanEstTime.cpp
new file mode 100644
index 0000000..ab1f829
--- /dev/null
+++ b/src/chanest/ChanEstTime.cpp
@@ -0,0 +1,58 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *	Channel estimation in time direction, base class
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later 
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT 
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "ChanEstTime.h"
+
+
+/* Implementation *************************************************************/
+void CPilotModiClass::InitRot(CParameter& Parameter) 
+{
+	/* Inits for timing correction. We need FFT size and start carrier */
+	/* Pre calculate the argument of the exp function */
+	rArgMult = (_REAL) -2.0 * crPi / Parameter.CellMappingTable.iFFTSizeN;
+	
+	/* Index of minimum useful carrier */
+	iKminAbs = Parameter.CellMappingTable.iShiftedKmin;
+}
+
+_COMPLEX CPilotModiClass::Rotate(const _COMPLEX cI, const int iCN, 
+								 const int iTiDi) const
+{
+	/* If "iTiDi" equals "0", rArg is also "0", we need no cos or sin
+	   function */
+	if (iTiDi != 0)
+	{
+		/* First calculate the argument */
+		const _REAL rArg = rArgMult * iTiDi * (iKminAbs + iCN);
+
+		/* * exp(2 * pi * TimeDiff / norm) */
+		return _COMPLEX(cos(rArg), sin(rArg)) * cI;
+	}
+	else
+		return cI;
+}
diff --git a/src/chanest/ChanEstTime.h b/src/chanest/ChanEstTime.h
new file mode 100644
index 0000000..61a0f70
--- /dev/null
+++ b/src/chanest/ChanEstTime.h
@@ -0,0 +1,74 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *	Base class of all channel estimation modules in time diretion
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later 
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT 
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#if !defined(CHANESTTIME_H__3B0BA6346234660_CA63_34523457A0D31912__INCLUDED_)
+#define CHANESTTIME_H__3B0BA6346234660_CA63_34523457A0D31912__INCLUDED_
+
+#include "../GlobalDefinitions.h"
+#include "../Parameter.h"
+#include "../util/Vector.h"
+#include "../matlib/Matlib.h"
+
+
+/* Classes ********************************************************************/
+/* Pilot modification class (e.g., rotation of complex vector) */
+class CPilotModiClass
+{
+public:
+	CPilotModiClass() {}
+	virtual ~CPilotModiClass() {}
+
+	void InitRot(CParameter& Parameter);
+
+//protected:
+	_COMPLEX Rotate(const _COMPLEX cI, const int iCN, const int iTiDi) const;
+
+private:
+	int		iKminAbs;
+	_REAL	rArgMult;
+};
+
+
+/* Base class for channel estimation in time direction. Defines the prototypes
+   which are common for derived classes */
+class CChanEstTime : public CPilotModiClass
+{
+public:
+	CChanEstTime() {}
+	virtual ~CChanEstTime() {}
+
+	virtual _REAL Estimate(CVectorEx<_COMPLEX>* pvecInputData, 
+						  CComplexVector& veccOutputData, 
+						  CVector<int>& veciMapTab, 
+						  CVector<_COMPLEX>& veccPilotCells, _REAL rSNR) = 0;
+
+	virtual int Init(CParameter& Parameter) = 0;
+};
+
+
+#endif // !defined(CHANESTTIME_H__3B0BA6346234660_CA63_34523457A0D31912__INCLUDED_)
diff --git a/src/chanest/ChannelEstimation.cpp b/src/chanest/ChannelEstimation.cpp
new file mode 100644
index 0000000..7295548
--- /dev/null
+++ b/src/chanest/ChannelEstimation.cpp
@@ -0,0 +1,1364 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *	Channel estimation and equalization
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "ChannelEstimation.h"
+#include <limits>
+
+
+/* Implementation *************************************************************/
+void CChannelEstimation::ProcessDataInternal(CParameter& Parameters)
+{
+    int		i, j, k;
+    int		iModSymNum;
+    _REAL	rCurSNREst;
+    _REAL	rOffsPDSEst;
+
+    /* Check if symbol ID index has changed by the synchronization unit. If it
+       has changed, reinit this module */
+    if ((*pvecInputData).GetExData().bSymbolIDHasChanged == TRUE)
+    {
+// FIXME: we loose one OFDM symbol by this call -> slower DRM signal acquisition
+        SetInitFlag();
+        return;
+    }
+
+
+// TODO: use CFIFO class for "matcHistory"!
+    /* Move data in history-buffer (from iLenHistBuff - 1 towards 0) */
+    for (j = 0; j < iLenHistBuff - 1; j++)
+    {
+        for (i = 0; i < iNumCarrier; i++)
+            matcHistory[j][i] = matcHistory[j + 1][i];
+    }
+
+    /* Write new symbol in memory */
+    for (i = 0; i < iNumCarrier; i++)
+        matcHistory[iLenHistBuff - 1][i] = (*pvecInputData)[i];
+
+    const int iSymbolCounter = (*pvecInputData).GetExData().iSymbolID;
+
+    Parameters.Lock();
+
+    /* Time interpolation *****************************************************/
+#ifdef USE_DD_WIENER_FILT_TIME
+    /* For decision directed channel estimation, it is important to know the
+       types of all cells, not only the pilot cells. Therefore, we have to take
+       care of frame ID here, too */
+    if (iSymbolCounter == 0)
+    {
+        /* Frame ID of this FAC block stands for the new block. We need
+           the ID of the old block, therefore we have to subtract "1" */
+        iCurrentFrameID = Parameters.iFrameIDReceiv - 1;
+        if (iCurrentFrameID < 0)
+            iCurrentFrameID = NUM_FRAMES_IN_SUPERFRAME - 1;
+    }
+
+    /* Set absolute symbol position */
+    const int iCurSymbIDTiInt =
+        iCurrentFrameID * iNumSymPerFrame + iSymbolCounter;
+#else
+    /* For regular channel estimation, only the positions of the pilots are
+       important. These positions are the same in each frame, independent of the
+       frame number */
+    const int iCurSymbIDTiInt = (*pvecInputData).GetExData().iSymbolID;
+#endif
+
+    /* Update the pilot memory for rpil tag of RSCI */
+    UpdateRSIPilotStore(Parameters, pvecInputData, Parameters.CellMappingTable.matiMapTab[iCurSymbIDTiInt],
+                        Parameters.CellMappingTable.matcPilotCells[iCurSymbIDTiInt], iSymbolCounter);
+
+
+    /* Get symbol-counter for next symbol. Use the count from the frame
+       synchronization (in OFDM.cpp). Call estimation routine */
+    const _REAL rSNRAftTiInt =
+        pTimeInt->Estimate(pvecInputData, veccPilots,
+                           Parameters.CellMappingTable.matiMapTab[iCurSymbIDTiInt],
+                           Parameters.CellMappingTable.matcPilotCells[iCurSymbIDTiInt],
+                           /* The channel estimation is based on the pilots so
+                              it needs the SNR on the pilots. Do a correction */
+                           rSNREstimate * rSNRTotToPilCorrFact);
+
+    /* Debar initialization of channel estimation in time direction */
+    if (iInitCnt > 0)
+    {
+        iInitCnt--;
+
+        /* Do not put out data in initialization phase */
+        iOutputBlockSize = 0;
+
+        /* Do not continue */
+        Parameters.Unlock();
+        return;
+    }
+    else
+        iOutputBlockSize = iNumCarrier;
+
+    /* Define DC carrier for robustness mode D because there is no pilot */
+    if (iDCPos != 0)
+        veccPilots[iDCPos] = (CReal) 0.0;
+
+
+    /* -------------------------------------------------------------------------
+       Use time-interpolated channel estimate for timing synchronization
+       tracking */
+    TimeSyncTrack.Process(Parameters, veccPilots,
+                          (*pvecInputData).GetExData().iCurTimeCorr, rLenPDSEst /* out */,
+                          rOffsPDSEst /* out */);
+
+    /* Store current delay in history */
+    vecrDelayHist.AddEnd(rLenPDSEst);
+
+
+    /* Frequency-interploation ************************************************/
+    switch (TypeIntFreq)
+    {
+    case FLINEAR:
+        /**********************************************************************\
+         * Linear interpolation												  *
+        \**********************************************************************/
+        /* Set first pilot position */
+        veccChanEst[0] = veccPilots[0];
+
+        for (j = 0, k = 1; j < iNumCarrier - iScatPilFreqInt;
+                j += iScatPilFreqInt, k++)
+        {
+            /* Set values at second time pilot position in cluster */
+            veccChanEst[j + iScatPilFreqInt] = veccPilots[k];
+
+            /* Interpolation cluster */
+            for (i = 1; i < iScatPilFreqInt; i++)
+            {
+                /* E.g.: c(x) = (c_4 - c_0) / 4 * x + c_0 */
+                veccChanEst[j + i] =
+                    (veccChanEst[j + iScatPilFreqInt] - veccChanEst[j]) /
+                    (_REAL) (iScatPilFreqInt) * (_REAL) i + veccChanEst[j];
+            }
+        }
+        break;
+
+    case FDFTFILTER:
+        /**********************************************************************\
+         * DFT based algorithm												  *
+        \**********************************************************************/
+        /* Special case with robustness mode D: pilots in all carriers!
+           so no processing is required, the channel estimation is
+           simply the pilots */
+        if (iNumIntpFreqPil == iNumCarrier)
+        {
+            veccChanEst = veccPilots;
+            break;
+        }
+        /* ---------------------------------------------------------------------
+           Put all pilots at the beginning of the vector. The "real" length of
+           the input vector is longer than the number of pilots, but we
+           calculate the FFT only over "iNumCarrier / iScatPilFreqInt + 1"
+           values (this is the number of pilot positions) */
+        /* Weighting pilots with window */
+        veccPilots *= vecrDFTWindow;
+
+        /* Transform in time-domain */
+        veccPilots = Ifft(veccPilots, FftPlanShort);
+
+        /* Set values outside a defined bound to zero, zero padding (noise
+           filtering). Copy second half of spectrum at the end of the new vector
+           length and zero out samples between the two parts of the spectrum */
+        veccIntPil.Merge(
+            /* First part of spectrum */
+            veccPilots(1, iStartZeroPadding),
+            /* Zero padding in the middle, length: Total length minus length of
+               the two parts at the beginning and end */
+            CComplexVector(Zeros(iLongLenFreq - 2 * iStartZeroPadding),
+                           Zeros(iLongLenFreq - 2 * iStartZeroPadding)),
+            /* Set the second part of the actual spectrum at the end of the new
+               vector */
+            veccPilots(iNumIntpFreqPil - iStartZeroPadding + 1,
+                       iNumIntpFreqPil));
+
+        /* Transform back in frequency-domain */
+        veccIntPil = Fft(veccIntPil, FftPlanLong);
+
+        /* Remove weighting with DFT window by inverse multiplication */
+        veccChanEst = veccIntPil(1, iNumCarrier) * vecrDFTwindowInv;
+        break;
+
+    case FWIENER:
+        /**********************************************************************\
+         * Wiener filter													   *
+        \**********************************************************************/
+        /* Wiener filter update --------------------------------------------- */
+        /* Do not update filter in case of simulation */
+        if (Parameters.eSimType == CParameter::ST_NONE)
+        {
+            /* Update Wiener filter each OFDM symbol. Use current estimates */
+            UpdateWienerFiltCoef(rSNRAftTiInt, rLenPDSEst / iNumCarrier,
+                                 rOffsPDSEst / iNumCarrier);
+        }
+
+
+        /* Actual Wiener interpolation (FIR filtering) ---------------------- */
+        /* FIR filter of the pilots with filter taps. We need to filter the
+           pilot positions as well to improve the SNR estimation (which
+           follows this procedure) */
+        for (j = 0; j < iNumCarrier; j++)
+        {
+// TODO: Do only calculate channel estimation for data cells, not for pilot
+// cells (exeption: if we want to use SNR estimation based on pilots, we also
+// need Wiener on these cells!)
+            /* Convolution */
+            veccChanEst[j] = _COMPLEX((_REAL) 0.0, (_REAL) 0.0);
+
+            for (i = 0; i < iLengthWiener; i++)
+            {
+                veccChanEst[j] +=
+                    matcFiltFreq[j][i] * veccPilots[veciPilOffTab[j] + i];
+            }
+        }
+        break;
+    }
+
+
+    /* Equalize the output vector ------------------------------------------- */
+    /* Calculate squared magnitude of channel estimation */
+    vecrSqMagChanEst = SqMag(veccChanEst);
+
+    /* Write to output vector. Take oldest symbol of history for output. Also,
+       ship the channel state at a certain cell */
+    for (i = 0; i < iNumCarrier; i++)
+    {
+        (*pvecOutputData)[i].cSig = matcHistory[0][i] / veccChanEst[i];
+
+#ifdef USE_MAX_LOG_MAP
+        /* In case of MAP we need the squared magnitude for the calculation of
+           the metric */
+        (*pvecOutputData)[i].rChan = vecrSqMagChanEst[i];
+#else
+        /* In case of hard-desicions, we need the magnitude of the channel for
+           the calculation of the metric */
+        (*pvecOutputData)[i].rChan = sqrt(vecrSqMagChanEst[i]);
+#endif
+    }
+
+
+    /* -------------------------------------------------------------------------
+       Calculate symbol ID of the current output block and set parameter */
+    (*pvecOutputData).GetExData().iSymbolID =
+        (*pvecInputData).GetExData().iSymbolID - iLenHistBuff + 1;
+
+
+    /* SNR estimation ------------------------------------------------------- */
+    /* Modified symbol ID, check range {0, ..., iNumSymPerFrame} */
+    iModSymNum = (*pvecOutputData).GetExData().iSymbolID;
+
+    while (iModSymNum < 0)
+        iModSymNum += iNumSymPerFrame;
+
+    /* Two different types of SNR estimation are available */
+    switch (TypeSNREst)
+    {
+    case SNR_PIL:
+        /* Use estimated channel and compare it to the received pilots. This
+           estimation works only if the channel estimation was successful */
+        for (i = 0; i < iNumCarrier; i++)
+        {
+            /* Identify pilot positions. Use MODIFIED "iSymbolID" (See lines
+               above) */
+            if (_IsScatPil(Parameters.CellMappingTable.matiMapTab[iModSymNum][i]))
+            {
+                /* We assume that the channel estimation in "veccChanEst" is
+                   noise free (e.g., the wiener interpolation does noise
+                   reduction). Thus, we have an estimate of the received signal
+                   power \hat{r} = s * \hat{h}_{wiener} */
+                const _COMPLEX cModChanEst = veccChanEst[i] *
+                                             Parameters.CellMappingTable.matcPilotCells[iModSymNum][i];
+
+
+                /* Calculate and average noise and signal estimates --------- */
+                /* The noise estimation is difference between the noise reduced
+                   signal and the noisy received signal
+                   \tilde{n} = \hat{r} - r */
+                IIR1(rNoiseEst, SqMag(matcHistory[0][i] - cModChanEst),
+                     rLamSNREstFast);
+
+                /* The received signal power estimation is just \hat{r} */
+                IIR1(rSignalEst, SqMag(cModChanEst), rLamSNREstFast);
+
+                /* Calculate final result (signal to noise ratio) */
+                rCurSNREst = CalAndBoundSNR(rSignalEst, rNoiseEst);
+
+                /* Average the SNR with a two sided recursion. Apply correction
+                   factor, too */
+                IIR1TwoSided(rSNREstimate, rCurSNREst / rSNRTotToPilCorrFact,
+                             rLamSNREstFast,	rLamSNREstSlow);
+            }
+        }
+        break;
+
+    case SNR_FAC:
+        /* SNR estimation based on FAC cells and hard decisions */
+        /* SNR estimation with initialization */
+        if (iSNREstInitCnt > 0)
+        {
+            for (i = 0; i < iNumCarrier; i++)
+            {
+                /* Only use the last frame of the initialization phase for
+                   initial SNR estimation to debar initialization phase of
+                   synchronization and channel estimation units */
+                if (iSNREstInitCnt < iNumSymPerFrame * iNumCarrier)
+                {
+                    const int iCurCellFlag =
+                        Parameters.CellMappingTable.matiMapTab[iModSymNum][i];
+
+                    /* Initial signal estimate. Use channel estimation from all
+                       data and pilot cells. Apply averaging */
+                    if ((_IsData(iCurCellFlag)) || (_IsPilot(iCurCellFlag)))
+                    {
+                        /* Signal estimation */
+                        rSignalEst += vecrSqMagChanEst[i];
+                        iSNREstIniSigAvCnt++;
+                    }
+
+                    /* Noise estimation from all data cells from tentative
+                       decisions */
+                    if (_IsFAC(iCurCellFlag)) /* FAC cell */
+                    {
+                        rNoiseEst += vecrSqMagChanEst[i] *
+                                     SqMag(MinDist4QAM((*pvecOutputData)[i].cSig));
+
+                        iSNREstIniNoiseAvCnt++;
+                    }
+                }
+            }
+
+            iSNREstInitCnt--;
+        }
+        else
+        {
+            /* Only right after initialization phase apply initial SNR
+               value */
+            if (bSNRInitPhase == TRUE)
+            {
+                /* Normalize average */
+                rSignalEst /= iSNREstIniSigAvCnt;
+                rNoiseEst /= iSNREstIniNoiseAvCnt;
+
+                bSNRInitPhase = FALSE;
+            }
+
+            /* replace SNR estimate of current symbol */
+            rNoiseEstSum -= vecrNoiseEstFACSym[iModSymNum];
+            rSignalEstSum -= vecrSignalEstFACSym[iModSymNum];
+
+            vecrNoiseEstFACSym[iModSymNum] = 0.0;
+            vecrSignalEstFACSym[iModSymNum] = 0.0;
+
+            for (i = 0; i < iNumCarrier; i++)
+            {
+                /* Only use FAC cells for this SNR estimation method */
+                if (_IsFAC(Parameters.CellMappingTable.matiMapTab[iModSymNum][i]))
+                {
+                    /* Get tentative decision for this FAC QAM symbol. FAC is
+                       always 4-QAM. Calculate all distances to the four
+                       possible constellation points of a 4-QAM and use the
+                       squared result of the returned distance vector */
+                    const CReal rCurErrPow =
+                        SqMag(MinDist4QAM((*pvecOutputData)[i].cSig));
+
+                    /* Use decision together with channel estimate to get
+                       estimates for signal and noise */
+                    vecrNoiseEstFACSym[iModSymNum] += rCurErrPow * vecrSqMagChanEst[i];
+                    vecrSignalEstFACSym[iModSymNum] += vecrSqMagChanEst[i];
+                }
+            }
+
+            rNoiseEstSum += vecrNoiseEstFACSym[iModSymNum];
+            rSignalEstSum += vecrSignalEstFACSym[iModSymNum];
+
+            /* Average SNR estimation from whole frame by exponentially forgetting IIR */
+            IIR1(rNoiseEst, rNoiseEstSum, rLamSNREstFast);
+            IIR1(rSignalEst, rSignalEstSum, rLamSNREstFast);
+
+            /* Calculate final result (signal to noise ratio) */
+            rCurSNREst = CalAndBoundSNR(rSignalEst, rNoiseEst);
+
+            /* Consider correction factor for average signal energy */
+            rSNREstimate = rCurSNREst * rSNRFACSigCorrFact;
+        }
+        break;
+    }
+
+    /* OPH: WMER, WMM and WMF estimation ------------------------------------ */
+    for (i = 0; i < iNumCarrier; i++)
+    {
+        /* Use MSC cells for this SNR estimation method */
+        if (_IsMSC(Parameters.CellMappingTable.matiMapTab[iModSymNum][i]))
+        {
+            CReal rCurErrPow = 0.0;
+
+            /* Get tentative decision for this MSC QAM symbol and calculate
+               squared distance as a measure for the noise. MSC can be 16 or
+               64 QAM */
+            switch (Parameters.eMSCCodingScheme)
+            {
+            case CS_3_SM:
+            case CS_3_HMSYM:
+            case CS_3_HMMIX:
+                rCurErrPow = SqMag(MinDist64QAM((*pvecOutputData)[i].cSig));
+                break;
+
+            case CS_2_SM:
+                rCurErrPow = SqMag(MinDist16QAM((*pvecOutputData)[i].cSig));
+                break;
+
+            default:
+                break;
+            }
+
+            /* Use decision together with channel estimate to get
+               estimates for signal and noise (for each carrier) */
+            IIR1(vecrNoiseEstMSC[i], rCurErrPow * vecrSqMagChanEst[i],
+                 rLamMSCSNREst);
+
+            IIR1(vecrSigEstMSC[i], vecrSqMagChanEst[i],
+                 rLamMSCSNREst);
+
+            /* Calculate MER on MSC cells */
+            IIR1(rNoiseEstMSCMER, rCurErrPow, rLamSNREstFast);
+
+            /* OPH: Update accumulators for RSCI MERs */
+            rNoiseEstMERAcc += rCurErrPow;
+            rNoiseEstWMMAcc += rCurErrPow * vecrSqMagChanEst[i];
+            rSignalEstWMMAcc += vecrSqMagChanEst[i];
+            iCountMERAcc ++;
+        }
+        else if (_IsFAC(Parameters.CellMappingTable.matiMapTab[iModSymNum][i]))
+        {
+            /* Update accumulators for RSCI WMF */
+            CReal rCurErrPow = SqMag(MinDist4QAM((*pvecOutputData)[i].cSig));
+            rNoiseEstWMFAcc += rCurErrPow * vecrSqMagChanEst[i];
+            rSignalEstWMFAcc += vecrSqMagChanEst[i];
+        }
+    }
+
+    /* SNR and Doppler are updated every symbol.
+     * TODO is this necessary ? */
+
+    if (bSNRInitPhase == FALSE)
+    {
+        const _REAL rNomBWSNR = rSNREstimate * rSNRSysToNomBWCorrFact;
+
+        /* Bound the SNR at 0 dB */
+        if (rNomBWSNR > 1.0 )
+            Parameters.SetSNR(10.0 * log10(rNomBWSNR));
+        else
+            Parameters.SetSNR(0.0);
+    }
+
+    /* Doppler estimation is only implemented in the
+     * Wiener time interpolation module */
+    if (TypeIntTime == TWIENER)
+        Parameters.rSigmaEstimate = TimeWiener.GetSigma();
+    else
+        Parameters.rSigmaEstimate = -1.0;
+
+    /* After processing last symbol of the frame */
+    if (iModSymNum == iNumSymPerFrame - 1)
+    {
+
+        /* set minimum and maximum delay from history */
+        _REAL rMinDelay = 1000.0;
+        _REAL rMaxDelay = 0.0;
+        for (int i = 0; i < iLenDelayHist; i++)
+        {
+            if (rMinDelay > vecrDelayHist[i])
+                rMinDelay = vecrDelayHist[i];
+            if(rMaxDelay < vecrDelayHist[i])
+                rMaxDelay = vecrDelayHist[i];
+        }
+
+        /* Return delay in ms */
+        _REAL rDelayScale = _REAL(iFFTSizeN) / _REAL(iSampleRate * iNumIntpFreqPil * iScatPilFreqInt) * 1000.0;
+        Parameters.rMinDelay = rMinDelay * rDelayScale;
+        Parameters.rMaxDelay = rMaxDelay * rDelayScale;
+
+        /* Calculate and generate RSCI measurement values */
+        /* rmer (MER for MSC) */
+        CReal rMER =
+            CalAndBoundSNR(AV_DATA_CELLS_POWER, rNoiseEstMERAcc / iCountMERAcc);
+
+        /* Bound MER at 0 dB */
+        Parameters.rMER = (rMER > (_REAL) 1.0 ? (_REAL) 10.0 * log10(rMER) : (_REAL) 0.0);
+
+        /* rwmm (WMER for MSC)*/
+        CReal rWMM = AV_DATA_CELLS_POWER *
+                     CalAndBoundSNR(rSignalEstWMMAcc, rNoiseEstWMMAcc);
+
+        /* Bound the MER at 0 dB */
+        Parameters.rWMERMSC = (rWMM > (_REAL) 1.0 ? (_REAL) 10.0 * log10(rWMM) : (_REAL) 0.0);
+
+        /* rwmf (WMER for FAC) */
+        CReal rWMF = AV_DATA_CELLS_POWER *
+                     CalAndBoundSNR(rSignalEstWMFAcc, rNoiseEstWMFAcc);
+
+        /* Bound the MER at 0 dB */
+        Parameters.rWMERFAC = (rWMF > (_REAL) 1.0 ? (_REAL) 10.0 * log10(rWMF) : (_REAL) 0.0);
+
+        /* Reset all the accumulators and counters */
+        rNoiseEstMERAcc = (_REAL) 0.0;
+        iCountMERAcc = 0;
+        rSignalEstWMMAcc = (_REAL) 0.0;
+        rNoiseEstWMMAcc = (_REAL) 0.0;
+        rSignalEstWMFAcc = (_REAL) 0.0;
+        rNoiseEstWMFAcc = (_REAL) 0.0;
+
+        if (Parameters.bMeasureDelay)
+            TimeSyncTrack.CalculateRdel(Parameters);
+
+        if (Parameters.bMeasureDoppler)
+            TimeSyncTrack.CalculateRdop(Parameters);
+
+        if (Parameters.bMeasureInterference)
+        {
+            /* Calculate interference tag */
+            CalculateRint(Parameters);
+        }
+    }
+
+    Parameters.Unlock();
+
+    /* Interferer consideration --------------------------------------------- */
+    if (bInterfConsid == TRUE)
+    {
+        for (i = 0; i < iNumCarrier; i++)
+        {
+            /* Weight the channel estimates with the SNR estimate of the current
+               carrier to consider the higher noise variance caused by
+               interferers */
+            (*pvecOutputData)[i].rChan *=
+                CalAndBoundSNR(vecrSigEstMSC[i], vecrNoiseEstMSC[i]);
+        }
+    }
+}
+
+/* OPH: Calculate the values for the rint RSCI tag */
+void CChannelEstimation::CalculateRint(CParameter& Parameters)
+{
+    CReal rMaxNoiseEst = (CReal) 0.0;
+    CReal rSumNoiseEst = (CReal) 0.0;
+    CReal rSumSigEst  = (CReal) 0.0;
+    int iMaxIntCarrier = 0;
+
+    /* Find peak noise and add up noise and signal estimates */
+    for (int i = 0; i < iNumCarrier; i++)
+    {
+        CReal rNoiseEstMSC = vecrNoiseEstMSC[i];
+        if (rNoiseEstMSC> rMaxNoiseEst)
+        {
+            rMaxNoiseEst = rNoiseEstMSC;
+            iMaxIntCarrier = i;
+        }
+        rSumNoiseEst += rNoiseEstMSC;
+        rSumSigEst += vecrSigEstMSC[i];
+    }
+
+    /* Interference to noise ratio */
+    _REAL rINRtmp = CalAndBoundSNR(rMaxNoiseEst, rSumNoiseEst / iNumCarrier);
+    Parameters.rINR = (rINRtmp > (_REAL) 1.0 ? (_REAL) 10.0 * log10(rINRtmp) : (_REAL) 0.0);
+
+    /* Interference to (single) carrier ratio */
+    _REAL rICRtmp = CalAndBoundSNR(rMaxNoiseEst,
+                                   AV_DATA_CELLS_POWER * rSumSigEst/iNumCarrier);
+
+
+    Parameters.rICR = (rICRtmp > (_REAL) 1.0 ? (_REAL) 10.0 * log10(rICRtmp) : (_REAL) 0.0);
+
+    /* Interferer frequency */
+    Parameters.rIntFreq = ((_REAL) iMaxIntCarrier + Parameters.CellMappingTable.iCarrierKmin) /
+                             Parameters.CellMappingTable.iFFTSizeN * iSampleRate;
+}
+
+void CChannelEstimation::InitInternal(CParameter& Parameters)
+{
+    Parameters.Lock();
+    /* Get parameters from global struct */
+    iScatPilTimeInt = Parameters.CellMappingTable.iScatPilTimeInt;
+    iScatPilFreqInt = Parameters.CellMappingTable.iScatPilFreqInt;
+    iNumIntpFreqPil = Parameters.CellMappingTable.iNumIntpFreqPil;
+    iNumCarrier = Parameters.CellMappingTable.iNumCarrier;
+    iFFTSizeN = Parameters.CellMappingTable.iFFTSizeN;
+    iNumSymPerFrame = Parameters.CellMappingTable.iNumSymPerFrame;
+    iSampleRate = Parameters.GetSigSampleRate();
+
+    /* Length of guard-interval with respect to FFT-size! */
+    rGuardSizeFFT = (_REAL) iNumCarrier *
+                    Parameters.CellMappingTable.RatioTgTu.iEnum / Parameters.CellMappingTable.RatioTgTu.iDenom;
+
+    /* If robustness mode D is active, get DC position. This position cannot
+       be "0" since in mode D no 5 kHz mode is defined (see DRM-standard).
+       Therefore we can also use this variable to get information whether
+       mode D is active or not (by simply write: "if (iDCPos != 0)") */
+    if (Parameters.GetWaveMode() == RM_ROBUSTNESS_MODE_D)
+    {
+        /* Identify DC carrier position */
+        for (int i = 0; i < iNumCarrier; i++)
+        {
+            if (_IsDC(Parameters.CellMappingTable.matiMapTab[0][i]))
+                iDCPos = i;
+        }
+    }
+    else
+        iDCPos = 0;
+
+    /* FFT must be longer than "iNumCarrier" because of zero padding effect (
+       not in robustness mode D! -> "iLongLenFreq = iNumCarrier") */
+    iLongLenFreq = iNumCarrier + iScatPilFreqInt - 1;
+
+    /* Init vector for received data at pilot positions */
+    veccPilots.Init(iNumIntpFreqPil);
+
+    /* Init vector for interpolated pilots */
+    veccIntPil.Init(iLongLenFreq);
+
+    /* Init plans for FFT (faster processing of Fft and Ifft commands) */
+    FftPlanShort.Init(iNumIntpFreqPil);
+    FftPlanLong.Init(iLongLenFreq);
+
+    /* Choose time interpolation method and set pointer to correcponding
+       object */
+    switch (TypeIntTime)
+    {
+    case TLINEAR:
+        pTimeInt = &TimeLinear;
+        break;
+
+    case TWIENER:
+        pTimeInt = &TimeWiener;
+        break;
+    }
+
+#ifdef USE_DD_WIENER_FILT_TIME
+    /* Reset frame ID counter */
+    iCurrentFrameID = 0;
+#endif
+
+    /* Init time interpolation interface and set delay for interpolation */
+    iLenHistBuff = pTimeInt->Init(Parameters);
+
+    /* Init time synchronization tracking unit */
+    TimeSyncTrack.Init(Parameters, iLenHistBuff);
+
+    /* Set channel estimation delay in global struct. This is needed for
+       simulation */
+    Parameters.iChanEstDelay = iLenHistBuff;
+
+
+    /* Init window for DFT operation for frequency interpolation ------------ */
+    /* Simplified version of "Low-complexity Channel Estimator Based on
+       Windowed DFT and Scalar Wiener Fitler for OFDM Systems" by Baoguo Yang,
+       Zhigang Cao and K. B. Letaief */
+    /* Init memory */
+    vecrDFTWindow.Init(iNumIntpFreqPil);
+    vecrDFTwindowInv.Init(iNumCarrier);
+
+    /* Set window coefficients. Do not use the edges of the windows */
+    const _REAL rWinExpFact = (_REAL) 0.0828; /* Value taken from paper */
+
+    const int iOvlSamOneSideShort =
+        (int) Ceil(rWinExpFact * iNumIntpFreqPil / 2);
+    const int iOvlSamOneSideLong = iOvlSamOneSideShort * iScatPilFreqInt;
+
+    const int iExpWinLenShort = iNumIntpFreqPil + 2 * iOvlSamOneSideShort;
+    const int iExpWinLenLong = iNumCarrier + 2 * iOvlSamOneSideLong;
+
+    CRealVector vecrExpWinShort(iExpWinLenShort);
+    CRealVector vecrExpWinLong(iExpWinLenLong);
+
+    switch (eDFTWindowingMethod)
+    {
+    case DFT_WIN_RECT:
+        vecrDFTWindow = Ones(iNumIntpFreqPil);
+        vecrDFTwindowInv = Ones(iNumCarrier);
+        break;
+
+    case DFT_WIN_HAMM:
+        vecrExpWinShort = Hamming(iExpWinLenShort);
+        vecrDFTWindow = vecrExpWinShort(iOvlSamOneSideShort + 1,
+                                        iExpWinLenShort - iOvlSamOneSideShort);
+
+        vecrExpWinLong = Hamming(iExpWinLenLong);
+        vecrDFTwindowInv = (CReal) 1.0 / vecrExpWinLong(iOvlSamOneSideLong + 1,
+                           iExpWinLenLong - iOvlSamOneSideLong);
+        break;
+
+    case DFT_WIN_HANN:
+        vecrExpWinShort = Hann(iExpWinLenShort);
+        vecrDFTWindow = vecrExpWinShort(iOvlSamOneSideShort + 1,
+                                        iExpWinLenShort - iOvlSamOneSideShort);
+
+        vecrExpWinLong = Hann(iExpWinLenLong);
+        vecrDFTwindowInv = (CReal) 1.0 / vecrExpWinLong(iOvlSamOneSideLong + 1,
+                           iExpWinLenLong - iOvlSamOneSideLong);
+        break;
+    }
+
+    /* Set start index for zero padding in time domain for DFT method */
+    iStartZeroPadding = (int) rGuardSizeFFT;
+    if (iStartZeroPadding > iNumIntpFreqPil)
+        iStartZeroPadding = iNumIntpFreqPil;
+
+    /* Allocate memory for channel estimation */
+    veccChanEst.Init(iNumCarrier);
+    vecrSqMagChanEst.Init(iNumCarrier);
+
+    /* Allocate memory for history buffer (Matrix) and zero out */
+    matcHistory.Init(iLenHistBuff, iNumCarrier,
+                     _COMPLEX((_REAL) 0.0, (_REAL) 0.0));
+
+    /* After an initialization we do not put out data before the number symbols
+       of the channel estimation delay have been processed */
+    iInitCnt = iLenHistBuff - 1;
+
+    /* SNR correction factor for the different SNR estimation types. For the
+       FAC method, the average signal power has to be considered. For the pilot
+       based method, only the SNR on the pilots are evaluated. Therefore, to get
+       the total SNR, a correction has to be applied */
+    rSNRFACSigCorrFact = Parameters.CellMappingTable.rAvPowPerSymbol / CReal(iNumCarrier);
+    rSNRTotToPilCorrFact = Parameters.CellMappingTable.rAvScatPilPow *
+                           (_REAL) iNumCarrier / Parameters.CellMappingTable.rAvPowPerSymbol;
+
+    /* Correction factor for transforming the estimated system SNR in the SNR
+       where the noise bandwidth is according to the nominal DRM bandwidth */
+    rSNRSysToNomBWCorrFact = Parameters.GetSysToNomBWCorrFact();
+
+    /* Inits for SNR estimation (noise and signal averages) */
+    rSignalEst = (_REAL) 0.0;
+    rNoiseEst = (_REAL) 0.0;
+    rNoiseEstMSCMER = (_REAL) 0.0;
+    rSNREstimate = (_REAL) pow((_REAL) 10.0, INIT_VALUE_SNR_ESTIM_DB / 10);
+    vecrNoiseEstMSC.Init(iNumCarrier, (_REAL) 0.0);
+    vecrSigEstMSC.Init(iNumCarrier, (_REAL) 0.0);
+
+    /* For SNR estimation initialization */
+    iSNREstIniSigAvCnt = 0;
+    iSNREstIniNoiseAvCnt = 0;
+
+    /* for FAC SNR estimation */
+    vecrNoiseEstFACSym.Init(iNumSymPerFrame, (_REAL) 0.0);
+    vecrSignalEstFACSym.Init(iNumSymPerFrame, (_REAL) 0.0);
+    rNoiseEstSum = 0.0;
+    rSignalEstSum = 0.0;
+
+    /* We only have an initialization phase for SNR estimation method based on
+       the tentative decisions of FAC cells */
+    if (TypeSNREst == SNR_FAC)
+        bSNRInitPhase = TRUE;
+    else
+        bSNRInitPhase = FALSE;
+
+    /* 5 DRM frames to start initial SNR estimation after initialization phase
+       of other units */
+    iSNREstInitCnt = 5 * iNumSymPerFrame;
+
+    /* Lambda for IIR filter */
+    rLamSNREstFast = IIR1Lam(TICONST_SNREST_FAST, (CReal) iSampleRate /
+                             Parameters.CellMappingTable.iSymbolBlockSize);
+    rLamSNREstSlow = IIR1Lam(TICONST_SNREST_SLOW, (CReal) iSampleRate /
+                             Parameters.CellMappingTable.iSymbolBlockSize);
+    rLamMSCSNREst = IIR1Lam(TICONST_SNREST_MSC, (CReal) iSampleRate /
+                            Parameters.CellMappingTable.iSymbolBlockSize);
+
+    /* Init delay spread length estimation (index) */
+    rLenPDSEst = (_REAL) 0.0;
+
+    /* Init history for delay values */
+    /* Duration of OFDM symbol */
+    const _REAL rTs = (CReal) (Parameters.CellMappingTable.iFFTSizeN +
+                               Parameters.CellMappingTable.iGuardSize) / iSampleRate;
+
+    iLenDelayHist = (int) (LEN_HIST_DELAY_LOG_FILE_S / rTs);
+    vecrDelayHist.Init(iLenDelayHist, (CReal) 0.0);
+
+
+    /* Inits for Wiener interpolation in frequency direction ---------------- */
+    /* Length of wiener filter */
+    switch (Parameters.GetWaveMode())
+    {
+    case RM_ROBUSTNESS_MODE_A:
+        iLengthWiener = LEN_WIENER_FILT_FREQ_RMA;
+        break;
+
+    case RM_ROBUSTNESS_MODE_B:
+        iLengthWiener = LEN_WIENER_FILT_FREQ_RMB;
+        break;
+
+    case RM_ROBUSTNESS_MODE_C:
+        iLengthWiener = LEN_WIENER_FILT_FREQ_RMC;
+        break;
+
+    case RM_ROBUSTNESS_MODE_D:
+        iLengthWiener = LEN_WIENER_FILT_FREQ_RMD;
+        break;
+
+    default:
+        break;
+    }
+
+
+    /* Inits for wiener filter ---------------------------------------------- */
+    /* In frequency direction we can use pilots from both sides for
+       interpolation */
+    iPilOffset = iLengthWiener / 2;
+
+    /* Allocate memory */
+    matcFiltFreq.Init(iNumCarrier, iLengthWiener);
+
+    /* Pilot offset table */
+    veciPilOffTab.Init(iNumCarrier);
+
+    /* Number of different wiener filters */
+    iNumWienerFilt = (iLengthWiener - 1) * iScatPilFreqInt + 1;
+
+    /* Allocate temporary matlib vector for filter coefficients */
+    matcWienerFilter.Init(iNumWienerFilt, iLengthWiener);
+
+    /* Distinguish between simulation and regular receiver. When we run a
+       simulation, the parameters are taken from simulation init */
+    if (Parameters.eSimType == CParameter::ST_NONE)
+    {
+        /* Initial Wiener filter. Use initial SNR definition and assume that the
+           PDS ranges from the beginning of the guard-intervall to the end */
+        UpdateWienerFiltCoef(
+            pow((CReal) 10.0, INIT_VALUE_SNR_WIEN_FREQ_DB / 10),
+            (CReal) Parameters.CellMappingTable.RatioTgTu.iEnum /
+            Parameters.CellMappingTable.RatioTgTu.iDenom, (CReal) 0.0);
+    }
+    else
+    {
+        /* Get simulation SNR on the pilot positions and set PDS to entire
+           guard-interval length */
+        UpdateWienerFiltCoef(
+            pow((CReal) 10.0, Parameters.GetSysSNRdBPilPos() / 10),
+            (CReal) Parameters.CellMappingTable.RatioTgTu.iEnum /
+            Parameters.CellMappingTable.RatioTgTu.iDenom, (CReal) 0.0);
+    }
+
+
+    /* Define block-sizes for input and output */
+    iInputBlockSize = iNumCarrier;
+    iMaxOutputBlockSize = iNumCarrier;
+
+
+    /* inits for RSCI pilot store */
+    matcRSIPilotStore.Init(iNumSymPerFrame / iScatPilTimeInt, iNumCarrier/iScatPilFreqInt + 1,
+                           _COMPLEX(_REAL(0.0),_REAL(0.0)));
+    iTimeDiffAccuRSI = 0;
+
+    Parameters.Unlock();
+}
+
+CComplexVector CChannelEstimation::FreqOptimalFilter(int iFreqInt, int iDiff,
+        CReal rSNR,
+        CReal rRatPDSLen,
+        CReal rRatPDSOffs,
+        int iLength)
+{
+    /*
+    	We assume that the power delay spread is a rectangle function in the time
+    	domain (sinc-function in the frequency domain). Length and position of this
+    	window are adapted according to the current estimated PDS.
+    */
+    int				i;
+    CRealVector		vecrRpp(iLength);
+    CRealVector		vecrRhp(iLength);
+    CRealVector		vecrH(iLength);
+    CComplexVector	veccH(iLength);
+
+    /* Calculation of R_hp, this is the SHIFTED correlation function */
+    for (i = 0; i < iLength; i++)
+    {
+        const int iCurPos = i * iFreqInt - iDiff;
+
+        vecrRhp[i] = Sinc((CReal) iCurPos * rRatPDSLen);
+    }
+
+    /* Calculation of R_pp */
+    for (i = 0; i < iLength; i++)
+    {
+        const int iCurPos = i * iFreqInt;
+
+        vecrRpp[i] = Sinc((CReal) iCurPos * rRatPDSLen);
+    }
+
+    /* Add SNR at first tap */
+    vecrRpp[0] += (CReal) 1.0 / rSNR;
+
+    /* Call levinson algorithm to solve matrix system for optimal solution */
+    vecrH = Levinson(vecrRpp, vecrRhp);
+
+    /* Correct the optimal filter coefficients. Shift the rectangular
+       function in the time domain to the correct position (determined by
+       the "rRatPDSOffs") by multiplying in the frequency domain
+       with exp(j w T) */
+    for (i = 0; i < iLength; i++)
+    {
+        const int iCurPos = i * iFreqInt - iDiff;
+
+        const CReal rArgExp =
+            (CReal) crPi * iCurPos * (rRatPDSLen + rRatPDSOffs * 2);
+
+        veccH[i] = vecrH[i] * CComplex(Cos(rArgExp), Sin(rArgExp));
+    }
+
+    return veccH;
+}
+
+void CChannelEstimation::UpdateWienerFiltCoef(CReal rNewSNR, CReal rRatPDSLen,
+        CReal rRatPDSOffs)
+{
+    int	j, i;
+    int	iDiff;
+    int	iCurPil;
+
+    /* Calculate all possible wiener filters */
+    for (j = 0; j < iNumWienerFilt; j++)
+    {
+        matcWienerFilter[j] = FreqOptimalFilter(iScatPilFreqInt, j, rNewSNR,
+                                                rRatPDSLen, rRatPDSOffs, iLengthWiener);
+    }
+
+
+#if 0
+    /* Save filter coefficients */
+    static FILE* pFile = fopen("test/wienerfreq.dat", "w");
+    for (j = 0; j < iNumWienerFilt; j++)
+    {
+        for (i = 0; i < iLengthWiener; i++)
+        {
+            fprintf(pFile, "%e %e\n", Real(matcWienerFilter[j][i]),
+                    Imag(matcWienerFilter[j][i]));
+        }
+    }
+    fflush(pFile);
+#endif
+
+
+    /* Set matrix with filter taps, one filter for each carrier */
+    for (j = 0; j < iNumCarrier; j++)
+    {
+        /* We define the current pilot position as the last pilot which the
+           index "j" has passed */
+        iCurPil = (int) (j / iScatPilFreqInt);
+
+        /* Consider special cases at the edges of the DRM spectrum */
+        if (iCurPil < iPilOffset)
+        {
+            /* Special case: left edge */
+            veciPilOffTab[j] = 0;
+        }
+        else if (iCurPil - iPilOffset > iNumIntpFreqPil - iLengthWiener)
+        {
+            /* Special case: right edge */
+            veciPilOffTab[j] = iNumIntpFreqPil - iLengthWiener;
+        }
+        else
+        {
+            /* In the middle */
+            veciPilOffTab[j] = iCurPil - iPilOffset;
+        }
+
+        /* Special case for robustness mode D, since the DC carrier is not used
+           as a pilot and therefore we use the same method for the edges of the
+           spectrum also in the middle of robustness mode D */
+        if (iDCPos != 0)
+        {
+            if ((iDCPos - iCurPil < iLengthWiener) && (iDCPos - iCurPil > 0))
+            {
+                /* Left side of DC carrier */
+                veciPilOffTab[j] = iDCPos - iLengthWiener;
+            }
+
+            if ((iCurPil - iDCPos < iLengthWiener) && (iCurPil - iDCPos > 0))
+            {
+                /* Right side of DC carrier */
+                veciPilOffTab[j] = iDCPos + 1;
+            }
+        }
+
+        /* Difference between the position of the first pilot (for filtering)
+           and the position of the observed carrier */
+        iDiff = j - veciPilOffTab[j] * iScatPilFreqInt;
+
+        /* Copy correct filter in matrix */
+        for (i = 0; i < iLengthWiener; i++)
+            matcFiltFreq[j][i] = matcWienerFilter[iDiff][i];
+    }
+}
+
+_REAL CChannelEstimation::CalAndBoundSNR(const _REAL rSignalEst, const _REAL rNoiseEst)
+{
+    _REAL rReturn;
+    const _REAL epsilon = numeric_limits<_REAL>::epsilon();
+
+    /* "rNoiseEst" must not be near zero */
+
+    if ((rNoiseEst < -epsilon) || (rNoiseEst > epsilon))
+        rReturn = rSignalEst / rNoiseEst;
+    else
+        rReturn = (_REAL) 1.0;
+
+    /* Bound the SNR at 0 dB */
+    if (rReturn < (_REAL) 1.0)
+        rReturn = (_REAL) 1.0;
+
+    return rReturn;
+}
+
+
+#if 0
+_REAL CChannelEstimation::GetSNREstdB() const
+{
+    if (bSNRInitPhase == TRUE)
+        return -1.0;
+
+    const _REAL rNomBWSNR = rSNREstimate * rSNRSysToNomBWCorrFact;
+
+    /* Bound the SNR at 0 dB */
+    if ((rNomBWSNR > (_REAL) 1.0) && (bSNRInitPhase == FALSE))
+        return (_REAL) 10.0 * log10(rNomBWSNR);
+    else
+        return (_REAL) 0.0;
+}
+
+_REAL CChannelEstimation::GetMSCMEREstdB()
+{
+    /* Calculate final result (signal to noise ratio) and consider correction
+       factor for average signal energy */
+    const _REAL rCurMSCMEREst = rSNRSysToNomBWCorrFact *
+                                CalAndBoundSNR(AV_DATA_CELLS_POWER, rNoiseEstMSCMER);
+
+    /* Bound the MCS MER at 0 dB */
+    if (rCurMSCMEREst > (_REAL) 1.0)
+        return (_REAL) 10.0 * log10(rCurMSCMEREst);
+    else
+        return (_REAL) 0.0;
+}
+
+_REAL CChannelEstimation::GetMSCWMEREstdB()
+{
+    _REAL rAvNoiseEstMSC = (_REAL) 0.0;
+    _REAL rAvSigEstMSC = (_REAL) 0.0;
+
+    /* Lock resources */
+    Lock();
+    {
+        /* Average results from all carriers */
+        for (int i = 0; i < iNumCarrier; i++)
+        {
+            rAvNoiseEstMSC += vecrNoiseEstMSC[i];
+            rAvSigEstMSC += vecrSigEstMSC[i];
+        }
+    }
+    Unlock();
+
+    /* Calculate final result (signal to noise ratio) and consider correction
+       factor for average signal energy */
+    const _REAL rCurMSCWMEREst = rSNRSysToNomBWCorrFact *
+                                 CalAndBoundSNR(rAvSigEstMSC, rAvNoiseEstMSC);
+
+    /* Bound the MCS MER at 0 dB */
+    if (rCurMSCWMEREst > (_REAL) 1.0)
+        return (_REAL) 10.0 * log10(rCurMSCWMEREst);
+    else
+        return (_REAL) 0.0;
+}
+
+_REAL CChannelEstimation::GetSigma()
+{
+    /* Doppler estimation is only implemented in the Wiener time interpolation
+       module */
+    if (TypeIntTime == TWIENER)
+        return TimeWiener.GetSigma();
+    else
+        return -1.0;
+}
+
+_REAL CChannelEstimation::GetDelay() const
+{
+    /* Delay in ms */
+    return rLenPDSEst * iFFTSizeN /
+           (iSampleRate * iNumIntpFreqPil * iScatPilFreqInt) * 1000;
+}
+
+_REAL CChannelEstimation::GetMinDelay()
+{
+    /* Lock because of vector "vecrDelayHist" access */
+    //Lock();
+
+    /* Return minimum delay in history */
+    _REAL rMinDelay = 1000.0;
+    for (int i = 0; i < iLenDelayHist; i++)
+    {
+        if (rMinDelay > vecrDelayHist[i])
+            rMinDelay = vecrDelayHist[i];
+    }
+
+    //Unlock();
+
+    /* Return delay in ms */
+    return rMinDelay * iFFTSizeN /
+           (iSampleRate * iNumIntpFreqPil * iScatPilFreqInt) * 1000;
+}
+#endif
+
+void CChannelEstimation::GetTransferFunction(CVector<_REAL>& vecrData,
+        CVector<_REAL>& vecrGrpDly,
+        CVector<_REAL>& vecrScale)
+{
+    /* Init output vectors */
+    vecrData.Init(iNumCarrier, (_REAL) 0.0);
+    vecrGrpDly.Init(iNumCarrier, (_REAL) 0.0);
+    vecrScale.Init(iNumCarrier, (_REAL) 0.0);
+
+    /* Do copying of data only if vector is of non-zero length which means that
+       the module was already initialized */
+    if (iNumCarrier != 0)
+    {
+        _REAL rDiffPhase, rOldPhase;
+
+        /* Lock resources */
+        Lock();
+
+        /* TODO - decide if this allows the if(i==0) test to be removed */
+        rOldPhase = Angle(veccChanEst[0]);
+
+        /* Init constants for normalization */
+        const _REAL rTu = (CReal) iFFTSizeN / iSampleRate;
+        const _REAL rNormData = (_REAL) _MAXSHORT * _MAXSHORT;
+
+        /* Copy data in output vector and set scale
+           (carrier index as x-scale) */
+        for (int i = 0; i < iNumCarrier; i++)
+        {
+            /* Transfer function */
+            const _REAL rNormSqMagChanEst = SqMag(veccChanEst[i]) / rNormData;
+
+            if (rNormSqMagChanEst > 0)
+                vecrData[i] = (_REAL) 10.0 * Log10(rNormSqMagChanEst);
+            else
+                vecrData[i] = RET_VAL_LOG_0;
+
+            /* Group delay */
+            if (i == 0)
+            {
+                /* At position 0 we cannot calculate a derivation -> use
+                   the same value as position 0 */
+                rDiffPhase = Angle(veccChanEst[1]) - Angle(veccChanEst[0]);
+            }
+            else
+                rDiffPhase = Angle(veccChanEst[i]) - rOldPhase;
+
+            /* Take care of wrap around of angle() function */
+            if (rDiffPhase > WRAP_AROUND_BOUND_GRP_DLY)
+                rDiffPhase -= 2.0 * crPi;
+            if (rDiffPhase < -WRAP_AROUND_BOUND_GRP_DLY)
+                rDiffPhase += 2.0 * crPi;
+
+            /* Apply normalization */
+            vecrGrpDly[i] = rDiffPhase * rTu * 1000.0 /* ms */;
+
+            /* Store old phase */
+            rOldPhase = Angle(veccChanEst[i]);
+
+            /* Scale (carrier index) */
+            vecrScale[i] = i;
+        }
+
+        /* Release resources */
+        Unlock();
+    }
+}
+
+void CChannelEstimation::GetSNRProfile(CVector<_REAL>& vecrData,
+                                       CVector<_REAL>& vecrScale)
+{
+    int i;
+
+    /* Init output vectors */
+    vecrData.Init(iNumCarrier, (_REAL) 0.0);
+    vecrScale.Init(iNumCarrier, (_REAL) 0.0);
+
+    /* Do copying of data only if vector is of non-zero length which means that
+       the module was already initialized */
+    if (iNumCarrier != 0)
+    {
+        /* Lock resources */
+        Lock();
+
+        /* We want to suppress the carriers on which no SNR measurement can be
+           performed (DC carrier, frequency pilots carriers) */
+        int iNewNumCar = 0;
+        for (i = 0; i < iNumCarrier; i++)
+        {
+            if (vecrSigEstMSC[i] != (_REAL) 0.0)
+                iNewNumCar++;
+        }
+
+        /* Init output vectors for new size */
+        vecrData.Init(iNewNumCar, (_REAL) 0.0);
+        vecrScale.Init(iNewNumCar, (_REAL) 0.0);
+
+        /* Copy data in output vector and set scale
+           (carrier index as x-scale) */
+        int iCurOutIndx = 0;
+        for (i = 0; i < iNumCarrier; i++)
+        {
+            /* Suppress carriers where no SNR measurement is possible */
+            if (vecrSigEstMSC[i] != (_REAL) 0.0)
+            {
+                /* Calculate final result (signal to noise ratio). Consider
+                   correction factor for average signal energy */
+                const _REAL rNomBWSNR =
+                    CalAndBoundSNR(vecrSigEstMSC[i], vecrNoiseEstMSC[i]) *
+                    rSNRFACSigCorrFact * rSNRSysToNomBWCorrFact;
+
+                /* Bound the SNR at 0 dB */
+                if ((rNomBWSNR > (_REAL) 1.0) && (bSNRInitPhase == FALSE))
+                    vecrData[iCurOutIndx] = (_REAL) 10.0 * Log10(rNomBWSNR);
+                else
+                    vecrData[iCurOutIndx] = (_REAL) 0.0;
+
+                /* Scale (carrier index) */
+                vecrScale[iCurOutIndx] = i;
+
+                iCurOutIndx++;
+            }
+        }
+
+        /* Release resources */
+        Unlock();
+    }
+}
+
+void CChannelEstimation::GetAvPoDeSp(CVector<_REAL>& vecrData,
+                                     CVector<_REAL>& vecrScale,
+                                     _REAL& rLowerBound, _REAL& rHigherBound,
+                                     _REAL& rStartGuard, _REAL& rEndGuard,
+                                     _REAL& rPDSBegin, _REAL& rPDSEnd)
+{
+    /* Lock resources */
+    Lock();
+
+    TimeSyncTrack.GetAvPoDeSp(vecrData, vecrScale, rLowerBound,
+                              rHigherBound, rStartGuard, rEndGuard, rPDSBegin, rPDSEnd, iSampleRate);
+
+    /* Release resources */
+    Unlock();
+}
+
+void CChannelEstimation::UpdateRSIPilotStore(CParameter& Parameters, CVectorEx<_COMPLEX>* pvecInputData,
+        CVector<int>& veciMapTab, CVector<_COMPLEX>& veccPilotCells, const int iSymbolCounter)
+{
+    int			i;
+    int			iPiHiIdx;
+    //int			iTimeDiffNew;
+    _COMPLEX	cNewPilot;
+
+    /* Clear time diff accumulator at start of the frame */
+    if (iSymbolCounter == 0)
+    {
+        iTimeDiffAccuRSI = 0;
+    }
+    else
+    {
+        /* Add the latest timing step onto the reference value */
+        iTimeDiffAccuRSI += (*pvecInputData).GetExData().iCurTimeCorr;
+    }
+
+
+    /* calculate the spacing between scattered pilots in a given symbol */
+    int iScatPilFreqSpacing = iScatPilFreqInt * iScatPilTimeInt;
+
+    /* Data is stored in the array with one row per pilot repetition, and in freq order in each row */
+    /* Each row has one element per pilot-bearing carrier */
+    /* This avoids having a jagged array with different lengths in different rows */
+    int iRow = iSymbolCounter / Parameters.CellMappingTable.iScatPilTimeInt;
+
+    int iScatPilFreqInt = Parameters.CellMappingTable.iScatPilFreqInt;
+
+
+    /* Find the first pilot */
+    int iFirstPilotCarrier = 0;
+
+    while (!_IsScatPil(veciMapTab[iFirstPilotCarrier]) )
+        iFirstPilotCarrier += iScatPilFreqInt;
+
+
+    /* Fill in the matrix for channel estimates at the pilot positions -------- */
+    /* Step by the pilot spacing in a given symbol */
+    for (i = iFirstPilotCarrier, iPiHiIdx = iFirstPilotCarrier/iScatPilFreqInt;
+            i < iNumCarrier; i += iScatPilFreqSpacing, iPiHiIdx+=iScatPilTimeInt)
+    {
+        /* Identify and calculate transfer function at the pilot positions */
+        if (_IsScatPil(veciMapTab[i])) /* This will almost always be true */
+        {
+            /* Add new channel estimate: h = r / s, h: transfer function of the
+               channel, r: received signal, s: transmitted signal */
+            cNewPilot = (*pvecInputData)[i] / veccPilotCells[i];
+
+            /* We need to correct pilots due to timing corrections */
+            /* Calculate timing difference: use the one you want to correct (the current one = 0) - the reference one */
+            cNewPilot =	pTimeInt->Rotate(cNewPilot, i, -iTimeDiffAccuRSI);
+
+        }
+        else /* it must be the DC carrier in mode D. Set to complex zero */
+        {
+            cNewPilot = _COMPLEX(_REAL(0.0),_REAL(0.0));
+        }
+
+        /* Store it in the matrix */
+        matcRSIPilotStore[iRow][iPiHiIdx] = cNewPilot;
+    }
+
+    /* Is it the last symbol of the frame? If so, transfer to the CParam object for output via RSI */
+    if (iSymbolCounter == Parameters.CellMappingTable.iNumSymPerFrame - 1)
+    {
+        /* copy into CParam object */
+        Parameters.matcReceivedPilotValues.Init(iNumSymPerFrame / iScatPilTimeInt, iNumCarrier/iScatPilFreqInt + 1,
+                _COMPLEX(_REAL(0.0),_REAL(0.0)));
+        Parameters.matcReceivedPilotValues = matcRSIPilotStore;
+        /* copy it a row at a time (vector provides an assignment operator)
+        for (i=0; i<iNumSymPerFrame / iScatPilTimeInt; i++)
+        	Parameters.matcReceivedPilotValues[i] = matcRSIPilotStore[i];
+        */
+
+
+        /* clear the local copy */
+        matcRSIPilotStore.Init(iNumSymPerFrame / iScatPilTimeInt, iNumCarrier/iScatPilFreqInt + 1,
+                               _COMPLEX(_REAL(0.0),_REAL(0.0)));
+
+    }
+}
diff --git a/src/chanest/ChannelEstimation.h b/src/chanest/ChannelEstimation.h
new file mode 100644
index 0000000..a0ec370
--- /dev/null
+++ b/src/chanest/ChannelEstimation.h
@@ -0,0 +1,272 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *	See ChannelEstimation.cpp
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#if !defined(CHANEST_H__3B0BA660_CA63_4344_BB2B_23E7A0D31912__INCLUDED_)
+#define CHANEST_H__3B0BA660_CA63_4344_BB2B_23E7A0D31912__INCLUDED_
+
+#include "../Parameter.h"
+#include "../util/Modul.h"
+#include "../ofdmcellmapping/OFDMCellMapping.h"
+#include "../ofdmcellmapping/CellMappingTable.h"
+#include "../tables/TableQAMMapping.h"
+#include "../matlib/Matlib.h"
+#include "../sync/TimeSyncTrack.h"
+#include "TimeLinear.h"
+#include "TimeWiener.h"
+
+
+/* Definitions ****************************************************************/
+#define LEN_WIENER_FILT_FREQ_RMA		6
+#define LEN_WIENER_FILT_FREQ_RMB		11
+#define LEN_WIENER_FILT_FREQ_RMC		11
+#define LEN_WIENER_FILT_FREQ_RMD		13
+
+/* Time constant for IIR averaging of fast signal power estimation */
+#define TICONST_SNREST_FAST				((CReal) 30.0) /* sec */
+
+/* Time constant for IIR averaging of slow signal power estimation */
+#define TICONST_SNREST_SLOW				((CReal) 100.0) /* sec */
+
+/* Time constant for IIR averaging of MSC signal / noise power estimation */
+#define TICONST_SNREST_MSC				((CReal) 1.0) /* sec */
+
+/* Initial value for SNR */
+#define INIT_VALUE_SNR_WIEN_FREQ_DB		((_REAL) 30.0) /* dB */
+
+/* SNR estimation initial SNR value */
+#define INIT_VALUE_SNR_ESTIM_DB			((_REAL) 20.0) /* dB */
+
+/* Wrap around bound for calculation of group delay. It is wraped by the 2 pi
+   periodicity of the angle() function */
+#define WRAP_AROUND_BOUND_GRP_DLY		((_REAL) 4.0)
+
+/* Set length of history for delay values for minimum search. Since the
+   delay estimation is optimized for channel estimation performance and
+   therefore the delay is usually estimated as too long, it is better for the
+   log file to use the minimum value in a certain time period for a good
+   estimate of the true delay */
+#define LEN_HIST_DELAY_LOG_FILE_S		((CReal) 1.0) /* sec */
+
+/* max frame len for FAC SNR estimates for each symbol of frame */
+#define MAX_NUM_SYM_PER_FRAME			RMD_NUM_SYM_PER_FRAME
+
+/* Classes ********************************************************************/
+class CChannelEstimation : public CReceiverModul<_COMPLEX, CEquSig>
+{
+public:
+    CChannelEstimation() : eDFTWindowingMethod(DFT_WIN_HAMM),
+        TypeIntFreq(FWIENER), TypeIntTime(TWIENER),
+        TypeSNREst(SNR_FAC), iLenHistBuff(0),
+        rNoiseEst(0.0), rSignalEst(0.0),
+        rNoiseEstWMMAcc(0.0), rSignalEstWMMAcc(0.0), rNoiseEstWMFAcc(0.0),
+        rSignalEstWMFAcc(0.0), rNoiseEstMERAcc(0.0),iCountMERAcc(0),
+        bInterfConsid(FALSE) {}
+
+    virtual ~CChannelEstimation() {}
+
+    enum ETypeIntFreq {FLINEAR, FDFTFILTER, FWIENER};
+    enum ETypeIntTime {TLINEAR, TWIENER};
+    enum ETypeSNREst {SNR_FAC, SNR_PIL};
+
+    void GetTransferFunction(CVector<_REAL>& vecrData,
+                             CVector<_REAL>& vecrGrpDly,	CVector<_REAL>& vecrScale);
+    void GetAvPoDeSp(CVector<_REAL>& vecrData, CVector<_REAL>& vecrScale,
+                     _REAL& rLowerBound, _REAL& rHigherBound,
+                     _REAL& rStartGuard, _REAL& rEndGuard, _REAL& rPDSBegin,
+                     _REAL& rPDSEnd);
+    void GetSNRProfile(CVector<_REAL>& vecrData, CVector<_REAL>& vecrScale);
+
+    CTimeLinear* GetTimeLinear() {
+        return &TimeLinear;
+    }
+    CTimeWiener* GetTimeWiener() {
+        return &TimeWiener;
+    }
+    CTimeSyncTrack* GetTimeSyncTrack() {
+        return &TimeSyncTrack;
+    }
+
+    /* Set (get) frequency and time interpolation algorithm */
+    void SetFreqInt(ETypeIntFreq eNewTy) {
+        TypeIntFreq = eNewTy;
+    }
+    ETypeIntFreq GetFreqInt() {
+        return TypeIntFreq;
+    }
+    void SetTimeInt(ETypeIntTime eNewTy) {
+        TypeIntTime = eNewTy;
+        SetInitFlag();
+    }
+    ETypeIntTime GetTimeInt() const {
+        return TypeIntTime;
+    }
+
+    void SetIntCons(const _BOOLEAN bNewIntCons) {
+        bInterfConsid = bNewIntCons;
+    }
+    _BOOLEAN GetIntCons() {
+        return bInterfConsid;
+    }
+
+
+    /* Which SNR estimation algorithm */
+    void SetSNREst(ETypeSNREst eNewTy) {
+        TypeSNREst = eNewTy;
+        SetInitFlag();
+    }
+    ETypeSNREst GetSNREst() {
+        return TypeSNREst;
+    }
+
+    void StartSaRaOffAcq() {
+        TimeSyncTrack.StartSaRaOffAcq();
+        SetInitFlag();
+    }
+
+protected:
+    enum EDFTWinType {DFT_WIN_RECT, DFT_WIN_HAMM, DFT_WIN_HANN};
+    EDFTWinType				eDFTWindowingMethod;
+
+    int					iSampleRate;
+    int					iNumSymPerFrame;
+
+    CChanEstTime*			pTimeInt;
+
+    CTimeLinear				TimeLinear;
+    CTimeWiener				TimeWiener;
+
+    CTimeSyncTrack			TimeSyncTrack;
+
+    ETypeIntFreq			TypeIntFreq;
+    ETypeIntTime			TypeIntTime;
+    ETypeSNREst				TypeSNREst;
+
+    int						iNumCarrier;
+
+    CMatrix<_COMPLEX>		matcHistory;
+
+    int						iLenHistBuff;
+
+    int						iScatPilFreqInt; /* Frequency interpolation */
+    int						iScatPilTimeInt; /* Time interpolation */
+
+    CComplexVector			veccChanEst;
+    CRealVector				vecrSqMagChanEst;
+
+    int						iFFTSizeN;
+
+    CReal					rGuardSizeFFT;
+
+    CRealVector				vecrDFTWindow;
+    CRealVector				vecrDFTwindowInv;
+
+    int						iLongLenFreq;
+    CComplexVector			veccPilots;
+    CComplexVector			veccIntPil;
+    CFftPlans				FftPlanShort;
+    CFftPlans				FftPlanLong;
+
+    int						iNumIntpFreqPil;
+
+    CReal					rLamSNREstFast;
+    CReal					rLamSNREstSlow;
+    CReal					rLamMSCSNREst;
+
+    _REAL					rNoiseEst;
+    _REAL					rNoiseEstMSCMER;
+    _REAL					rSignalEst;
+    CVector<_REAL>			vecrNoiseEstMSC;
+    CVector<_REAL>			vecrSigEstMSC;
+    _REAL					rSNREstimate;
+    _REAL					rNoiseEstSum;
+    _REAL					rSignalEstSum;
+    CRealVector				vecrNoiseEstFACSym;
+    CRealVector				vecrSignalEstFACSym;
+    _REAL					rSNRChanEstCorrFact;
+    _REAL					rSNRFACSigCorrFact;
+    _REAL					rSNRTotToPilCorrFact;
+    _REAL					rSNRSysToNomBWCorrFact;
+
+    /* OPH: Accumulators for calculating the RSCI MER, WMF, and WMM (these are averages, not filtered values) */
+    _REAL					rNoiseEstWMMAcc;
+    _REAL					rSignalEstWMMAcc;
+    _REAL					rNoiseEstWMFAcc;
+    _REAL					rSignalEstWMFAcc;
+    _REAL					rNoiseEstMERAcc;
+    int						iCountMERAcc;
+
+    _BOOLEAN				bInterfConsid;
+
+    /* Needed for GetDelay() */
+    _REAL					rLenPDSEst;
+    CShiftRegister<CReal>	vecrDelayHist;
+    int						iLenDelayHist;
+
+    int						iStartZeroPadding;
+
+    int						iInitCnt;
+    int						iSNREstIniSigAvCnt;
+    int						iSNREstIniNoiseAvCnt;
+    int						iSNREstInitCnt;
+    _BOOLEAN				bSNRInitPhase;
+    _REAL CalAndBoundSNR(const _REAL rSignalEst, const _REAL rNoiseEst);
+
+    /* OPH: RSCI interference tag calculation */
+    void CalculateRint(CParameter& Parameters);
+    void UpdateRSIPilotStore(CParameter& Parameters, CVectorEx<_COMPLEX>* pvecInputData,
+                             CVector<int>& veciMapTab, CVector<_COMPLEX>& veccPilotCells, const int iSymbolCounter);
+
+    CMatrix<_COMPLEX>	matcRSIPilotStore;
+    int iTimeDiffAccuRSI; /* Accumulator for time differences for RSI pilot output */
+
+    /* Wiener interpolation in frequency direction */
+    void UpdateWienerFiltCoef(CReal rNewSNR, CReal rRatPDSLen,
+                              CReal rRatPDSOffs);
+
+    CComplexVector FreqOptimalFilter(int iFreqInt, int iDiff, CReal rSNR,
+                                     CReal rRatPDSLen, CReal rRatPDSOffs,
+                                     int iLength);
+    CMatrix<_COMPLEX>		matcFiltFreq;
+    int						iLengthWiener;
+    CVector<int>			veciPilOffTab;
+
+    int						iDCPos;
+    int						iPilOffset;
+    int						iNumWienerFilt;
+    CComplexMatrix			matcWienerFilter;
+
+#ifdef USE_DD_WIENER_FILT_TIME
+    int						iCurrentFrameID;
+#endif
+
+    virtual void InitInternal(CParameter& Parameters);
+    virtual void ProcessDataInternal(CParameter& Parameters);
+};
+
+
+#endif // !defined(CHANEST_H__3B0BA660_CA63_4344_BB2B_23E7A0D31912__INCLUDED_)
diff --git a/src/chanest/IdealChannelEstimation.cpp b/src/chanest/IdealChannelEstimation.cpp
new file mode 100644
index 0000000..ef4635b
--- /dev/null
+++ b/src/chanest/IdealChannelEstimation.cpp
@@ -0,0 +1,169 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *	
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "IdealChannelEstimation.h"
+
+
+/* Implementation *************************************************************/
+void CIdealChanEst::ProcessDataInternal(CParameter& Parameters)
+{
+	int i, j;
+
+	/* Calculation of channel tranfer function ------------------------------ */
+	/*	pvecInputData.cSig		equalized signal \hat{s}(t)
+		pvecInputData2.tOut		received signal r(t)
+		pvecInputData2.tIn		transmitted signal s(t)
+		pvecInputData2.tRef		received signal without noise (channel
+									reference signal) */
+	for (i = 0; i < iNumCarrier; i++)
+	{
+		/* Extract channel estimate from equalized signal */
+		veccEstChan[i] = (*pvecInputData2)[i].tOut / (*pvecInputData)[i].cSig;
+
+		/* Calculate reference signal for channel from fading taps. We have
+		   to do it this way to avoid errors from ICI
+		   (inter-carrier-interfearence). Consider offset from guard-interval
+		   removal (additional phase rotation) */
+		veccRefChan[i] = (_REAL) 0.0;
+		for (j = 0; j < Parameters.iNumTaps; j++)
+			veccRefChan[i] += Rotate((*pvecInputData2)[0].veccTap[j], i,
+				Parameters.iPathDelay[j] + Parameters.iOffUsfExtr);
+
+		/* Normalize result */
+		veccRefChan[i] *= Parameters.rGainCorr;
+	}
+
+	/* Debar DC carriers, set them to zero */
+	for (i = 0; i < iNumDCCarriers; i++)
+	{
+		veccEstChan[i + iStartDCCar] = _COMPLEX((_REAL) 0.0, (_REAL) 0.0);
+		veccRefChan[i + iStartDCCar] = _COMPLEX((_REAL) 0.0, (_REAL) 0.0);
+	}
+
+	/* Start evaluation results after exceeding the start count */
+	if (iStartCnt > 0)
+		iStartCnt--;
+	else
+	{
+		/* MSE for all carriers */
+		for (i = 0; i < iNumCarrier; i++)
+			vecrMSEAverage[i] += SqMag(veccEstChan[i] - veccRefChan[i]);
+
+		/* New values have been added, increase counter for final result
+		   calculation */
+		lAvCnt++;
+	}
+
+
+	/* Equalize the output vector ------------------------------------------- */
+	/* Write to output vector. Also, ship the channel state at a certain cell */
+	for (i = 0; i < iNumCarrier; i++)
+	{
+#ifdef USE_MAX_LOG_MAP
+		/* In case of MAP we need the squared magnitude for the calculation of
+		   the metric */
+		(*pvecOutputData)[i].rChan = SqMag(veccRefChan[i]);
+#else
+		/* In case of hard-desicions, we need the magnitude of the channel for
+		   the calculation of the metric */
+		(*pvecOutputData)[i].rChan = abs(veccRefChan[i]);
+#endif
+
+		/* If we do not want to get the actual channel estimate but the
+		   ideal equalized signal, we should do it this way to be ICI free */
+		(*pvecOutputData)[i].cSig = (*pvecInputData2)[i].tOut *
+			(*pvecInputData2)[i].tIn / (*pvecInputData2)[i].tRef;
+	}
+
+	/* Set symbol number for output vector */
+	(*pvecOutputData).GetExData().iSymbolID = 
+		(*pvecInputData).GetExData().iSymbolID;
+}
+
+void CIdealChanEst::InitInternal(CParameter& Parameters)
+{
+	/* Init base class for modifying the pilots (rotation) */
+	CPilotModiClass::InitRot(Parameters);
+
+	/* Get local parameters */
+	iNumCarrier = Parameters.CellMappingTable.iNumCarrier;
+	iNumSymPerFrame = Parameters.CellMappingTable.iNumSymPerFrame;
+	iDFTSize = Parameters.CellMappingTable.iFFTSizeN;
+
+	/* Parameters for debaring the DC carriers from evaluation. First check if
+	   we have only useful part on the right side of the DC carrier */
+	if (Parameters.CellMappingTable.iCarrierKmin > 0)
+	{
+		/* In this case, no DC carriers are in the useful spectrum */
+		iNumDCCarriers = 0;
+		iStartDCCar = 0;
+	}
+	else
+	{
+		if (Parameters.GetWaveMode() == RM_ROBUSTNESS_MODE_A)
+		{
+			iNumDCCarriers = 3;
+			iStartDCCar = abs(Parameters.CellMappingTable.iCarrierKmin) - 1;
+		}
+		else
+		{
+			iNumDCCarriers = 1;
+			iStartDCCar = abs(Parameters.CellMappingTable.iCarrierKmin);
+		}
+	}
+
+	/* Init average counter */
+	lAvCnt = 0;
+
+	/* Init start count (debar initialization of channel estimation) */
+	iStartCnt = 20;
+
+	/* Additional delay from long interleaving has to be considered */
+    if (Parameters.GetInterleaverDepth() == SI_LONG)
+		iStartCnt += Parameters.CellMappingTable.iNumSymPerFrame * D_LENGTH_LONG_INTERL;
+
+
+	/* Allocate memory for intermedia results */
+	veccEstChan.Init(iNumCarrier);
+	veccRefChan.Init(iNumCarrier);
+	vecrMSEAverage.Init(iNumCarrier, (_REAL) 0.0); /* Reset average with zeros */
+
+	/* Define block-sizes for inputs and output */
+	iInputBlockSize = iNumCarrier;
+	iInputBlockSize2 = iNumCarrier;
+	iOutputBlockSize = iNumCarrier;
+}
+
+void CIdealChanEst::GetResults(CVector<_REAL>& vecrResults)
+{
+	vecrResults.Init(iNumCarrier, (_REAL) 0.0);
+
+	/* Copy data in return vector */
+	for (int i = 0; i < iNumCarrier; i++)
+		vecrResults[i] = vecrMSEAverage[i] / lAvCnt;
+}
diff --git a/src/chanest/IdealChannelEstimation.h b/src/chanest/IdealChannelEstimation.h
new file mode 100644
index 0000000..477edb6
--- /dev/null
+++ b/src/chanest/IdealChannelEstimation.h
@@ -0,0 +1,70 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *	See Data.cpp
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#if !defined(IDEALCHANEST_H__3B0BA660_CA3452341912__INCLUDED_)
+#define IDEALCHANEST_H__3B0BA660_CA3452341912__INCLUDED_
+
+#include "../Parameter.h"
+#include "../util/Modul.h"
+#include "../matlib/Matlib.h"
+#include "../util/Vector.h"
+#include "ChanEstTime.h" /* Because of "CPilotModiClass" */
+#include "../interleaver/SymbolInterleaver.h" /* Because of "D_LENGTH_LONG_INTERL" */
+
+
+/* Classes ********************************************************************/
+class CIdealChanEst :
+	public CSimulationModul<CEquSig, CEquSig, CChanSimDataDemod>, 
+	public CPilotModiClass
+{
+public:
+	CIdealChanEst() {}
+	virtual ~CIdealChanEst() {}
+
+	void GetResults(CVector<_REAL>& vecrResults);
+
+protected:
+	int	iNumCarrier;
+	int iNumSymPerFrame;
+	int iStartDCCar;
+	int iNumDCCarriers;
+	int iChanEstDelay;
+	int iDFTSize;
+
+	CVector<_COMPLEX>	veccEstChan;
+	CVector<_COMPLEX>	veccRefChan;
+	CVector<_REAL>		vecrMSEAverage;
+	long int			lAvCnt;
+	int					iStartCnt;
+
+	virtual void InitInternal(CParameter& Parameters);
+	virtual void ProcessDataInternal(CParameter& Parameters);
+};
+
+
+#endif // !defined(IDEALCHANEST_H__3B0BA660_CA3452341912__INCLUDED_)
diff --git a/src/chanest/TimeLinear.cpp b/src/chanest/TimeLinear.cpp
new file mode 100644
index 0000000..36f5783
--- /dev/null
+++ b/src/chanest/TimeLinear.cpp
@@ -0,0 +1,141 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *	Linear channel estimation in time direction
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later 
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT 
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "TimeLinear.h"
+
+
+/* Implementation *************************************************************/
+_REAL CTimeLinear::Estimate(CVectorEx<_COMPLEX>* pvecInputData, 
+						    CComplexVector& veccOutputData, 
+						    CVector<int>& veciMapTab, 
+						    CVector<_COMPLEX>& veccPilotCells, _REAL rSNR)
+{
+	int			i, j;
+	int			iPiHiIndex;
+	int			iTimeDiffOld;
+	int			iTimeDiffNew;
+	_COMPLEX	cOldPilot;
+	_COMPLEX	cNewPilot;
+	_COMPLEX	cGrad;
+
+	/* Channel estimation buffer -------------------------------------------- */
+	/* Move data in channel estimation-buffer 
+	   (from iLenHistBuff - 1 towards 0) */
+	for (j = 0; j < iLenHistBuff - 1; j++)
+	{
+		for (i = 0; i < iNumIntpFreqPil; i++)
+			matcChanEstHist[j][i] = matcChanEstHist[j + 1][i];
+	}
+
+	/* Clear current symbol for new channel estimates */
+	for (i = 0; i < iNumIntpFreqPil; i++)
+		matcChanEstHist[iLenHistBuff - 1][i] = 
+			_COMPLEX((_REAL) 0.0, (_REAL) 0.0);
+
+
+	/* Timing correction history -------------------------------------------- */
+	/* Update timing correction history (shift register) */
+	vecTiCorrHist.AddEnd(0);
+
+	/* Add new one to all history values */
+	for (i = 0; i < iLenTiCorrHist; i++)
+		vecTiCorrHist[i] += (*pvecInputData).GetExData().iCurTimeCorr;
+
+
+	/* Main loop ------------------------------------------------------------ */
+	/* Identify and calculate transfer function at the pilot positions */
+	for (i = 0; i < iNumCarrier; i++)
+	{
+		if (_IsScatPil(veciMapTab[i]))
+		{
+			/* Pilots are only every "iScatPilFreqInt"'th carrier */
+			iPiHiIndex = i / iScatPilFreqInt;
+
+			/* h = r / s, h: transfer function of channel, r: received signal, 
+			   s: transmitted signal */
+			matcChanEstHist[iLenHistBuff - 1][iPiHiIndex] = 
+				(*pvecInputData)[i] / veccPilotCells[i];
+
+			/* Linear interpolate in time direction from this current pilot to 
+			   the corresponding pilot in the last symbol of the history */
+			for (j = 1; j < iLenHistBuff - 1; j++)
+			{
+				/* We need to correct pilots due to timing corrections ------ */
+				/* Calculate timing difference to old and new pilot */
+				iTimeDiffOld = vecTiCorrHist[0]	- vecTiCorrHist[j];
+				iTimeDiffNew = 0				- vecTiCorrHist[j];
+				
+				/* Correct pilot information for phase rotation */
+				cOldPilot = Rotate(
+					matcChanEstHist[0][iPiHiIndex], i, iTimeDiffOld);
+				cNewPilot = Rotate(
+					matcChanEstHist[iLenHistBuff - 1][iPiHiIndex], i,
+					iTimeDiffNew);
+
+
+				/* Linear interpolation ------------------------------------- */
+				/* First, calculate gradient */
+				cGrad = (cNewPilot - cOldPilot) / (_REAL) (iLenHistBuff - 1);
+
+				/* Apply linear interpolation to cells in between */
+				matcChanEstHist[j][iPiHiIndex] = cGrad * (_REAL) j + cOldPilot;
+			}
+		}
+	}
+
+	/* Copy channel estimation from current symbol in output buffer */
+	for (i = 0; i < iNumIntpFreqPil; i++)
+		veccOutputData[i] = matcChanEstHist[0][i];
+
+	/* No SNR improvement by linear interpolation */
+	return rSNR;
+}
+
+int CTimeLinear::Init(CParameter& Parameter)
+{
+	/* Init base class, must be at the beginning of this init! */
+	CPilotModiClass::InitRot(Parameter);
+
+	/* Get parameters from global struct */
+	iNumCarrier = Parameter.CellMappingTable.iNumCarrier;
+	iNumIntpFreqPil = Parameter.CellMappingTable.iNumIntpFreqPil;
+	iScatPilFreqInt = Parameter.CellMappingTable.iScatPilFreqInt;
+
+	/* Set length of history-buffer according to time-int-index */
+	iLenHistBuff = Parameter.CellMappingTable.iScatPilTimeInt + 1;
+	
+	/* Init timing correction history with zeros */
+	iLenTiCorrHist = iLenHistBuff - 1;
+	vecTiCorrHist.Init(iLenTiCorrHist, 0);
+
+	/* Allocate memory for channel estimation history and init with ones */
+	matcChanEstHist.Init(iLenHistBuff, iNumIntpFreqPil, _COMPLEX(1.0, 0.0));
+
+	/* Return delay of channel estimation in time direction */
+	return iLenHistBuff;
+}
diff --git a/src/chanest/TimeLinear.h b/src/chanest/TimeLinear.h
new file mode 100644
index 0000000..728f8b5
--- /dev/null
+++ b/src/chanest/TimeLinear.h
@@ -0,0 +1,70 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *	See TimeLinear.cpp
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later 
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT 
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#if !defined(TIMELINEAR_H__3B0BA6346234660_CA63_4344_BBE7A0D31912__INCLUDED_)
+#define TIMELINEAR_H__3B0BA6346234660_CA63_4344_BBE7A0D31912__INCLUDED_
+
+#include "../GlobalDefinitions.h"
+#include "../Parameter.h"
+#include "../util/Vector.h"
+#include "../ofdmcellmapping/OFDMCellMapping.h"
+#include "../matlib/Matlib.h"
+#include "ChanEstTime.h"
+
+
+/* Definitions ****************************************************************/
+#define MAX_NO_SYMB_IN_HISTORY_LIN			(RMA_SCAT_PIL_TIME_INT + 1)		
+
+
+/* Classes ********************************************************************/
+class CTimeLinear : public CChanEstTime
+{
+public:
+	CTimeLinear() {}
+	virtual ~CTimeLinear() {}
+
+	virtual int Init(CParameter& Parameter);
+	virtual _REAL Estimate(CVectorEx<_COMPLEX>* pvecInputData, 
+						   CComplexVector& veccOutputData, 
+						   CVector<int>& veciMapTab, 
+						   CVector<_COMPLEX>& veccPilotCells, _REAL rSNR);
+
+protected:
+	int					iNumCarrier;
+	int					iNumIntpFreqPil;
+	int					iScatPilFreqInt;
+	CMatrix<_COMPLEX>	matcChanEstHist;
+
+	int					iLenHistBuff;
+
+	CShiftRegister<int>	vecTiCorrHist;
+	int					iLenTiCorrHist;
+};
+
+
+#endif // !defined(TIMELINEAR_H__3B0BA6346234660_CA63_4344_BBE7A0D31912__INCLUDED_)
diff --git a/src/chanest/TimeWiener.cpp b/src/chanest/TimeWiener.cpp
new file mode 100644
index 0000000..d06c385
--- /dev/null
+++ b/src/chanest/TimeWiener.cpp
@@ -0,0 +1,691 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *	Wiener filter in time direction for channel estimation
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "TimeWiener.h"
+
+
+/* Implementation *************************************************************/
+_REAL CTimeWiener::Estimate(CVectorEx<_COMPLEX>* pvecInputData,
+						    CComplexVector& veccOutputData,
+						    CVector<int>& veciMapTab,
+						    CVector<_COMPLEX>& veccPilotCells, _REAL rSNR)
+{
+	int			j, i;
+	int			iPiHiIdx;
+	int			iTimeDiffNew;
+	_COMPLEX	cNewPilot;
+
+	/* Timing correction history -------------------------------------------- */
+	/* Shift old vaules and add a "0" at the beginning of the vector */
+	vecTiCorrHist.AddBegin(0);
+
+	/* Add new one to all history values except of the current one */
+	for (i = 1; i < iLenTiCorrHist; i++)
+		vecTiCorrHist[i] += (*pvecInputData).GetExData().iCurTimeCorr;
+
+
+	/* Update histories for channel estimates at the pilot positions -------- */
+	for (i = 0, iPiHiIdx = 0; i < iNumCarrier; i += iScatPilFreqInt, iPiHiIdx++)
+	{
+		/* Identify and calculate transfer function at the pilot positions */
+		if (_IsScatPil(veciMapTab[i]))
+		{
+			/* Save channel estimates at the pilot positions for each carrier.
+			   Move old estimates and put new value. Use reversed order to
+			   prepare vector for convolution */
+			for (j = iLengthWiener - 1; j > 0; j--)
+			{
+				matcChanAtPilPos[j][iPiHiIdx] =
+					matcChanAtPilPos[j - 1][iPiHiIdx];
+			}
+
+			/* Add new channel estimate: h = r / s, h: transfer function of the
+			   channel, r: received signal, s: transmitted signal */
+			matcChanAtPilPos[0][iPiHiIdx] =
+				(*pvecInputData)[i] / veccPilotCells[i];
+
+
+			/* Estimation of the channel correlation function --------------- */
+			/* We calcuate the estimation for one symbol first and average this
+			   result */
+			for (j = 0; j < iNumTapsSigEst; j++)
+			{
+				/* Correct pilot information for phase rotation */
+				iTimeDiffNew = vecTiCorrHist[iScatPilTimeInt * j];
+				cNewPilot = Rotate(matcChanAtPilPos[j][iPiHiIdx], i,
+					iTimeDiffNew);
+
+				/* Use IIR filtering for averaging */
+				IIR1(veccTiCorrEst[j],
+					Conj(matcChanAtPilPos[0][iPiHiIdx]) * cNewPilot,
+					rLamTiCorrAv);
+			}
+		}
+
+
+		/* Wiener interpolation and filtering ------------------------------- */
+		/* This check is for robustness mode D since "iScatPilFreqInt" is "1"
+		   in this case it would include the DC carrier in the for-loop */
+		if (!_IsDC(veciMapTab[i]))
+		{
+			/* Read current filter phase from table */
+			const int iCurrFiltPhase = matiFiltPhaseTable[iPiHiIdx]
+				[(*pvecInputData).GetExData().iSymbolID];
+
+
+#ifdef USE_DD_WIENER_FILT_TIME
+// Get length of current filter, TODO: better solution
+			const int iCurFiltLen = vecvecPilIdx[iCurrFiltPhase].Size();
+			CComplexVector veccZFHestDD(iCurFiltLen);
+
+			int iPilIdx = 0;
+			int iDatIdx = 0;
+
+			for (j = 0; j < iCurFiltLen; j++)
+			{
+				/* Build vector for filtering. Make sure that pilot cells and
+				   DD-data cells are at the correct place */
+				CComplex cNewPilot;
+				if (vecvecPilIdx[iCurrFiltPhase][j].bIsPilot == TRUE)
+				{
+					cNewPilot = matcChanAtPilPos[iPilIdx][iPiHiIdx];
+					iPilIdx++;
+				}
+				else
+				{
+					cNewPilot = matcChanAtDataPos[iDatIdx][iPiHiIdx];
+					iDatIdx++;
+				}
+
+				/* We need to correct pilots due to timing corrections */
+				/* Calculate timing difference */
+				iTimeDiffNew = vecTiCorrHist[
+					vecvecPilIdx[iCurrFiltPhase][j].iIdx + iCurrFiltPhase] -
+					vecTiCorrHist[iLenHistBuff - 1];
+
+				/* Correct pilot information for phase rotation */
+				veccZFHestDD[j] = Rotate(cNewPilot, i, iTimeDiffNew);
+			}
+
+			/* Convolution */
+			const CComplex cCurChanEst =
+				Sum(veccZFHestDD * matrFiltTime[iCurrFiltPhase]);
+
+			/* Received signal must be delayed (we are using a FIFO here) */
+			matcRecSigHist[iPiHiIdx].Add((*pvecInputData)[i]);
+			matiMapTabHist[iPiHiIdx].Add(veciMapTab[i]);
+
+			const CComplex cCurRecSig = matcRecSigHist[iPiHiIdx].Get();
+			const int iCurMapTab = matiMapTabHist[iPiHiIdx].Get();
+
+			/* Make decision and store result in history */
+			/* Make sure current cell is a data cell */
+			if (!_IsPilot(iCurMapTab))
+			{
+				/* The dicision directed channel estimation is calculated as
+				   follows: h_DD = r / Dec(r / h) */
+				CComplex cCurDDChanEst;
+
+				/* Find out which coding scheme is used for this cell */
+				if (_IsFAC(iCurMapTab) || (_IsSDC(iCurMapTab) &&
+					(eSDCQAMMode == CParameter::CS_1_SM)))
+				{
+					/* 4-QAM */
+					cCurDDChanEst =
+						cCurRecSig / Dec4QAM(cCurRecSig / cCurChanEst);
+				}
+				else if (_IsSDC(iCurMapTab) || (_IsMSC(iCurMapTab) &&
+					(eMSCQAMMode == CParameter::CS_2_SM)))
+				{
+					/* 16-QAM */
+					cCurDDChanEst =
+						cCurRecSig / Dec16QAM(cCurRecSig / cCurChanEst);
+				}
+				else
+				{
+					/* 64-QAM */
+					cCurDDChanEst =
+						cCurRecSig / Dec64QAM(cCurRecSig / cCurChanEst);
+				}
+
+				/* Save channel estimates at the data positions for each
+				   carrier. Move old estimates and put new value. Use reversed
+				   order */
+				for (j = iLenDDHist - 1; j > 0; j--)
+				{
+					matcChanAtDataPos[j][iPiHiIdx] =
+						matcChanAtDataPos[j - 1][iPiHiIdx];
+				}
+
+				matcChanAtDataPos[0][iPiHiIdx] = cCurDDChanEst;
+			}
+#else
+			/* Convolution with one phase of the optimal filter */
+			/* Init sum */
+			_COMPLEX cCurChanEst = _COMPLEX((_REAL) 0.0, (_REAL) 0.0);
+			for (j = 0; j < iLengthWiener; j++)
+			{
+				/* We need to correct pilots due to timing corrections */
+				/* Calculate timing difference */
+				iTimeDiffNew =
+					vecTiCorrHist[j * iScatPilTimeInt + iCurrFiltPhase] -
+					vecTiCorrHist[iLenHistBuff - 1];
+
+				/* Correct pilot information for phase rotation */
+				cNewPilot =
+					Rotate(matcChanAtPilPos[j][iPiHiIdx], i, iTimeDiffNew);
+
+				/* Actual convolution with filter phase */
+				cCurChanEst += cNewPilot * matrFiltTime[iCurrFiltPhase][j];
+			}
+#endif
+
+			/* Copy channel estimation from current symbol in output buffer */
+			veccOutputData[iPiHiIdx] = cCurChanEst;
+		}
+	}
+
+
+	/* Update sigma estimation ---------------------------------------------- */
+	if (bTracking == TRUE)
+	{
+		/* Update filter coefficients once in one DRM frame */
+		if (iUpCntWienFilt > 0)
+		{
+			iUpCntWienFilt--;
+
+			/* Average estimated SNR values */
+			rAvSNR += rSNR;
+			iAvSNRCnt++;
+		}
+		else
+		{
+			/* Actual estimation of sigma */
+			rSigma = ModLinRegr(veccTiCorrEst);
+
+			/* Use overestimated sigma for filter update */
+			const _REAL rSigOverEst = rSigma * SIGMA_OVERESTIMATION_FACT;
+
+			/* Update the wiener filter, use averaged SNR */
+			if (rSigOverEst < rSigmaMax)
+				rMMSE = UpdateFilterCoef(rAvSNR / iAvSNRCnt, rSigOverEst);
+			else
+				rMMSE = UpdateFilterCoef(rAvSNR / iAvSNRCnt, rSigmaMax);
+
+			/* If no SNR improvent is achieved by the optimal filter, use
+			   SNR estimation for MMSE */
+			_REAL rNewSNR = (_REAL) 1.0 / rMMSE;
+			if (rNewSNR < rSNR)
+				rMMSE = (_REAL) 1.0 / rSNR;
+
+			/* Reset counter and sum (for SNR) */
+			iUpCntWienFilt = iNumSymPerFrame;
+			iAvSNRCnt = 0;
+			rAvSNR = (_REAL) 0.0;
+		}
+	}
+
+	/* Return the SNR improvement by Wiener interpolation in time direction */
+	return (_REAL) 1.0 / rMMSE;
+}
+
+int CTimeWiener::Init(CParameter& Parameters)
+{
+	/* Init base class, must be at the beginning of this init! */
+	CPilotModiClass::InitRot(Parameters);
+
+	/* Set local parameters */
+	const CCellMappingTable& Param = Parameters.CellMappingTable;
+	iNumCarrier = Param.iNumCarrier;
+	iScatPilTimeInt = Param.iScatPilTimeInt;
+	iScatPilFreqInt = Param.iScatPilFreqInt;
+	iNumSymPerFrame = Param.iNumSymPerFrame;
+	const int iNumIntpFreqPil = Param.iNumIntpFreqPil;
+
+	/* Generate filter phase table for Wiener filter */
+	GenFiltPhaseTable(Parameters.CellMappingTable.matiMapTab, iNumCarrier, iNumSymPerFrame, iScatPilTimeInt);
+
+	/* Init length of filter and maximum value of sigma (doppler) */
+	switch (Parameters.GetWaveMode())
+	{
+	case RM_ROBUSTNESS_MODE_A:
+		iLengthWiener = LEN_WIENER_FILT_TIME_RMA;
+		rSigmaMax = MAX_SIGMA_RMA;
+		break;
+
+	case RM_ROBUSTNESS_MODE_B:
+		iLengthWiener = LEN_WIENER_FILT_TIME_RMB;
+		rSigmaMax = MAX_SIGMA_RMB;
+		break;
+
+	case RM_ROBUSTNESS_MODE_C:
+		iLengthWiener = LEN_WIENER_FILT_TIME_RMC;
+		rSigmaMax = MAX_SIGMA_RMC;
+		break;
+
+	case RM_ROBUSTNESS_MODE_D:
+		iLengthWiener = LEN_WIENER_FILT_TIME_RMD;
+		rSigmaMax = MAX_SIGMA_RMD;
+		break;
+	
+	default:
+		break;
+	}
+
+	/* Set delay of this channel estimation type. The longer the delay is, the
+	   more "acausal" pilots can be used for interpolation. We use the same
+	   amount of causal and acausal filter taps here. Make sure that we get
+	   R_hp's which have the most energy collected:
+	   L = Np * TiPi - TiPi + 1 is the total number of cells which span our
+	   interpolation when we set a pilot on the left-most and right-most
+	   Ceil(L / 2) is the middle of the range, now we only have to consider
+	   half of the TiPi which is Floor(TiPi / 2) */
+	const int iSymDelyChanEst = (int) Ceil((CReal) (
+		iLengthWiener * iScatPilTimeInt - iScatPilTimeInt + 1) / 2) +
+		(int) Floor((CReal) iScatPilTimeInt / 2) - 1;
+
+	/* Set number of phases for wiener filter */
+	iNumFiltPhasTi = iScatPilTimeInt;
+
+	/* Set length of history-buffer */
+	iLenHistBuff = iSymDelyChanEst + 1;
+
+	/* Duration of useful part plus guard interval */
+	rTs = (_REAL) Parameters.CellMappingTable.iSymbolBlockSize / Parameters.GetSigSampleRate();
+
+	/* Total number of interpolated pilots in frequency direction. We have to
+	   consider the last pilot at the end ("+ 1") */
+	const int iTotNumPiFreqDir = iNumCarrier / iScatPilFreqInt + 1;
+
+	/* Allocate memory for Channel at pilot positions (matrix) and init with ones */
+	matcChanAtPilPos.Init(iLengthWiener, iTotNumPiFreqDir, _COMPLEX(1.0, 0.0));
+
+	/* Set number of taps for sigma estimation */
+	if (iLengthWiener < NUM_TAPS_USED4SIGMA_EST)
+		iNumTapsSigEst = iLengthWiener;
+	else
+		iNumTapsSigEst = NUM_TAPS_USED4SIGMA_EST;
+
+	/* Init vector for estimation of the correlation function in time direction
+	   (IIR average) */
+	veccTiCorrEst.Init(iNumTapsSigEst, (CReal) 0.0);
+
+	/* Init time constant for IIR filter for averaging correlation estimation.
+	   Consider averaging over frequency axis, too. Pilots in frequency
+	   direction are "iScatPilTimeInt * iScatPilFreqInt" apart */
+	const int iNumPilOneOFDMSym = iNumIntpFreqPil / iScatPilTimeInt;
+	rLamTiCorrAv = IIR1Lam(TICONST_TI_CORREL_EST * iNumPilOneOFDMSym,
+		(CReal) Parameters.GetSigSampleRate() / Parameters.CellMappingTable.iSymbolBlockSize);
+
+	/* Init update counter for Wiener filter update. We immediatly use the
+	   filtered result although right at the beginning there is no averaging.
+	   But sine the estimation usually starts with higher values and goes down
+	   to the correct one, this should not be critical */
+	iUpCntWienFilt = iNumSymPerFrame;
+
+	/* Init averaging of SNR values */
+	rAvSNR = (_REAL) 0.0;
+	iAvSNRCnt = 0;
+
+
+	/* Allocate memory for filter phases (Matrix) */
+	matrFiltTime.Init(iNumFiltPhasTi, iLengthWiener);
+
+	/* Length of the timing correction history buffer */
+	iLenTiCorrHist = iLengthWiener * iNumFiltPhasTi;
+
+	/* Init timing correction history with zeros */
+	vecTiCorrHist.Init(iLenTiCorrHist, 0);
+
+
+#ifdef USE_DD_WIENER_FILT_TIME
+	/* Allocate memory for Channel at data positions and init with ones */
+// TODO: we init the vectors longer than needed
+	iLenDDHist = iLengthWiener * iScatPilTimeInt;
+
+	matcChanAtDataPos.Init(iLenDDHist, iTotNumPiFreqDir, (CReal) 1.0);
+
+	/* Get modulation alphabet of MSC and SDC (MSC can only be 16- or 64-QAM,
+	   for SDC, only 4- or 16-QAM is possible) */
+	if (Parameters.eMSCCodingScheme == CParameter::CS_2_SM)
+		eMSCQAMMode = CParameter::CS_2_SM;
+	else
+		eMSCQAMMode = CParameter::CS_3_SM;
+
+	if (Parameters.eSDCCodingScheme == CParameter::CS_1_SM)
+		eSDCQAMMode = CParameter::CS_1_SM;
+	else
+		eSDCQAMMode = CParameter::CS_2_SM;
+
+	/* Init matrix for pilot and data indices */
+	vecvecPilIdx.Init(iNumFiltPhasTi);
+
+	/* Allocate memory for received signal history buffer and zero out */
+	matcRecSigHist.Init(iTotNumPiFreqDir);
+	matiMapTabHist.Init(iTotNumPiFreqDir);
+
+	for (int i = 0; i < iTotNumPiFreqDir; i++)
+	{
+		matcRecSigHist[i].Init(iLenHistBuff, (CReal) 0.0);
+		matiMapTabHist[i].Init(iLenHistBuff, 0);
+	}
+#endif
+
+
+	/* Calculate optimal filter --------------------------------------------- */
+	_REAL rSNR;
+
+	/* Distinguish between simulation and regular receiver. When we run a
+	   simulation, the parameters are taken from simulation init */
+	if (Parameters.eSimType == CParameter::ST_NONE)
+	{
+		/* Init SNR value */
+		rSNR = pow((CReal) 10.0, INIT_VALUE_SNR_WIEN_TIME_DB / 10);
+
+		/* Init sigma with a large value. This make the acquisition more
+		   robust in case of a large sample frequency offset. But we get more
+		   aliasing in the time domain and this could make the timing unit
+		   perform worse. Therefore, this is only a trade-off */
+		rSigma = rSigmaMax;
+	}
+	else
+	{
+		/* Get SNR on the pilot positions */
+		rSNR = pow((CReal) 10.0, Parameters.GetSysSNRdBPilPos() / 10);
+	
+		/* Sigma from channel profiles */
+		switch (Parameters.iDRMChannelNum)
+		{
+		case 1:
+		case 2:
+			rSigma = LOW_BOUND_SIGMA;
+			break;
+
+		case 4:
+			rSigma = 1.0 / 2;
+			break;
+
+		case 3:
+			rSigma = 1.2 / 2;
+			break;
+
+		case 5:
+			rSigma = 2.0 / 2;
+			break;
+
+		case 8:
+		case 10:
+		case 11:
+		case 12:
+			rSigma = (_REAL) Parameters.iSpecChDoppler / 2;
+			break;
+
+		default: /* Including channel number 6 */
+			rSigma = rSigmaMax / 2;
+			break;
+		}
+
+		/* Reset flag to inhibit parameter adaptation */
+		bTracking = FALSE;
+	}
+
+	/* Calculate initialization wiener filter taps and init MMSE */
+	rMMSE = UpdateFilterCoef(rSNR, rSigma);
+
+	/* Return delay of channel equalization */
+	return iLenHistBuff;
+}
+
+void CTimeWiener::GenFiltPhaseTable(const CMatrix<int>& matiMapTab,
+									const int iNumCarrier,
+									const int iNumSymPerFrame,
+									const int iScatPilTimeInt)
+{
+	/* Init matrix */
+	matiFiltPhaseTable.Init(iNumCarrier, iNumSymPerFrame);
+
+	/* Get the index of first symbol in a super-frame on where the first cell
+	   (carrier-index = 0) is a pilot. This is needed for determining the
+	   correct filter phase for the convolution */
+	int iFirstSymWithPilot = 0;
+	while (!_IsScatPil(matiMapTab[iFirstSymWithPilot][0]))
+		iFirstSymWithPilot++;
+
+	for (int i = 0; i < iNumCarrier; i++)
+	{
+		for (int j = 0; j < iNumSymPerFrame; j++)
+		{
+			/* Calculate filter phases for Wiener filter for each OFDM cell in
+			   a DRM frame */
+			matiFiltPhaseTable[i][j] = (iScatPilTimeInt -
+				(iNumSymPerFrame - j + iFirstSymWithPilot + i) %
+				iScatPilTimeInt) % iScatPilTimeInt;
+		}
+	}
+}
+
+_REAL CTimeWiener::UpdateFilterCoef(const _REAL rNewSNR, const _REAL rNewSigma)
+{
+	/* Calculate MMSE for wiener filtering for all phases and average */
+	_REAL rMMSE = (_REAL) 0.0;
+
+	/* One filter for all possible filter phases */
+	for (int j = 0; j < iNumFiltPhasTi; j++)
+	{
+		/* We have to define the dependency between the difference between the
+		   current pilot to the observed symbol in the history buffer and the
+		   indizes of the FiltTime array. Definition:
+		   Largest distance = index zero, index increases to smaller
+		   distances */
+		const int iCurrDiffPhase = -(iLenHistBuff - j - 1);
+
+		/* Calculate filter phase and average MMSE */
+#ifdef USE_DD_WIENER_FILT_TIME
+		rMMSE += TimeOptimalFiltDD(matrFiltTime[j], iScatPilTimeInt,
+			iCurrDiffPhase,	rNewSNR, rNewSigma, rTs, iLengthWiener, j);
+#else
+		rMMSE += TimeOptimalFilter(matrFiltTime[j], iScatPilTimeInt,
+			iCurrDiffPhase,	rNewSNR, rNewSigma, rTs, iLengthWiener);
+#endif
+	}
+
+	/* Normalize averaged MMSE */
+	rMMSE /= iNumFiltPhasTi;
+
+	return rMMSE;
+}
+
+CReal CTimeWiener::TimeOptimalFilter(CRealVector& vecrTaps, const int iTimeInt,
+									 const int iDiff, const CReal rNewSNR,
+									 const CReal rNewSigma, const CReal rTs,
+									 const int iLength)
+{
+	int i;
+
+	CRealVector vecrRpp(iLength);
+	CRealVector vecrRhp(iLength);
+
+	/* Factor for the argument of the exponetial function to generate the
+	   correlation function */
+	const CReal rFactorArgExp =
+		(CReal) -2.0 * crPi * crPi * rTs * rTs * rNewSigma * rNewSigma;
+
+	/* Doppler-spectrum for short-wave channel is Gaussian
+	   (Calculation of R_hp!) */
+	for (i = 0; i < iLength; i++)
+	{
+		const int iCurPos = i * iTimeInt + iDiff;
+
+		vecrRhp[i] = exp(rFactorArgExp * iCurPos * iCurPos);
+	}
+
+	/* Doppler-spectrum for short-wave channel is Gaussian
+	   (Calculation of R_pp!) */
+	for (i = 0; i < iLength; i++)
+	{
+		const int iCurPos = i * iTimeInt;
+
+		vecrRpp[i] = exp(rFactorArgExp * iCurPos * iCurPos);
+	}
+
+	/* Add SNR at first tap */
+	vecrRpp[0] += (CReal) 1.0 / rNewSNR;
+
+	/* Call levinson algorithm to solve matrix system for optimal solution */
+	vecrTaps = Levinson(vecrRpp, vecrRhp);
+
+	/* Return MMSE for the current wiener filter */
+	return (CReal) 1.0 - Sum(vecrRhp * vecrTaps);
+}
+
+#ifdef USE_DD_WIENER_FILT_TIME
+CReal CTimeWiener::TimeOptimalFiltDD(CRealVector& vecrTaps, const int iTimeInt,
+									 const int iDiff, const CReal rNewSNR,
+									 const CReal rNewSigma, const CReal rTs,
+									 const int iLength, const int iFiltPhase)
+{
+	int i, j;
+
+	/* Calculate number of pilot and DD cells. We use all cells up to the cell
+	   to be interpolated as pilot cells and after that only the regular
+	   pilot cells */
+	const int iTotNumCellsInRange = (iLength - 1) * iTimeInt + 1;
+
+	vecvecPilIdx[iFiltPhase].Init(0);
+	for (i = 0; i < iTotNumCellsInRange; i++)
+	{
+		if (i < -iDiff + 1)
+		{
+			/* Use only real pilots */
+			if (i % iTimeInt == 0)
+				vecvecPilIdx[iFiltPhase].Add(CDDPilIdx(i, TRUE));
+		}
+		else
+		{
+			if (i % iTimeInt == 0) /* Pilot or data cell? */
+				vecvecPilIdx[iFiltPhase].Add(CDDPilIdx(i, TRUE));
+			else
+				vecvecPilIdx[iFiltPhase].Add(CDDPilIdx(i, FALSE));
+		}
+	}
+
+	const int iNewLength = vecvecPilIdx[iFiltPhase].Size();
+
+	CComplexMatrix matcRpp(iNewLength, iNewLength);
+	CComplexVector veccRhp(iNewLength);
+
+	/* Factor for the argument of the exponetial function to generate the
+	   correlation function */
+	const CReal rFactorArgExp =
+		(CReal) -2.0 * crPi * crPi * rTs * rTs * rNewSigma * rNewSigma;
+
+	/* Doppler-spectrum for short-wave channel is Gaussian
+	   (Calculation of R_hp!) */
+	for (i = 0; i < iNewLength; i++)
+	{
+		const int iCurPos = vecvecPilIdx[iFiltPhase][i].iIdx + iDiff;
+
+		veccRhp[i] = exp(rFactorArgExp * iCurPos * iCurPos);
+	}
+
+	/* Doppler-spectrum for short-wave channel is Gaussian
+	   (Calculation of R_pp!) */
+	for (i = 0; i < iNewLength; i++)
+	{
+		for (j = 0; j < iNewLength; j++)
+		{
+			const int iCurPos = vecvecPilIdx[iFiltPhase][i].iIdx -
+				vecvecPilIdx[iFiltPhase][j].iIdx;
+
+			matcRpp[i][j] = exp(rFactorArgExp * iCurPos * iCurPos);
+
+			/* Add SNR (dependent on pilot or DD cell) */
+			if (i == j)
+			{
+				if (vecvecPilIdx[iFiltPhase][j].bIsPilot == TRUE)
+					matcRpp[i][j] += (CReal) 1.0 / rNewSNR;
+				else
+				{
+					/* DD cell has lower SNR */
+// TODO consider boosted pilots, consider decision errors!
+					matcRpp[i][j] += (CReal) 1.0 / rNewSNR *
+						AV_PILOT_POWER / AV_DATA_CELLS_POWER;
+				}
+			}
+		}
+	}
+
+	/* Call levinson algorithm to solve matrix system for optimal solution */
+// make sure size is correct FIXME: better solution!
+	vecrTaps.Init(iNewLength);
+
+	/* Calculate optimal filter (Since our correlations are real, the filter
+	   taps must be real, too */
+	vecrTaps = Real(Inv(matcRpp) * veccRhp);
+
+	/* Return MMSE for the current wiener filter */
+	return (CReal) 1.0 - Sum(Real(veccRhp * vecrTaps));
+}
+#endif
+
+CReal CTimeWiener::ModLinRegr(const CComplexVector& veccCorrEst)
+{
+	/* Modified linear regression to estimate the "sigma" of the Gaussian
+	   correlation function */
+	/* Get vector length */
+	const int iVecLen = veccCorrEst.GetSize();
+
+	/* Init vectors and variables */
+	CRealVector Tau(iVecLen);
+	CRealVector Z(iVecLen);
+	CRealVector W(iVecLen);
+
+	/* Generate the tau vector */
+	for (int i = 0; i < iVecLen; i++)
+		Tau[i] = (CReal) (i * iScatPilTimeInt);
+
+	/* Linearize acf equation:  y = a * exp(-b * x ^ 2)
+	   z = ln(y); w = x ^ 2
+	   -> z = a0 + a1 * w */
+	Z = Log(Abs(veccCorrEst));
+	W = Tau * Tau;
+
+	/* Apply linear regression */
+	const CReal A1 = LinRegr(W, Z);
+
+	/* Final sigma calculation from estimation and assumed Gaussian model */
+	const CReal rSigmaRet = (CReal) 0.5 / crPi * Sqrt((CReal) -2.0 * A1) / rTs;
+
+	/* Bound estimated sigma value */
+	if (rSigmaRet > rSigmaMax)
+		return rSigmaMax;
+	else if (rSigmaRet < LOW_BOUND_SIGMA)
+		return LOW_BOUND_SIGMA;
+	else
+		return rSigmaRet;
+}
diff --git a/src/chanest/TimeWiener.h b/src/chanest/TimeWiener.h
new file mode 100644
index 0000000..1f95b28
--- /dev/null
+++ b/src/chanest/TimeWiener.h
@@ -0,0 +1,174 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *	See TimeWiener.cpp
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#if !defined(TIMEWIENER_LINEAR_H__3B0BA660_C345345_4344_D31912__INCLUDED_)
+#define TIMEWIENER_LINEAR_H__3B0BA660_C345345_4344_D31912__INCLUDED_
+
+#include "../GlobalDefinitions.h"
+#include "../Parameter.h"
+#include "../util/Vector.h"
+#include "../ofdmcellmapping/OFDMCellMapping.h"
+#include "../matlib/Matlib.h"
+#include "ChanEstTime.h"
+#ifdef USE_DD_WIENER_FILT_TIME
+# include "../tables/TableQAMMapping.h"
+#endif
+
+
+/* Definitions ****************************************************************/
+/* Number of taps we want to use for sigma estimation */
+#define NUM_TAPS_USED4SIGMA_EST			3
+
+/* Lengths of wiener filter for wiener filtering in time direction */
+#define LEN_WIENER_FILT_TIME_RMA		5
+#define LEN_WIENER_FILT_TIME_RMB		7
+#define LEN_WIENER_FILT_TIME_RMC		9
+#define LEN_WIENER_FILT_TIME_RMD		9
+
+/* Maximum values for doppler for a specific robustness mode.
+   Parameters found by looking at resulting filter coefficients. The values
+   "rSigma" are set to the maximum possible doppler frequency which can be
+   interpolated by the pilot frequency grid. Since we have a Gaussian
+   power spectral density, the power is never exactely zero. Therefore we
+   determine the point where the PDS has fallen below a 50 dB limit */
+#define MAX_SIGMA_RMA					((_REAL) 1.6 /* Hz */ / 2)
+#define MAX_SIGMA_RMB					((_REAL) 2.7 /* Hz */ / 2)
+#define MAX_SIGMA_RMC					((_REAL) 5.7 /* Hz */ / 2)
+#define MAX_SIGMA_RMD					((_REAL) 4.5 /* Hz */ / 2)
+
+/* Define a lower bound for the doppler */
+#define LOW_BOUND_SIGMA					((_REAL) 0.1 /* Hz */ / 2)
+
+/* Initial value for SNR */
+#define INIT_VALUE_SNR_WIEN_TIME_DB		((_REAL) 25.0) /* dB */
+
+/* Time constant for IIR averaging of time correlation estimation */
+#define TICONST_TI_CORREL_EST			((CReal) 60.0) /* sec */
+
+/* Overestimation factor for sigma estimation.
+   We overestimate the sigma since the channel estimation result is much worse
+   if we use a sigma which is small than the real one compared to a value
+   which is bigger than the real one. Since we can only estimate on sigma for
+   all paths, it can happen that a path with a small gain but a high doppler
+   does not contribute enough on the global sigma estimation. Therefore the
+   overestimation */
+#define SIGMA_OVERESTIMATION_FACT		((_REAL) 3.0)
+
+
+/* Classes ********************************************************************/
+class CTimeWiener : public CChanEstTime
+{
+public:
+	CTimeWiener() : bTracking(FALSE) {}
+	virtual ~CTimeWiener() {}
+
+	virtual int Init(CParameter& Parameters);
+	virtual _REAL Estimate(CVectorEx<_COMPLEX>* pvecInputData,
+						   CComplexVector& veccOutputData,
+						   CVector<int>& veciMapTab,
+						   CVector<_COMPLEX>& veccPilotCells, _REAL rSNR);
+
+	_REAL GetSigma() {return rSigma * 2;}
+
+	void StartTracking() {bTracking = TRUE;}
+	void StopTracking() {bTracking = FALSE;}
+	
+protected:
+	CReal TimeOptimalFilter(CRealVector& vecrTaps, const int iTimeInt,
+							const int iDiff, const CReal rNewSNR,
+							const CReal rNewSigma, const CReal rTs,
+							const int iLength);
+	void GenFiltPhaseTable(const CMatrix<int>& matiMapTab, const int iNumCarrier,
+						   const int iNumSymPerFrame,
+						   const int iScatPilTimeInt);
+	_REAL UpdateFilterCoef(const _REAL rNewSNR, const _REAL rNewSigma);
+	CReal ModLinRegr(const CComplexVector& veccCorrEst);
+
+
+#ifdef USE_DD_WIENER_FILT_TIME
+	/* Decision directed Wiener */
+	class CDDPilIdx
+	{
+	public:
+		CDDPilIdx() : iIdx(0), bIsPilot(FALSE) {}
+		CDDPilIdx(int iNI, _BOOLEAN bNP) : iIdx(iNI), bIsPilot(bNP) {}
+		int			iIdx;
+		_BOOLEAN	bIsPilot;
+	};
+
+	CReal TimeOptimalFiltDD(CRealVector& vecrTaps, const int iTimeInt,
+							const int iDiff, const CReal rNewSNR,
+							const CReal rNewSigma, const CReal rTs,
+							const int iLength, const int iFiltPhase);
+
+	CMatrix<_COMPLEX>				matcChanAtDataPos;
+	int								iLenDDHist;
+	CParameter::ECodScheme			eMSCQAMMode, eSDCQAMMode;
+	CVector<CVector<CDDPilIdx> >	vecvecPilIdx;
+	CVector<CFIFO<CComplex> >		matcRecSigHist;
+	CVector<CFIFO<int> >			matiMapTabHist;
+#endif
+
+
+	CMatrix<int>		matiFiltPhaseTable;
+
+	int					iNumCarrier;
+
+	int					iLengthWiener;
+	int					iNumFiltPhasTi;
+	CRealMatrix			matrFiltTime;
+	
+	CMatrix<_COMPLEX>	matcChanAtPilPos;
+
+	CComplexVector		veccTiCorrEst;
+	CReal				rLamTiCorrAv;
+
+	int					iScatPilFreqInt; /* Frequency interpolation */
+	int					iScatPilTimeInt; /* Time interpolation */
+	int					iNumSymPerFrame;
+
+	int					iLenHistBuff;
+
+	CShiftRegister<int>	vecTiCorrHist;
+	int					iLenTiCorrHist;
+	int					iNumTapsSigEst;
+	int					iUpCntWienFilt;
+
+	_REAL				rTs;
+	_REAL				rSigma;
+	_REAL				rSigmaMax;
+
+	_REAL				rMMSE;
+	_REAL				rAvSNR;
+	int					iAvSNRCnt;
+
+	_BOOLEAN			bTracking;
+};
+
+
+#endif // !defined(TIMEWIENER_LINEAR_H__3B0BA660_C345345_4344_D31912__INCLUDED_)
diff --git a/src/datadecoding/DABMOT.cpp b/src/datadecoding/DABMOT.cpp
new file mode 100644
index 0000000..fd936cc
--- /dev/null
+++ b/src/datadecoding/DABMOT.cpp
@@ -0,0 +1,1716 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer, Andrea Russo, Doyle Richard, Julian Cable
+ *
+ * Description:
+ *	DAB MOT interface implementation
+ *
+ * 12/22/2003 Doyle Richard
+ *	- Header extension decoding
+ * 10/13/2005 Andrea Russo
+ *	- Broadcast WebSite application
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "DABMOT.h"
+#include "../util/Utilities.h"
+#include <algorithm>
+#include <assert.h>
+#include <cctype>
+#include <cstring>
+#include <fstream>
+#include <iostream>
+#ifdef HAVE_LIBZ
+#include <zlib.h>
+#else
+#ifdef HAVE_LIBFREEIMAGE
+# include <FreeImage.h>
+#endif
+#endif
+
+/* Implementation *************************************************************/
+ostream & operator<<(ostream & out, CDateAndTime & d)
+{
+	d.dump(out);
+	return out;
+}
+
+ostream & operator<<(ostream & out, CMOTObject & o)
+{
+	o.dump(out);
+	return out;
+}
+
+ostream & operator<<(ostream & out, CMOTDirectory & o)
+{
+	o.dump(out);
+	return out;
+}
+
+/******************************************************************************\
+* Encoder                                                                      *
+\******************************************************************************/
+void
+CMOTDABEnc::SetMOTObject(CMOTObject & NewMOTObject)
+{
+	size_t i;
+	CMOTObjectRaw MOTObjectRaw;
+
+	/* Get some necessary parameters of object */
+	const int iPicSizeBits = NewMOTObject.vecbRawData.Size();
+	const int iPicSizeBytes = iPicSizeBits / SIZEOF__BYTE;
+	const string strFileName = NewMOTObject.strName;
+
+	/* File name size is restricted (in this implementation) to 128 (2^7) bytes.
+	   If file name is longer, cut it. TODO: better solution: set Ext flag in
+	   "ContentName" header extension to allow larger file names */
+	size_t iFileNameSize = strFileName.size();
+	if (iFileNameSize > 128)
+		iFileNameSize = 128;
+
+	/* Copy actual raw data of object */
+	MOTObjectRaw.Body.Init(iPicSizeBits);
+	MOTObjectRaw.Body = NewMOTObject.vecbRawData;
+
+	/* Get content type and content sub type of object. We use the format string
+	   to get these informations about the object */
+	int iContentType = 0;		/* Set default value (general data) */
+	int iContentSubType = 0;	/* Set default value (gif) */
+
+	/* Get ending string which declares the type of the file. Make lowercase */
+
+	string strFormat;
+	strFormat.resize(NewMOTObject.strFormat.size());
+	transform(NewMOTObject.strFormat.begin(), NewMOTObject.strFormat.end(),
+			  strFormat.begin(), (int (*)(int)) tolower);
+
+	/* gif: 0, image: 2 */
+	if (strFormat.compare("gif") == 0)
+	{
+		iContentType = 2;
+		iContentSubType = 0;
+	}
+
+	/* jfif: 1, image: 2. Possible endings: jpg, jpeg, jfif */
+	if ((strFormat.compare("jpg") == 0) ||
+		(strFormat.compare("jpeg") == 0) || (strFormat.compare("jfif") == 0))
+	{
+		iContentType = 2;
+		iContentSubType = 1;
+	}
+
+	/* bmp: 2, image: 2 */
+	if (strFormat.compare("bmp") == 0)
+	{
+		iContentType = 2;
+		iContentSubType = 2;
+	}
+
+	/* png: 3, image: 2 */
+	if (strFormat.compare("png") == 0)
+	{
+		iContentType = 2;
+		iContentSubType = 3;
+	}
+
+	/* Header --------------------------------------------------------------- */
+	/* Header size (including header extension) */
+	const int iHeaderSize = 7 /* Header core  */  +
+		5 /* TriggerTime */  +
+		3 + iFileNameSize /* ContentName (header + actual name) */  +
+		2 /* VersionNumber */ ;
+
+	/* Allocate memory and reset bit access */
+	MOTObjectRaw.Header.Init(iHeaderSize * SIZEOF__BYTE);
+	MOTObjectRaw.Header.ResetBitAccess();
+
+	/* BodySize: This 28-bit field, coded as an unsigned binary number,
+	   indicates the total size of the body in bytes */
+	MOTObjectRaw.Header.Enqueue((uint32_t) iPicSizeBytes, 28);
+
+	/* HeaderSize: This 13-bit field, coded as an unsigned binary number,
+	   indicates the total size of the header in bytes */
+	MOTObjectRaw.Header.Enqueue((uint32_t) iHeaderSize, 13);
+
+	/* ContentType: This 6-bit field indicates the main category of the body's
+	   content */
+	MOTObjectRaw.Header.Enqueue((uint32_t) iContentType, 6);
+
+	/* ContentSubType: This 9-bit field indicates the exact type of the body's
+	   content depending on the value of the field ContentType */
+	MOTObjectRaw.Header.Enqueue((uint32_t) iContentSubType, 9);
+
+	/* Header extension ----------------------------------------------------- */
+	/* MOT Slideshow application: Only the MOT parameter ContentName is
+	   mandatory and must be used for each slide object that will be handled by
+	   the MOT decoder and the memory management of the Slide Show terminal */
+
+	/* TriggerTime: This parameter specifies the time for when the presentation
+	   takes place. The TriggerTime activates the object according to its
+	   ContentType. The value of the parameter field is coded in the UTC
+	   format */
+
+	/* PLI (Parameter Length Indicator): This 2-bit field describes the total
+	   length of the associated parameter. In this case:
+	   1 0 total parameter length = 5 bytes; length of DataField is 4 bytes */
+	MOTObjectRaw.Header.Enqueue((uint32_t) 2, 2);
+
+	/* ParamId (Parameter Identifier): This 6-bit field identifies the
+	   parameter. 1 0 1 (dec: 5) -> TriggerTime */
+	MOTObjectRaw.Header.Enqueue((uint32_t) 5, 6);
+
+	/* Validity flag = 0: "Now", MJD and UTC shall be ignored and be set to 0.
+	   Set MJD and UTC to zero. UTC flag is also zero -> short form */
+	MOTObjectRaw.Header.Enqueue((uint32_t) 0, 32);
+
+	/* VersionNumber: If several versions of an object are transferred, this
+	   parameter indicates its VersionNumber. The parameter value is coded as an
+	   unsigned binary number, starting at 0 and being incremented by 1 modulo
+	   256 each time the version changes. If the VersionNumber differs, the
+	   content of the body was modified */
+	/* PLI
+	   0 1 total parameter length = 2 bytes, length of DataField is 1 byte */
+	MOTObjectRaw.Header.Enqueue((uint32_t) 1, 2);
+
+	/* ParamId (Parameter Identifier): This 6-bit field identifies the
+	   parameter. 1 1 0 (dec: 6) -> VersionNumber */
+	MOTObjectRaw.Header.Enqueue((uint32_t) 6, 6);
+
+	/* Version number data field */
+	MOTObjectRaw.Header.Enqueue((uint32_t) 0, 8);
+
+	/* ContentName: The DataField of this parameter starts with a one byte
+	   field, comprising a 4-bit character set indicator (see table 3) and a
+	   4-bit Rfa field. The following character field contains a unique name or
+	   identifier for the object. The total number of characters is determined
+	   by the DataFieldLength indicator minus one byte */
+
+	/* PLI
+	   1 1 total parameter length depends on the DataFieldLength indicator */
+	MOTObjectRaw.Header.Enqueue((uint32_t) 3, 2);
+
+	/* ParamId (Parameter Identifier): This 6-bit field identifies the
+	   parameter. 1 1 0 0 (dec: 12) -> ContentName */
+	MOTObjectRaw.Header.Enqueue((uint32_t) 12, 6);
+
+	/* Ext (ExtensionFlag): This 1-bit field specifies the length of the
+	   DataFieldLength Indicator.
+	   0: the total parameter length is derived from the next 7 bits */
+	MOTObjectRaw.Header.Enqueue((uint32_t) 0, 1);
+
+	/* DataFieldLength Indicator: This field specifies as an unsigned binary
+	   number the length of the parameter's DataField in bytes. The length of
+	   this field is either 7 or 15 bits, depending on the setting of the
+	   ExtensionFlag */
+	MOTObjectRaw.Header.Enqueue((uint32_t) (1 /* header */  +
+											iFileNameSize	/* actual data */
+								), 7);
+
+	/* Character set indicator (0 0 0 0 complete EBU Latin based repertoire) */
+	MOTObjectRaw.Header.Enqueue((uint32_t) 0, 4);
+
+	/* Rfa 4 bits */
+	MOTObjectRaw.Header.Enqueue((uint32_t) 0, 4);
+
+	/* Character field */
+	for (i = 0; i < iFileNameSize; i++)
+		MOTObjectRaw.Header.Enqueue((uint32_t) strFileName[i], 8);
+
+	/* Generate segments ---------------------------------------------------- */
+	/* Header (header should not be partitioned! TODO) */
+	const int iPartiSizeHeader = 100;	/* Bytes */// TEST
+
+	PartitionUnits(MOTObjectRaw.Header, MOTObjSegments.vvbiHeader,
+				   iPartiSizeHeader);
+
+	/* Body */
+	const int iPartiSizeBody = 100;	/* Bytes */// TEST
+
+	PartitionUnits(MOTObjectRaw.Body, MOTObjSegments.vvbiBody,
+				   iPartiSizeBody);
+}
+
+void
+CMOTDABEnc::PartitionUnits(CVector < _BINARY > &vecbiSource,
+						   CVector < CVector < _BINARY > >&vecbiDest,
+						   const int iPartiSize)
+{
+	int i, j;
+	int iActSegSize;
+
+	/* Divide the generated units in partitions */
+	const int iSourceSize = vecbiSource.Size() / SIZEOF__BYTE;
+	const int iNumSeg = (int) ceil((_REAL) iSourceSize / iPartiSize);	/* Bytes */
+	const int iSizeLastSeg = iSourceSize -
+		(int) floor((_REAL) iSourceSize / iPartiSize) * iPartiSize;
+
+	/* Init memory for destination vector, reset bit access of source */
+	vecbiDest.Init(iNumSeg);
+	vecbiSource.ResetBitAccess();
+
+	for (i = 0; i < iNumSeg; i++)
+	{
+		/* All segments except the last one must have the size
+		   "iPartSizeHeader". If "iSizeLastSeg" is =, the source data size is
+		   a multiple of the partitions size. In this case, all units have
+		   the same size (-> "|| (iSizeLastSeg == 0)") */
+		if ((i < iNumSeg - 1) || (iSizeLastSeg == 0))
+			iActSegSize = iPartiSize;
+		else
+			iActSegSize = iSizeLastSeg;
+
+		/* Add segment data ------------------------------------------------- */
+		/* Header */
+		/* Allocate memory for body data and segment header bits (16) */
+		vecbiDest[i].Init(iActSegSize * SIZEOF__BYTE + 16);
+		vecbiDest[i].ResetBitAccess();
+
+		/* Segment header */
+		/* RepetitionCount: This 3-bit field indicates, as an unsigned
+		   binary number, the remaining transmission repetitions for the
+		   current object.
+		   In our current implementation, no repetitions used. TODO */
+		vecbiDest[i].Enqueue((uint32_t) 0, 3);
+
+		/* SegmentSize: This 13-bit field, coded as an unsigned binary
+		   number, indicates the size of the segment data field in bytes */
+		vecbiDest[i].Enqueue((uint32_t) iActSegSize, 13);
+
+		/* Body */
+		for (j = 0; j < iActSegSize * SIZEOF__BYTE; j++)
+			vecbiDest[i].Enqueue(vecbiSource.Separate(1), 1);
+	}
+}
+
+void
+CMOTDABEnc::GenMOTObj(CVector < _BINARY > &vecbiData,
+					  CVector < _BINARY > &vecbiSeg, const _BOOLEAN bHeader,
+					  const int iSegNum, const int iTranspID,
+					  const _BOOLEAN bLastSeg)
+{
+	int i;
+	CCRC CRCObject;
+
+	/* Standard settings for this implementation */
+	const _BOOLEAN bCRCUsed = TRUE;	/* CRC */
+	const _BOOLEAN bSegFieldUsed = TRUE;	/* segment field */
+	const _BOOLEAN bUsAccFieldUsed = TRUE;	/* user access field */
+	const _BOOLEAN bTransIDFieldUsed = TRUE;	/* transport ID field */
+
+/* Total length of object in bits */
+	int iTotLenMOTObj = 16 /* group header */ ;
+	if (bSegFieldUsed == TRUE)
+		iTotLenMOTObj += 16;
+	if (bUsAccFieldUsed == TRUE)
+	{
+		iTotLenMOTObj += 8;
+		if (bTransIDFieldUsed == TRUE)
+			iTotLenMOTObj += 16;
+	}
+	iTotLenMOTObj += vecbiSeg.Size();
+	if (bCRCUsed == TRUE)
+		iTotLenMOTObj += 16;
+
+	/* Init data vector */
+	vecbiData.Init(iTotLenMOTObj);
+	vecbiData.ResetBitAccess();
+
+	/* MSC data group header ------------------------------------------------ */
+	/* Extension flag: this 1-bit flag shall indicate whether the extension
+	   field is present, or not. Not used right now -> 0 */
+	vecbiData.Enqueue((uint32_t) 0, 1);
+
+	/* CRC flag: this 1-bit flag shall indicate whether there is a CRC at the
+	   end of the MSC data group */
+	if (bCRCUsed == TRUE)
+		vecbiData.Enqueue((uint32_t) 1, 1);
+	else
+		vecbiData.Enqueue((uint32_t) 0, 1);
+
+	/* Segment flag: this 1-bit flag shall indicate whether the segment field is
+	   present, or not */
+	if (bSegFieldUsed == TRUE)
+		vecbiData.Enqueue((uint32_t) 1, 1);
+	else
+		vecbiData.Enqueue((uint32_t) 0, 1);
+
+	/* User access flag: this 1-bit flag shall indicate whether the user access
+	   field is present, or not. We always use this field -> 1 */
+	if (bUsAccFieldUsed == TRUE)
+		vecbiData.Enqueue((uint32_t) 1, 1);
+	else
+		vecbiData.Enqueue((uint32_t) 0, 1);
+
+	/* Data group type: this 4-bit field shall define the type of data carried
+	   in the data group data field. Data group types:
+	   3: MOT header information
+	   4: MOT data */
+	if (bHeader == TRUE)
+		vecbiData.Enqueue((uint32_t) 3, 4);
+	else
+		vecbiData.Enqueue((uint32_t) 4, 4);
+
+	/* Continuity index: the binary value of this 4-bit field shall be
+	   incremented each time a MSC data group of a particular type, with a
+	   content different from that of the immediately preceding data group of
+	   the same type, is transmitted */
+	if (bHeader == TRUE)
+	{
+		vecbiData.Enqueue((uint32_t) iContIndexHeader, 4);
+
+		/* Increment modulo 16 */
+		iContIndexHeader++;
+		if (iContIndexHeader == 16)
+			iContIndexHeader = 0;
+	}
+	else
+	{
+		vecbiData.Enqueue((uint32_t) iContIndexBody, 4);
+
+		/* Increment modulo 16 */
+		iContIndexBody++;
+		if (iContIndexBody == 16)
+			iContIndexBody = 0;
+	}
+
+	/* Repetition index: the binary value of this 4-bit field shall signal the
+	   remaining number of repetitions of a MSC data group with the same data
+	   content, occurring in successive MSC data groups of the same type.
+	   No repetition used in this implementation right now -> 0, TODO */
+	vecbiData.Enqueue((uint32_t) 0, 4);
+
+	/* Extension field: this 16-bit field shall be used to carry the Data Group
+	   Conditional Access (DGCA) when general data or MOT data uses conditional
+	   access (Data group types 0010 and 0101, respectively). The DGCA contains
+	   the Initialization Modifier (IM) and additional Conditional Access (CA)
+	   information. For other Data group types, the Extension field is reserved
+	   for future additions to the Data group header.
+	   Extension field is not used in this implementation! */
+
+	/* Session header ------------------------------------------------------- */
+	/* Segment field */
+	if (bSegFieldUsed == TRUE)
+	{
+		/* Last: this 1-bit flag shall indicate whether the segment number field
+		   is the last or whether there are more to be transmitted */
+		if (bLastSeg == TRUE)
+			vecbiData.Enqueue((uint32_t) 1, 1);
+		else
+			vecbiData.Enqueue((uint32_t) 0, 1);
+
+		/* Segment number: this 15-bit field, coded as an unsigned binary number
+		   (in the range 0 to 32767), shall indicate the segment number.
+		   NOTE: The first segment is numbered 0 and the segment number is
+		   incremented by one at each new segment */
+		vecbiData.Enqueue((uint32_t) iSegNum, 15);
+	}
+
+	/* User access field */
+	if (bUsAccFieldUsed == TRUE)
+	{
+		/* Rfa (Reserved for future addition): this 3-bit field shall be
+		   reserved for future additions */
+		vecbiData.Enqueue((uint32_t) 0, 3);
+
+		/* Transport Id flag: this 1-bit flag shall indicate whether the
+		   Transport Id field is present, or not */
+		if (bTransIDFieldUsed == TRUE)
+			vecbiData.Enqueue((uint32_t) 1, 1);
+		else
+			vecbiData.Enqueue((uint32_t) 0, 1);
+
+		/* Length indicator: this 4-bit field, coded as an unsigned binary
+		   number (in the range 0 to 15), shall indicate the length n in bytes
+		   of the Transport Id and End user address fields.
+		   We do not use end user address field, only transport ID -> 2 */
+		if (bTransIDFieldUsed == TRUE)
+			vecbiData.Enqueue((uint32_t) 2, 4);
+		else
+			vecbiData.Enqueue((uint32_t) 0, 4);
+
+		/* Transport Id (Identifier): this 16-bit field shall uniquely identify
+		   one data object (file and header information) from a stream of such
+		   objects, It may be used to indicate the object to which the
+		   information carried in the data group belongs or relates */
+		if (bTransIDFieldUsed == TRUE)
+			vecbiData.Enqueue((uint32_t) iTranspID, 16);
+	}
+
+	/* MSC data group data field -------------------------------------------- */
+	vecbiSeg.ResetBitAccess();
+
+	for (i = 0; i < vecbiSeg.Size(); i++)
+		vecbiData.Enqueue(vecbiSeg.Separate(1), 1);
+
+	/* MSC data group CRC --------------------------------------------------- */
+	/* The data group CRC shall be a 16-bit CRC word calculated on the data
+	   group header, the session header and the data group data field. The
+	   generation shall be based on the ITU-T Recommendation X.25.
+	   At the beginning of each CRC word calculation, all shift register stage
+	   contents shall be initialized to "1". The CRC word shall be complemented
+	   (1's complement) prior to transmission */
+	if (bCRCUsed == TRUE)
+	{
+		/* Reset bit access */
+		vecbiData.ResetBitAccess();
+
+		/* Calculate the CRC and put it at the end of the segment */
+		CRCObject.Reset(16);
+
+		/* "byLengthBody" was defined in the header */
+		for (i = 0; i < iTotLenMOTObj / SIZEOF__BYTE - 2 /* CRC */ ; i++)
+			CRCObject.AddByte((_BYTE) vecbiData.Separate(SIZEOF__BYTE));
+
+		/* Now, pointer in "enqueue"-function is back at the same place,
+		   add CRC */
+		vecbiData.Enqueue(CRCObject.GetCRC(), 16);
+	}
+}
+
+_BOOLEAN
+CMOTDABEnc::GetDataGroup(CVector < _BINARY > &vecbiNewData)
+{
+	_BOOLEAN bLastSegment;
+
+	/* Init return value. Is overwritten in case the object is ready */
+	_BOOLEAN bObjectDone = FALSE;
+
+	if (bCurSegHeader == TRUE)
+	{
+		/* Check if this is last segment */
+		if (iSegmCntHeader == MOTObjSegments.vvbiHeader.Size() - 1)
+			bLastSegment = TRUE;
+		else
+			bLastSegment = FALSE;
+
+		/* Generate MOT object for header */
+		GenMOTObj(vecbiNewData, MOTObjSegments.vvbiHeader[iSegmCntHeader],
+				  TRUE, iSegmCntHeader, iTransportID, bLastSegment);
+
+		iSegmCntHeader++;
+		if (iSegmCntHeader == MOTObjSegments.vvbiHeader.Size())
+		{
+			/* Reset counter for body */
+			iSegmCntBody = 0;
+
+			/* Header is ready, transmit body now */
+			bCurSegHeader = FALSE;
+		}
+	}
+	else
+	{
+		/* Check that body size is not zero */
+		if (iSegmCntBody < MOTObjSegments.vvbiBody.Size())
+		{
+			/* Check if this is last segment */
+			if (iSegmCntBody == MOTObjSegments.vvbiBody.Size() - 1)
+				bLastSegment = TRUE;
+			else
+				bLastSegment = FALSE;
+
+			/* Generate MOT object for Body */
+			GenMOTObj(vecbiNewData,
+					  MOTObjSegments.vvbiBody[iSegmCntBody], FALSE,
+					  iSegmCntBody, iTransportID, bLastSegment);
+
+			iSegmCntBody++;
+		}
+
+		if (iSegmCntBody == MOTObjSegments.vvbiBody.Size())
+		{
+			/* Reset counter for header */
+			iSegmCntHeader = 0;
+
+			/* Body is ready, transmit header from next object */
+			bCurSegHeader = TRUE;
+			iTransportID++;
+
+			/* Signal that old object is done */
+			bObjectDone = TRUE;
+		}
+	}
+
+	/* Return status of object transmission */
+	return bObjectDone;
+}
+
+_REAL
+CMOTDABEnc::GetProgPerc() const
+{
+/*
+	Get percentage of processed data of current object.
+*/
+	const int
+		iTotNumSeg =
+		MOTObjSegments.vvbiHeader.Size() + MOTObjSegments.vvbiBody.Size();
+
+	return ((_REAL) iSegmCntBody + (_REAL) iSegmCntHeader) / iTotNumSeg;
+}
+
+void
+CMOTDABEnc::Reset()
+{
+	/* Reset continuity indices */
+	iContIndexHeader = 0;
+	iContIndexBody = 0;
+	iTransportID = 0;
+
+	/* Init counter for segments */
+	iSegmCntHeader = 0;
+	iSegmCntBody = 0;
+
+	/* Init flag which shows what is currently generated, header or body */
+	bCurSegHeader = TRUE;		/* Start with header */
+
+	/* Add a "null object" so that at least one valid object can be processed */
+	CMOTObject NullObject;
+	SetMOTObject(NullObject);
+}
+
+/******************************************************************************\
+* Decoder                                                                      *
+\******************************************************************************/
+CMOTDABDec::CMOTDABDec():MOTmode (unknown), MOTHeaders(),
+MOTDirectoryEntity(), MOTDirComprEntity(),
+MOTDirectory(), MOTCarousel(), qiNewObjects()
+{
+	assert(qiNewObjects.empty());
+}
+
+_BOOLEAN
+CMOTDABDec::NewObjectAvailable()
+{
+	return !qiNewObjects.empty();
+}
+
+void
+CMOTDABDec::GetNextObject(CMOTObject & NewMOTObject)
+{
+	TTransportID firstNew;
+#ifdef QT_CORE_LIB
+	guard.lock();
+	if(qiNewObjects.empty())
+	{
+		if(blocker.wait(&guard, 1000))
+		{
+			if(!qiNewObjects.empty())
+			{
+				firstNew = qiNewObjects.front();
+				qiNewObjects.pop();
+			}
+		}
+	}
+	else
+	{
+		firstNew = qiNewObjects.front();
+		qiNewObjects.pop();
+	}
+	guard.unlock();
+#else
+	firstNew = qiNewObjects.front();
+	qiNewObjects.pop();
+#endif
+	NewMOTObject = MOTCarousel[firstNew];
+}
+
+void
+CMOTDABDec::DeliverIfReady(TTransportID TransportID)
+{
+	CMOTObject & o = MOTCarousel[TransportID];
+	if ((!o.bComplete) && o.bHasHeader && o.Body.Ready())
+	{
+		o.bComplete = TRUE;
+		if (o.Body.IsZipped())
+		{
+			if (o.Body.uncompress() == FALSE)
+				/* Can't unzip so change the filename */
+				o.strName = string(o.strName.c_str()) + ".gz";
+		}
+		//cerr << o << endl;;
+		ostringstream ss; ss << o << endl;
+#ifdef QT_CORE_LIB
+		guard.lock();
+		qiNewObjects.push(TransportID);
+		blocker.wakeOne();
+		guard.unlock();
+#else
+		ofstream file;
+		file.open(o.strName.c_str());
+		file.write((char*)&o.Body.vecData[0], o.Body.vecData.Size());
+		file.close();		
+#endif
+	}
+}
+
+void
+CMOTDABDec::AddDataUnit(CVector < _BINARY > &vecbiNewData)
+{
+	int iLenGroupDataField;
+	CCRC CRCObject;
+	_BOOLEAN bCRCOk;
+	int iSegmentNum;
+	_BINARY biLastFlag;
+	_BINARY biTransportIDFlag = 0;
+	int iLenIndicat;
+	int iSegmentSize;
+	TTransportID TransportID = -1;
+
+	/* Get length of data unit */
+	iLenGroupDataField = vecbiNewData.Size();
+
+	/* CRC check ------------------------------------------------------------ */
+	/* We do the CRC check at the beginning no matter if it is used or not
+	   since we have to reset bit access for that */
+	/* Reset bit extraction access */
+	vecbiNewData.ResetBitAccess();
+
+	/* Check the CRC of this packet */
+	CRCObject.Reset(16);
+
+	/* "- 2": 16 bits for CRC at the end */
+	for (size_t i = 0; i < size_t(iLenGroupDataField / SIZEOF__BYTE) - 2; i++)
+		CRCObject.AddByte((_BYTE) vecbiNewData.Separate(SIZEOF__BYTE));
+
+	bCRCOk = CRCObject.CheckCRC(vecbiNewData.Separate(16));
+
+	/* MSC data group header ------------------------------------------------ */
+	/* Reset bit extraction access */
+	vecbiNewData.ResetBitAccess();
+
+	/* Extension flag */
+	const _BINARY biExtensionFlag = (_BINARY) vecbiNewData.Separate(1);
+
+	/* CRC flag */
+	const _BINARY biCRCFlag = (_BINARY) vecbiNewData.Separate(1);
+
+	/* Segment flag */
+	const _BINARY biSegmentFlag = (_BINARY) vecbiNewData.Separate(1);
+
+	/* User access flag */
+	const _BINARY biUserAccFlag = (_BINARY) vecbiNewData.Separate(1);
+
+	/* Data group type */
+	const int iDataGroupType = (int) vecbiNewData.Separate(4);
+
+	/* Continuity index (not yet used) */
+	vecbiNewData.Separate(4);
+
+	/* Repetition index (not yet used) */
+	vecbiNewData.Separate(4);
+
+	/* Extension field (not used) */
+	if (biExtensionFlag == 1)
+		vecbiNewData.Separate(16);
+
+	/* Session header ------------------------------------------------------- */
+	/* Segment field */
+	if (biSegmentFlag == 1)
+	{
+		/* Last */
+		biLastFlag = (_BINARY) vecbiNewData.Separate(1);
+
+		/* Segment number */
+		iSegmentNum = (int) vecbiNewData.Separate(15);
+	}
+	else
+	{
+		biLastFlag = 0;
+		iSegmentNum = 0;
+	}
+
+	/* User access field */
+	if (biUserAccFlag == 1)
+	{
+		/* Rfa (Reserved for future addition) */
+		vecbiNewData.Separate(3);
+
+		/* Transport Id flag */
+		biTransportIDFlag = (_BINARY) vecbiNewData.Separate(1);
+
+		/* Length indicator */
+		iLenIndicat = (int) vecbiNewData.Separate(4);
+
+		/* Transport Id */
+		if (biTransportIDFlag == 1)
+			TransportID = (int) vecbiNewData.Separate(16);
+
+		/* End user address field (not used) */
+		int iLenEndUserAddress;
+
+		if (biTransportIDFlag == 1)
+			iLenEndUserAddress = (iLenIndicat - 2) * SIZEOF__BYTE;
+		else
+			iLenEndUserAddress = iLenIndicat * SIZEOF__BYTE;
+
+		vecbiNewData.Separate(iLenEndUserAddress);
+	}
+    //cerr << "MOT: new data unit, tid " << TransportID << " CRC " << bCRCOk << " DG" << iDataGroupType << endl;
+
+	/* MSC data group data field -------------------------------------------- */
+	/* If CRC is not used enter if-block, if CRC flag is used, it must be ok to
+	   enter the if-block */
+	if ((biCRCFlag == 0) || ((biCRCFlag == 1) && (bCRCOk == TRUE)))
+	{
+		/* Segmentation header ---------------------------------------------- */
+		/* Repetition count (not used) */
+		int repetition_count = vecbiNewData.Separate(3);
+
+		(void)repetition_count; /* silence warnings */
+
+		/* Segment size */
+		iSegmentSize = (int) vecbiNewData.Separate(13);
+
+		/* Get MOT data ----------------------------------------------------- */
+		/* Segment number and user access data is needed */
+		if ((biSegmentFlag == 1) && (biUserAccFlag == 1) &&
+			(biTransportIDFlag == 1))
+		{
+			/* don't make any assumptions about the order or interleaving of
+			   Data Groups from the same or different objects.
+			 */
+
+			/* Distinguish between header and body */
+			if (iDataGroupType == 3)
+			{
+				/* Header information, i.e. the header core and the header
+				   extension, are transferred in Data Group type 3 */
+
+				if (MOTmode != headerMode)
+				{
+					/* mode change, throw away any directory */
+					MOTDirectory.Reset();
+                    //cerr << "Reset " << MOTDirectory << endl;
+				}
+				MOTmode = headerMode;
+
+				/* in theory, there can be only one header at a time, but
+				   lets be a bit more tolerant
+				 */
+				if (MOTHeaders.count(TransportID) == 0)
+				{
+					CBitReassembler o;
+					MOTHeaders[TransportID] = o;
+				}
+				CBitReassembler & o = MOTHeaders[TransportID];
+				o.AddSegment(vecbiNewData, iSegmentSize, iSegmentNum,
+							 biLastFlag);
+				/* if the header just got complete, see if the body is complete */
+				if (o.Ready())
+				{
+					MOTCarousel[TransportID].AddHeader(o.vecData);
+					DeliverIfReady(TransportID);
+				}
+			}
+			else if (iDataGroupType == 4)
+			{
+				/* Body data segments are transferred in Data Group type 4 */
+
+				/* don't worry about modes, just store everything in the carousel
+				   defer decisions until the object and either header or directory
+				   are complete
+				 */
+				map < TTransportID, CMOTObject >::iterator o =
+					MOTCarousel.find(TransportID);
+
+				if (o == MOTCarousel.end())
+				{
+					/* we never saw this before */
+					MOTCarousel[TransportID].TransportID = TransportID;
+					o = MOTCarousel.find(TransportID);
+				}
+				/* is this an old object we have completed? */
+				if (o->second.bComplete == FALSE)
+				{
+					o->second.Body.AddSegment(vecbiNewData, iSegmentSize,
+											  iSegmentNum, biLastFlag);
+				}
+				else
+				{
+					/* discard the segment */
+					vecbiNewData.Separate(iSegmentSize * SIZEOF__BYTE);
+				}
+
+				/* if the body just got complete we can see if its ready to deliver */
+				DeliverIfReady(TransportID);
+			}
+			else if (iDataGroupType == 6)	/* MOT directory */
+			{
+				if (MOTmode != directoryMode)
+				{
+					/* mode change, throw away any headers */
+					MOTHeaders.clear();
+					MOTDirectory.TransportID = -1;	/* forced reset */
+					MOTmode = directoryMode;
+                    //cerr << "Reset " << MOTDirectory << endl;
+				}
+
+				/* The carousel is changing */
+				if (MOTDirectory.TransportID != TransportID)
+				{
+					/* we never got all the previous directory */
+                    //cerr << " we never got all the previous directory " << TransportID << ", " << MOTDirectory.  TransportID << endl;
+					MOTDirectory.Reset();
+					MOTDirectory.TransportID = TransportID;
+					MOTDirectoryEntity.Reset();
+					MOTDirComprEntity.Reset();
+				}
+
+				if ((MOTDirectory.TransportID != TransportID) ||
+					((MOTDirectory.TransportID == TransportID)
+						&& (!MOTDirectoryEntity.Ready())))
+				{
+
+					/* Handle the new segment */
+
+					/* rely on the Add routine to check duplicates, set ready, etc. */
+					MOTDirectoryEntity.AddSegment(vecbiNewData,
+												  iSegmentSize,
+												  iSegmentNum, biLastFlag);
+					/* have we got the full directory ? */
+					if (MOTDirectoryEntity.Ready())
+					{
+                        //cerr << "Ready " << MOTDirectory << endl;
+						ProcessDirectory(MOTDirectoryEntity);
+						MOTDirectory.TransportID = TransportID;
+					}			/* END IF HAVE ALL OF THE NEW DIRECTORY */
+				}
+				else
+				{
+					vecbiNewData.Separate(iSegmentSize * SIZEOF__BYTE);
+				}
+			}					/* of DG type 6 */
+#if 0							//Commented until we can test it with a real compressed directory
+			else if (iDataGroupType == 7)	/* MOT directory compressed */
+			{
+				if (MOTmode != directoryMode)
+				{
+					/* mode change, throw away any headers */
+					MOTHeaders.clear();
+					MOTDirectory.TransportID = -1;	/* forced reset */
+					MOTmode = directoryMode;
+				}
+
+				/* The carousel is changing */
+				if (MOTDirectory.TransportID != TransportID)
+				{
+					/* we never got all the previous directory */
+					MOTDirectory.Reset();
+					MOTDirectory.TransportID = TransportID;
+					MOTDirectoryEntity.Reset();
+					MOTDirComprEntity.Reset();
+				}
+
+				if ((MOTDirectory.TransportID != TransportID) ||
+					((MOTDirectory.TransportID == TransportID)
+						&& (!MOTDirComprEntity.Ready())))
+				{
+					/* Handle the new segment */
+
+					/* rely on the Add routine to check duplicates, set ready, etc. */
+					MOTDirComprEntity.AddSegment(vecbiNewData,
+												 iSegmentSize,
+												 iSegmentNum, biLastFlag);
+					/* have we got the full directory ? */
+					if (MOTDirComprEntity.Ready())
+					{
+						/* uncompress data and extract directory */
+
+						/* Compression Flag - must be 1 */
+
+						const _BOOLEAN bCompressionFlag =
+							MOTDirComprEntity.vecData.
+							Separate(1) ? TRUE : FALSE;
+
+						/* rfu */
+						MOTDirComprEntity.vecData.Separate(1);
+
+						/* EntitySize */
+						MOTDirComprEntity.vecData.Separate(30);
+
+						/* CompressionID */
+						MOTDirComprEntity.vecData.Separate(8);
+
+						/* rfu */
+						MOTDirComprEntity.vecData.Separate(2);
+
+						/* Uncompressed DataLength */
+						MOTDirComprEntity.vecData.Separate(30);
+
+						CBitReassembler MOTDirectoryData;
+
+						MOTDirectoryData.vecData =
+							MOTDirComprEntity.vecData.
+							Separate(MOTDirComprEntity.vecData.Size() -
+									 (9 * SIZEOF__BYTE));
+
+						if (bCompressionFlag
+							&& MOTDirectoryData.IsZipped()
+							&& MOTDirectoryData.uncompress())
+						{
+							ProcessDirectory(MOTDirectoryData);
+
+							MOTDirectory.TransportID = TransportID;
+						}
+						else
+						{
+							/* reset */
+							MOTDirComprEntity.Reset();
+						}
+
+					}			/* END IF HAVE ALL OF THE NEW DIRECTORY */
+				}
+				else
+				{
+					vecbiNewData.Separate(iSegmentSize * SIZEOF__BYTE);
+				}
+			}					/* of DG type 7 */
+#endif
+			else
+			{
+				vecbiNewData.Separate(iSegmentSize * SIZEOF__BYTE);
+			}
+		}
+	}
+}
+
+void
+CMOTDABDec::ProcessDirectory(CBitReassembler & MOTDir)
+{
+	MOTDirectory.AddHeader(MOTDir.vecData);
+
+	/* first reset the "I'm in the carousel" flag for all objects
+	   and set the "I was in the carousel for the relevant objects
+	   then set the "I'm in the carousel" flag for all objects in the
+	   new directory.
+	   Then delete the objects from the carousel that need deleting
+	   leave objects alone that were never in a carousel, they might
+	   become valid later. */
+
+	/* save bodies of old carousel */
+	map < TTransportID, CByteReassembler > Body;
+	for (map < TTransportID,
+		 CMOTObject >::iterator m =
+		 MOTCarousel.begin(); m != MOTCarousel.end(); m++)
+	{
+		Body[m->first] = m->second.Body;
+	}
+	MOTCarousel.erase(MOTCarousel.begin(), MOTCarousel.end());
+
+    //cerr << "decode directory " << MOTDirectory.  iNumberOfObjects << " === " << MOTDirectory.vecObjects.size() << " {";
+
+	MOTDirectory.vecObjects.clear();
+
+	for (size_t i = 0; i < size_t(MOTDirectory.iNumberOfObjects); i++)
+	{
+		/* add each header to the carousel */
+		TTransportID tid = (TTransportID) MOTDir.vecData.Separate(16);
+		MOTCarousel[tid].AddHeader(MOTDir.vecData);
+		/* keep any bodies or body fragments previously received */
+		map < TTransportID, CByteReassembler >::iterator b = Body.find(tid);
+		if (b != Body.end())
+			MOTCarousel[tid].Body = b->second;
+		/* mark objects which are in the new directory */
+		MOTDirectory.vecObjects.push_back(tid);
+        //cerr << tid << " ";
+		DeliverIfReady(tid);
+	}
+    //cerr << "}" << endl;
+
+}
+
+void
+CDateAndTime::extract_absolute(CVector < _BINARY > &vecbiData)
+{
+	vecbiData.Separate(1);		/* rfa */
+	CModJulDate ModJulDate(vecbiData.Separate(17));
+	day = ModJulDate.GetDay();
+	month = ModJulDate.GetMonth();
+	year = ModJulDate.GetYear();
+	vecbiData.Separate(1);		/* rfa */
+	lto_flag = (int) vecbiData.Separate(1);
+	utc_flag = (int) vecbiData.Separate(1);
+	hours = (int) vecbiData.Separate(5);
+	minutes = (int) vecbiData.Separate(6);
+	if (utc_flag != 0)
+	{
+		seconds = (int) vecbiData.Separate(6);
+		vecbiData.Separate(10);	/* rfa */
+	}
+	else
+	{
+		seconds = 0;
+	}
+	if (lto_flag != 0)
+	{
+		vecbiData.Separate(2);	/* rfa */
+		int sign = (int) vecbiData.Separate(1);
+		half_hours = (int) vecbiData.Separate(5);
+		if (sign == 1)
+			half_hours = 0 - half_hours;
+	}
+	else
+	{
+		half_hours = 0;
+	}
+}
+
+void
+CDateAndTime::extract_relative(CVector < _BINARY > &vecbiData)
+{
+	int granularity = (int) vecbiData.Separate(2);
+	int interval = (int) vecbiData.Separate(6);
+	time_t t = time(NULL);
+	switch (granularity)
+	{
+	case 0:
+		t += 2 * 60 * interval;
+		break;
+	case 1:
+		t += 30 * 60 * interval;
+		break;
+	case 2:
+		t += 2 * 60 * 60 * interval;
+		break;
+	case 3:
+		t += 24 * 60 * 60 * interval;
+		break;
+	}
+	struct tm *tmp = gmtime(&t);
+	year = tmp->tm_year;
+	month = tmp->tm_mon;
+	day = tmp->tm_mday;
+	hours = tmp->tm_hour;
+	minutes = tmp->tm_min;
+	seconds = tmp->tm_sec;
+}
+
+void
+CDateAndTime::dump(ostream & out)
+{
+	out << year << '/' << uint16_t(month) << '/' << uint16_t(day);
+	out << " " << hours << ':' << minutes << ':' << seconds;
+	out << " flags: " << utc_flag << ':' << lto_flag << ':' << half_hours;
+}
+
+void
+CMOTObjectBase::decodeExtHeader(_BYTE & bParamId, int &iHeaderFieldLen,
+								int &iDataFieldLen,
+								CVector < _BINARY > &vecbiHeader) const
+{
+	int iPLI = (int) vecbiHeader.Separate(2);
+	bParamId = (unsigned char) vecbiHeader.Separate(6);
+
+	iHeaderFieldLen = 1;
+
+	switch (iPLI)
+	{
+	case 0:
+		/* Total parameter length = 1 byte; no DataField
+		   available */
+		iDataFieldLen = 0;
+		break;
+
+	case 1:
+		/* Total parameter length = 2 bytes, length of DataField
+		   is 1 byte */
+		iDataFieldLen = 1;
+		break;
+
+	case 2:
+		/* Total parameter length = 5 bytes; length of DataField
+		   is 4 bytes */
+		iDataFieldLen = 4;
+		break;
+
+	case 3:
+		/* Total parameter length depends on the DataFieldLength
+		   indicator (the maximum parameter length is
+		   32770 bytes) */
+
+		/* Ext (ExtensionFlag): This 1-bit field specifies the
+		   length of the DataFieldLength Indicator and is coded
+		   as follows:
+		   - 0: the total parameter length is derived from the
+		   next 7 bits;
+		   - 1: the total parameter length is derived from the
+		   next 15 bits */
+		_BINARY biExt = (_BINARY) vecbiHeader.Separate(1);
+
+		/* Get data field length */
+		if (biExt == 0)
+		{
+			iDataFieldLen = (int) vecbiHeader.Separate(7);
+			iHeaderFieldLen++;
+		}
+		else
+		{
+			iDataFieldLen = (int) vecbiHeader.Separate(15);
+			iHeaderFieldLen += 2;
+		}
+	}
+}
+
+void
+CReassembler::cachelast(CVector < _BYTE > &vecDataIn, size_t iSegSize)
+{
+	vecLastSegment.Init(iSegSize);
+	for (size_t i = 0; i < iSegSize; i++)
+		vecLastSegment[i] = vecDataIn.Separate(8);
+}
+
+void
+CReassembler::copyin(CVector < _BYTE > &vecDataIn, size_t iSegNum,
+					 size_t bytes)
+{
+	size_t offset = iSegNum * iSegmentSize;
+	size_t iNewSize = offset + bytes;
+	if (size_t(vecData.Size()) < iNewSize)
+		vecData.Enlarge(iNewSize - vecData.Size());
+	for (size_t i = 0; i < bytes; i++)
+		vecData[offset + i] = vecDataIn.Separate(8);
+}
+
+void
+CReassembler::AddSegment(CVector < _BYTE > &vecDataIn,
+						 int iSegSize, int iSegNum, _BOOLEAN bLast)
+{
+	if (bLast)
+	{
+		if (iLastSegmentNum == -1)
+		{
+			iLastSegmentNum = iSegNum;
+			iLastSegmentSize = iSegSize;
+			/* three cases:
+			   1: single segment - easy! (actually degenerate with case 3)
+			   2: multi-segment and the last segment came first.
+			   3: normal - some segment, not the last, came first,
+			   we know the segment size
+			 */
+			if (iSegNum == 0)
+			{					/* case 1 */
+				copyin(vecDataIn, 0, iSegSize);
+			}
+			else if (iSegmentSize == 0)
+			{					/* case 2 */
+				cachelast(vecDataIn, iSegSize);
+			}
+			else
+			{					/* case 3 */
+				copyin(vecDataIn, iSegNum, iSegSize);
+			}
+		}						/* otherwise do nothing as we already have the last segment */
+	}
+	else
+	{
+		iSegmentSize = iSegSize;
+		if (Tracker.HaveSegment(iSegNum) == FALSE)
+		{
+			copyin(vecDataIn, iSegNum, iSegSize);
+		}
+	}
+	Tracker.AddSegment(iSegNum);	/* tracking the last segment makes the Ready work! */
+
+	if ((iLastSegmentSize != -1)	/* we have the last segment */
+		&& (bReady == FALSE)	/* we haven't already completed reassembly */
+		&& Tracker.Ready()		/* there are no gaps */
+		)
+	{
+		if (vecLastSegment.Size() > 0)
+		{
+			/* we have everything, but the last segment came first */
+			copylast();
+		}
+		bReady = TRUE;
+	}
+	//qDebug("AddSegment %d last %d ready %d\n", iSegNum, bLast?1:0, bReady?1:0);
+}
+
+void
+CReassembler::copylast()
+{
+	size_t offset = iLastSegmentNum * iSegmentSize;
+	vecData.Enlarge(vecLastSegment.Size());
+	for (size_t i = 0; i < size_t(vecLastSegment.Size()); i++)
+		vecData[offset + i] = vecLastSegment[i];
+	vecLastSegment.Init(0);
+}
+
+void
+CBitReassembler::cachelast(CVector < _BYTE > &vecDataIn, size_t iSegSize)
+{
+	vecLastSegment.Init(8 * iSegSize);
+	vecLastSegment.ResetBitAccess();
+	for (size_t i = 0; i < 8 * iSegSize; i++)
+		vecLastSegment[i] = vecDataIn.Separate(1);
+}
+
+void
+CBitReassembler::copyin(CVector < _BYTE > &vecDataIn, size_t iSegNum,
+						size_t bytes)
+{
+	size_t offset = iSegNum * 8 * iSegmentSize;
+	size_t bits = 8 * bytes;
+	size_t iNewSize = offset + bits;
+	if (size_t(vecData.Size()) < iNewSize)
+		vecData.Enlarge(iNewSize - vecData.Size());
+	for (size_t i = 0; i < bits; i++)
+		vecData[offset + i] = vecDataIn.Separate(1);
+}
+
+void
+CBitReassembler::copylast()
+{
+	size_t offset = iLastSegmentNum * 8 * iSegmentSize;
+	vecData.Enlarge(vecLastSegment.Size());
+	for (size_t i = 0; i < size_t(vecLastSegment.Size()); i++)
+		vecData[offset + i] = vecLastSegment[i];
+	vecLastSegment.Init(0);
+	vecLastSegment.ResetBitAccess();
+}
+
+string
+CMOTObjectBase::extractString(CVector < _BINARY > &vecbiData, int iLen) const
+{
+	string strVar;
+	for (size_t i = 0; i < size_t(iLen); i++)
+	{
+		strVar += (char) vecbiData.Separate(SIZEOF__BYTE);
+	}
+	return strVar;
+}
+
+void
+CMOTDirectory::Reset ()
+{
+    CMOTObjectBase::Reset ();
+    bSortedHeaderInformation = FALSE;
+    DirectoryIndex.clear ();
+    bCompressionFlag = FALSE;
+    iCarouselPeriod = -1;
+    iNumberOfObjects = 0;
+    iSegmentSize = 0;
+}
+
+
+void
+CMOTDirectory::AddHeader(CVector < _BINARY > &vecbiHeader)
+{
+	int iDirectorySize;
+
+	/* compression flag - must be zero */
+	bCompressionFlag = vecbiHeader.Separate(1) ? TRUE : FALSE;
+
+	/* rfu */
+	vecbiHeader.Separate(1);
+
+	/* Directory size: not used */
+	iDirectorySize = (int) vecbiHeader.Separate(30); (void)iDirectorySize;
+
+	/* Number of objects */
+	iNumberOfObjects = (int) vecbiHeader.Separate(16);
+
+	/* Carousel period */
+	iCarouselPeriod = (int) vecbiHeader.Separate(24);
+
+	/*  rfu */
+	vecbiHeader.Separate(1);
+
+	/* Rfa: not used */
+	vecbiHeader.Separate(2);
+
+	/* Segment size: not used */
+	iSegmentSize = (int) vecbiHeader.Separate(13);
+	/* Directory extension length */
+	int iDirectoryExtensionLength = (int) vecbiHeader.Separate(16);
+
+	/* Use all header extension data blocks */
+	int iSizeRec = iDirectoryExtensionLength;
+
+	/* Use all header extension data blocks */
+	while (iSizeRec > 0)
+	{
+		_BYTE bParamId;
+		int iHdrFieldLen, iDataFieldLen, iTmp;
+
+		decodeExtHeader(bParamId, iHdrFieldLen, iDataFieldLen, vecbiHeader);
+
+		iSizeRec -= (iHdrFieldLen + iDataFieldLen);
+
+		switch (bParamId)
+		{
+		case 0:				/* SortedHeaderInformation */
+			bSortedHeaderInformation = TRUE;
+			break;
+		case 1:				/* DefaultPermitOutdatedVersions */
+			iTmp = (int) vecbiHeader.Separate(iDataFieldLen * SIZEOF__BYTE);
+			if (iTmp == 0)
+				bPermitOutdatedVersions = FALSE;
+			else
+				bPermitOutdatedVersions = TRUE;
+			break;
+		case 9:				/* DefaultExpiration */
+			if (iDataFieldLen == 1)
+			{
+				/* relative */
+				ExpireTime.extract_relative(vecbiHeader);
+			}
+			else
+			{
+				/* absolute */
+				ExpireTime.extract_absolute(vecbiHeader);
+			}
+			break;
+		case 34:				/* DirectoryIndex */
+		{
+			_BYTE iProfile = (_BYTE) vecbiHeader.Separate(SIZEOF__BYTE);
+			DirectoryIndex[iProfile] =
+				extractString(vecbiHeader, iDataFieldLen - 1);
+		}
+			break;
+		default:
+			if (iDataFieldLen > 0)
+				vecbiHeader.Separate(iDataFieldLen * SIZEOF__BYTE);
+			break;
+		}
+	}
+}
+
+_BOOLEAN
+CReassembler::IsZipped() const
+{
+/*
+	Check if the header file is a gzip header
+
+	see GZIP file format specification
+	http://www.ietf.org/rfc/rfc1952.txt
+*/
+	if(vecData.Size()<3)
+		return FALSE;
+	/* Check for gzip header [31, 139, 8] */
+	if ((vecData[0] == 31) && (vecData[1] == 139) && (vecData[2] == 8))
+		return TRUE;
+	else
+		return FALSE;
+}
+
+unsigned int
+CReassembler::gzGetOriginalSize() const
+{
+/*
+	Get the original size from a gzip file
+	last 4 bytes contains the original file size (ISIZE)
+
+	see GZIP file format specification
+	http://www.ietf.org/rfc/rfc1952.txt
+*/
+	CVector < _BYTE > byHeader(4);
+
+	const int iLastByte = vecData.Size() - 1;
+
+	byHeader[0] = vecData[iLastByte - 3];
+	byHeader[1] = vecData[iLastByte - 2];
+	byHeader[2] = vecData[iLastByte - 1];
+	byHeader[3] = vecData[iLastByte];
+
+	return byHeader[0] + (byHeader[1] << 8) + (byHeader[2] << 16) +
+		(byHeader[3] << 24);
+}
+
+_BOOLEAN
+CReassembler::uncompress()
+{
+#ifdef HAVE_LIBZ
+	CVector < _BYTE > vecbRawDataOut;
+	/* Extract the original file size */
+	unsigned long dest_len = gzGetOriginalSize();
+
+	if (dest_len < MAX_DEC_NUM_BYTES_ZIP_DATA)
+	{
+		vecbRawDataOut.Init(dest_len);
+
+		int zerr;
+		z_stream stream;
+		memset(&stream, 0, sizeof(stream));
+		if ((zerr = inflateInit2(&stream, -MAX_WBITS)) != Z_OK)
+			return FALSE;
+
+		/* skip past minimal gzip header */
+		stream.next_in = &vecData[10];
+		stream.avail_in = vecData.Size() - 10;
+
+		stream.next_out = &vecbRawDataOut[0];
+		stream.avail_out = vecbRawDataOut.Size();
+
+		zerr = inflate(&stream, Z_NO_FLUSH);
+		dest_len = vecbRawDataOut.Size() - stream.avail_out;
+
+		if (zerr != Z_OK && zerr != Z_STREAM_END)
+			return FALSE;
+
+		inflateEnd(&stream);
+
+		if (zerr != Z_OK && zerr != Z_STREAM_END)
+			return FALSE;
+
+		vecData.Init(dest_len);
+		vecData = vecbRawDataOut;
+		return TRUE;
+	}
+	else
+	{
+		vecData.Init(0);
+		return FALSE;
+	}
+#else
+#	ifdef HAVE_LIBFREEIMAGE
+	CVector < _BYTE > vecbRawDataOut;
+	CVector < _BYTE > &vecbRawDataIn = vecData;
+	/* Extract the original file size */
+	const unsigned long dest_len = gzGetOriginalSize();
+
+	if (dest_len < MAX_DEC_NUM_BYTES_ZIP_DATA)
+	{
+		vecbRawDataOut.Init(dest_len);
+
+		/* Actual decompression call */
+		const int zerr = FreeImage_ZLibGUnzip(&vecbRawDataOut[0],
+											  dest_len, &vecbRawDataIn[0],
+											  vecbRawDataIn.Size());
+
+		if (zerr > 0)
+		{
+			/* Copy data */
+			vecData.Init(zerr);
+			vecData = vecbRawDataOut;
+			return TRUE;
+		}
+		else
+		{
+			vecData.Init(0);
+			return FALSE;
+		}
+	}
+	else
+	{
+		vecData.Init(0);
+		return FALSE;
+	}
+#	else
+	return FALSE;
+#	endif
+#endif
+}
+
+static const char *txt[] = { "txt", "txt", "html", 0 };
+static const char *img[] = { "gif", "jpeg", "bmp", "png", 0 };
+static const char *audio[] = { "mpg", "mp2", "mp3", "mpg", "mp2", "mp3",
+	"pcm", "aiff", "atrac", "atrac2", "mp4", 0
+};
+static const char *video[] = { "mpg", "mp2", "mp4", "h263", 0 };
+
+void
+CMOTObject::AddHeader(CVector < _BINARY > &vecbiHeader)
+{
+
+	/* HeaderSize and BodySize */
+	iBodySize = (int) vecbiHeader.Separate(28);
+	size_t iHeaderSize = (size_t) vecbiHeader.Separate(13);
+
+	/* Content type and content sub-type */
+	iContentType = (int) vecbiHeader.Separate(6);
+	iContentSubType = (int) vecbiHeader.Separate(9);
+	/* 7 bytes for header core */
+	int iSizeRec = iHeaderSize - 7;
+
+	/* Use all header extension data blocks */
+	while (iSizeRec > 0)
+	{
+		_BYTE bParamId;
+		int iHdrFieldLen, iDataFieldLen, iTmp;
+
+		decodeExtHeader(bParamId, iHdrFieldLen, iDataFieldLen, vecbiHeader);
+
+		iSizeRec -= (iHdrFieldLen + iDataFieldLen);
+
+		switch (bParamId)
+		{
+		case 1:				/* PermitOutdatedVersions */
+			iTmp = (int) vecbiHeader.Separate(iDataFieldLen * SIZEOF__BYTE);
+			if (iTmp == 0)
+				bPermitOutdatedVersions = FALSE;
+			else
+				bPermitOutdatedVersions = TRUE;
+			break;
+		case 5:				/* TriggerTime - OBSOLETE */
+			/* not decoded - skip */
+			(void) vecbiHeader.Separate(iDataFieldLen * SIZEOF__BYTE);
+			break;
+		case 6:				/* Version - OBSOLETE */
+			iVersion = (int) vecbiHeader.Separate(SIZEOF__BYTE);
+			break;
+		case 7:				/* RetransmissionDistance */
+			/* not decoded - skip */
+			(void) vecbiHeader.Separate(iDataFieldLen * SIZEOF__BYTE);
+			break;
+		case 9:				/* Expiration */
+			if (iDataFieldLen == 1)
+			{
+				/* relative */
+				ExpireTime.extract_relative(vecbiHeader);
+			}
+			else
+			{
+				/* absolute */
+				ExpireTime.extract_absolute(vecbiHeader);
+			}
+			break;
+		case 10:				/* Priority */
+			/* not decoded - skip */
+			(void) vecbiHeader.Separate(iDataFieldLen * SIZEOF__BYTE);
+			break;
+		case 11:				/* Label */
+			/* not decoded - skip */
+			(void) vecbiHeader.Separate(iDataFieldLen * SIZEOF__BYTE);
+			break;
+		case 12:				/* Content Name */
+			/* TODO - convert characters to UNICODE */
+			iCharacterSetForName = vecbiHeader.Separate(4);
+			/* rfa  */
+			vecbiHeader.Separate(4);
+			strName = extractString(vecbiHeader, iDataFieldLen - 1);
+			break;
+		case 13:				/* UniqueBodyVersion */
+			iUniqueBodyVersion = (int) vecbiHeader.Separate(32);
+			break;
+		case 15:				/* Content Description */
+			iCharacterSetForDescription = vecbiHeader.Separate(4);
+
+			/* rfa */
+			vecbiHeader.Separate(4);
+
+			strContentDescription =
+				extractString(vecbiHeader, iDataFieldLen - 1);
+			break;
+		case 16:				/* Mime Type */
+			strMimeType = extractString(vecbiHeader, iDataFieldLen);
+			break;
+		case 17:				/* Compression Type */
+			iCompressionType =
+				(int) vecbiHeader.Separate(iDataFieldLen * SIZEOF__BYTE);
+			break;
+		case 0x21:				/* ProfileSubset */
+		{
+			vecbProfileSubset.clear();
+			for (size_t i = 0; i < size_t(iDataFieldLen); i++)
+				vecbProfileSubset.push_back((_BYTE) vecbiHeader.
+											Separate(SIZEOF__BYTE));
+		}
+			break;
+		case 0x23:				/* CAInfo */
+			/* not decoded - skip */
+			(void) vecbiHeader.Separate(iDataFieldLen * SIZEOF__BYTE);
+			break;
+		case 0x24:				/* CAReplacementObject */
+			/* not decoded - skip */
+			(void) vecbiHeader.Separate(iDataFieldLen * SIZEOF__BYTE);
+			break;
+		case 0x25:				/* ScopeStart */
+			ScopeStart.extract_absolute(vecbiHeader);
+			break;
+		case 0x26:				/* ScopeEnd */
+			ScopeEnd.extract_absolute(vecbiHeader);
+			break;
+		case 0x27:				/* ScopeId */
+			iScopeId = vecbiHeader.Separate(iDataFieldLen * SIZEOF__BYTE);
+			break;
+		default:
+			/* not decoded - skip */
+			if (iDataFieldLen > 0)
+				(void) vecbiHeader.Separate(iDataFieldLen * SIZEOF__BYTE);
+			break;
+		}
+	}
+	/* set strFormat */
+	switch (iContentType)
+	{
+	case 1:
+		strFormat = txt[iContentSubType];
+		break;
+	case 2:
+		strFormat = img[iContentSubType];
+		break;
+	case 3:
+		strFormat = audio[iContentSubType];
+		break;
+	case 4:
+		strFormat = video[iContentSubType];
+		break;
+	}
+	bHasHeader = TRUE;
+}
+
+void
+CMOTObject::dump(ostream & out)
+{
+	out << "MOT(" << TransportID << "):";
+	out << " Name: " << strName;
+	out << ':' << iCharacterSetForName;
+	out << " Description: " << strContentDescription;
+	out << ':' << iCharacterSetForDescription;
+	out << " mime: " << strMimeType;
+	out << " content: " << iContentType << '/' << iContentSubType;
+	out << " UniqueBodyVersion: " << iUniqueBodyVersion;
+	out << " Expires: " << ExpireTime;
+	out << " PermitOutdatedVersions: " << bPermitOutdatedVersions;
+	out << " Scope: " << hex << iScopeId << dec << " from " << ScopeStart <<
+		" to " << ScopeEnd;
+	out << " CompressionType: " << iCompressionType;
+	out << " Version: " << iVersion;
+	out << " Priority: " << iPriority;
+	out << " RetransmissionDistance: " << iRetransmissionDistance;
+	out << " format: " << strFormat;
+	out << " length: " << iBodySize;
+}
+
+void
+CMOTDirectory::dump(ostream & out)
+{
+	out << "MOTDIR(" << TransportID << "):";
+	out << " Expires: " << ExpireTime;
+	out << " PermitOutdatedVersions: " << bPermitOutdatedVersions;
+	out << " CarouselPeriod: " << iCarouselPeriod;
+	out << " SegmentSize: " << iSegmentSize;
+	out << " CompressionFlag: " << bCompressionFlag;
+	out << " SortedHeaderInformation: " << bSortedHeaderInformation;
+	out << " indices { ";
+	for (map < _BYTE, string >::iterator di = DirectoryIndex.begin();
+		 di != DirectoryIndex.end(); di++)
+    {
+		out << hex << int(di->first) << dec << " => " << di->second;
+		out.flush();
+    }
+	out << " }";
+	out << " there are " << iNumberOfObjects << " objects {";
+	for (size_t i = 0; i < vecObjects.size(); i++)
+		out << " " << vecObjects[i];
+	out << " }";
+}
diff --git a/src/datadecoding/DABMOT.h b/src/datadecoding/DABMOT.h
new file mode 100644
index 0000000..9d27f5c
--- /dev/null
+++ b/src/datadecoding/DABMOT.h
@@ -0,0 +1,606 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer, Andrea Russo, Julian Cable
+ *
+ * Description:
+ *	See DABMOT.cpp
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#if !defined(DABMOT_H__3B0UBVE98732KJVEW363E7A0D31912__INCLUDED_)
+#define DABMOT_H__3B0UBVE98732KJVEW363E7A0D31912__INCLUDED_
+
+#include "../GlobalDefinitions.h"
+#include "../util/Vector.h"
+#include "../util/CRC.h"
+#include <time.h>
+#include <map>
+#include <queue>
+#ifdef QT_CORE_LIB
+# include <QWaitCondition>
+# include <QMutex>
+#endif
+
+
+/* Definitions ****************************************************************/
+/* Invalid data segment number. Shall be a negative value since the test for
+   invalid data segment number is always "if (iDataSegNum < 0)" */
+#define INVALID_DATA_SEG_NUM			-1
+
+/* Maximum number of bytes for zip'ed files. We need to specify this number to
+   avoid segmentation faults due to erroneous zip header giving a much too high
+   number of bytes */
+#define MAX_DEC_NUM_BYTES_ZIP_DATA		1000000	/* 1 MB */
+
+/* Registrered BWS profiles (ETSI TS 101 498-1) */
+#define RESERVED_PROFILE	0x00
+#define BASIC_PROFILE		0x01
+#define TOP_NEWS_PROFILE	0x02
+#define UNRESTRICTED_PC_PROFILE 0xFF
+/* Classes ********************************************************************/
+
+
+class CMOTObjectRaw
+{
+  public:
+    CMOTObjectRaw ()
+    {
+	Reset ();
+    }
+
+    CMOTObjectRaw (const CMOTObjectRaw & nOR)
+    {
+	Header = nOR.Header;
+	Body = nOR.Body;
+    }
+
+    CMOTObjectRaw & operator= (const CMOTObjectRaw & nOR)
+    {
+	Header = nOR.Header;
+	Body = nOR.Body;
+	return *this;
+    }
+
+    void Reset ()
+    {
+	Header.Init (0);
+	Body.Init (0);
+    }
+
+    CVector < _BINARY > Header;
+    CVector < _BINARY > Body;
+};
+
+class CDateAndTime
+{
+  public:
+
+    CDateAndTime():utc_flag(0), lto_flag(0), half_hours(0),
+        year(0), month(0), day(0), hours(0), minutes(0), seconds(0)
+    {}
+
+    void extract_relative (CVector < _BINARY > &vecbiData);
+    void extract_absolute (CVector < _BINARY > &vecbiData);
+    void Reset ()
+    {
+        utc_flag = 0;
+        lto_flag = 0;
+        half_hours = 0;
+        year = 0;
+        month = 0;
+        day = 0;
+        hours = 0;
+        minutes = 0;
+        seconds = 0;
+    }
+
+	void dump(ostream& out);
+
+    int utc_flag, lto_flag, half_hours;
+    uint16_t year;
+    uint8_t month, day;
+    int hours, minutes, seconds;
+};
+
+typedef int TTransportID;
+
+class CSegmentTracker
+{
+  public:
+
+    CSegmentTracker ()
+    {
+	Reset ();
+    }
+
+    void Reset ()
+    {
+	vecbHaveSegment.clear ();
+    }
+
+    size_t size ()
+    {
+	return vecbHaveSegment.size ();
+    }
+
+    _BOOLEAN Ready ()
+    {
+	if (vecbHaveSegment.size () == 0)
+	    return FALSE;
+	for (size_t i = 0; i < vecbHaveSegment.size (); i++)
+	  {
+	      if (vecbHaveSegment[i] == FALSE)
+		{
+		    return FALSE;
+		}
+	  }
+	return TRUE;
+    }
+
+    void AddSegment (int iSegNum)
+    {
+	if ((iSegNum + 1) > int (vecbHaveSegment.size ()))
+	    vecbHaveSegment.resize (iSegNum + 1, FALSE);
+	vecbHaveSegment[iSegNum] = TRUE;
+    }
+
+    _BOOLEAN HaveSegment (int iSegNum)
+    {
+	if (iSegNum < int (vecbHaveSegment.size ()))
+	    return vecbHaveSegment[iSegNum];
+	return FALSE;
+    }
+
+  protected:
+    vector < _BOOLEAN > vecbHaveSegment;
+};
+
+class CReassembler
+{
+  public:
+
+	CReassembler(): vecData(), vecLastSegment(),
+		iLastSegmentNum(-1), iLastSegmentSize(-1), iSegmentSize(0),
+		Tracker(), bReady(false)
+    {
+    }
+
+    CReassembler (const CReassembler & r):iLastSegmentNum (r.iLastSegmentNum),
+	iLastSegmentSize (r.iLastSegmentSize),
+	iSegmentSize (r.iSegmentSize), Tracker (r.Tracker), bReady (r.bReady)
+    {
+	vecData.Init (r.vecData.Size ());
+	vecData = r.vecData;
+	vecLastSegment.Init (r.vecLastSegment.Size ());
+	vecLastSegment = r.vecLastSegment;
+    }
+
+    virtual ~ CReassembler ()
+    {
+    }
+
+    inline CReassembler & operator= (const CReassembler & r)
+    {
+	iLastSegmentNum = r.iLastSegmentNum;
+	iLastSegmentSize = r.iLastSegmentSize;
+	iSegmentSize = r.iSegmentSize;
+	Tracker = r.Tracker;
+	vecData.Init (r.vecData.Size ());
+	vecData = r.vecData;
+	vecLastSegment.Init (r.vecLastSegment.Size ());
+	vecLastSegment = r.vecLastSegment;
+	bReady = r.bReady;
+
+	return *this;
+    }
+
+    void Reset ()
+    {
+	vecData.Init (0);
+	vecData.ResetBitAccess ();
+	vecLastSegment.Init (0);
+	vecLastSegment.ResetBitAccess ();
+	iLastSegmentNum = -1;
+	iLastSegmentSize = -1;
+	iSegmentSize = 0;
+	Tracker.Reset ();
+	bReady = FALSE;
+    }
+
+    _BOOLEAN Ready ()
+    {
+	return bReady;
+    }
+
+    void AddSegment (CVector < _BYTE > &vecDataIn,
+		     int iSegSize, int iSegNum, _BOOLEAN bLast = FALSE);
+
+    _BOOLEAN IsZipped () const;
+    _BOOLEAN uncompress();
+
+    CVector < _BYTE > vecData;
+
+  protected:
+
+    virtual void copyin (CVector < _BYTE > &vecDataIn, size_t iSegNum,
+			 size_t bytes);
+    virtual void cachelast (CVector < _BYTE > &vecDataIn, size_t iSegSize);
+    virtual void copylast ();
+
+    unsigned int gzGetOriginalSize () const;
+
+    CVector < _BYTE > vecLastSegment;
+    int iLastSegmentNum;
+    int iLastSegmentSize;
+    size_t iSegmentSize;
+    CSegmentTracker Tracker;
+    _BOOLEAN bReady;
+};
+
+class CBitReassembler:public CReassembler
+{
+  public:
+    CBitReassembler ():CReassembler ()
+    {
+    }
+    CBitReassembler (const CBitReassembler & r):CReassembler (r)
+    {
+    }
+
+  protected:
+    virtual void copyin (CVector < _BYTE > &vecDataIn, size_t iSegNum,
+			 size_t bytes);
+    virtual void cachelast (CVector < _BYTE > &vecDataIn, size_t iSegSize);
+    virtual void copylast ();
+};
+
+typedef CReassembler CByteReassembler;
+
+class CMOTObjectBase
+{
+  public:
+
+    CMOTObjectBase ():TransportID(-1),ExpireTime(),bPermitOutdatedVersions(FALSE)
+    {
+		Reset ();
+    }
+
+    virtual ~CMOTObjectBase () { }
+
+    virtual void Reset ()
+    {
+		TransportID = -1;
+		ExpireTime.Reset ();
+		bPermitOutdatedVersions = FALSE;
+    }
+
+    void decodeExtHeader (_BYTE & bParamId,
+			  int &iHeaderFieldLen, int &iDataFieldLen,
+			  CVector < _BINARY > &vecbiHeader) const;
+
+    string extractString (CVector < _BINARY > &vecbiData, int iLen) const;
+
+    TTransportID TransportID;
+    CDateAndTime ExpireTime;
+    _BOOLEAN bPermitOutdatedVersions;
+
+};
+
+class CMOTDirectory:public CMOTObjectBase
+{
+  public:
+
+    CMOTDirectory ():CMOTObjectBase(), iCarouselPeriod(0),
+    iNumberOfObjects(0), iSegmentSize(0),
+    bCompressionFlag(FALSE), bSortedHeaderInformation(FALSE),
+    DirectoryIndex(), vecObjects()
+    {
+    }
+
+    CMOTDirectory (const CMOTDirectory & nD):CMOTObjectBase (nD),
+		iCarouselPeriod (nD.iCarouselPeriod),
+		iNumberOfObjects (nD.iNumberOfObjects),
+		iSegmentSize (nD.iSegmentSize),
+		bCompressionFlag (nD.bCompressionFlag),
+		bSortedHeaderInformation (nD.bSortedHeaderInformation),
+		DirectoryIndex (nD.DirectoryIndex)
+    {
+    }
+
+    virtual ~CMOTDirectory ()
+    {
+    }
+
+    inline CMOTDirectory & operator= (const CMOTDirectory & nD)
+    {
+		TransportID = nD.TransportID;
+		ExpireTime = nD.ExpireTime;
+		bPermitOutdatedVersions = nD.bPermitOutdatedVersions;
+		bSortedHeaderInformation = nD.bSortedHeaderInformation;
+		bCompressionFlag = nD.bCompressionFlag;
+		iCarouselPeriod = nD.iCarouselPeriod;
+		DirectoryIndex = nD.DirectoryIndex;
+		iNumberOfObjects = nD.iNumberOfObjects;
+		iSegmentSize = nD.iSegmentSize;
+
+		return *this;
+    }
+
+    virtual void Reset ();
+
+    virtual void AddHeader (CVector < _BINARY > &vecbiHeader);
+
+	void dump(ostream&);
+
+    int iCarouselPeriod, iNumberOfObjects, iSegmentSize;
+    _BOOLEAN bCompressionFlag, bSortedHeaderInformation;
+    map < _BYTE, string > DirectoryIndex;
+    vector < TTransportID > vecObjects;
+};
+
+/* we define this to reduce the need for copy constructors and operator=
+   since CReassembler has a good set, the defaults will do for this, but not
+   for classes with CVector members
+*/
+
+class CMOTObject:public CMOTObjectBase
+{
+  public:
+
+    CMOTObject ():CMOTObjectBase(), vecbRawData(),
+    bComplete(FALSE), bHasHeader(FALSE), Body(),
+    strName(""), iBodySize(0), iCharacterSetForName(0), iCharacterSetForDescription(0),
+    strFormat(""), strMimeType(""), iCompressionType(0), strContentDescription(""),
+    iVersion(0), iUniqueBodyVersion(0), iContentType(0), iContentSubType(0),
+    iPriority(0), iRetransmissionDistance(0), vecbProfileSubset(),
+    ScopeStart(), ScopeEnd(), iScopeId(0), bReady(FALSE)
+    {
+    }
+
+    CMOTObject (const CMOTObject & nO):CMOTObjectBase (nO),
+	bComplete (nO.bComplete),
+	bHasHeader (nO.bHasHeader),
+	strName (nO.strName),
+	iBodySize(nO.iBodySize),
+	iCharacterSetForName (nO.iCharacterSetForName),
+	iCharacterSetForDescription (nO.iCharacterSetForDescription),
+	strFormat (nO.strFormat),
+	strMimeType (nO.strMimeType),
+	iCompressionType (nO.iCompressionType),
+	strContentDescription (nO.strContentDescription),
+	iVersion (nO.iVersion),
+	iUniqueBodyVersion (nO.iUniqueBodyVersion),
+	iContentType (nO.iContentType),
+	iContentSubType (nO.iContentSubType),
+	iPriority (nO.iPriority),
+	iRetransmissionDistance (nO.iRetransmissionDistance),
+	vecbProfileSubset (nO.vecbProfileSubset),
+	ScopeStart (nO.ScopeStart),
+	ScopeEnd (nO.ScopeEnd), iScopeId (nO.iScopeId)
+    {
+        Body = nO.Body;
+        vecbRawData.Init (nO.vecbRawData.Size ());
+        vecbRawData = nO.vecbRawData;
+    }
+
+    virtual ~ CMOTObject ()
+    {
+    }
+
+    inline CMOTObject & operator= (const CMOTObject & nO)
+    {
+        TransportID = nO.TransportID;
+        ExpireTime = nO.ExpireTime;
+        bPermitOutdatedVersions = nO.bPermitOutdatedVersions;
+        bComplete = nO.bComplete;
+        bHasHeader = nO.bHasHeader;
+        strFormat = nO.strFormat;
+        strName = nO.strName;
+        iBodySize = nO.iBodySize;
+        iCharacterSetForName = nO.iCharacterSetForName;
+        iCharacterSetForDescription = nO.iCharacterSetForDescription;
+        strMimeType = nO.strMimeType;
+        iCompressionType = nO.iCompressionType;
+        strContentDescription = nO.strContentDescription;
+        iVersion = nO.iVersion;
+        iUniqueBodyVersion = nO.iUniqueBodyVersion;
+        iContentType = nO.iContentType;
+        iContentSubType = nO.iContentSubType;
+        iPriority = nO.iPriority;
+        iRetransmissionDistance = nO.iRetransmissionDistance;
+        vecbProfileSubset = nO.vecbProfileSubset;
+        ScopeStart = nO.ScopeStart;
+        ScopeEnd = nO.ScopeEnd;
+        iScopeId = nO.iScopeId;
+        Body = nO.Body;
+
+        vecbRawData.Init (nO.vecbRawData.Size ());
+        vecbRawData = nO.vecbRawData;
+
+        return *this;
+    }
+
+
+    void Reset ()
+    {
+        vecbRawData.Init (0);
+        bComplete = FALSE;
+        bHasHeader = FALSE;
+        Body.Reset ();
+        strFormat = "";
+        strName = "";
+        iBodySize = 0;
+        iCharacterSetForName = 0;
+        iCharacterSetForDescription = 0;
+        strMimeType = "";
+        iCompressionType = 0;
+        strContentDescription = "";
+        iVersion = 0;
+        iUniqueBodyVersion = 0;
+        iContentType = 0;
+        iContentSubType = 0;
+        iPriority = 0;
+        iRetransmissionDistance = 0;
+        vecbProfileSubset.clear ();
+        ScopeStart.Reset ();
+        ScopeEnd.Reset ();
+        iScopeId = 0;
+    }
+
+	void dump(ostream&);
+
+    void AddHeader (CVector < _BINARY > &header);
+
+    /* for encoding */
+    CVector < _BYTE > vecbRawData;
+
+    _BOOLEAN bComplete, bHasHeader;
+    CByteReassembler Body;
+    string strName;
+    int iBodySize;
+    int iCharacterSetForName;
+    int iCharacterSetForDescription;
+    string strFormat;
+    string strMimeType;
+    int iCompressionType;
+    string strContentDescription;
+    int iVersion, iUniqueBodyVersion;
+    int iContentType, iContentSubType;
+    int iPriority;
+    int iRetransmissionDistance;
+    vector < _BYTE > vecbProfileSubset;
+
+    /* the following for EPG Objects */
+    CDateAndTime ScopeStart, ScopeEnd;
+    int iScopeId;
+
+  protected:
+    _BOOLEAN bReady;
+};
+
+
+/* Encoder ------------------------------------------------------------------ */
+class CMOTDABEnc
+{
+  public:
+    CMOTDABEnc ():MOTObject(), MOTObjSegments(),
+    iSegmCntHeader(0), iSegmCntBody(0), bCurSegHeader(FALSE),
+    iContIndexHeader(0), iContIndexBody(0), iTransportID(0)
+    {
+    }
+
+    virtual ~CMOTDABEnc ()
+    {
+    }
+
+    void Reset ();
+    _BOOLEAN GetDataGroup (CVector < _BINARY > &vecbiNewData);
+    void SetMOTObject (CMOTObject & NewMOTObject);
+    _REAL GetProgPerc () const;
+
+  protected:
+    class CMOTObjSegm
+    {
+      public:
+	CVector < CVector < _BINARY > >vvbiHeader;
+	CVector < CVector < _BINARY > >vvbiBody;
+    };
+
+    void GenMOTSegments (CMOTObjSegm & MOTObjSegm);
+    void PartitionUnits (CVector < _BINARY > &vecbiSource,
+			 CVector < CVector < _BINARY > >&vecbiDest,
+			 const int iPartiSize);
+
+    void GenMOTObj (CVector < _BINARY > &vecbiData,
+		    CVector < _BINARY > &vecbiSeg, const _BOOLEAN bHeader,
+		    const int iSegNum, const int iTranspID,
+		    const _BOOLEAN bLastSeg);
+
+    CMOTObject MOTObject;
+    CMOTObjSegm MOTObjSegments;
+
+    int iSegmCntHeader;
+    int iSegmCntBody;
+    _BOOLEAN bCurSegHeader;
+
+    int iContIndexHeader;
+    int iContIndexBody;
+
+    int iTransportID;
+};
+
+/* Decoder ------------------------------------------------------------------ */
+
+class CMOTDABDec
+{
+  public:
+
+    CMOTDABDec ();
+
+    virtual ~ CMOTDABDec ()
+    {
+    }
+
+    /* client methods */
+    void GetNextObject (CMOTObject & NewMOTObject);
+
+    void GetObject (CMOTObject & NewMOTObject, TTransportID TransportID)
+    {
+        NewMOTObject = MOTCarousel[TransportID];
+    }
+
+    void GetDirectory (CMOTDirectory & MOTDirectoryOut)
+    {
+        MOTDirectoryOut = MOTDirectory;
+    }
+
+    _BOOLEAN NewObjectAvailable ();
+
+    /* push from lower level */
+    void AddDataUnit (CVector < _BINARY > &vecbiNewData);
+
+  protected:
+
+    void ProcessDirectory (CBitReassembler &MOTDir);
+
+    void DeliverIfReady (TTransportID TransportID);
+
+    /* These fields are the in-progress carousel objects */
+    enum
+    { unknown, headerMode, directoryMode } MOTmode;
+    /* strictly, there should be only one of these! */
+    map < TTransportID, CBitReassembler > MOTHeaders;
+    CBitReassembler MOTDirectoryEntity;
+    CBitReassembler MOTDirComprEntity;
+
+    /* These fields are the cached complete carousel */
+    CMOTDirectory MOTDirectory;
+    map < TTransportID, CMOTObject > MOTCarousel;
+    queue < TTransportID > qiNewObjects;
+#ifdef QT_CORE_LIB
+    QMutex guard;
+    QWaitCondition blocker;
+#endif
+};
+
+#endif // !defined(DABMOT_H__3B0UBVE98732KJVEW363E7A0D31912__INCLUDED_)
+
diff --git a/src/datadecoding/DataDecoder.cpp b/src/datadecoding/DataDecoder.cpp
new file mode 100644
index 0000000..00bc857
--- /dev/null
+++ b/src/datadecoding/DataDecoder.cpp
@@ -0,0 +1,569 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer, Julian Cable
+ *
+ * Description:
+ *	Data module (using multimedia information carried in DRM stream)
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "DataDecoder.h"
+#include "epgutil.h"
+#include "Journaline.h"
+#include "Experiment.h"
+#include <iostream>
+
+CDataDecoder::CDataDecoder ():iServPacketID (0), DoNotProcessData (TRUE),
+	Journaline(*new CJournaline()),
+	Experiment(*new CExperiment()),
+    iOldJournalineServiceID (0),
+    strDataDirectory(DEFAULT_DATA_FILES_DIRECTORY)
+{
+		for(size_t i=0; i<MAX_NUM_PACK_PER_STREAM; i++)
+			eAppType[i] = AT_NOT_SUP;
+}
+
+CDataDecoder::~CDataDecoder ()
+{
+	delete &Journaline;
+}
+
+void
+CDataDecoder::ProcessDataInternal(CParameter & Parameters)
+{
+	int i, j;
+	int iPacketID;
+	int iNewContInd;
+	int iNewPacketDataSize;
+	int iOldPacketDataSize;
+	int iNumSkipBytes;
+	_BINARY biFirstFlag;
+	_BINARY biLastFlag;
+	_BINARY biPadPackInd;
+	CCRC CRCObject;
+
+	/* Check if something went wrong in the initialization routine */
+	if (DoNotProcessData == TRUE)
+		return;
+
+	/* CRC check for all packets -------------------------------------------- */
+	/* Reset bit extraction access */
+	(*pvecInputData).ResetBitAccess();
+
+	for (j = 0; j < iNumDataPackets; j++)
+	{
+		/* Check the CRC of this packet */
+		CRCObject.Reset(16);
+
+		/* "- 2": 16 bits for CRC at the end */
+		for (i = 0; i < iTotalPacketSize - 2; i++)
+		{
+			_BYTE b =pvecInputData->Separate(SIZEOF__BYTE);
+			CRCObject.AddByte(b);
+		}
+
+		/* Store result in vector and show CRC in multimedia window */
+		uint16_t crc = pvecInputData->Separate(16);
+		int iShortID = Parameters.GetCurSelDataService();
+		if (CRCObject.CheckCRC(crc) == TRUE)
+		{
+			veciCRCOk[j] = 1;	/* CRC ok */
+			Parameters.DataComponentStatus[iShortID].SetStatus(RX_OK);
+		}
+		else
+		{
+			veciCRCOk[j] = 0;	/* CRC wrong */
+			Parameters.DataComponentStatus[iShortID].SetStatus(CRC_ERROR);
+		}
+	}
+
+	/* Extract packet data -------------------------------------------------- */
+	/* Reset bit extraction access */
+	(*pvecInputData).ResetBitAccess();
+
+	for (j = 0; j < iNumDataPackets; j++)
+	{
+		/* Check if CRC was ok */
+		if (veciCRCOk[j] == 1)
+		{
+			/* Read header data --------------------------------------------- */
+			/* First flag */
+			biFirstFlag = (_BINARY) (*pvecInputData).Separate(1);
+
+			/* Last flag */
+			biLastFlag = (_BINARY) (*pvecInputData).Separate(1);
+
+			/* Packet ID */
+			iPacketID = (int) (*pvecInputData).Separate(2);
+
+			/* Padded packet indicator (PPI) */
+			biPadPackInd = (_BINARY) (*pvecInputData).Separate(1);
+
+			/* Continuity index (CI) */
+			iNewContInd = (int) (*pvecInputData).Separate(3);
+
+			/* Act on parameters given in header */
+			/* Continuity index: this 3-bit field shall increment by one
+			   modulo-8 for each packet with this packet Id */
+			if ((iContInd[iPacketID] + 1) % 8 != iNewContInd)
+				DataUnit[iPacketID].bOK = FALSE;
+
+			/* Store continuity index */
+			iContInd[iPacketID] = iNewContInd;
+
+			/* Reset flag for data unit ok when receiving the first packet of
+			   a new data unit */
+			if (biFirstFlag == 1)
+			{
+				DataUnit[iPacketID].Reset();
+				DataUnit[iPacketID].bOK = TRUE;
+			}
+
+			/* If all packets are received correctely, data unit is ready */
+			if (biLastFlag == 1)
+			{
+				if (DataUnit[iPacketID].bOK == TRUE)
+					DataUnit[iPacketID].bReady = TRUE;
+			}
+
+			/* Data field --------------------------------------------------- */
+			/* Get size of new data block */
+			if (biPadPackInd == 1)
+			{
+				/* Padding is present: the first byte gives the number of
+				   useful data bytes in the data field. */
+				iNewPacketDataSize =
+					(int) (*pvecInputData).Separate(SIZEOF__BYTE) *
+					SIZEOF__BYTE;
+
+				if (iNewPacketDataSize > iMaxPacketDataSize)
+				{
+					/* Error, reset flags */
+					DataUnit[iPacketID].bOK = FALSE;
+					DataUnit[iPacketID].bReady = FALSE;
+
+					/* Set values to read complete packet size */
+					iNewPacketDataSize = iNewPacketDataSize;
+					iNumSkipBytes = 2;	/* Only CRC has to be skipped */
+				}
+				else
+				{
+					/* Number of unused bytes ("- 2" because we also have the
+					   one byte which stored the size, the other byte is the
+					   header) */
+					iNumSkipBytes = iTotalPacketSize - 2 -
+						iNewPacketDataSize / SIZEOF__BYTE;
+				}
+
+				/* Packets with no useful data are permitted if no packet
+				   data is available to fill the logical frame. The PPI
+				   shall be set to 1 and the first byte of the data field
+				   shall be set to 0 to indicate no useful data. The first
+				   and last flags shall be set to 1. The continuity index
+				   shall be incremented for these empty packets */
+				if ((biFirstFlag == 1) &&
+					(biLastFlag == 1) && (iNewPacketDataSize == 0))
+				{
+					/* Packet with no useful data, reset flag */
+					DataUnit[iPacketID].bReady = FALSE;
+				}
+			}
+			else
+			{
+				iNewPacketDataSize = iMaxPacketDataSize;
+
+				/* All bytes are useful bytes, only CRC has to be skipped */
+				iNumSkipBytes = 2;
+			}
+
+			/* Add new data to data unit vector (bit-wise copying) */
+			iOldPacketDataSize = DataUnit[iPacketID].vecbiData.Size();
+
+			DataUnit[iPacketID].vecbiData.Enlarge(iNewPacketDataSize);
+
+			/* Read useful bits */
+			for (i = 0; i < iNewPacketDataSize; i++)
+				DataUnit[iPacketID].vecbiData[iOldPacketDataSize + i] =
+					(_BINARY) (*pvecInputData).Separate(1);
+
+			/* Read bytes which are not used */
+			for (i = 0; i < iNumSkipBytes; i++)
+				(*pvecInputData).Separate(SIZEOF__BYTE);
+
+			/* Use data unit ------------------------------------------------ */
+			if (DataUnit[iPacketID].bReady == TRUE)
+			{
+				/* Decode all IDs regardless whether activated or not
+				   (iPacketID == or != iServPacketID) */
+				/* Only DAB multimedia is supported */
+				//cout << "new data unit for packet id " << iPacketID << " apptype " << eAppType[iPacketID] << endl;
+
+				if(eAppType[iPacketID] == AT_NOT_SUP)
+				{
+					int iCurSelDataServ = Parameters.GetCurSelDataService();
+					// TODO int iCurDataStreamID = Parameters.Service[iCurSelDataServ].DataParam.iStreamID;
+					for (int i = 0; i <=3; i++)
+					{
+						if(Parameters.Service[iCurSelDataServ].DataParam.iPacketID == iPacketID)
+						{
+							eAppType[iPacketID] = GetAppType(Parameters.Service[iCurSelDataServ].DataParam);
+						}
+					}
+				}
+
+				switch (eAppType[iPacketID])
+				{
+				case AT_MOTSLIDESHOW:	/* MOTSlideshow */
+					/* Packet unit decoding */
+					MOTObject[iPacketID].
+						AddDataUnit(DataUnit[iPacketID].vecbiData);
+					break;
+				case AT_EPG:	/* EPG */
+					/* Packet unit decoding */
+					//cout << iEPGPacketID << " " << iPacketID << endl; cout.flush();
+					if(iEPGPacketID == -1)
+					{
+						cerr << "data unit received but EPG packetId not set" << endl;
+						iEPGPacketID = iPacketID;
+					}
+					MOTObject[iEPGPacketID].AddDataUnit(DataUnit[iPacketID].vecbiData);
+					break;
+
+				case AT_BROADCASTWEBSITE:	/* MOT Broadcast Web Site */
+					/* Packet unit decoding */
+					MOTObject[iPacketID].AddDataUnit(DataUnit[iPacketID].vecbiData);
+					break;
+
+				case AT_JOURNALINE:
+					Journaline.AddDataUnit(DataUnit[iPacketID].vecbiData);
+					break;
+
+				case AT_EXPERIMENTAL:
+					Experiment.AddDataUnit(DataUnit[iPacketID].vecbiData);
+					break;
+
+				default:		/* do nothing */
+					;
+				}
+
+				/* Packet was used, reset it now for new filling with new data
+				   (this will also reset the flag
+				   "DataUnit[iPacketID].bReady") */
+				DataUnit[iPacketID].Reset();
+			}
+		}
+		else
+		{
+			/* Skip incorrect packet */
+			for (i = 0; i < iTotalPacketSize; i++)
+				(*pvecInputData).Separate(SIZEOF__BYTE);
+		}
+	}
+	if(iEPGService >= 0)	/* if EPG decoding is active */
+		DecodeEPG(Parameters);
+}
+
+void
+CDataDecoder::DecodeEPG(const CParameter & Parameters)
+{
+	/* Application Decoding - must run all the time and in background */
+	if ((DoNotProcessData == FALSE)
+		&& (iEPGPacketID >= 0)
+		&& MOTObject[iEPGPacketID].NewObjectAvailable())
+	{
+		//cerr << "EPG object" << endl;
+		CMOTObject NewObj;
+		MOTObject[iEPGPacketID].GetNextObject(NewObj);
+		string fileName;
+		bool advanced = false;
+		if (NewObj.iContentType == 7)
+		{
+			for (size_t i = 0; i < NewObj.vecbProfileSubset.size(); i++)
+				if (NewObj.vecbProfileSubset[i] == 2)
+				{
+					advanced = true;
+					break;
+				}
+			int iScopeId = NewObj.iScopeId;
+			if (iScopeId == 0)
+				iScopeId = Parameters.Service[iEPGService].iServiceID;
+			fileName = epgFilename(NewObj.ScopeStart, iScopeId,
+								   NewObj.iContentSubType, advanced);
+
+#if !defined(HAVE_LIBZ) && !defined(HAVE_LIBFREEIMAGE)
+			const string& s = NewObj.strName;
+			if (s.size() >= 3)
+				if (s.substr(s.size() - 3, 3) == ".gz")
+					fileName += ".gz";
+#endif
+		}
+		else
+		{
+			fileName = NewObj.strName;
+		}
+
+        string path = strDataDirectory+"/EPG/"+fileName;
+		mkdirs(path);
+		//cerr << "writing EPG file " << path << endl;
+		FILE *f = fopen(path.c_str(), "wb");
+		if (f)
+		{
+			fwrite(&NewObj.Body.vecData.front(), 1,
+				   NewObj.Body.vecData.size(), f);
+			fclose(f);
+		}
+	}
+}
+
+void
+CDataDecoder::InitInternal(CParameter & Parameters)
+{
+	int iTotalNumInputBits;
+	int iTotalNumInputBytes;
+	int iCurDataStreamID;
+	int iCurSelDataServ;
+
+	/* Init error flag */
+	DoNotProcessData = FALSE;
+
+	/* Get current selected data service */
+	iCurSelDataServ = Parameters.GetCurSelDataService();
+
+	/* Get current data stream ID */
+	iCurDataStreamID =
+		Parameters.Service[iCurSelDataServ].DataParam.iStreamID;
+
+	/* Get number of total input bits (and bytes) for this module */
+	iTotalNumInputBits = Parameters.iNumDataDecoderBits;
+	iTotalNumInputBytes = iTotalNumInputBits / SIZEOF__BYTE;
+
+	/* Get the packet ID of the selected service */
+	iServPacketID =
+		Parameters.Service[iCurSelDataServ].DataParam.iPacketID;
+
+	/* Init application type (will be overwritten by correct type later */
+	eAppType[iServPacketID] = AT_NOT_SUP;
+
+	/* Check, if service is activated. Also, only packet services can be
+	   decoded */
+	if ((iCurDataStreamID != STREAM_ID_NOT_USED) &&
+		(Parameters.Service[iCurSelDataServ].DataParam.
+		 ePacketModInd == CDataParam::PM_PACKET_MODE))
+	{
+		/* Calculate total packet size. DRM standard: packet length: this
+		   field indicates the length in bytes of the data field of each
+		   packet specified as an unsigned binary number (the total packet
+		   length is three bytes longer as it includes the header and CRC
+		   fields) */
+		iTotalPacketSize =
+			Parameters.Service[iCurSelDataServ].DataParam.iPacketLen + 3;
+
+		/* Check total packet size, could be wrong due to wrong SDC */
+		if ((iTotalPacketSize <= 0) ||
+			(iTotalPacketSize > iTotalNumInputBytes))
+		{
+			/* Set error flag */
+			DoNotProcessData = TRUE;
+		}
+		else
+		{
+			/* Maximum number of bits for the data part in a packet
+			   ("- 3" because two bits for CRC and one for the header) */
+			iMaxPacketDataSize = (iTotalPacketSize - 3) * SIZEOF__BYTE;
+
+			/* Number of data packets in one data block */
+			iNumDataPackets = iTotalNumInputBytes / iTotalPacketSize;
+
+			eAppType[iServPacketID] = GetAppType(Parameters.Service[iCurSelDataServ].DataParam);
+
+			/* Check, if service ID of Journaline application has
+			   changed, that indicates that a new transmission is
+			   received -> reset decoder in this case. Otherwise
+			   use old buffer. That ensures that the decoder keeps
+			   old data in buffer when synchronization was lost for
+			   a short time */
+			const uint32_t iNewServID = Parameters.Service[iCurSelDataServ].iServiceID;
+
+			if((eAppType[iServPacketID]==AT_JOURNALINE) && (iOldJournalineServiceID != iNewServID))
+			{
+
+				// Problem: if two different services point to the same stream, they have different
+				// IDs and the Journaline is reset! TODO: fix this problem...
+
+				/* Reset Journaline decoder and store the new service
+				   ID number */
+				Journaline.Reset();
+				iOldJournalineServiceID = iNewServID;
+			}
+
+			/* Init vector for storing the CRC results for each packet */
+			veciCRCOk.Init(iNumDataPackets);
+
+			/* Reset data units for all possible data IDs */
+			for (int i = 0; i < MAX_NUM_PACK_PER_STREAM; i++)
+			{
+				DataUnit[i].Reset();
+
+				/* Reset continuity index (CI) */
+				iContInd[i] = 0;
+			}
+		}
+	}
+	else
+		DoNotProcessData = TRUE;
+
+	/* Set input block size */
+	iInputBlockSize = iTotalNumInputBits;
+
+	iEPGService = -1;			/* no service */
+	iEPGPacketID = -1;
+
+	/* look for EPG */
+	for (int i = 0; i <= 3; i++)
+	{
+		if ((Parameters.Service[i].DataParam.eAppDomain ==
+			 CDataParam::AD_DAB_SPEC_APP)
+			&& (Parameters.Service[i].DataParam.iUserAppIdent == 7))
+		{
+			iEPGService = i;
+			iEPGPacketID = Parameters.Service[i].DataParam.iPacketID;
+			eAppType[iEPGPacketID] = AT_EPG;
+			//cerr << "EPG packet id " << iEPGPacketID << endl;
+		}
+	}
+}
+
+_BOOLEAN
+	CDataDecoder::GetMOTObject(CMOTObject & NewObj,
+							   const EAppType eAppTypeReq)
+{
+	_BOOLEAN bReturn = FALSE;
+
+	/* Lock resources */
+	Lock();
+
+	/* Check if data service is current MOT application */
+	if ((DoNotProcessData == FALSE)
+		&& (eAppType[iServPacketID] == eAppTypeReq)
+		&& MOTObject[iServPacketID].NewObjectAvailable())
+	{
+		MOTObject[iServPacketID].GetNextObject(NewObj);
+		bReturn = TRUE;
+	}
+	/* Release resources */
+	Unlock();
+
+	return bReturn;
+}
+
+_BOOLEAN
+	CDataDecoder::GetMOTDirectory(CMOTDirectory & MOTDirectoryOut,
+								  const EAppType eAppTypeReq)
+{
+	_BOOLEAN bReturn = FALSE;
+
+	/* Lock resources */
+	Lock();
+
+	/* Check if data service is current MOT application */
+	if ((DoNotProcessData == FALSE)
+		&& (eAppType[iServPacketID] == eAppTypeReq))
+	{
+		MOTObject[iServPacketID].GetDirectory(MOTDirectoryOut);
+		bReturn = TRUE;
+	}
+	/* Release resources */
+	Unlock();
+
+	return bReturn;
+}
+
+void
+CDataDecoder::GetNews(const int iObjID, CNews & News)
+{
+	/* Lock resources */
+	Lock();
+
+	/* Check if data service is Journaline application */
+	if ((DoNotProcessData == FALSE)
+		&& (eAppType[iServPacketID] == AT_JOURNALINE))
+	{
+		Journaline.GetNews(iObjID, News);
+	}
+
+	/* Release resources */
+	Unlock();
+}
+
+CDataDecoder::EAppType CDataDecoder::GetAppType(const CDataParam& DataParam)
+{
+	EAppType eAppType = AT_NOT_SUP;
+
+		/* Only DAB application supported */
+	if (DataParam.eAppDomain == CDataParam::AD_DAB_SPEC_APP)
+	{
+		/* Get application identifier of current selected service, only
+		   used with DAB */
+		const int iDABUserAppIdent = DataParam.iUserAppIdent;
+
+		switch (iDABUserAppIdent)
+		{
+		case DAB_AT_MOTSLIDESHOW:		/* MOTSlideshow */
+			eAppType = AT_MOTSLIDESHOW;
+			break;
+
+		case DAB_AT_BROADCASTWEBSITE:		/* MOT Broadcast Web Site */
+			eAppType = AT_BROADCASTWEBSITE;
+			break;
+
+		case DAB_AT_TPEG:
+			eAppType = AT_TPEG;
+			break;
+
+		case DAB_AT_DGPS:
+			eAppType = AT_DGPS;
+			break;
+
+		case DAB_AT_TMC:
+			eAppType = AT_TMC;
+			break;
+
+		case DAB_AT_EPG:
+			eAppType  = AT_EPG;
+			break;
+
+		case DAB_AT_JAVA:
+			eAppType = AT_JAVA;
+			break;
+
+		case DAB_AT_JOURNALINE:	/* Journaline */
+			eAppType  = AT_JOURNALINE;
+			break;
+
+		case AT_DMB: case AT_VOICE: case AT_MIDDLEWARE: case AT_IPDC:
+		case DAB_AT_DREAM_EXPERIMENTAL:	/* Just save the objects as files */
+			eAppType  = AT_EXPERIMENTAL;
+			break;
+		}
+	}
+	return eAppType;
+}
diff --git a/src/datadecoding/DataDecoder.h b/src/datadecoding/DataDecoder.h
new file mode 100644
index 0000000..d9a5608
--- /dev/null
+++ b/src/datadecoding/DataDecoder.h
@@ -0,0 +1,130 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *	See DataDecoder.cpp
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#if !defined(DATADECODER_H__3B0BA660_CA3452363E7A0D31912__INCLUDED_)
+#define DATADECODER_H__3B0BA660_CA3452363E7A0D31912__INCLUDED_
+
+#include "../GlobalDefinitions.h"
+#include "../Parameter.h"
+#include "../util/Modul.h"
+#include "../util/CRC.h"
+#include "../util/Vector.h"
+#include "DABMOT.h"
+#include "MOTSlideShow.h"
+
+class CExperiment;
+class CJournaline;
+class CNews;
+
+/* Definitions ****************************************************************/
+/* Maximum number of packets per stream */
+#define MAX_NUM_PACK_PER_STREAM					4
+
+/* Define for application types */
+#define DAB_AT_DREAM_EXPERIMENTAL 1
+#define DAB_AT_MOTSLIDESHOW 2
+#define DAB_AT_BROADCASTWEBSITE 3
+#define DAB_AT_TPEG 4
+#define DAB_AT_DGPS 5
+#define DAB_AT_TMC 	6
+#define DAB_AT_EPG 	7
+#define DAB_AT_JAVA 	8
+#define DAB_AT_DMB 	9
+#define DAB_AT_IPDC 	0xa
+#define DAB_AT_VOICE 	0xb
+#define DAB_AT_MIDDLEWARE 	0xc
+#define DAB_AT_JOURNALINE 0x44A
+
+class CDataDecoder:public CReceiverModul < _BINARY, _BINARY >
+{
+  public:
+    CDataDecoder ();
+    virtual ~CDataDecoder ();
+
+    enum EAppType
+    { AT_NOT_SUP, AT_MOTSLIDESHOW, AT_JOURNALINE,
+	AT_BROADCASTWEBSITE, AT_TPEG, AT_DGPS, AT_TMC, AT_EPG,
+	    AT_JAVA, AT_EXPERIMENTAL, AT_DMB, AT_VOICE, AT_MIDDLEWARE, AT_IPDC
+    };
+
+    _BOOLEAN GetMOTObject (CMOTObject & NewPic, const EAppType eAppTypeReq);
+    _BOOLEAN GetMOTDirectory (CMOTDirectory & MOTDirectoryOut, const EAppType eAppTypeReq);
+	CMOTDABDec *getApplication(int iPacketID) { return (iPacketID>=0 && iPacketID<3)?&MOTObject[iPacketID]:NULL; }
+    void GetNews (const int iObjID, CNews & News);
+    EAppType GetAppType ()
+    {
+		return eAppType[iServPacketID];
+    }
+    void setDataDirectory(const string& s) { strDataDirectory = s; }
+
+  protected:
+    class CDataUnit
+    {
+      public:
+	CVector < _BINARY > vecbiData;
+	_BOOLEAN bOK;
+	_BOOLEAN bReady;
+
+	void Reset ()
+	{
+	    vecbiData.Init (0);
+	    bOK = FALSE;
+	    bReady = FALSE;
+	}
+    };
+
+    int iTotalPacketSize;
+    int iNumDataPackets;
+    int iMaxPacketDataSize;
+    int iServPacketID;
+    CVector < int >veciCRCOk;
+
+    _BOOLEAN DoNotProcessData;
+
+    int iContInd[MAX_NUM_PACK_PER_STREAM];
+    CDataUnit DataUnit[MAX_NUM_PACK_PER_STREAM];
+    CMOTDABDec MOTObject[MAX_NUM_PACK_PER_STREAM];
+    CJournaline& Journaline;
+    CExperiment& Experiment;
+    uint32_t iOldJournalineServiceID;
+    string strDataDirectory;
+
+    EAppType eAppType[MAX_NUM_PACK_PER_STREAM];
+
+    virtual void InitInternal (CParameter & Parameters);
+    virtual void ProcessDataInternal (CParameter & Parameters);
+
+    int iEPGService;
+    int iEPGPacketID;
+    void DecodeEPG(const CParameter& Parameters);
+	EAppType GetAppType(const CDataParam&);
+
+};
+
+
+#endif // !defined(DATADECODER_H__3B0BA660_CA3452363E7A0D31912__INCLUDED_)
diff --git a/src/datadecoding/DataEncoder.cpp b/src/datadecoding/DataEncoder.cpp
new file mode 100644
index 0000000..90fe879
--- /dev/null
+++ b/src/datadecoding/DataEncoder.cpp
@@ -0,0 +1,179 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer, Julian Cable
+ *
+ * Description:
+ *	Data module (using multimedia information carried in DRM stream)
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "DataEncoder.h"
+
+/* Implementation *************************************************************/
+
+void
+CDataEncoder::GeneratePacket(CVector < _BINARY > &vecbiPacket)
+{
+	int i;
+	_BOOLEAN bLastFlag;
+
+	/* Init size for whole packet, not only body */
+	vecbiPacket.Init(iTotalPacketSize);
+	vecbiPacket.ResetBitAccess();
+
+	/* Calculate remaining data size to be transmitted */
+	const int iRemainSize = vecbiCurDataUnit.Size() - iCurDataPointer;
+
+	/* Header --------------------------------------------------------------- */
+	/* First flag */
+	if (iCurDataPointer == 0)
+		vecbiPacket.Enqueue((uint32_t) 1, 1);
+	else
+		vecbiPacket.Enqueue((uint32_t) 0, 1);
+
+	/* Last flag */
+	if (iRemainSize > iPacketLen)
+	{
+		vecbiPacket.Enqueue((uint32_t) 0, 1);
+		bLastFlag = FALSE;
+	}
+	else
+	{
+		vecbiPacket.Enqueue((uint32_t) 1, 1);
+		bLastFlag = TRUE;
+	}
+
+	/* Packet Id */
+	vecbiPacket.Enqueue((uint32_t) iPacketID, 2);
+
+	/* Padded packet indicator (PPI) */
+	if (iRemainSize < iPacketLen)
+		vecbiPacket.Enqueue((uint32_t) 1, 1);
+	else
+		vecbiPacket.Enqueue((uint32_t) 0, 1);
+
+	/* Continuity index (CI) */
+	vecbiPacket.Enqueue((uint32_t) iContinInd, 3);
+
+	/* Increment index modulo 8 (1 << 3) */
+	iContinInd++;
+	if (iContinInd == 8)
+		iContinInd = 0;
+
+	/* Body ----------------------------------------------------------------- */
+	if (iRemainSize >= iPacketLen)
+	{
+		if (iRemainSize == iPacketLen)
+		{
+			/* Last packet */
+			for (i = 0; i < iPacketLen; i++)
+				vecbiPacket.Enqueue(vecbiCurDataUnit.Separate(1), 1);
+		}
+		else
+		{
+			for (i = 0; i < iPacketLen; i++)
+			{
+				vecbiPacket.Enqueue(vecbiCurDataUnit.Separate(1), 1);
+				iCurDataPointer++;
+			}
+		}
+	}
+	else
+	{
+		/* Padded packet. If the PPI is 1 then the first byte shall indicate
+		   the number of useful bytes that follow, and the data field is
+		   completed with padding bytes of value 0x00 */
+		vecbiPacket.Enqueue((uint32_t) (iRemainSize / SIZEOF__BYTE),
+							SIZEOF__BYTE);
+
+		/* Data */
+		for (i = 0; i < iRemainSize; i++)
+			vecbiPacket.Enqueue(vecbiCurDataUnit.Separate(1), 1);
+
+		/* Padding */
+		for (i = 0; i < iPacketLen - iRemainSize; i++)
+			vecbiPacket.Enqueue(vecbiCurDataUnit.Separate(1), 1);
+	}
+
+	/* If this was the last packet, get data for next data unit */
+	if (bLastFlag == TRUE)
+	{
+		/* Generate new data unit */
+		MOTSlideShowEncoder.GetDataUnit(vecbiCurDataUnit);
+		vecbiCurDataUnit.ResetBitAccess();
+
+		/* Reset data pointer and continuity index */
+		iCurDataPointer = 0;
+	}
+
+	/* CRC ------------------------------------------------------------------ */
+	CCRC CRCObject;
+
+	/* Reset bit access */
+	vecbiPacket.ResetBitAccess();
+
+	/* Calculate the CRC and put it at the end of the segment */
+	CRCObject.Reset(16);
+
+	/* "byLengthBody" was defined in the header */
+	for (i = 0; i < (iTotalPacketSize / SIZEOF__BYTE - 2); i++)
+		CRCObject.AddByte(_BYTE(vecbiPacket.Separate(SIZEOF__BYTE)));
+
+	/* Now, pointer in "enqueue"-function is back at the same place, add CRC */
+	vecbiPacket.Enqueue(CRCObject.GetCRC(), 16);
+}
+
+int
+CDataEncoder::Init(CParameter & Param)
+{
+	/* Init packet length and total packet size (the total packet length is
+	   three bytes longer as it includes the header and CRC fields) */
+
+// TODO we only use always the first service right now
+	const int iCurSelDataServ = 0;
+
+// CAudioSourceEncoderImplementation::InitInternalTx already have the lock
+//	Param.Lock();
+
+	iPacketLen =
+		Param.Service[iCurSelDataServ].DataParam.iPacketLen * SIZEOF__BYTE;
+	iTotalPacketSize = iPacketLen + 24 /* CRC + header = 24 bits */ ;
+
+	iPacketID = Param.Service[iCurSelDataServ].DataParam.iPacketID;
+
+// CAudioSourceEncoderImplementation::InitInternalTx already have the lock
+//	Param.Unlock();
+
+	/* Init DAB MOT encoder object */
+	MOTSlideShowEncoder.Init();
+
+	/* Generate first data unit */
+	MOTSlideShowEncoder.GetDataUnit(vecbiCurDataUnit);
+	vecbiCurDataUnit.ResetBitAccess();
+
+	/* Reset pointer to current position in data unit and continuity index */
+	iCurDataPointer = 0;
+	iContinInd = 0;
+
+	/* Return total packet size */
+	return iTotalPacketSize;
+}
diff --git a/src/datadecoding/DataEncoder.h b/src/datadecoding/DataEncoder.h
new file mode 100644
index 0000000..12ae0b9
--- /dev/null
+++ b/src/datadecoding/DataEncoder.h
@@ -0,0 +1,69 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *	See DataDecoder.cpp
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#ifndef __DATA_ENCODER_H
+#define __DATA_ENCODER_H
+
+#include "../GlobalDefinitions.h"
+#include "../Parameter.h"
+#include "../util/Modul.h"
+#include "../util/CRC.h"
+#include "../util/Vector.h"
+#include "DABMOT.h"
+#include "MOTSlideShow.h"
+
+class CDataEncoder
+{
+  public:
+    CDataEncoder ()
+    {
+    }
+    virtual ~ CDataEncoder ()
+    {
+    }
+
+    int Init (CParameter & Param);
+    void GeneratePacket (CVector < _BINARY > &vecbiPacket);
+
+    CMOTSlideShowEncoder *GetSliShowEnc ()
+    {
+	return &MOTSlideShowEncoder;
+    }
+
+  protected:
+    CMOTSlideShowEncoder MOTSlideShowEncoder;
+    CVector < _BINARY > vecbiCurDataUnit;
+
+    int iPacketLen;
+    int iTotalPacketSize;
+    int iCurDataPointer;
+    int iPacketID;
+    int iContinInd;
+};
+
+#endif
diff --git a/src/datadecoding/Experiment.cpp b/src/datadecoding/Experiment.cpp
new file mode 100644
index 0000000..b456ca5
--- /dev/null
+++ b/src/datadecoding/Experiment.cpp
@@ -0,0 +1,71 @@
+/******************************************************************************\
+ * British Broadcasting Corporation
+ * Copyright (c) 2010
+ *
+ * Author(s):
+ *	Julian Cable
+ *
+ * Description:
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "Experiment.h"
+#include <iostream>
+
+CExperiment::CExperiment() : dgdec(NULL)
+{
+	/* Create decoder instance. Pass the pointer to this object. This is needed
+	   for the call-back functions! */
+	dgdec = DAB_DATAGROUP_DECODER_createDec(dg_cb, this);
+}
+
+CExperiment::~CExperiment()
+{
+	/* Delete decoder instances */
+	if (dgdec != NULL)
+		DAB_DATAGROUP_DECODER_deleteDec(dgdec);
+}
+
+void CExperiment::AddDataUnit(CVector<_BINARY>& vecbiNewData)
+{
+	const int iSizeBytes = vecbiNewData.Size() / SIZEOF__BYTE;
+
+	if (iSizeBytes > 0)
+	{
+		/* Bits to byte conversion */
+		CVector<_BYTE> vecbyData(iSizeBytes);
+		vecbiNewData.ResetBitAccess();
+
+		for (int i = 0; i < iSizeBytes; i++)
+			vecbyData[i] = (_BYTE) vecbiNewData.Separate(SIZEOF__BYTE);
+
+		/* Add new data unit to Journaline decoder library */
+		DAB_DATAGROUP_DECODER_putData(dgdec, iSizeBytes, &vecbyData[0]);
+	}
+}
+
+void CExperiment::dg_cb(const DAB_DATAGROUP_DECODER_msc_datagroup_header_t*,
+		const unsigned long len, const unsigned char* buf, void* data)
+{
+	cerr << "experimental dab data group length " << len << " bytes" << endl;
+	CExperiment* This = reinterpret_cast<CExperiment*>(data);
+	cerr << (char*)buf;
+	// TODO
+	(void)This;
+}
diff --git a/src/datadecoding/Experiment.h b/src/datadecoding/Experiment.h
new file mode 100644
index 0000000..81c885c
--- /dev/null
+++ b/src/datadecoding/Experiment.h
@@ -0,0 +1,55 @@
+
+/******************************************************************************\
+ * British Broadcasting Corporation
+ * Copyright (c) 2010
+ *
+ * Author(s):
+ *	Julian Cable
+ *
+ * Description:
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#ifndef __EXPERIMENT_H
+#define __EXPERIMENT_H
+
+#include "../GlobalDefinitions.h"
+#include "../util/Vector.h"
+# include "journaline/dabdatagroupdecoder.h"
+
+/* Definitions ****************************************************************/
+
+
+/* Classes ********************************************************************/
+
+class CExperiment
+{
+public:
+	CExperiment();
+	virtual ~CExperiment();
+
+	void AddDataUnit(CVector<_BINARY>& vecbiNewData);
+
+protected:
+	DAB_DATAGROUP_DECODER_t	dgdec;
+	static void dg_cb(const DAB_DATAGROUP_DECODER_msc_datagroup_header_t*,
+		const unsigned long len, const unsigned char* buf, void* data);
+};
+
+#endif
diff --git a/src/datadecoding/Journaline.cpp b/src/datadecoding/Journaline.cpp
new file mode 100644
index 0000000..25e9f07
--- /dev/null
+++ b/src/datadecoding/Journaline.cpp
@@ -0,0 +1,200 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "Journaline.h"
+#ifdef WIN32
+# include <winsock2.h>
+#else
+# include <netinet/in.h>
+#endif
+
+#include "journaline/newssvcdec_impl.h" // for log variables
+
+CJournaline::CJournaline() : dgdec(NULL), newsdec(NULL)
+{
+	/* This will be the first call to the Journaline decoder open function, the
+	   pointer to the decoders must have a defined value (NULL) to avoid
+	   unpredictable behaviour in the "ResetOpenJournalineDecoder()" function */
+	ResetOpenJournalineDecoder();
+}
+
+CJournaline::~CJournaline()
+{
+	/* Delete decoder instances */
+	if (newsdec != NULL)
+		NEWS_SVC_DEC_deleteDec(newsdec);
+
+	if (dgdec != NULL)
+		DAB_DATAGROUP_DECODER_deleteDec(dgdec);
+}
+
+void CJournaline::ResetOpenJournalineDecoder()
+{
+	/* 1 MB memory for news decoder */
+	unsigned long max_memory = 1024 * 1024;
+
+	/* No limit for number of NML objects (except max_memory limitation) */
+	unsigned long max_objects = 0;
+
+	/* No extended header will be used */
+	unsigned long extended_header_len = 0;
+
+	/* If decoder was initialized before, delete old instance */
+	if (newsdec != NULL)
+		NEWS_SVC_DEC_deleteDec(newsdec);
+
+	if (dgdec != NULL)
+		DAB_DATAGROUP_DECODER_deleteDec(dgdec);
+
+	/* Create decoder instance. Pass the pointer to this object. This is needed
+	   for the call-back functions! */
+	dgdec = DAB_DATAGROUP_DECODER_createDec(dg_cb, this);
+	newsdec = NEWS_SVC_DEC_createDec(obj_avail_cb, max_memory, &max_objects,
+		extended_header_len, this);
+}
+
+void CJournaline::AddFile(const string filename)
+{
+	FILE *f = fopen(filename.c_str(), "rb");
+	bool err=false;
+	showDdNewsSvcDecInfo=1;
+	showDdNewsSvcDecErr=1;
+	while(!feof(f))
+	{
+		unsigned char buf[8192];
+		uint16_t s;
+		size_t n = fread(&s, 2, 1, f);
+		if(n!=1)
+		{
+			err=true;
+			break;
+		}
+		unsigned long size = ntohs(s);
+		if(size>8192)
+			break;
+		n = fread(buf, 1, size, f);
+		if(n==size)
+		{
+			if(NEWS_SVC_DEC_putData(newsdec, size, buf)!=1)
+				fprintf(stderr, "error decoding jml");
+		}
+		else
+		{
+			err=true;
+			break;
+		}
+	}
+	if(!err)
+		fclose(f);
+	showDdNewsSvcDecInfo=0;
+	showDdNewsSvcDecErr=0;
+}
+
+void CJournaline::AddDataUnit(CVector<_BINARY>& vecbiNewData)
+{
+	const int iSizeBytes = vecbiNewData.Size() / SIZEOF__BYTE;
+
+	if (iSizeBytes > 0)
+	{
+		/* Bits to byte conversion */
+		CVector<_BYTE> vecbyData(iSizeBytes);
+		vecbiNewData.ResetBitAccess();
+
+		for (int i = 0; i < iSizeBytes; i++)
+			vecbyData[i] = (_BYTE) vecbiNewData.Separate(SIZEOF__BYTE);
+
+		/* Add new data unit to Journaline decoder library */
+		DAB_DATAGROUP_DECODER_putData(dgdec, iSizeBytes, &vecbyData[0]);
+	}
+}
+
+void CJournaline::GetNews(const int iObjID, CNews& News)
+{
+	/* Init News object in case no object is available */
+	News.sTitle = "";
+	News.vecItem.Init(0);
+
+	NML::RawNewsObject_t rno;
+	unsigned long elen = 0;
+	unsigned long len = 0;
+	if(newsdec && NEWS_SVC_DEC_get_news_object(newsdec, iObjID, &elen, &len, rno.nml))
+	{
+		rno.nml_len = static_cast<unsigned short>(len);
+		rno.extended_header_len = static_cast<unsigned short>(elen);
+		RemoveNMLEscapeSequences handler;
+		NML *nml = NMLFactory::Instance()->CreateNML(rno, &handler);
+
+		/* Title */
+		News.sTitle = nml->GetTitle();
+
+		/* Items */
+		const int iNumItems = nml->GetNrOfItems();
+		News.vecItem.Init(iNumItems);
+
+		/* For "keep in cache" function, init with zero length */
+		CVector<NML::NewsObjectId_t> iAvailIDs(0);
+
+		for (int i = 0; i < iNumItems; i++)
+		{
+			/* Text */
+			News.vecItem[i].sText = nml->GetItemText(i);
+
+			/* Link */
+			if (nml->isMenu())
+			{
+				elen = len = 0;
+
+				/* Check availability of linked object */
+				if (NEWS_SVC_DEC_get_news_object(newsdec, nml->GetLinkId(i),
+					&elen, &len, rno.nml))
+				{
+					/* Assign link */
+					News.vecItem[i].iLink = nml->GetLinkId(i);
+
+					/* Store link in vector for "keep in cache" function */
+					iAvailIDs.Add(nml->GetLinkId(i));
+				}
+				else
+				{
+					/* Not yet received */
+					News.vecItem[i].iLink = JOURNALINE_LINK_NOT_ACTIVE;
+				}
+			}
+			else
+				News.vecItem[i].iLink = JOURNALINE_IS_NO_LINK; /* No link */
+		}
+
+		const int iAvailIDsSize = iAvailIDs.Size();
+		if (iAvailIDsSize > 0)
+		{
+			/* Tell the decoder to keep the linked objects in cache */
+			NEWS_SVC_DEC_keep_in_cache(newsdec, iAvailIDsSize, &iAvailIDs[0]);
+		}
+
+		delete nml;
+	}
+}
diff --git a/src/datadecoding/Journaline.h b/src/datadecoding/Journaline.h
new file mode 100644
index 0000000..8f7ea7e
--- /dev/null
+++ b/src/datadecoding/Journaline.h
@@ -0,0 +1,86 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#if !defined(JOURNALINE_H__3B0UBVE987346456363LIHGEW982__INCLUDED_)
+#define JOURNALINE_H__3B0UBVE987346456363LIHGEW982__INCLUDED_
+
+#include "../GlobalDefinitions.h"
+#include "../util/Vector.h"
+# include "journaline/NML.h"
+# include "journaline/newssvcdec.h"
+# include "journaline/dabdatagroupdecoder.h"
+
+/* Definitions ****************************************************************/
+/* Definitions for links which objects are not yet received or items which
+   do not have links (no menu) */
+#define JOURNALINE_IS_NO_LINK			-2
+#define JOURNALINE_LINK_NOT_ACTIVE		-1
+
+
+/* Classes ********************************************************************/
+struct CNewsItem
+{
+	string	sText;
+	int		iLink;
+};
+
+class CNews
+{
+public:
+	CNews() : sTitle(""), vecItem(0) {}
+
+	string				sTitle;
+	CVector<CNewsItem>	vecItem;
+};
+
+
+class CJournaline
+{
+public:
+	CJournaline();
+	virtual ~CJournaline();
+
+	void GetNews(int iObjID, CNews& News);
+	void AddDataUnit(CVector<_BINARY>& vecbiNewData);
+	void Reset() {ResetOpenJournalineDecoder();}
+	void AddFile(const string filename);
+
+protected:
+	DAB_DATAGROUP_DECODER_t	dgdec;
+	NEWS_SVC_DEC_decoder_t	newsdec;
+
+	void ResetOpenJournalineDecoder();
+
+	/* Callback functions for journaline decoder internal tasks */
+	static void obj_avail_cb(unsigned long, NEWS_SVC_DEC_obj_availability_t*,
+		void*) {}
+	static void dg_cb(const DAB_DATAGROUP_DECODER_msc_datagroup_header_t*,
+		const unsigned long len, const unsigned char* buf, void* data)
+		{NEWS_SVC_DEC_putData(((CJournaline*) data)->newsdec, len, buf);}
+};
+
+#endif // !defined(JOURNALINE_H__3B0UBVE987346456363LIHGEW982__INCLUDED_)
diff --git a/src/datadecoding/MOTSlideShow.cpp b/src/datadecoding/MOTSlideShow.cpp
new file mode 100644
index 0000000..01c36d0
--- /dev/null
+++ b/src/datadecoding/MOTSlideShow.cpp
@@ -0,0 +1,181 @@
+ /******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *	MOT applications (MOT Slideshow and Broadcast Web Site)
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "MOTSlideShow.h"
+
+
+/* Implementation *************************************************************/
+/******************************************************************************\
+* Encoder                                                                      *
+\******************************************************************************/
+void
+CMOTSlideShowEncoder::GetDataUnit (CVector < _BINARY > &vecbiNewData)
+{
+    /* Get new data group from MOT encoder. If the last MOT object was
+       completely transmitted, this functions returns true. In this case, put
+       a new picture to the MOT encoder object */
+    if (MOTDAB.GetDataGroup (vecbiNewData) == TRUE)
+	AddNextPicture ();
+}
+
+_BOOLEAN
+CMOTSlideShowEncoder::GetTransStat (string & strCurPict, _REAL & rCurPerc) const
+{
+/*
+	Name and current percentage of transmitted data of current picture.
+*/
+    strCurPict = strCurObjName;
+    rCurPerc = MOTDAB.GetProgPerc ();
+
+    if (vecPicFileNames.Size () != 0)
+	return TRUE;
+    else
+	return FALSE;
+}
+
+string
+CMOTSlideShowEncoder::TransformFilename(string strFileName)
+{
+    if (bRemovePath)
+    {
+        /* Keep only the filename */
+#ifdef _WIN32
+        const size_t pos = strFileName.rfind('\\');
+#else
+        const size_t pos = strFileName.rfind('/');
+#endif
+        if (pos != string::npos)
+            strFileName.erase(0, pos + 1);
+    }
+    else
+    {
+#ifdef _WIN32
+        /* Remove the C:\ if any */
+        if (strFileName.length() >= 2)
+        {
+            if (strFileName[1] == ':' &&
+                ((strFileName[0]>='A' && strFileName[0]<='Z') ||
+                 (strFileName[0]>='a' && strFileName[0]<='z')))
+            {  
+                strFileName.erase(0, 2);
+                /* Remove the first '\' if any */
+                if (strFileName.length() >= 1)
+                {
+                    if (strFileName[0] == '\\')
+                        strFileName.erase(0, 1);
+                }
+            }
+        }
+        /* Replace all '\' by '/' */
+        const int len = strFileName.length();
+        for (int i = 0; i < len; i++)
+            if (strFileName[i] == '\\')
+                strFileName[i] = '/';
+#else
+        /* Remove the first '/' if any */
+        if (strFileName.length() >= 1)
+        {
+            if (strFileName[0] == '/')
+                strFileName.erase(0, 1);
+        }
+#endif
+    }
+    return strFileName;
+}
+
+void
+CMOTSlideShowEncoder::Init ()
+{
+    /* Reset picture counter for browsing in the vector of file names. Start
+       with first picture */
+    iPictureCnt = 0;
+    strCurObjName = "";
+
+    MOTDAB.Reset ();
+
+    AddNextPicture ();
+}
+
+void
+CMOTSlideShowEncoder::AddNextPicture ()
+{
+    /* Make sure at least one picture is in container */
+    if (vecPicFileNames.Size () > 0)
+      {
+	  /* Get current file name */
+	  strCurObjName = vecPicFileNames[iPictureCnt].strName;
+
+	  /* Try to open file binary */
+	  FILE *pFiBody = fopen (strCurObjName.c_str (), "rb");
+
+	  if (pFiBody != NULL)
+	    {
+		CMOTObject MOTPicture;
+		_BYTE byIn;
+
+		/* Set file name and format string */
+		MOTPicture.strName = TransformFilename(vecPicFileNames[iPictureCnt].strName);
+		MOTPicture.strFormat = vecPicFileNames[iPictureCnt].strFormat;
+
+		/* Fill body data with content of selected file */
+		MOTPicture.vecbRawData.Init (0);
+
+		while (fread ((void *) &byIn, size_t (1), size_t (1), pFiBody)
+		       != size_t (0))
+		  {
+		      /* Add one byte = SIZEOF__BYTE bits */
+		      MOTPicture.vecbRawData.Enlarge (SIZEOF__BYTE);
+		      MOTPicture.vecbRawData.Enqueue ((uint32_t) byIn,
+						      SIZEOF__BYTE);
+		  }
+
+		/* Close the file afterwards */
+		fclose (pFiBody);
+
+		MOTDAB.SetMOTObject (MOTPicture);
+	    }
+
+	  /* Set file counter to next picture, test for wrap around */
+	  iPictureCnt++;
+	  if (iPictureCnt == vecPicFileNames.Size ())
+	      iPictureCnt = 0;
+      }
+}
+
+void
+CMOTSlideShowEncoder::AddFileName (const string & strFileName,
+				   const string & strFormat)
+{
+    /* Only ContentSubType "JFIF" (JPEG) and ContentSubType "PNG" are allowed
+       for SlideShow application (not tested here!) */
+    /* Add file name to the list */
+    const int iOldNumObj = vecPicFileNames.Size ();
+    vecPicFileNames.Enlarge (1);
+    vecPicFileNames[iOldNumObj].strName = strFileName;
+    vecPicFileNames[iOldNumObj].strFormat = strFormat;
+}
diff --git a/src/datadecoding/MOTSlideShow.h b/src/datadecoding/MOTSlideShow.h
new file mode 100644
index 0000000..db29a19
--- /dev/null
+++ b/src/datadecoding/MOTSlideShow.h
@@ -0,0 +1,75 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#if !defined(MOTSLIDESHOW_H__3B0UBVE98732KJVEW363LIHGEW982__INCLUDED_)
+#define MOTSLIDESHOW_H__3B0UBVE98732KJVEW363LIHGEW982__INCLUDED_
+
+#include "../GlobalDefinitions.h"
+#include "../util/Vector.h"
+#include "DABMOT.h"
+
+
+/* Classes ********************************************************************/
+/* Encoder ------------------------------------------------------------------ */
+class CMOTSlideShowEncoder
+{
+  public:
+    CMOTSlideShowEncoder (): vecPicFileNames(0), bRemovePath(FALSE)
+    {
+    }
+    virtual ~ CMOTSlideShowEncoder ()
+    {
+    }
+
+    void Init ();
+
+    void GetDataUnit (CVector < _BINARY > &vecbiNewData);
+
+    void AddFileName(const string & strFileName, const string & strFormat);
+    void ClearAllFileNames() {vecPicFileNames.Init(0);}
+    void SetPathRemoval(_BOOLEAN bNewRemovePath) {bRemovePath=bNewRemovePath;}
+    _BOOLEAN GetTransStat(string & strCurPict, _REAL & rCurPerc) const;
+
+  protected:
+    struct SPicDescr
+    {
+	string strName, strFormat;
+    };
+    void AddNextPicture ();
+    string TransformFilename(const string strFileName);
+
+    CMOTDABEnc MOTDAB;
+
+    CVector < SPicDescr > vecPicFileNames;
+    int iPictureCnt;
+
+    string strCurObjName;
+
+    _BOOLEAN bRemovePath;
+};
+
+#endif // !defined(MOTSLIDESHOW_H__3B0UBVE98732KJVEW363LIHGEW982__INCLUDED_)
diff --git a/src/datadecoding/epgutil.cpp b/src/datadecoding/epgutil.cpp
new file mode 100644
index 0000000..343f3cd
--- /dev/null
+++ b/src/datadecoding/epgutil.cpp
@@ -0,0 +1,125 @@
+/******************************************************************************\
+ * British Broadcasting Corporation
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Julian Cable
+ *
+ * Description:
+ *	ETSI DAB/DRM Electronic Programme Guide utilities
+ *
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "epgutil.h"
+#include <iomanip>
+#include <iostream>
+#include <sstream>
+#ifdef _WIN32
+#include <io.h>
+#include <direct.h>
+#else
+#include <sys/stat.h>
+#endif
+using namespace std;
+
+#ifdef _WIN32
+# define mkdir(a,b) _mkdir(a)
+#endif
+
+void
+mkdirs (const string & path)
+{
+    /* forward slashes only, since this is a MOT ContentName */
+    size_t n = path.find_last_of ('/');
+    if (n == string::npos)
+	return;
+    string left, sep = "";
+    for (size_t p = 0; p < n;)
+      {
+	  size_t q = path.find ('/', p);
+	  if (q == string::npos)
+	      return;
+	  string dir = path.substr (p, q - p);
+	  left += sep + dir;
+      sep = PATH_SEPARATOR;
+	  mkdir (left.c_str (), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
+	  p = q + 1;
+      }
+}
+
+// this is the old dream one
+string
+epgFilename (const CDateAndTime & date, uint32_t sid, int type, bool advanced)
+{
+    string name;
+    ostringstream s (name);
+    s << setfill ('0') << setw (4) << date.year;
+    s << setw (2) << int (date.month) << setw(2) << int (date.day);
+    s << hex << setw (4) << ((unsigned long) sid);
+    switch (type)
+      {
+      case 0:
+	  s << 'S';
+	  break;
+      case 1:
+	  s << 'P';
+	  break;
+      case 2:
+	  s << 'G';
+	  break;
+      }
+    if (advanced)
+	s << ".EHA";
+    else
+	s << ".EHB";
+    return s.str ();
+}
+
+string
+epgFilename_etsi (const CDateAndTime & date, uint32_t sid, int type, bool advanced)
+{
+    (void)type;
+    string name;
+    ostringstream s (name);
+    s << "w" << setfill ('0') << setw (4) << date.year;
+    s << setw (2) << int (date.month) << setw(2) << int (date.day);
+    s << "d" << hex << setw (4) << ((unsigned long) sid);
+    if (advanced)
+	s << ".EHA";
+    else
+	s << ".EHB";
+    return s.str ();
+}
+
+string
+epgFilename_dab (const CDateAndTime & date, uint32_t sid, int type, bool advanced)
+{
+    (void)type;
+    string name;
+    ostringstream s (name);
+    s << "w" << setfill ('0') << setw (4) << date.year;
+    s << setw (2) << int (date.month) << setw(2) << int (date.day);
+    s << "d" << hex << setw (6) << ((unsigned long) sid);
+    if (advanced)
+	s << ".EHA";
+    else
+	s << ".EHB";
+    return s.str ();
+}
diff --git a/src/datadecoding/epgutil.h b/src/datadecoding/epgutil.h
new file mode 100644
index 0000000..342ad9a
--- /dev/null
+++ b/src/datadecoding/epgutil.h
@@ -0,0 +1,47 @@
+/******************************************************************************\
+ * British Broadcasting Corporation
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Julian Cable
+ *
+ * Description:
+ *	ETSI DAB/DRM Electronic Programme Guide utilities
+ *
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#ifndef _EPGUTIL_H
+#define _EPGUTIL_H
+
+#include "DABMOT.h"
+
+void mkdirs (const string & path);
+
+string epgFilename (const CDateAndTime & date,
+		    uint32_t sid, int type, bool advanced);
+string epgFilename_etsi (const CDateAndTime & date,
+		    uint32_t sid, int type, bool advanced);
+string epgFilename_dab (const CDateAndTime & date,
+		    uint32_t sid, int type, bool advanced);
+
+string epgFilename2 (const CDateAndTime & date,
+		    uint32_t sid, int type, bool advanced);
+
+#endif
diff --git a/src/datadecoding/journaline/NML.cpp b/src/datadecoding/journaline/NML.cpp
new file mode 100644
index 0000000..a68f2e2
--- /dev/null
+++ b/src/datadecoding/journaline/NML.cpp
@@ -0,0 +1,884 @@
+/*
+ *
+ * This file is part of the 'NewsService Journaline(R) Decoder'
+ *
+ * Copyright (c) 2003, 2001-2014 by Fraunhofer IIS, Erlangen, Germany
+ *
+ * --------------------------------------------------------------------
+ *
+ * For NON-COMMERCIAL USE,
+ * the 'NewsService Journaline(R) Decoder' is free software;
+ * you can redistribute it and/or modify it under the terms of
+ * the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * The 'NewsService Journaline(R) Decoder' is distributed in the hope
+ * that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with the 'NewsService Journaline(R) Decoder';
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ *
+ * If you use this software in a project with user interaction, please
+ * provide the following text to the user in an appropriate place:
+ * "Features NewsService Journaline(R) decoder technology by
+ * Fraunhofer IIS, Erlangen, Germany.
+ * For more information visit http://www.iis.fhg.de/dab"
+ *
+ * --------------------------------------------------------------------
+ *
+ * To use the 'NewsService Journaline(R) Decoder' software for
+ * COMMERCIAL purposes, please contact Fraunhofer IIS for a
+ * commercial license (see below for contact information)!
+ *
+ * --------------------------------------------------------------------
+ *
+ * Contact:
+ *   Fraunhofer IIS, Department 'Broadcast Applications'
+ *   Am Wolfsmantel 33, 91058 Erlangen, Germany
+ *   http://www.iis.fraunhofer.de/dab
+ *   mailto:bc-info at iis.fraunhofer.de
+ *
+ */
+
+//////////////////////////////////////////////////////////////////////////////
+/// @brief NML class
+///
+/// handling of NML (news markup language for Journaline) data
+///
+/// @file       NML.cpp
+/// @author     Michael Reichenb�cher <rbr at iis.fraunhofer.de>
+///
+/// $Id: NML.cpp,v 1.9 2001-2014/09/30 10:33:58 jcable Exp $
+///
+/// Module:     Journaline(R)
+///
+/// Copyright:  (C) 2003-2001-2014 by Fraunhofer IIS-A, IT-Services, Erlangen
+///
+/// Compiler:   gcc version 3.3 20030226 (prerelease)
+///             Microsoft Visual C++ .NET
+///
+//////////////////////////////////////////////////////////////////////////////
+
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <zlib.h>
+#include "NML.h"
+#include "Splitter.h"
+#include "cpplog.h"
+
+static int Inflate(unsigned char *dest,
+                   unsigned long *destLen,
+                   const unsigned char *source,
+                   unsigned long sourceLen);
+
+/// maximum length of a raw NML object
+const unsigned int NML::NML_MAX_LEN = 4092;
+
+/// maximum number of hierarchy levels
+const unsigned int NML::NML_MAX_NR_OF_LEVELS = 20; // levels 0(root menu)..19
+
+/// maximum number of menu items
+const unsigned int NML::NML_MAX_NR_OF_MENU_ITEMS = 32;
+
+/// maximum number of watches
+const unsigned int NML::MAX_NR_OF_WATCHES = NML::NML_MAX_NR_OF_MENU_ITEMS + 1;
+
+/// minimum number of bytes in a menu or list item
+const unsigned int NML::NML_MIN_NR_OF_ITEM_BYTES = 3;
+
+/// number of header bytes
+const unsigned int NML::NML_NR_OF_HEADER_BYTES = 3;
+
+/// object id of root object
+const NML::NewsObjectId_t NML::ROOT_OBJECT_ID = 0x0000;
+
+/// textual description of NML object types
+const char *NML::ObjectTypeString[]=
+  {"illegal", "menu", "plain", "title", "list"};
+
+
+
+
+
+NMLFactory *NMLFactory::_instance = 0;
+
+NMLFactory::NMLFactory()
+{
+}
+
+NMLFactory::~NMLFactory()
+{
+}
+
+
+/// NMLFactory Singleton Instance
+/// @return The (only) instance of NMLFactory
+NMLFactory *NMLFactory::Instance(void)
+{
+  if (!_instance) _instance = new NMLFactory;
+  return _instance;
+}
+
+
+/// NMLFactory Singleton ExitInstance
+/// destroys the (only) instance of NMLFactory)
+void NMLFactory::ExitInstance(void)
+{
+  delete _instance;
+}
+
+
+
+/// generate an NML Error object from a raw news object
+/// generates a fake NML object containing an error message.
+/// The title of the error message will be error_msg, and the
+/// body will consist of a hex dump of the erroneous NML object.
+/// and a hex dump of the raw news object
+/// @param oid        NML object id
+/// @param rno        raw NML object
+/// @param error_msg  error message
+/// @return  pointer to created NML errordump object (delete after use!)
+NML *NMLFactory::CreateErrorDump(NML::NewsObjectId_t oid,
+                                 const NML::RawNewsObject_t & rno,
+                                 const char *error_msg)
+{
+  log_err << "CreateErrorDump" << endmsg;
+
+  NML *n = CreateError(oid, error_msg);
+  n->SetErrorDump(oid, rno, error_msg);
+  return n;
+}
+
+
+
+/// generate an invalid NML error object
+/// The title of the error message will be title, and the
+/// body will consist of a hex dump of the erroneous NML object.
+/// and a hex dump of the raw news object
+/// @param oid    NML object id
+/// @param title  title error message
+/// @return  pointer to error object (delete after use!)
+NML *NMLFactory::CreateError(NML::NewsObjectId_t oid,
+                             const char *title)
+{
+  log_err << "CreateError" << endmsg;
+
+  NML *n = new NML();
+  n->_valid = false;
+  n->_news.object_id = oid;
+  n->_news.title = title;
+  n->_news.object_type = NML::TITLE;
+  n->_news.static_flag = false;
+  n->_news.revision_index = 0x00;
+  return n;
+}
+
+
+/// dump raw NML object
+/// @param rno  raw NML news object
+/// @return  dump of NML object as string
+std::string DumpRaw(const NML::RawNewsObject_t & rno)
+{
+  return HexDump(rno.nml, static_cast<int>(rno.nml_len), 8);
+}
+
+
+
+/// dump news object to stream
+/// @param os  output stream to dump to
+/// @return  output stream (for chained stream io)
+std::ostream & NML::operator<<(std::ostream & os) const
+{
+  return os << Dump();
+}
+
+
+/// dump the news object as string
+/// @return  dump as string
+std::string NML::Dump(void) const
+{
+  char buf[4096];
+  std::string items = "";
+  unsigned int nr_of_items = GetNrOfItems();
+  for(unsigned int i=0; i<nr_of_items; i++)
+  {
+    if (isMenu())
+    {
+      sprintf(buf,
+              "Link #%d [%04x] %s\n",
+              i,
+              GetLinkId(i),
+              (isLinkIdAvailable(i)?"is":"would be"));
+    }
+    else
+    {
+      sprintf(buf, "Item #%d is\n", i);
+    }
+    items += buf;
+    items += HexDump(GetItemText(i).c_str(),
+                     GetItemText(i).size());
+  }
+
+  sprintf(buf,
+          "object_id=%04x, object_type: %s(%d), static_flag=%1x,\n"
+          "revision=%d,extended_header_len=%d,nr_of_items=%d\n",
+          GetObjectId(),
+          GetObjectTypeString(),
+          GetObjectType(),
+          isStatic(),
+          GetRevisionIndex(),
+          (int)_news.extended_header.size(),
+          nr_of_items);
+  std::string s = buf;
+  if (_news.extended_header.size())
+  {
+    s += "\nextended header: ";
+    s += HexDump(_news.extended_header.c_str(),
+                 _news.extended_header.size());
+  }
+  s += "\ntitle=\n";
+  s += HexDump(_news.title.c_str(),
+               _news.title.size());
+  s += "\nitems:\n";
+  s += items;
+  return s;
+}
+
+//ignore datasections and return a new char pointer pointing to
+//a buffer without datasections and will manipulate p and plen accordingly
+//reslen is an out parameter returning the size of the buffer
+//returns a newly created buffer containing pure nml data on success
+//returns 0 on error
+unsigned char* NMLFactory::getNextSection( const unsigned char*& p, unsigned short& plen, unsigned short& reslen )
+{
+	register int i = 0;
+	register int j = 0;
+	register int dslen;
+	unsigned char* res = (unsigned char*)malloc( plen + 1 );
+
+	// we will loop through the entire data until a break case is met
+	while( i < plen )
+	{
+		if( p[i] == 0x1a // datasection begin
+		 || p[i] == 0x1b // datasection continue
+		){
+			// we take the length of the datasection and add it
+			// to the current position in order to ignore it
+			dslen = p[i+1] + 1;
+			// make a safety check for that the length is still in bounds
+			if( dslen > ( plen - i ) )
+			{
+				// we got an invalid datasection
+				// abort!
+				reslen = 0;
+				free( res );
+				return 0;
+			}
+			// we can safely skip the datasection now
+			i += 2 + dslen;
+			            continue;	
+		}
+
+		if( !(p[i] & 0xF0) ) // any jml code
+		{
+			// we can quit the loop here since we reached
+			// another jml code section
+			break;
+		}
+
+		// well, here we can copy the contents right over
+		res[j++] = p[i++];
+	}
+
+	// adjust the pointer and its length
+	p    += i;
+	plen -= i;
+
+	// make a safety null termination
+	res[j] = '\0';
+
+	// finally return the result
+	reslen = j;
+	return res;
+}
+
+/// @brief create an NML object from raw NML
+/// An NML object will be created from the specified raw news object,
+/// even if the raw news object is invalid. In this case, an error
+/// NML object is created containing a hexadecimal dump of the erroneous
+/// input.
+/// A handler for NML escape code sequences, e.g.
+/// RemoveNMLEscapeSequences or NMLEscapeSequences2HTML  must be specified,
+/// so that escape code sequences can be handled in an application specific way.
+/// @param rno                 raw NML object
+/// @param EscapeCodeHandler   handler for NML escape codes
+/// @return  pointer to created NML news object (delete after use!)
+NML* NMLFactory::CreateNML( const NML::RawNewsObject_t& rno, const NMLEscapeCodeHandler* EscapeCodeHandler )
+{
+	NML*           n          = new NML();
+	char           buf[256];
+	char*          error      = &buf[0];
+	std::string    tmp_string;
+	unsigned char* pure_text;
+
+	// at least header needs to be present
+	if( rno.nml_len < 4 )
+	{
+		sprintf( error, "Error: NML has only %u bytes", rno.nml_len );
+		n->SetErrorDump( 0x0815, rno, error );
+		return n;
+	}
+
+	// extract object id
+	n->_news.object_id = static_cast<unsigned short>( (rno.nml[0]<<8) + rno.nml[1] );
+
+	// check for reserved object types
+	if( ( ( rno.nml[2] >> 5 ) == 0 ) || ( ( rno.nml[2] >> 5 ) > NML::LIST ) )
+	{
+		sprintf( error, "Error: NML has illegal object type 0x%02x", rno.nml[2] >> 5 );
+		n->SetErrorDump( n->_news.object_id, rno, error );
+		return n;
+	}
+
+	// extract further header data: object_id, static, compressed, revision
+	n->_news.object_type    = static_cast< NML::object_type_t >( rno.nml[2] >> 5 );
+	n->_news.static_flag    = (rno.nml[2] & 0x10) != 0;
+	bool compressed_flag    = (rno.nml[2] & 0x08) != 0;
+	n->_news.revision_index = static_cast< unsigned char >( rno.nml[2] & 0x07 );
+	unsigned short len      = rno.nml_len - NML::NML_NR_OF_HEADER_BYTES;
+
+	// extended header checks
+	if( rno.extended_header_len > len )
+	{
+		sprintf( error, "Error: NML extended header too big (%u>%u)", rno.extended_header_len, len );
+		n->SetErrorDump( n->_news.object_id, rno, error );
+		return n;
+	}
+	len -= rno.extended_header_len;
+	const unsigned char* pStart = rno.nml + NML::NML_NR_OF_HEADER_BYTES + rno.extended_header_len;
+	const unsigned char* p = pStart;
+
+	NML::RawNewsObject_t uncompressed;
+
+	// if compressed then decompress body
+	if( compressed_flag )
+	{
+		// check GZIP magic bytes
+		if( *p != 0x08 )
+		{
+			// unknown (not libz) compression
+			sprintf( error, "Error: NML with unknown compression 0x%02x", *p );
+			log_err << error << endmsg;
+			n->SetErrorDump( n->_news.object_id, rno, error );
+			return n;
+		}
+		p++;
+		len--;
+
+		// copy header
+		memcpy( uncompressed.nml, rno.nml, NML::NML_NR_OF_HEADER_BYTES + rno.extended_header_len );
+		unsigned long ulen = 4092;
+		int rv = Inflate( uncompressed.nml + NML::NML_NR_OF_HEADER_BYTES + rno.extended_header_len, &ulen, p, len );
+
+		if( !rv )
+		{
+			sprintf( error, "Error: could not uncompress NML body (%d)", rv );
+			n->SetErrorDump(n->_news.object_id, rno, error);
+			return n;
+		}
+
+		/*
+		log_info
+			<< "decompressed NML, "
+			<< len << " -> " << ulen
+			<< endmsg;
+		*/
+
+		if( ulen + NML::NML_NR_OF_HEADER_BYTES + rno.extended_header_len > NML::NML_MAX_LEN )
+		{
+			sprintf( error, "Error: uncompressed NML body too big (%lu bytes)",
+				ulen + NML::NML_NR_OF_HEADER_BYTES + rno.extended_header_len );
+			n->SetErrorDump(n->_news.object_id, rno, error);
+			return n;
+		}
+
+		// => ulen < NML::NML_MAX_LEN
+		uncompressed.nml_len = static_cast<unsigned short>(ulen);
+		p = uncompressed.nml + NML::NML_NR_OF_HEADER_BYTES + rno.extended_header_len;
+		len = uncompressed.nml_len;
+
+		/*
+		log_info
+			<< "compressed NML len=" << rno.nml_len
+			<< ", uncompressed NML len= " << uncompressed.nml_len
+			<< endmsg;
+		*/
+	}
+	// wasn't compressed, so just copy content
+	else
+	{
+		uncompressed.nml_len = rno.nml_len;
+		memcpy( uncompressed.nml, rno.nml, rno.nml_len );
+	}
+
+	// check for title section
+	if( *p != 0x01 )
+	{
+		sprintf( error, "Error: expected NML Code 0x01, got 0x%02x", *p );
+		n->SetErrorDump( n->_news.object_id, uncompressed, error );
+		return n;
+	}
+	len--;
+	p++;
+
+	unsigned short pure_txt_len = 0;
+
+	// extract title
+	pure_text = getNextSection( p, len, pure_txt_len );
+	if( !pure_text )
+	{
+		sprintf( error, "Error: ignoreDataSections() returned illegal data section" );
+		n->SetErrorDump( n->_news.object_id, uncompressed, error );
+		return n;
+	}
+	tmp_string.assign( reinterpret_cast< const char* >( pure_text ), pure_txt_len );
+	free( pure_text );
+	// report title to codehandler
+	EscapeCodeHandler->Convert( n->_news.title, tmp_string );
+
+	n->_news.item.clear();
+
+	// title object only needs title..
+	if( n->_news.object_type == NML::TITLE )
+		return n;
+
+	// plain text message will need a text message as well
+	if( n->_news.object_type == NML::PLAIN )
+	{
+		if( *p != 0x03 )
+		{
+			sprintf( error, "Error: expected NML Code 0x03, got 0x%02x", *p );
+			n->SetErrorDump( n->_news.object_id, uncompressed, error );
+			return n;
+		}
+		len--;
+		p++;
+		pure_text = getNextSection( p, len, pure_txt_len );
+		if( !pure_text )
+		{
+			sprintf(error, "Error: ignoreDataSections() returned illegal data section" );
+			n->SetErrorDump( n->_news.object_id, uncompressed, error );
+			return n;
+		}
+		tmp_string.assign( (const char *)(pure_text), pure_txt_len);
+		free( pure_text );
+		NML::Item_t item;
+		EscapeCodeHandler->Convert( item.text, tmp_string );
+		n->_news.item.push_back( item );
+		return n;
+	}
+	// menu object will need link items
+	else if( n->_news.object_type == NML::MENU )
+	{
+		while( len > NML::NML_MIN_NR_OF_ITEM_BYTES )
+		{
+			if( *p != 0x02 )
+			{
+				sprintf( error, "Error: expected NML Code 0x02, got 0x%02x", *p );
+				n->SetErrorDump( n->_news.object_id, uncompressed, error );
+				return n;
+			}
+			len--;
+			p++;
+
+			NML::Item_t item;
+			item.link_id = static_cast<unsigned short>( ( p[0]<<8 ) + p[1] );
+			item.link_id_available = false;
+			len -= 2;
+			p   += 2;
+
+			pure_text = getNextSection( p, len, pure_txt_len );
+			if( !pure_text )
+			{
+				sprintf( error, "Error: ignoreDataSections() returned illegal data section" );
+				n->SetErrorDump( n->_news.object_id, uncompressed, error );
+				return n;
+			}
+			tmp_string.assign(reinterpret_cast<const char *>(pure_text), pure_txt_len);
+			free( pure_text );
+			EscapeCodeHandler->Convert( item.text, tmp_string );
+
+			n->_news.item.push_back( item );
+		}
+	}
+	// list item will need list items
+	else if( n->_news.object_type == NML::LIST )
+	{
+		NML::Item_t item;
+		while( len > NML::NML_MIN_NR_OF_ITEM_BYTES )
+		{
+			if( *p != 0x04 && *p != 0x05 )
+			{
+				sprintf( error, "Error: expected NML Code 0x04 or 0x05, got 0x%02x", *p );
+				n->SetErrorDump( n->_news.object_id, uncompressed, error );
+				return n;
+			}
+//			bool newRow = (*p == 0x04);
+			len--;
+			p++;
+
+			pure_text = getNextSection( p, len, pure_txt_len );
+			if( !pure_text )
+			{
+				sprintf( error, "Error: ignoreDataSections() returned illegal data section" );
+				n->SetErrorDump( n->_news.object_id, uncompressed, error );
+				return n;
+			}
+			tmp_string.assign( reinterpret_cast<const char *>(pure_text), pure_txt_len );
+			free( pure_text );
+			EscapeCodeHandler->Convert( item.text, tmp_string );
+
+			n->_news.item.push_back( item );
+		}
+	}
+
+	// all went well, mark as valid
+	n->_valid = true;
+	return n;
+}
+
+
+
+/// default NML constructor
+NML::NML()
+{
+  _valid = false;
+  _news.object_type = NML::TITLE;
+  _news.object_id = 0x0815;
+  _news.title = "uninit. NML";
+}
+
+
+/// copy NML constructor
+/// @param prototype  NML object to clone
+NML::NML(const NML & prototype)
+{
+  *this = prototype;
+}
+
+
+/// NML assignment operator
+/// @param prototype  NML object to clone
+/// @return reference to cloned object
+const NML & NML::operator=(const NML & prototype)
+{
+  _valid = prototype._valid;
+  _news = prototype._news;
+  _EscapeCodeHandler = prototype._EscapeCodeHandler;
+  return *this;
+}
+
+
+/// NML comparison operator
+/// @param prototype  NML object to compare this with
+/// @retval true  NML objects are equal
+bool NML::operator==(const NML & prototype) const
+{
+  if (_news.item.size()!=prototype._news.item.size()) return false;
+  for (unsigned int i=0; i<_news.item.size(); i++)
+  {
+    if (!(_news.item[i]==prototype._news.item[i])) return false;
+  }
+  return (_valid != prototype._valid)
+    && (_news.object_id != prototype._news.object_id)
+    && (_news.static_flag == prototype._news.static_flag)
+    && (_news.revision_index == prototype._news.revision_index)
+    && (_news.extended_header == prototype._news.extended_header)
+    && (_news.title == prototype._news.title);
+}
+
+
+/// comparison operator for NML menu/list items
+/// @param lhs  left hand side of NML object comparison
+/// @param rhs  right hand side of NML object comparison
+/// @retval true  NML objects are equal
+bool operator==(const NML::Item_t &lhs, const NML::Item_t &rhs)
+{
+  return (lhs.text==rhs.text);
+}
+
+
+/// destructor
+NML::~NML()
+{
+}
+
+
+/// set NML to an error object
+/// generates a fake NML object containing an error message.
+/// The title of the error message will be error_msg, and the
+/// body will consist of a hex dump of the erroneous raw NML object.
+/// and a hex dump of the raw news object
+/// @param oid        NML object id
+/// @param rno        raw NML object
+/// @param error      error message
+void NML::SetErrorDump(NewsObjectId_t oid,
+                       const RawNewsObject_t & rno,
+                       const char *error)
+{
+  log_err << "NML::SetErrorDump: " << error << endmsg;
+
+  _news.object_type = NML::PLAIN;
+  _news.object_id = oid;
+  _news.static_flag = false;
+  _news.revision_index = 0;
+  _news.title = error;
+
+  Splitter s;
+  std::vector<std::string> lines;
+  std::vector<std::string>::const_iterator lines_i;
+  s.Split(lines, DumpRaw(rno));
+
+  _news.item.clear();
+  for (lines_i=lines.begin(); lines_i!=lines.end(); lines_i++)
+  {
+    NML::Item_t item;
+    item.text = *lines_i;
+    _news.item.push_back(item);
+  }
+}
+
+
+/// hexadecimal dump of field of unsigned chars
+/// @param p               field
+/// @param len             length of field
+/// @param bytes_per_line  how many hexadecimal bytes should be
+///                        displayed on one line of the hexdump
+/// @return  hexdump as string
+std::string HexDump(const char *p,
+                    unsigned int len,
+                    unsigned int bytes_per_line)
+{
+  return HexDump(reinterpret_cast<const unsigned char *>(p),
+                 len,
+                 bytes_per_line);
+}
+
+
+/// hexadecimal dump of field of unsigned chars
+/// @param p               field
+/// @param len             length of field
+/// @param bytes_per_line  how many hexadecimal bytes should be
+///                        displayed on one line of the hexdump
+/// @return  hexdump as string
+std::string HexDump(const unsigned char *p,
+        unsigned int len,
+        unsigned int bytes_per_line)
+{
+  std::string dump, ascii;
+  unsigned int i;
+
+  for (i=0; i<len; i++)
+  {
+    char buf[4];
+    sprintf(buf, "%02x ", p[i]);
+    ascii += (isprint(p[i]))?p[i]:'.';
+    dump += buf;
+    if (i%bytes_per_line==bytes_per_line-1)
+    {
+      dump += " " + ascii + "\n";
+      ascii = "";
+    }
+  }
+  if (i%bytes_per_line)
+  {
+    for (; i%bytes_per_line; i++)
+    {
+      dump += "   ";
+    }
+    dump += " " + ascii + "\n";
+  }
+
+  return dump;
+}
+
+
+/// for decompressing deflated (RFC1951) data
+/// @param dest       where to store decompressed data
+/// @param destLen    maximum number of bytes of decompressed data
+/// @param source     compressed (deflated) data
+/// @param sourceLen  length of compressed data
+/// @retval  Z_OK     iff source was inflated successfully
+int Inflate(unsigned char *dest,
+            unsigned long *destLen,
+            const unsigned char *source,
+            unsigned long sourceLen)
+{
+  z_stream stream;
+  int err;
+  stream.next_in = const_cast<Bytef*>(source);
+  stream.avail_in = static_cast<uInt>(sourceLen);
+  if (static_cast<uLong>(stream.avail_in) != sourceLen)
+  {
+    log_err << "avail_in=" << static_cast<uLong>(stream.avail_in)
+            << "!= sourceLen=" << sourceLen
+            << endmsg;
+    return 0;
+  }
+
+  stream.next_out = dest;
+  stream.avail_out = static_cast<uInt>(*destLen);
+  if (static_cast<uLong>(stream.avail_out) != *destLen)
+  {
+    log_err << "avail_out=" << static_cast<uLong>(stream.avail_out)
+            << "!= *destLen=" << *destLen
+            << endmsg;
+    return 0;
+  }
+
+  stream.zalloc = 0;
+  stream.zfree = 0;
+
+  err = inflateInit2(&stream, -15);
+  if (err != Z_OK)
+  {
+    log_err << "inflateInit2 failed with " << err
+            << endmsg;
+    return 0;
+  }
+
+  err = inflate(&stream, Z_FINISH);
+  if (err != Z_STREAM_END)
+  {
+    log_err << "inflate failed with " << err
+            << endmsg;
+    inflateEnd(&stream);
+    return 0;
+  }
+  *destLen = stream.total_out;
+
+  err = inflateEnd(&stream);
+  if (err != Z_OK)
+  {
+    log_err << "inflateEnd failed with " << err
+            << endmsg;
+    return 0;
+  }
+  return 1;
+}
+
+
+
+
+RemoveNMLEscapeSequences::RemoveNMLEscapeSequences()
+{
+}
+
+
+RemoveNMLEscapeSequences::~RemoveNMLEscapeSequences()
+{
+}
+
+
+/// remove NML escape sequences
+/// substitutes some NML sequences but removes most.
+/// the result can be displayed on a standard UTF-8 capable
+/// terminal.
+/// @attention NML data sections and extended NML codes are silently ignored
+/// @param src   source string (including NML escape sequences)
+/// @param dest  UTF-8 string
+/// @return  always true
+bool RemoveNMLEscapeSequences::Convert(std::string & dest,
+                                       const std::string & src) const
+{
+  dest = "";
+
+  for (unsigned int i=0; i<src.length(); i++)
+  {
+    switch(src[i])
+    {
+    case 0x10: // replace preferred line break with LF
+      dest += 0x0a;
+      break;
+    case 0x12: // highlight begin -> ignore
+    case 0x13: // highlight end -> ignore
+      break;
+    case 0x1A: // data section begin -> read over next bytes
+    case 0x1B: // data section continuation -> read over next bytes
+      ++i;
+      i += src[i] + 1;
+      break;
+    case 0x1C: // extended code begin -> ignore next byte
+    case 0x1D: // extended code end -> ignore next byte
+      i++;
+      break;
+    default:
+      dest += src[i];
+      break;
+    }
+  }
+  return true;
+}
+
+NMLEscapeSequences2HTML::NMLEscapeSequences2HTML()
+{
+}
+
+
+NMLEscapeSequences2HTML::~NMLEscapeSequences2HTML()
+{
+}
+
+
+/// replace NML escape sequences with HTML tags
+/// replaces most NML escape sequences with the corresponding
+/// HTML tags.
+/// The result can be displayed on a standard UTF-8 capable
+/// HTML Browser.
+/// @attention NML data sections and extended NML codes are silently ignored
+/// @param  src source string (including NML escape sequences)
+/// @param  dest UTF-8 string
+/// @return  always true
+bool NMLEscapeSequences2HTML::Convert(std::string & dest,
+                                      const std::string & src) const
+{
+  dest = "";
+
+  for (unsigned int i=0; i<src.length(); i++)
+  {
+    switch(src[i])
+    {
+    case 0x10: // replace preferred line break with <br> tag
+      dest += "<br/>\n";
+      break;
+    case 0x12: // highlight begin -> <em>
+      dest += "<em>";
+      break;
+    case 0x13: // highlight end -> </em>
+      dest += "</em>";
+      break;
+    case 0x1A: // data section begin -> read over next bytes
+    case 0x1B: // data section continuation -> read over next bytes
+      ++i;
+      i += static_cast<unsigned char>(src[i]) + 1;
+      break;
+    case 0x1C: // extended code begin -> ignore next byte
+    case 0x1D: // extended code end -> ignore next byte
+      i++;
+      break;
+    default:
+      dest += src[i];
+      break;
+    }
+  }
+  return true;
+}
+
diff --git a/src/datadecoding/journaline/NML.h b/src/datadecoding/journaline/NML.h
new file mode 100644
index 0000000..6ad86bc
--- /dev/null
+++ b/src/datadecoding/journaline/NML.h
@@ -0,0 +1,379 @@
+/* 
+ *
+ * This file is part of the 'NewsService Journaline(R) Decoder'
+ * 
+ * Copyright (c) 2003, 2001-2014 by Fraunhofer IIS, Erlangen, Germany
+ * 
+ * --------------------------------------------------------------------
+ * 
+ * For NON-COMMERCIAL USE,
+ * the 'NewsService Journaline(R) Decoder' is free software;
+ * you can redistribute it and/or modify it under the terms of
+ * the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * The 'NewsService Journaline(R) Decoder' is distributed in the hope
+ * that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with the 'NewsService Journaline(R) Decoder';
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ * 
+ * If you use this software in a project with user interaction, please
+ * provide the following text to the user in an appropriate place:
+ * "Features NewsService Journaline(R) decoder technology by
+ * Fraunhofer IIS, Erlangen, Germany.
+ * For more information visit http://www.iis.fhg.de/dab"
+ * 
+ * --------------------------------------------------------------------
+ * 
+ * To use the 'NewsService Journaline(R) Decoder' software for
+ * COMMERCIAL purposes, please contact Fraunhofer IIS for a
+ * commercial license (see below for contact information)!
+ * 
+ * --------------------------------------------------------------------
+ * 
+ * Contact:
+ *   Fraunhofer IIS, Department 'Broadcast Applications'
+ *   Am Wolfsmantel 33, 91058 Erlangen, Germany
+ *   http://www.iis.fraunhofer.de/dab
+ *   mailto:bc-info at iis.fraunhofer.de
+ * 
+ */
+
+//////////////////////////////////////////////////////////////////////////////
+/// @brief NML class
+///
+/// handling of NML (news markup language for Journaline) data
+///
+/// @file       NML.h
+/// @author     Michael Reichenb�cher <rbr at iis.fraunhofer.de>
+///
+/// $Id: NML.h,v 1.3 2008/12/26 20:04:53 jcable Exp $
+///
+/// Module:     Journaline(R)
+///
+/// Copyright:  (C) 2003-2001-2014 by Fraunhofer IIS-A, IT-Services, Erlangen
+///
+/// Compiler:   gcc version 3.3 20030226 (prerelease)
+///             Microsoft Visual C++ .NET
+///
+//////////////////////////////////////////////////////////////////////////////
+
+
+#ifndef _NML_H_
+#define _NML_H_
+
+
+#ifdef _MSC_VER
+#pragma warning(push,3)
+#pragma warning(disable:4018)
+#pragma warning(disable:4100)
+#pragma warning(disable:4514)
+#pragma warning(disable:4786)
+#endif
+
+#include <string>
+#include <vector>
+#include <ios>
+
+#ifdef _MSC_VER
+#pragma warning(pop)
+#pragma warning(disable:4786)
+#pragma warning(disable:4514)
+#endif
+
+// utility functions
+std::string HexDump(const unsigned char *p,
+                    unsigned int len,
+                    unsigned int bytes_per_line = 16);
+std::string HexDump(const char *p,
+                    unsigned int len,
+                    unsigned int bytes_per_line = 16);
+
+
+
+/// interface for NML escape code handlers
+class NMLEscapeCodeHandler
+{
+ public:
+  virtual bool Convert(std::string & dest,
+                       const std::string & src) const = 0;
+  virtual ~NMLEscapeCodeHandler() {}
+};
+
+
+/// handle NML escape codes by removing them
+class RemoveNMLEscapeSequences : public NMLEscapeCodeHandler
+{
+ public:
+  RemoveNMLEscapeSequences();
+  virtual ~RemoveNMLEscapeSequences();
+
+  bool Convert(std::string & dest,
+               const std::string & src) const;
+};
+
+
+/// handle NML escape codes by converting them to HTML codes
+class NMLEscapeSequences2HTML : public NMLEscapeCodeHandler
+{
+ public:
+  NMLEscapeSequences2HTML();
+  virtual ~NMLEscapeSequences2HTML();
+
+  bool Convert(std::string & dest,
+               const std::string & src) const;
+};
+
+
+
+/// NML (news markup language for Journaline)
+class NML
+{
+  friend class NMLFactory;
+
+ public:
+  //-------------------- constants --------------------
+  static const unsigned int NML_MAX_LEN;
+  static const unsigned int NML_MAX_NR_OF_LEVELS;
+  static const unsigned int NML_MAX_NR_OF_MENU_ITEMS;
+  static const unsigned int MAX_NR_OF_WATCHES;
+  static const unsigned int NML_MIN_NR_OF_ITEM_BYTES;
+  static const unsigned int NML_NR_OF_HEADER_BYTES;
+  static const unsigned short ROOT_OBJECT_ID;
+  static const char *ObjectTypeString[];
+
+  //-------------------- types ------------------------
+
+  /// NML object types
+  typedef enum {INVALID, MENU, PLAIN, TITLE, LIST} object_type_t;
+
+  /// NML object id
+  typedef unsigned short NewsObjectId_t;
+
+  /// NML raw news object
+  typedef struct
+  {
+    unsigned short nml_len;             ///< total length of NML data
+    unsigned short extended_header_len; ///< length of ext. NML header
+    unsigned char nml[4096];            ///< NML data
+  } RawNewsObject_t;
+
+  /// NML list or menu item
+  typedef struct
+  {
+    std::string text;       ///< used for lists and menus
+    unsigned short link_id; ///< only used for Menus
+    bool link_id_available; ///< only used for Menus
+  } Item_t;
+
+  /// parsed NML news object
+  typedef struct
+  {
+    NewsObjectId_t object_id;     ///< NML object id
+    object_type_t object_type;    ///< NML object type
+    bool static_flag;             ///< static flag
+    unsigned char revision_index; ///< revision index
+    std::string extended_header;  ///< extended header bytes (unparsed)
+    std::string title;            ///< parsed title string
+    std::vector<Item_t> item;     ///< items of list or menu object
+  } News_t;
+
+  //-------------------- lifetime --------------------
+  NML();
+  NML(const NML & prototype);
+  ~NML();
+
+  //-------------------- operators --------------------
+  const NML & operator=(const NML & prototype);
+  bool operator==(const NML & prototype) const;
+  std::ostream & operator<<(std::ostream & os) const;
+
+  //-------------------- inquiry methods --------------
+  std::string Dump(void) const;
+
+  /// check whether NML object is valid
+  /// @retval false iff fake news object (error message)
+  inline bool           isValid(void) const
+  {
+    return _valid;
+  }
+
+  /// check whether NML object is the root object
+  /// @retval true if object is the root object
+  inline bool           isRootObject(void) const
+  {
+    return (GetObjectId()==ROOT_OBJECT_ID);
+  }
+
+  /// check whether NML object is a menu
+  /// @retval true if object is a menu object
+  inline bool           isMenu(void) const
+  {
+    return (GetObjectType()==MENU);
+  }
+
+  /// check whether NML object is static
+  /// @retval true if object is static
+  inline bool           isStatic(void) const
+  {
+    return _news.static_flag;
+  }
+
+  /// NML object type
+  /// @return object type
+  inline object_type_t  GetObjectType(void) const
+  {
+    return _news.object_type;
+  }
+
+  /// NML object type string
+  /// @return object type as string
+  inline const char *GetObjectTypeString(void) const
+  {
+    if (_news.object_type<=LIST)
+    {
+      return NML::ObjectTypeString[_news.object_type];
+    }
+    else
+    {
+      return "illegal";
+    }
+  }
+
+  /// NML object id
+  /// @return object id
+  inline NewsObjectId_t GetObjectId(void) const
+  {
+    return _news.object_id;
+  }
+
+  /// NML revision index
+  /// @return revision index
+  inline unsigned char  GetRevisionIndex(void) const
+  {
+    return _news.revision_index;
+  }
+  
+  /// NML extended header
+  /// @return extended header as string
+  inline std::string    GetExtendedHeader(void) const
+  {
+    return _news.extended_header;
+  }
+
+  /// title of NML object
+  /// @return title in UTF8-Coding
+  inline std::string    GetTitle(void) const
+  {
+    return _news.title;
+  }
+
+  /// number of items contained in NML object
+  /// @return number of items for lists and menus, 0 otherwise
+  inline unsigned int   GetNrOfItems(void) const
+  {
+    return _news.item.size();
+  }
+
+  /// vector of items contained in NML object
+  /// @return items for lists and menus, empty otherwise
+  inline const std::vector<Item_t> & GetItems(void) const
+  {
+    return _news.item;
+  }
+
+  /// get specified item contained in NML object
+  /// @return item text of i-th item
+  inline std::string     GetItemText(unsigned int i) const
+  {
+    return (i<GetNrOfItems())?_news.item[i].text:""; 
+  }
+
+  /// get specified link id contained in NML menu.
+  /// Will only have a useful value if
+  /// - the NML object is a menu
+  /// - the index is not out of range
+  /// @return link id of i-th menu item
+  inline NewsObjectId_t  GetLinkId(unsigned int i) const
+  {
+    if (i>=GetNrOfItems()) return 0x0815;
+    return _news.item[i].link_id;
+  }
+
+  /// check availability of a depending link id
+  /// @param i  index of item in menu
+  /// @retval true iff item's link id is available
+  inline bool            isLinkIdAvailable(unsigned int i) const
+  {
+    return (i<GetNrOfItems()) ? _news.item[i].link_id_available : false;
+  }
+
+  //-------------------- modifier methods -------------
+
+  /// set object id
+  /// @param oid object id
+  inline void SetObjectId(NewsObjectId_t oid)
+  {
+    _news.object_id = oid;
+  }
+
+  /// set i-th linked object id (in a menu) availability flag
+  /// @param i index
+  /// @param f new availability value
+  inline void SetLinkAvailability(unsigned int i, bool f)
+  {
+    if (isMenu() && (i<GetNrOfItems()))
+      _news.item[i].link_id_available = f;
+  }
+
+  void SetError(NewsObjectId_t oid, const char *title);
+  void SetErrorDump(NewsObjectId_t oid,
+                    const RawNewsObject_t & rno,
+                    const char *error_msg);
+
+ private:
+  bool _valid;
+  News_t _news;
+  NMLEscapeCodeHandler *_EscapeCodeHandler;
+};
+
+bool operator==(const NML::Item_t &, const NML::Item_t &);
+std::string DumpRaw(const NML::RawNewsObject_t & rno);
+
+
+
+// factory class for NML objects
+class NMLFactory
+{
+ public:
+  static NMLFactory *Instance(void);
+  static void ExitInstance(void);
+
+  NML *CreateNML(const NML::RawNewsObject_t & rno,
+                 const NMLEscapeCodeHandler *EscapeCodeHandler);
+  NML *CreateError(NML::NewsObjectId_t oid,
+                   const char *title);
+  NML *CreateErrorDump(NML::NewsObjectId_t oid,
+                       const NML::RawNewsObject_t & rno,
+                       const char *error_msg);
+
+ private:
+  static NMLFactory *_instance;
+  NMLFactory();
+  ~NMLFactory();
+  NMLFactory & operator=(const NMLFactory &);
+  NMLFactory(const NMLFactory &);
+  unsigned char* getNextSection( const unsigned char*& p, unsigned short& plen, unsigned short& reslen );
+
+};
+
+
+#endif
diff --git a/src/datadecoding/journaline/Splitter.cpp b/src/datadecoding/journaline/Splitter.cpp
new file mode 100644
index 0000000..caddc5d
--- /dev/null
+++ b/src/datadecoding/journaline/Splitter.cpp
@@ -0,0 +1,141 @@
+/* 
+ *
+ * This file is part of the 'NewsService Journaline(R) Decoder'
+ * 
+ * Copyright (c) 2003, 2001-2014 by Fraunhofer IIS, Erlangen, Germany
+ * 
+ * --------------------------------------------------------------------
+ * 
+ * For NON-COMMERCIAL USE,
+ * the 'NewsService Journaline(R) Decoder' is free software;
+ * you can redistribute it and/or modify it under the terms of
+ * the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * The 'NewsService Journaline(R) Decoder' is distributed in the hope
+ * that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with the 'NewsService Journaline(R) Decoder';
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ * 
+ * If you use this software in a project with user interaction, please
+ * provide the following text to the user in an appropriate place:
+ * "Features NewsService Journaline(R) decoder technology by
+ * Fraunhofer IIS, Erlangen, Germany.
+ * For more information visit http://www.iis.fhg.de/dab"
+ * 
+ * --------------------------------------------------------------------
+ * 
+ * To use the 'NewsService Journaline(R) Decoder' software for
+ * COMMERCIAL purposes, please contact Fraunhofer IIS for a
+ * commercial license (see below for contact information)!
+ * 
+ * --------------------------------------------------------------------
+ * 
+ * Contact:
+ *   Fraunhofer IIS, Department 'Broadcast Applications'
+ *   Am Wolfsmantel 33, 91058 Erlangen, Germany
+ *   http://www.iis.fraunhofer.de/dab
+ *   mailto:bc-info at iis.fraunhofer.de
+ * 
+ */
+
+//////////////////////////////////////////////////////////////////////////////
+/// different string splitting routines
+///
+/// @file       Splitter.cpp
+/// @author     Michael Reichenb�cher <rbr at iis.fraunhofer.de>
+///
+/// $Id: Splitter.cpp,v 1.2 2008/12/26 17:18:08 jcable Exp $
+///
+/// Module:     Journaline(R)
+///
+/// Copyright:  (C) 2003-2001-2014 by Fraunhofer IIS-A, IT-Services, Erlangen
+///
+/// Compiler:   gcc version 3.3 20030226 (prerelease)
+///             Microsoft Visual C++ .NET
+///
+//////////////////////////////////////////////////////////////////////////////
+
+#include "Splitter.h"
+
+
+Splitter::Splitter()
+{
+  SetLineBreakCharacter('\n');
+}
+
+
+Splitter::~Splitter()
+{
+}
+
+
+/// @brief set line break character for Split
+/// sets the LineBreakCharacter used by the Split
+/// method
+/// @param lbc  line break character
+/// @return     always returns true
+bool Splitter::SetLineBreakCharacter(char lbc)
+{
+  if (lbc==0) return false;
+  _LineBreak = lbc;
+  return true;
+}
+
+
+/// @brief split a string into a vector of lines
+/// splits a string consisting of several lines
+/// (seperated by the LineBreakCharacter) into
+/// an array containing the lines
+/// (excluding the LineBreakCharacter)
+/// @attention
+///   An empty string will split into an array
+///   consisting of only the empty string
+/// @param dest  vector of lines
+/// @param src   source string
+/// @return      always returns true
+bool Splitter::Split(std::vector<std::string> & dest,
+                     const std::string & src) const
+{
+  std::string::size_type left, right;
+  dest.clear();
+
+  if (src.size()==0)
+  {
+    dest.push_back("");
+    return true;
+  }
+
+  for (left=0,right=0;;)
+  {
+    // search first non-delimiter
+    left = src.find_first_not_of(_LineBreak, right);
+    if (left==std::string::npos)
+    {
+      // rest of the string are delimiters
+      //dest.push_back("");
+      break;
+    }
+    // search first delimiter after series of non-delimiters
+    // => right>left (or right=npos!)
+    right = src.find_first_of(_LineBreak, left);
+    if (right==std::string::npos)
+    {
+      // rest of the string are non-delimiters
+      dest.push_back(src.substr(left));
+      break;
+    }
+    // substring src[left,right[ are non-delimiters
+    dest.push_back(src.substr(left, right - left));
+  }
+
+  return true;
+}
diff --git a/src/datadecoding/journaline/Splitter.h b/src/datadecoding/journaline/Splitter.h
new file mode 100644
index 0000000..51b88fc
--- /dev/null
+++ b/src/datadecoding/journaline/Splitter.h
@@ -0,0 +1,114 @@
+/* 
+ *
+ * This file is part of the 'NewsService Journaline(R) Decoder'
+ * 
+ * Copyright (c) 2003, 2001-2014 by Fraunhofer IIS, Erlangen, Germany
+ * 
+ * --------------------------------------------------------------------
+ * 
+ * For NON-COMMERCIAL USE,
+ * the 'NewsService Journaline(R) Decoder' is free software;
+ * you can redistribute it and/or modify it under the terms of
+ * the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * The 'NewsService Journaline(R) Decoder' is distributed in the hope
+ * that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with the 'NewsService Journaline(R) Decoder';
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ * 
+ * If you use this software in a project with user interaction, please
+ * provide the following text to the user in an appropriate place:
+ * "Features NewsService Journaline(R) decoder technology by
+ * Fraunhofer IIS, Erlangen, Germany.
+ * For more information visit http://www.iis.fhg.de/dab"
+ * 
+ * --------------------------------------------------------------------
+ * 
+ * To use the 'NewsService Journaline(R) Decoder' software for
+ * COMMERCIAL purposes, please contact Fraunhofer IIS for a
+ * commercial license (see below for contact information)!
+ * 
+ * --------------------------------------------------------------------
+ * 
+ * Contact:
+ *   Fraunhofer IIS, Department 'Broadcast Applications'
+ *   Am Wolfsmantel 33, 91058 Erlangen, Germany
+ *   http://www.iis.fraunhofer.de/dab
+ *   mailto:bc-info at iis.fraunhofer.de
+ * 
+ */
+
+//////////////////////////////////////////////////////////////////////////////
+/// different string splitting routines
+///
+/// @file       Splitter.h
+/// @author     Michael Reichenb�cher <rbr at iis.fraunhofer.de>
+///
+/// $Id: Splitter.h,v 1.3 2008/12/26 20:04:53 jcable Exp $
+///
+/// Module:     Journaline(R)
+///
+/// Copyright:  (C) 2003-2001-2014 by Fraunhofer IIS-A, IT-Services, Erlangen
+///
+/// Compiler:   gcc version 3.3 20030226 (prerelease)
+///             Microsoft Visual C++ .NET
+///
+//////////////////////////////////////////////////////////////////////////////
+
+
+#ifndef _SPLITTER_H_
+#define _SPLITTER_H_
+
+#ifdef _MSC_VER
+#pragma warning(push,3)
+#pragma warning(disable:4514)
+#pragma warning(disable:4786)
+#endif
+
+#include <string>
+#include <vector>
+
+#ifdef _MSC_VER
+#pragma warning(pop)
+#pragma warning(disable:4786)
+#pragma warning(disable:4514)
+#endif
+
+
+
+/// interface for string splitting routines
+class StringSplitter
+{
+ public:
+  virtual bool Split(std::vector<std::string> & dest,
+                     const std::string & src) const = 0;
+  virtual ~StringSplitter() {}
+};
+
+
+/// line splitter algorithm
+class Splitter : public StringSplitter
+{
+ public:
+  Splitter();
+  virtual ~Splitter();
+
+  virtual bool SetLineBreakCharacter(char lbc);
+  virtual bool Split(std::vector<std::string> & dest,
+                     const std::string & src) const;
+ private:
+  char _LineBreak;
+};
+
+
+#endif
+
diff --git a/src/datadecoding/journaline/cpplog.h b/src/datadecoding/journaline/cpplog.h
new file mode 100644
index 0000000..8103233
--- /dev/null
+++ b/src/datadecoding/journaline/cpplog.h
@@ -0,0 +1,74 @@
+/* 
+ *
+ * This file is part of the 'NewsService Journaline(R) Decoder'
+ * 
+ * Copyright (c) 2003, 2001-2014 by Fraunhofer IIS, Erlangen, Germany
+ * 
+ * --------------------------------------------------------------------
+ * 
+ * For NON-COMMERCIAL USE,
+ * the 'NewsService Journaline(R) Decoder' is free software;
+ * you can redistribute it and/or modify it under the terms of
+ * the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * The 'NewsService Journaline(R) Decoder' is distributed in the hope
+ * that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with the 'NewsService Journaline(R) Decoder';
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ * 
+ * If you use this software in a project with user interaction, please
+ * provide the following text to the user in an appropriate place:
+ * "Features NewsService Journaline(R) decoder technology by
+ * Fraunhofer IIS, Erlangen, Germany.
+ * For more information visit http://www.iis.fhg.de/dab"
+ * 
+ * --------------------------------------------------------------------
+ * 
+ * To use the 'NewsService Journaline(R) Decoder' software for
+ * COMMERCIAL purposes, please contact Fraunhofer IIS for a
+ * commercial license (see below for contact information)!
+ * 
+ * --------------------------------------------------------------------
+ * 
+ * Contact:
+ *   Fraunhofer IIS, Department 'Broadcast Applications'
+ *   Am Wolfsmantel 33, 91058 Erlangen, Germany
+ *   http://www.iis.fraunhofer.de/dab
+ *   mailto:bc-info at iis.fraunhofer.de
+ * 
+ */
+
+#ifndef __CPP_LOG__
+#define __CPP_LOG__
+
+#ifdef _MSC_VER
+#pragma warning(push,3)
+#pragma warning(disable:4514)
+#endif
+
+#include <iostream>
+
+#ifdef _MSC_VER
+#pragma warning(pop)
+#pragma warning(disable:4514)
+#endif
+
+
+#define log_err  { std::cerr << __FILE__ << ":" << __LINE__ << ": "
+#define log_err_api  { std::cerr << __FILE__ << ":" << __LINE__ << ": "
+#define log_warn { std::cerr << __FILE__ << ":" << __LINE__ << ": "
+#define log_info { std::cout << __FILE__ << ":" << __LINE__ << ": "
+#define log_info_nots { std::cout << __FILE__ << ":" << __LINE__ << ": "
+#define endmsg std::endl; }
+
+
+#endif
diff --git a/src/datadecoding/journaline/crc_8_16.c b/src/datadecoding/journaline/crc_8_16.c
new file mode 100644
index 0000000..13de37b
--- /dev/null
+++ b/src/datadecoding/journaline/crc_8_16.c
@@ -0,0 +1,403 @@
+/* 
+ *
+ * This file is part of the 'NewsService Journaline(R) Decoder'
+ * 
+ * Copyright (c) 2003, 2001-2014 by Fraunhofer IIS, Erlangen, Germany
+ * 
+ * --------------------------------------------------------------------
+ * 
+ * For NON-COMMERCIAL USE,
+ * the 'NewsService Journaline(R) Decoder' is free software;
+ * you can redistribute it and/or modify it under the terms of
+ * the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * The 'NewsService Journaline(R) Decoder' is distributed in the hope
+ * that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with the 'NewsService Journaline(R) Decoder';
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ * 
+ * If you use this software in a project with user interaction, please
+ * provide the following text to the user in an appropriate place:
+ * "Features NewsService Journaline(R) decoder technology by
+ * Fraunhofer IIS, Erlangen, Germany.
+ * For more information visit http://www.iis.fhg.de/dab"
+ * 
+ * --------------------------------------------------------------------
+ * 
+ * To use the 'NewsService Journaline(R) Decoder' software for
+ * COMMERCIAL purposes, please contact Fraunhofer IIS for a
+ * commercial license (see below for contact information)!
+ * 
+ * --------------------------------------------------------------------
+ * 
+ * Contact:
+ *   Fraunhofer IIS, Department 'Broadcast Applications'
+ *   Am Wolfsmantel 33, 91058 Erlangen, Germany
+ *   http://www.iis.fraunhofer.de/dab
+ *   mailto:bc-info at iis.fraunhofer.de
+ * 
+ */
+
+/*!
+ * @file crc_8_16.c
+ * @brief CRC calculation
+ *
+ * functions for calculating and checking 8bit or 16bit
+ * CRC (cyclic redundancy check) checksums.
+ * 
+ * For 8 bit CRC calculation, the polynomial used is
+ * \f$ x^8+x^4+x^3+x^2+1 \f$
+ *
+ * For 16 bit CRC calculations, the polynomial used is
+ * \f$ x^{16}+x^{12}+x^5+1 \f$
+ *
+ * $Id: crc_8_16.c,v 1.1 2008/12/17 17:15:54 jcable Exp $
+ *
+ * Author:      Monica Redon Segrera and Nuria Llombart Juan
+ *
+ * Copyright:  (C) 2003-2001-2014 by Fraunhofer IIS-A, IT-Services, Erlangen
+ *
+ * Created:     2001-02-01
+ *
+ * Version:     2001-2014-03-02
+ */
+
+#include "crc_8_16.h"
+
+/*! Global variable in which the CRC-16 table is stored */ 
+static const unsigned short CRC_Table_16[256] = {
+   0x0,   0x1021,   0x2042,   0x3063,   0x4084,   0x50A5,   0x60C6,   0x70E7,   
+0x8108,   0x9129,   0xA14A,   0xB16B,   0xC18C,   0xD1AD,   0xE1CE,   0xF1EF,   
+0x1231,    0x210,   0x3273,   0x2252,   0x52B5,   0x4294,   0x72F7,   0x62D6,   
+0x9339,   0x8318,   0xB37B,   0xA35A,   0xD3BD,   0xC39C,   0xF3FF,   0xE3DE,   
+0x2462,   0x3443,    0x420,   0x1401,   0x64E6,   0x74C7,   0x44A4,   0x5485,   
+0xA56A,   0xB54B,   0x8528,   0x9509,   0xE5EE,   0xF5CF,   0xC5AC,   0xD58D,   
+0x3653,   0x2672,   0x1611,    0x630,   0x76D7,   0x66F6,   0x5695,   0x46B4,   
+0xB75B,   0xA77A,   0x9719,   0x8738,   0xF7DF,   0xE7FE,   0xD79D,   0xC7BC,   
+0x48C4,   0x58E5,   0x6886,   0x78A7,    0x840,   0x1861,   0x2802,   0x3823,   
+0xC9CC,   0xD9ED,   0xE98E,   0xF9AF,   0x8948,   0x9969,   0xA90A,   0xB92B,   
+0x5AF5,   0x4AD4,   0x7AB7,   0x6A96,   0x1A71,    0xA50,   0x3A33,   0x2A12,   
+0xDBFD,   0xCBDC,   0xFBBF,   0xEB9E,   0x9B79,   0x8B58,   0xBB3B,   0xAB1A,   
+0x6CA6,   0x7C87,   0x4CE4,   0x5CC5,   0x2C22,   0x3C03,    0xC60,   0x1C41,   
+0xEDAE,   0xFD8F,   0xCDEC,   0xDDCD,   0xAD2A,   0xBD0B,   0x8D68,   0x9D49,   
+0x7E97,   0x6EB6,   0x5ED5,   0x4EF4,   0x3E13,   0x2E32,   0x1E51,   0xE70,   
+0xFF9F,   0xEFBE,   0xDFDD,   0xCFFC,   0xBF1B,   0xAF3A,   0x9F59,   0x8F78,   
+0x9188,   0x81A9,   0xB1CA,   0xA1EB,   0xD10C,   0xC12D,   0xF14E,   0xE16F,   
+0x1080,     0xA1,   0x30C2,   0x20E3,   0x5004,   0x4025,   0x7046,   0x6067,   
+0x83B9,   0x9398,   0xA3FB,   0xB3DA,   0xC33D,   0xD31C,   0xE37F,   0xF35E,   
+ 0x2B1,   0x1290,   0x22F3,   0x32D2,   0x4235,   0x5214,   0x6277,   0x7256,   
+0xB5EA,   0xA5CB,   0x95A8,   0x8589,   0xF56E,   0xE54F,   0xD52C,   0xC50D,   
+0x34E2,   0x24C3,   0x14A0,    0x481,   0x7466,   0x6447,   0x5424,   0x4405,   
+0xA7DB,   0xB7FA,   0x8799,   0x97B8,   0xE75F,   0xF77E,   0xC71D,   0xD73C,   
+0x26D3,   0x36F2,    0x691,   0x16B0,   0x6657,   0x7676,   0x4615,   0x5634,   
+0xD94C,   0xC96D,   0xF90E,   0xE92F,   0x99C8,   0x89E9,   0xB98A,   0xA9AB,   
+0x5844,   0x4865,   0x7806,   0x6827,   0x18C0,    0x8E1,   0x3882,   0x28A3,   
+0xCB7D,   0xDB5C,   0xEB3F,   0xFB1E,   0x8BF9,   0x9BD8,   0xABBB,   0xBB9A,   
+0x4A75,   0x5A54,   0x6A37,   0x7A16,    0xAF1,   0x1AD0,   0x2AB3,   0x3A92,   
+0xFD2E,   0xED0F,   0xDD6C,   0xCD4D,   0xBDAA,   0xAD8B,   0x9DE8,   0x8DC9,   
+0x7C26,   0x6C07,   0x5C64,   0x4C45,   0x3CA2,   0x2C83,   0x1CE0,    0xCC1,   
+0xEF1F,   0xFF3E,   0xCF5D,   0xDF7C,   0xAF9B,   0xBFBA,   0x8FD9,   0x9FF8,   
+0x6E17,   0x7E36,   0x4E55,   0x5E74,   0x2E93,   0x3EB2,    0xED1,   0x1EF0 
+};
+
+/*! Global variable in which the CRC-8 table is stored */ 
+static const unsigned char CRC_Table_8[256] = {
+ 0x0,   0x1D,   0x3A,   0x27,   0x74,   0x69,   0x4E,   0x53,   0xE8,   0xF5,   
+0xD2,   0xCF,   0x9C,   0x81,   0xA6,   0xBB,   0xCD,   0xD0,   0xF7,   0xEA,   
+0xB9,   0xA4,   0x83,   0x9E,   0x25,   0x38,   0x1F,    0x2,   0x51,   0x4C,   
+0x6B,   0x76,   0x87,   0x9A,   0xBD,   0xA0,   0xF3,   0xEE,   0xC9,   0xD4,   
+0x6F,   0x72,   0x55,   0x48,   0x1B,    0x6,   0x21,   0x3C,   0x4A,   0x57,   
+0x70,   0x6D,   0x3E,   0x23,    0x4,   0x19,   0xA2,   0xBF,   0x98,   0x85,   
+0xD6,   0xCB,   0xEC,   0xF1,   0x13,    0xE,   0x29,   0x34,   0x67,   0x7A,   
+0x5D,   0x40,   0xFB,   0xE6,   0xC1,   0xDC,   0x8F,   0x92,   0xB5,   0xA8,   
+0xDE,   0xC3,   0xE4,   0xF9,   0xAA,   0xB7,   0x90,   0x8D,   0x36,   0x2B,   
+ 0xC,   0x11,   0x42,   0x5F,   0x78,   0x65,   0x94,   0x89,   0xAE,   0xB3,   
+0xE0,   0xFD,   0xDA,   0xC7,   0x7C,   0x61,   0x46,   0x5B,    0x8,   0x15,   
+0x32,   0x2F,   0x59,   0x44,   0x63,   0x7E,   0x2D,   0x30,   0x17,    0xA,   
+0xB1,   0xAC,   0x8B,   0x96,   0xC5,   0xD8,   0xFF,   0xE2,   0x26,   0x3B,   
+0x1C,    0x1,   0x52,   0x4F,   0x68,   0x75,   0xCE,   0xD3,   0xF4,   0xE9,   
+0xBA,   0xA7,   0x80,   0x9D,   0xEB,   0xF6,   0xD1,   0xCC,   0x9F,   0x82,   
+0xA5,   0xB8,    0x3,   0x1E,   0x39,   0x24,   0x77,   0x6A,   0x4D,   0x50,   
+0xA1,   0xBC,   0x9B,   0x86,   0xD5,   0xC8,   0xEF,   0xF2,   0x49,   0x54,   
+0x73,   0x6E,   0x3D,   0x20,    0x7,   0x1A,   0x6C,   0x71,   0x56,   0x4B,   
+0x18,    0x5,   0x22,   0x3F,   0x84,   0x99,   0xBE,   0xA3,   0xF0,   0xED,   
+0xCA,   0xD7,   0x35,   0x28,    0xF,   0x12,   0x41,   0x5C,   0x7B,   0x66,   
+0xDD,   0xC0,   0xE7,   0xFA,   0xA9,   0xB4,   0x93,   0x8E,   0xF8,   0xE5,   
+0xC2,   0xDF,   0x8C,   0x91,   0xB6,   0xAB,   0x10,    0xD,   0x2A,   0x37,   
+0x64,   0x79,   0x5E,   0x43,   0xB2,   0xAF,   0x88,   0x95,   0xC6,   0xDB,   
+0xFC,   0xE1,   0x5A,   0x47,   0x60,   0x7D,   0x2E,   0x33,   0x14,    0x9,   
+0x7F,   0x62,   0x45,   0x58,    0xB,   0x16,   0x31,   0x2C,   0x97,   0x8A,   
+0xAD,   0xB0,   0xE3,   0xFE,   0xD9,   0xC4
+};
+
+
+/*!
+ * @brief create CRC-16 table
+ *
+ * creates the necessary table for being used in the 
+ * efficient calculation of the 16 bit CRC.
+ *
+ * @note
+ * this is obsolete - the CRC calculations are done with the
+ * (hardcoded) CRC_Table_16
+ *
+ * CreationDate: 2001-02-02
+ *
+ * Version:      2001-2014-03-02
+ *
+ * @param usCRC_Table
+ *   the table is returned into an array of length 256
+ */
+void CRC_Init_16(unsigned short usCRC_Table[])
+{
+  /* declare necessary variables: */
+  unsigned short i, c, c8_5, c15_12, c_mb, c_lb, c7_5, c7_4, c12_9, c15_13;
+
+  /* calculate the CRC-16 value for the input data i 
+     and the previous CRC-16 equal to zero */
+  for(i=0; i<256; i++)
+  {
+    /* shift the four most significant bits to different positions */
+    c_mb = (unsigned short) ((i & 0xf0) >> 4);
+    c7_4 = (unsigned short) (c_mb << 4);
+    c7_5 = (unsigned short) (c7_4 << 1);
+    c12_9 = (unsigned short) (c7_5 << 4);
+    c15_13 = (unsigned short) (c12_9 << 3);
+
+    /* shift the four least significant bits to different positions */
+    c_lb = (unsigned short) (i & 0x0f);
+    c8_5 = (unsigned short) (c_lb << 5);
+    c15_12 = (unsigned short) (c8_5 << 7);
+
+    /* calculate the CRC-16 value */
+    c = (unsigned short) ((c_mb^c_lb) & 0x000f);
+    c |= (c7_4^c8_5^c7_5) & 0x00f0;
+    c |= (c12_9^c8_5^c7_5) & 0x0f00;
+    c |= (c15_12^c15_13^c12_9) & 0xf000;
+
+    usCRC_Table[i] = c;
+  }
+}
+
+
+/*!
+ * @brief create CRC-8 table
+ *
+ * creates the necessary table for being used in the 
+ * efficient calculation of the 8 bit CRC
+ *
+ * @note
+ * this is obsolete - the CRC calculations are done with the
+ * (hardcoded) CRC_Table_8
+ *
+ * CreationDate: 2001-02-02
+ *
+ * Version:      2001-2014-03-02
+ *
+ * @param ucCRC_Table
+ *   the table is returned into an array of length 256
+ */
+void CRC_Init_8(unsigned char ucCRC_Table[])
+{
+    /* declare necessary variables: */
+  unsigned char c, c_mb, c7_4, c7_2, c7_3, c5_4, c_lb, c1_0a, c1_0, c2_0, 
+                c2a, c2, c3;
+  unsigned short i;
+
+    /* calculate the CRC-8 value for the input data i 
+       and the previous CRC-8 equal to zero */
+  for(i=0; i<256; i++)
+  {
+      /* shift the data to different positions */
+    c7_2 = (unsigned char) (i << 2);
+    c7_3 = (unsigned char) (c7_2 << 1);
+    c7_4 = (unsigned char) (c7_3 << 1);
+    c5_4 = (unsigned char) (i >> 2);
+
+      /* shift the four most significant bits to different positions */
+    c_mb = (unsigned char) ((i & 0xf0) >> 4);
+    c1_0a = (unsigned char) (c_mb & 0x03);
+    c3 = (unsigned char) (c1_0a << 3);
+    c2a = (unsigned char) ((c1_0a << 2) & 0x04);
+    c2 = (unsigned char) ((c1_0a << 1) & 0x04);
+    c2_0 = (unsigned char) (c_mb >>1);
+    c1_0 = (unsigned char) (c2_0 >> 1);
+   
+      /* get the four least significant bits */
+    c_lb = (unsigned char) (i & 0x0f);
+
+      /* calculate the CRC-8 value */
+    c = (unsigned char) ((c_lb^c1_0a^c2_0^c1_0^c7_2^c7_3^c3^c2a^c2) & 0x0f);
+    c |= (c7_2^c7_3^c7_4^c5_4) & 0xf0;
+
+    ucCRC_Table[i] = c;
+  }
+}
+
+
+/*!
+ * @brief calculate CRC-16
+ *
+ * calculates the 16 bit CRC value of the provided data and
+ * returns it
+ *
+ * CreationDate: 2001-02-02
+ *
+ * Version:      2001-2014-03-02
+ *
+ * @param cDataPointer
+ *   pointer to the first data byte.
+ * @param iLength
+ *   size of the data in bytes
+ * @return
+ *   CRC-16 value
+ */
+unsigned short CRC_Build_16(const unsigned char *cDataPointer, 
+                            const unsigned long iLength)
+{
+  /* declare and initialize necessary variables: */
+  unsigned long l;
+  register unsigned short iData;
+  unsigned short iCRC_16=0xffff;
+
+  /* check for valid parameters: */
+  assert(iLength > 0);
+
+  /* calculate recursively the CRC-16, byte by byte of the data */
+  for(l=0; l<iLength; l++)
+  {
+    /* get the next data byte */
+    iData = (unsigned short) (*cDataPointer++ & 0xff);
+    /* calculate the table index with the data and the most significant
+       byte of the previous CRC-16 */
+    iData ^= ((iCRC_16 >> 8) & 0x00ff);
+    /* access to the table */
+    iData = *(CRC_Table_16 + iData);
+    /* calculate the new CRC-16 value with the table output and the
+       least significant byte of the previous CRC-16 */
+    iCRC_16 = (unsigned short) (iData ^ (iCRC_16 << 8));  
+  }
+
+  /* return the inverted CRC-16 value */
+  return((unsigned short) (iCRC_16 ^ 0xffff));
+}
+
+
+/*!
+ * @brief calculate 8 bit CRC
+ *
+ * calculates the 8 bit CRC value of the provided data and
+ * returns it
+ *
+ * CreationDate: 2001-02-02
+ *
+ * Version:      2001-2014-03-02
+ *
+ * @param cDataPointer
+ *   pointer to the first data byte.
+ * @param iLength
+ *   size of the data in bytes
+ * @return unsigned char with the CRC-8 value
+ */
+unsigned char CRC_Build_8(const unsigned char *cDataPointer, 
+                          const unsigned long iLength)
+{
+  /* declare and initialize necessary variables: */
+  unsigned long l;
+  register unsigned char cData=0;
+  unsigned char iCRC_8=0xff;
+
+  /* check for valid parameters: */
+  assert(iLength > 0);
+
+  /* calculate recursively the CRC-16, byte by byte of the data */
+  for(l=0; l<iLength; l++)
+  {
+    /* get the next data byte */
+    cData = *cDataPointer++;
+    /* calculate the new CRC-8 value by accessing to the table with 
+       the data and the previuos CRC-8 */
+    iCRC_8 = *(CRC_Table_8 + (iCRC_8 ^ cData));
+  }
+
+  /* return the inverted CRC-8 value */
+  return((unsigned char) (iCRC_8 ^ 0xff));
+}
+  
+
+/*!
+ * @brief check whether data matches CRC-16
+ *
+ * compares the 16 bit CRC value of the provided data
+ * to the provided 16 bit value
+ *
+ * CreationDate: 2001-02-02
+ *
+ * Version:      2001-2014-03-02
+ *
+ * @param cDataPointer
+ *   pointer to the first data byte.
+ * @param  iLength
+ *   size of the data in bytes
+ * @param iCRC_16
+ *   received CRC-16 value
+ * @retval 1  There are no errors
+ * @retval 0  The received CRC-16 is different to the CRC-16
+ *            calculated in the receiver.
+ */
+char CRC_Check_16(const unsigned char *cDataPointer, 
+                  const unsigned long iLength, 
+                  const unsigned short iCRC_16)
+{
+  unsigned short iReceiverCRC;
+  
+  /* calculate the CRC-16 value with the received data */  
+  iReceiverCRC = CRC_Build_16(cDataPointer,iLength);
+
+  /* compare the two CRC-16 values */
+  return((char) (iCRC_16 == iReceiverCRC));
+}
+ 
+
+/*!
+ * @brief check whether data matches CRC-8
+ *
+ * compares the 8 bit CRC value of the provided data
+ * to the provided 8 bit value
+ *
+ * CreationDate: 2001-02-02
+ *
+ * Version:      2001-2014-03-02
+ *
+ * @param cDataPointer
+ *   pointer to the first data byte.
+ * @param iLength
+ *   size of the data in bytes
+ * @param iCRC_8
+ *   received CRC-8 value
+ * @retval 1  There are no errors
+ * @retval 0  The received CRC-8 is different to the CRC-8
+ *            calculated in the receiver.
+ */
+char CRC_Check_8(const unsigned char *cDataPointer, 
+                 const unsigned long iLength, 
+                 const unsigned char iCRC_8)
+{
+  unsigned char iReceiverCRC;
+
+  /* calculate the CRC-8 value with the received data */
+  iReceiverCRC = CRC_Build_8(cDataPointer,iLength);
+
+  /* compare the two CRC-8 values */   
+  return ((char) (iReceiverCRC == iCRC_8));
+} 
+
diff --git a/src/datadecoding/journaline/crc_8_16.h b/src/datadecoding/journaline/crc_8_16.h
new file mode 100644
index 0000000..5574bca
--- /dev/null
+++ b/src/datadecoding/journaline/crc_8_16.h
@@ -0,0 +1,100 @@
+/* 
+ *
+ * This file is part of the 'NewsService Journaline(R) Decoder'
+ * 
+ * Copyright (c) 2003, 2001-2014 by Fraunhofer IIS, Erlangen, Germany
+ * 
+ * --------------------------------------------------------------------
+ * 
+ * For NON-COMMERCIAL USE,
+ * the 'NewsService Journaline(R) Decoder' is free software;
+ * you can redistribute it and/or modify it under the terms of
+ * the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * The 'NewsService Journaline(R) Decoder' is distributed in the hope
+ * that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with the 'NewsService Journaline(R) Decoder';
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ * 
+ * If you use this software in a project with user interaction, please
+ * provide the following text to the user in an appropriate place:
+ * "Features NewsService Journaline(R) decoder technology by
+ * Fraunhofer IIS, Erlangen, Germany.
+ * For more information visit http://www.iis.fhg.de/dab"
+ * 
+ * --------------------------------------------------------------------
+ * 
+ * To use the 'NewsService Journaline(R) Decoder' software for
+ * COMMERCIAL purposes, please contact Fraunhofer IIS for a
+ * commercial license (see below for contact information)!
+ * 
+ * --------------------------------------------------------------------
+ * 
+ * Contact:
+ *   Fraunhofer IIS, Department 'Broadcast Applications'
+ *   Am Wolfsmantel 33, 91058 Erlangen, Germany
+ *   http://www.iis.fraunhofer.de/dab
+ *   mailto:bc-info at iis.fraunhofer.de
+ * 
+ */
+
+
+
+/*!
+ * @brief       CRC calculation
+ *
+ * functions for CRC calculation
+ *
+ * @file        crc_8_16.h
+ *
+ * $Id: crc_8_16.h,v 1.2 2008/12/26 17:18:08 jcable Exp $
+ *
+ * Author:      Monica Redon Segrera and Nuria Llombart Juan
+ *
+ * Copyright:  (C) 2003-2001-2014 by Fraunhofer IIS-A, IT-Services, Erlangen
+ *
+ * Created:     2001-01-02
+ *
+ * Version:     2001-2014-03-02
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+/* calculates the CRC-16 value */
+unsigned short CRC_Build_16(const unsigned char *cDataPointer, 
+                            const unsigned long iLength);
+
+/* calculates the CRC-8 value */
+unsigned char CRC_Build_8(const unsigned char *cDataPointer, 
+                          const unsigned long iLength);
+
+/* checks if there are errors in the received data */
+char CRC_Check_16(const unsigned char *cDataPointer, 
+                  const unsigned long iLength, 
+                  const unsigned short iCRC_16);
+
+/* checks if there are errors in the received data */
+char CRC_Check_8(const unsigned char *cDataPointer, 
+                 const unsigned long iLength,
+                 const unsigned char iCRC_8);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
diff --git a/src/datadecoding/journaline/dabdatagroupdecoder.h b/src/datadecoding/journaline/dabdatagroupdecoder.h
new file mode 100644
index 0000000..6abe13e
--- /dev/null
+++ b/src/datadecoding/journaline/dabdatagroupdecoder.h
@@ -0,0 +1,218 @@
+/* 
+ *
+ * This file is part of the 'NewsService Journaline(R) Decoder'
+ * 
+ * Copyright (c) 2003, 2001-2014 by Fraunhofer IIS, Erlangen, Germany
+ * 
+ * --------------------------------------------------------------------
+ * 
+ * For NON-COMMERCIAL USE,
+ * the 'NewsService Journaline(R) Decoder' is free software;
+ * you can redistribute it and/or modify it under the terms of
+ * the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * The 'NewsService Journaline(R) Decoder' is distributed in the hope
+ * that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with the 'NewsService Journaline(R) Decoder';
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ * 
+ * If you use this software in a project with user interaction, please
+ * provide the following text to the user in an appropriate place:
+ * "Features NewsService Journaline(R) decoder technology by
+ * Fraunhofer IIS, Erlangen, Germany.
+ * For more information visit http://www.iis.fhg.de/dab"
+ * 
+ * --------------------------------------------------------------------
+ * 
+ * To use the 'NewsService Journaline(R) Decoder' software for
+ * COMMERCIAL purposes, please contact Fraunhofer IIS for a
+ * commercial license (see below for contact information)!
+ * 
+ * --------------------------------------------------------------------
+ * 
+ * Contact:
+ *   Fraunhofer IIS, Department 'Broadcast Applications'
+ *   Am Wolfsmantel 33, 91058 Erlangen, Germany
+ *   http://www.iis.fraunhofer.de/dab
+ *   mailto:bc-info at iis.fraunhofer.de
+ * 
+ */
+
+#ifndef __DAB_DATAGROUP_DECODER__
+#define __DAB_DATAGROUP_DECODER__
+
+/*!
+ * @brief Journaline(R) news service DAB data group decoder interface
+ *
+ * @file dabdatagroupdecoder.h
+ *
+ * 			techidee GmbH
+ *
+ * Project:   NewsBox
+ *
+ * Author:    Thomas Fruehwald
+ *
+ * Compiler:	gcc
+ *
+ * Module:    DAB data group decoder
+ *
+ * Creation date:  2003-08-02
+ *
+ * Last modified:  2001-2014-02-25 (rbr)
+ *
+ * This decoder will accept DAB data groups, check their validity and
+ * pass on the valid (Journaline) data groups.
+ *
+ * To use it, you have to implement the callback for handling
+ * the output in your application.
+ * Then use createDec to create an instance,
+ * putData to put DAB data groups into the decoder
+ * and in the end, use deleteDec to destroy the instance.
+ *
+ * @attention
+ * only the features needed for the news service "Journaline(R)"
+ * are implemented in this DAB data group decoder, i.e.
+ * - extension_flag=0 (no extension field will be processed)
+ * - crc_flag=1 (Journaline data groups always have a CRC)
+ * - segment_flag=0 (Journaline data groups are never segmented)
+ * - user_access_flag=0 (no user access field will be processed)
+ * - data_group_type=0 (only "general data" data groups are processed)
+ *
+ * @attention
+ * The DAB data group decoder is not thread safe.
+ * 
+ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*! @brief dab data group decoder instance type */
+typedef const void*  DAB_DATAGROUP_DECODER_t;
+
+/*!
+  @brief MSC data group header
+  @sa ETSI EN 300 401 V1.3.3 (2001-05) section 5.3.3.1
+*/
+typedef struct
+{
+  unsigned char  extension_flag;    /*!< extension flag (1 bit) */
+  unsigned char  crc_flag;          /*!< CRC flag (1 bit) */
+  unsigned char  segment_flag;      /*!< segment flag (1 bit) */
+  unsigned char  user_access_flag;  /*!< user access flag (1 bit) */
+  unsigned char  datagroup_type;    /*!< data group type (4 bit) */
+  unsigned char  continuity_index;  /*!< continuity index (4 bit) */
+  unsigned char  repetition_index;  /*!< repitition index (4 bit) */
+  unsigned short extension_field;   /*!< extension field (16 bit), only
+                                         present when extension flag is 1 */
+} DAB_DATAGROUP_DECODER_msc_datagroup_header_t;
+
+
+/*!
+ * @brief DAB data group callback function
+ *
+ * A callback function of this type must be registered at creation time
+ * of the DAB data group decoder instance.
+ *
+ * It will be called whenever a DAB data group
+ * fed into the decoder using DAB_DATAGROUP_DECODER_putData
+ * has been processed successfully, i.e. it is a valid
+ * (Journaline specific) data group and can fed into the news service
+ * decoder.
+ *
+ * @param header
+ *   MSC data group header
+ * @param len
+ *   length in bytes of MSC data group data field
+ * @param buf
+ *   MSC data group data field
+ * @param arg
+ *   user specified data pointer (as specified in createDec)
+ */
+typedef void(DAB_DATAGROUP_DECODER_data)
+  (  
+    const DAB_DATAGROUP_DECODER_msc_datagroup_header_t *header,
+    const unsigned long len,
+    const unsigned char *buf,
+    void *arg
+  );
+
+
+
+/*******************************************
+ * 1. object lifetime control              *
+ *******************************************/
+
+/*!
+ * @brief Create a DAB data group decoder instance
+ *
+ * call this before anything else
+ *
+ * @param data
+ *   DAB data group decoder callback function
+ * @param arg
+ *   user specified data pointer (will only be passed to callback)
+ * @return DAB data group decoder instance
+ */
+DAB_DATAGROUP_DECODER_t DAB_DATAGROUP_DECODER_createDec(
+  DAB_DATAGROUP_DECODER_data *data,
+  void  *arg
+  );  
+
+
+/*!
+ * @brief Delete a DAB data group decoder instance
+ *
+ * call this at shutdown time
+ *
+ * @param decoder
+ *   DAB data group decoder instance
+ */
+void DAB_DATAGROUP_DECODER_deleteDec(const DAB_DATAGROUP_DECODER_t decoder);
+
+
+
+/*******************************************
+ * 2. data provision                       *
+ *******************************************/
+
+/*!
+ * @brief Put data into DAB data group decoder
+ * 
+ * The input for the DAB data group decoder consists of
+ * complete DAB data groups.
+ * 
+ * A CRC check is done if the CRC flag is set in the
+ * data group header.
+ *
+ * @param decoder
+ *   DAB data group decoder instance
+ *   (as obtained by DAB_DATAGROUP_DECODER_createDec)
+ * @param len
+ *   length in bytes of MSC data group
+ * @param buf
+ *   DAB data group
+ *
+ * @retval 0  on failure
+ * @retval 1  on success
+ */
+unsigned long DAB_DATAGROUP_DECODER_putData(
+  const DAB_DATAGROUP_DECODER_t  decoder,
+  const unsigned long  len,
+  const unsigned char *buf
+  );
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __DAB_DATAGROUP_DECODER__ */
diff --git a/src/datadecoding/journaline/dabdgdec_impl.c b/src/datadecoding/journaline/dabdgdec_impl.c
new file mode 100644
index 0000000..b99f92f
--- /dev/null
+++ b/src/datadecoding/journaline/dabdgdec_impl.c
@@ -0,0 +1,320 @@
+/* 
+ *
+ * This file is part of the 'NewsService Journaline(R) Decoder'
+ * 
+ * Copyright (c) 2003, 2001-2014 by Fraunhofer IIS, Erlangen, Germany
+ * 
+ * --------------------------------------------------------------------
+ * 
+ * For NON-COMMERCIAL USE,
+ * the 'NewsService Journaline(R) Decoder' is free software;
+ * you can redistribute it and/or modify it under the terms of
+ * the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * The 'NewsService Journaline(R) Decoder' is distributed in the hope
+ * that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with the 'NewsService Journaline(R) Decoder';
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ * 
+ * If you use this software in a project with user interaction, please
+ * provide the following text to the user in an appropriate place:
+ * "Features NewsService Journaline(R) decoder technology by
+ * Fraunhofer IIS, Erlangen, Germany.
+ * For more information visit http://www.iis.fhg.de/dab"
+ * 
+ * --------------------------------------------------------------------
+ * 
+ * To use the 'NewsService Journaline(R) Decoder' software for
+ * COMMERCIAL purposes, please contact Fraunhofer IIS for a
+ * commercial license (see below for contact information)!
+ * 
+ * --------------------------------------------------------------------
+ * 
+ * Contact:
+ *   Fraunhofer IIS, Department 'Broadcast Applications'
+ *   Am Wolfsmantel 33, 91058 Erlangen, Germany
+ *   http://www.iis.fraunhofer.de/dab
+ *   mailto:bc-info at iis.fraunhofer.de
+ * 
+ */
+
+/**
+*** 			techidee GmbH
+*** Projekt:	NewsBox
+*** Autor:		Thomas Fruehwald
+***
+*** Compiler:	gcc
+*** Modul:
+		dab datagroup decoder implementation
+***
+***
+**/
+#ifdef _MSC_VER
+# include <malloc.h>
+# include <memory.h>
+#else
+# include <stdlib.h>
+#endif
+
+#include "dabdatagroupdecoder.h"
+#include "dabdgdec_impl.h"
+#include "log.h"
+#include "crc_8_16.h"
+
+#ifdef __cplusplus
+extern "C"
+#endif
+
+int showDdDabDgDecInfo;
+int showDdDabDgDecErr;
+
+DAB_DATAGROUP_DECODER_t DAB_DATAGROUP_DECODER_createDec(
+	DAB_DATAGROUP_DECODER_data *data,
+	void	*arg
+	)
+{
+	DAB_DGDEC_IMPL_t *dec=(DAB_DGDEC_IMPL_t*)malloc(
+		sizeof(DAB_DGDEC_IMPL_t));
+	if(dec==0)
+	{
+		if(showDdDabDgDecErr)
+		{
+			logit(LOG_ERR, "out of memory requesting %d bytes",
+				sizeof(*dec));
+		}
+		return 0;
+	}
+
+	dec->magicId=DAB_DGDEC_MAGIC_ID;
+	dec->cb=data;
+	dec->arg=arg;
+	return (const DAB_DATAGROUP_DECODER_t)dec;
+}
+
+#ifdef __cplusplus
+extern "C"
+#endif
+void DAB_DATAGROUP_DECODER_deleteDec
+	(const DAB_DATAGROUP_DECODER_t decoder)
+{
+	DAB_DGDEC_IMPL_t *dec=(DAB_DGDEC_IMPL_t*)decoder;
+	if(dec==0)
+	{
+		if(showDdDabDgDecErr)
+		{
+			logit(LOG_ERR, "invalid parameter");
+		}
+		return;
+	}
+
+	if(dec->magicId!=DAB_DGDEC_MAGIC_ID)
+	{
+		if(showDdDabDgDecErr)
+		{
+			logit(LOG_ERR, "invalid parameter: not a datagroup decoder");
+		}
+		return;
+	}
+
+	free(dec);
+}
+
+#ifdef __cplusplus
+extern "C"
+#endif
+unsigned long DAB_DATAGROUP_DECODER_putData(
+		const DAB_DATAGROUP_DECODER_t	decoder,
+		const unsigned long	len,
+		const unsigned char *buf
+	)
+{
+	DAB_DGDEC_IMPL_t *dec=(DAB_DGDEC_IMPL_t*)decoder;
+
+	DAB_DATAGROUP_DECODER_msc_datagroup_header_t header;
+	unsigned long session_header_len=0;	/* we expect segment flag to be 0 */
+	unsigned long header_len;
+	const unsigned char *data_field;
+	unsigned long data_len;
+	unsigned short crc_field;
+	unsigned char c;
+ 
+
+#if 0
+	logit(LOG_ERR_DUMP, "data:", buf, len);
+#endif
+
+	if(dec->magicId!=DAB_DGDEC_MAGIC_ID)
+	{
+		if(showDdDabDgDecErr)
+		{
+			logit(LOG_ERR, "invalid parameter: not a datagroup decoder");
+		}
+		return 0;
+	}
+
+	if(!DAB_DGDEC_IMPL_extractMscDatagroupHeader(len, buf, &header))
+	{
+		if(showDdDabDgDecErr)
+		{
+			logit(LOG_ERR, "invalid datagroup header");
+		}
+		return 0;
+	}
+
+	if(showDdDabDgDecInfo)
+	{
+		DAB_DGDEC_IMPL_showMscDatagroupHeader(&header);
+	}
+
+	if(header.segment_flag)
+	{
+		if(showDdDabDgDecErr)
+		{
+			logit(LOG_ERR, "decoder does not work with segement_flag");
+		}
+		return 0;
+	}
+
+	header_len=2+header.extension_flag*2+session_header_len;
+	data_field=buf+header_len;
+	data_len=len-header_len;
+
+	if(data_len==0)
+	{
+		if(showDdDabDgDecErr)
+		{
+			logit(LOG_ERR, "length of datafield is zero!!!");
+		}
+		return 0;
+	}
+
+	if(header.crc_flag)
+	{
+		if(data_len<2)
+		{
+			if(showDdDabDgDecErr)
+			{
+				logit(LOG_ERR, "length of datafield is wrong!!!");
+			}
+			return 0;
+		}
+		data_len-=2;
+
+		c=buf[len-2];
+		crc_field=(unsigned short)(c<<8);
+		c=buf[len-1];
+		crc_field=(unsigned short)(crc_field+c);
+		if(!DAB_DGDEC_IMPL_checkCrc(buf, len-2, crc_field))
+		{
+			if(showDdDabDgDecErr)
+			{
+				logit(LOG_ERR, "crc error");
+			}
+			return 0;
+		}
+
+    if (header.datagroup_type!=0)
+    {
+			if(showDdDabDgDecInfo)
+			{
+				logit(LOG_INFO, "unexpected type %d", header.datagroup_type);
+			}
+      return 0;
+    }
+	}
+	
+	dec->cb(&header, data_len, data_field, dec->arg);
+	return 1;
+}
+
+int DAB_DGDEC_IMPL_checkCrc(const unsigned char *buf,
+	unsigned long len, unsigned short crc_field)
+{
+  return CRC_Check_16(buf, len, crc_field);
+}
+
+int DAB_DGDEC_IMPL_extractMscDatagroupHeader(
+	unsigned long len,
+	const unsigned char *buf,
+	DAB_DATAGROUP_DECODER_msc_datagroup_header_t *header)
+{
+	unsigned char c;
+	if(len < 2)
+	{
+		if(showDdDabDgDecErr)
+		{
+			logit(LOG_ERR, "not enough data");
+		}
+		return 0;
+	}
+
+	c=buf[0];
+	header->extension_flag=(unsigned char)((c&0x80)!=0);
+	header->crc_flag=(unsigned char)((c&0x40)!=0);
+	header->segment_flag=(unsigned char)((c&0x20)!=0);
+	header->user_access_flag=(unsigned char)((c&0x10)!=0);
+	header->datagroup_type=(unsigned char)(c&0x0F);
+
+	c=buf[1];
+	header->continuity_index=(unsigned char)((c&0xF0)>>4);
+	header->repetition_index=(unsigned char)(c&0x0F);
+
+	if(header->extension_flag)
+	{
+		if(len<4)
+		{
+			if(showDdDabDgDecErr)
+			{
+				logit(LOG_ERR, "not enough data");
+			}
+			return 0;
+		}
+
+		c=buf[2];
+		header->extension_field=(unsigned short)(c<<8);
+		c=buf[3];
+    /* type behaviour of vc6.0 is not conformant to */
+    /* header->extension_field+=(unsigned short)c; */
+    /* Therefore the uncommon syntax is used here. */
+		header->extension_field=(unsigned short)(header->extension_field+c);
+	}
+	else
+	{
+		header->extension_field=0xFFFF;
+	}
+	
+	return 1;
+}
+
+void DAB_DGDEC_IMPL_showMscDatagroupHeader(
+	DAB_DATAGROUP_DECODER_msc_datagroup_header_t *header)
+{
+	logit(LOG_INFO,
+		"extension_flag: %d\n"
+		"crc_flag: %d\n"
+		"segment_flag: %d\n"
+		"user_access_flag: %d\n"
+		"datagroup_type: 0x%x\n"
+		"continuity_index: 0x%x\n"
+		"repetition_index: 0x%x\n"
+		"extension_field: 0x%x\n",
+
+		header->extension_flag,
+		header->crc_flag,
+		header->segment_flag,
+		header->user_access_flag,
+		header->datagroup_type,
+		header->continuity_index,
+		header->repetition_index,
+		header->extension_field
+	);
+}
diff --git a/src/datadecoding/journaline/dabdgdec_impl.h b/src/datadecoding/journaline/dabdgdec_impl.h
new file mode 100644
index 0000000..86e240c
--- /dev/null
+++ b/src/datadecoding/journaline/dabdgdec_impl.h
@@ -0,0 +1,95 @@
+/* 
+ *
+ * This file is part of the 'NewsService Journaline(R) Decoder'
+ * 
+ * Copyright (c) 2003, 2001-2014 by Fraunhofer IIS, Erlangen, Germany
+ * 
+ * --------------------------------------------------------------------
+ * 
+ * For NON-COMMERCIAL USE,
+ * the 'NewsService Journaline(R) Decoder' is free software;
+ * you can redistribute it and/or modify it under the terms of
+ * the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * The 'NewsService Journaline(R) Decoder' is distributed in the hope
+ * that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with the 'NewsService Journaline(R) Decoder';
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ * 
+ * If you use this software in a project with user interaction, please
+ * provide the following text to the user in an appropriate place:
+ * "Features NewsService Journaline(R) decoder technology by
+ * Fraunhofer IIS, Erlangen, Germany.
+ * For more information visit http://www.iis.fhg.de/dab"
+ * 
+ * --------------------------------------------------------------------
+ * 
+ * To use the 'NewsService Journaline(R) Decoder' software for
+ * COMMERCIAL purposes, please contact Fraunhofer IIS for a
+ * commercial license (see below for contact information)!
+ * 
+ * --------------------------------------------------------------------
+ * 
+ * Contact:
+ *   Fraunhofer IIS, Department 'Broadcast Applications'
+ *   Am Wolfsmantel 33, 91058 Erlangen, Germany
+ *   http://www.iis.fraunhofer.de/dab
+ *   mailto:bc-info at iis.fraunhofer.de
+ * 
+ */
+
+#ifndef __DAB_DGDEC_IMPL__
+#define __DAB_DGDEC_IMPL__
+/**
+*** 			techidee GmbH
+*** Projekt:	NewsBox
+*** Autor:		Thomas Fruehwald
+***
+*** Compiler:	gcc
+*** Modul:
+		dab datagroup decoder
+		implementation
+***
+***
+**/
+#include "dabdatagroupdecoder.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int showDdDabDgDecInfo;
+extern int showDdDabDgDecErr;
+
+#define DAB_DGDEC_MAGIC_ID	0x49871
+
+typedef struct
+{
+	unsigned long				magicId;
+	DAB_DATAGROUP_DECODER_data	*cb;
+	void 						*arg;
+} DAB_DGDEC_IMPL_t;
+
+int DAB_DGDEC_IMPL_extractMscDatagroupHeader(
+	unsigned long len,
+	const unsigned char *buf,
+	DAB_DATAGROUP_DECODER_msc_datagroup_header_t *header);
+void DAB_DGDEC_IMPL_showMscDatagroupHeader(
+	DAB_DATAGROUP_DECODER_msc_datagroup_header_t *header);
+
+int DAB_DGDEC_IMPL_checkCrc(const unsigned char *buf,
+	unsigned long len, unsigned short crc_field);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __DAB_DGDEC_IMPL__ */
diff --git a/src/datadecoding/journaline/log.c b/src/datadecoding/journaline/log.c
new file mode 100644
index 0000000..72ccf40
--- /dev/null
+++ b/src/datadecoding/journaline/log.c
@@ -0,0 +1,64 @@
+/* 
+ *
+ * This file is part of the 'NewsService Journaline(R) Decoder'
+ * 
+ * Copyright (c) 2003, 2001-2014 by Fraunhofer IIS, Erlangen, Germany
+ * 
+ * --------------------------------------------------------------------
+ * 
+ * For NON-COMMERCIAL USE,
+ * the 'NewsService Journaline(R) Decoder' is free software;
+ * you can redistribute it and/or modify it under the terms of
+ * the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * The 'NewsService Journaline(R) Decoder' is distributed in the hope
+ * that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with the 'NewsService Journaline(R) Decoder';
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ * 
+ * If you use this software in a project with user interaction, please
+ * provide the following text to the user in an appropriate place:
+ * "Features NewsService Journaline(R) decoder technology by
+ * Fraunhofer IIS, Erlangen, Germany.
+ * For more information visit http://www.iis.fhg.de/dab"
+ * 
+ * --------------------------------------------------------------------
+ * 
+ * To use the 'NewsService Journaline(R) Decoder' software for
+ * COMMERCIAL purposes, please contact Fraunhofer IIS for a
+ * commercial license (see below for contact information)!
+ * 
+ * --------------------------------------------------------------------
+ * 
+ * Contact:
+ *   Fraunhofer IIS, Department 'Broadcast Applications'
+ *   Am Wolfsmantel 33, 91058 Erlangen, Germany
+ *   http://www.iis.fraunhofer.de/dab
+ *   mailto:bc-info at iis.fraunhofer.de
+ * 
+ */
+
+
+#include <stdarg.h>
+#include <stdio.h>
+
+void logit(unsigned long level, const char *file, const int line, int api_err,
+           int dumpBuffer, int nots, const char * format, ...)
+{
+  va_list va;
+  va_start (va, format);
+  fprintf(stderr, "error (%lu) in file %s, line %d\n", level, file, line);
+  fprintf(stderr, "(api_err=%d, dumpBuffer=%d,nots=%d)\n", api_err, dumpBuffer, nots);
+  vfprintf(stderr, format, va);
+  fprintf(stderr, "\n\n");
+  va_end(va);
+}
diff --git a/src/datadecoding/journaline/log.h b/src/datadecoding/journaline/log.h
new file mode 100644
index 0000000..e9ff123
--- /dev/null
+++ b/src/datadecoding/journaline/log.h
@@ -0,0 +1,81 @@
+/* 
+ *
+ * This file is part of the 'NewsService Journaline(R) Decoder'
+ * 
+ * Copyright (c) 2003, 2001-2014 by Fraunhofer IIS, Erlangen, Germany
+ * 
+ * --------------------------------------------------------------------
+ * 
+ * For NON-COMMERCIAL USE,
+ * the 'NewsService Journaline(R) Decoder' is free software;
+ * you can redistribute it and/or modify it under the terms of
+ * the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * The 'NewsService Journaline(R) Decoder' is distributed in the hope
+ * that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with the 'NewsService Journaline(R) Decoder';
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ * 
+ * If you use this software in a project with user interaction, please
+ * provide the following text to the user in an appropriate place:
+ * "Features NewsService Journaline(R) decoder technology by
+ * Fraunhofer IIS, Erlangen, Germany.
+ * For more information visit http://www.iis.fhg.de/dab"
+ * 
+ * --------------------------------------------------------------------
+ * 
+ * To use the 'NewsService Journaline(R) Decoder' software for
+ * COMMERCIAL purposes, please contact Fraunhofer IIS for a
+ * commercial license (see below for contact information)!
+ * 
+ * --------------------------------------------------------------------
+ * 
+ * Contact:
+ *   Fraunhofer IIS, Department 'Broadcast Applications'
+ *   Am Wolfsmantel 33, 91058 Erlangen, Germany
+ *   http://www.iis.fraunhofer.de/dab
+ *   mailto:bc-info at iis.fraunhofer.de
+ * 
+ */
+
+#ifndef __LOG__
+#define __LOG__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define LOG_ERR       1, __FILE__, __LINE__, 0, 0, 0
+#define LOG_ERR_API   1, __FILE__, __LINE__, 1, 0, 0
+#define LOG_ERR_DUMP  1, __FILE__, __LINE__, 0, 1, 0
+
+#define LOG_WARN      2, __FILE__, __LINE__, 0, 0, 0
+#define LOG_WARN_DUMP 2, __FILE__, __LINE__, 0, 1, 0
+
+#define LOG_INFO      4, __FILE__, __LINE__, 0, 0, 0
+#define LOG_INFO_NOTS 4, __FILE__, __LINE__, 0, 0, 1
+#define LOG_INFO_DUMP 4, __FILE__, __LINE__, 0, 1, 0
+
+void logit(unsigned long level,
+           const char *file,
+           const int line,
+           int api_err,
+           int dumpBuffer,
+           int nots,
+           const char *format,
+           ...);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/datadecoding/journaline/newsobject.cpp b/src/datadecoding/journaline/newsobject.cpp
new file mode 100644
index 0000000..00b5f96
--- /dev/null
+++ b/src/datadecoding/journaline/newsobject.cpp
@@ -0,0 +1,174 @@
+/* 
+ *
+ * This file is part of the 'NewsService Journaline(R) Decoder'
+ * 
+ * Copyright (c) 2003, 2001-2014 by Fraunhofer IIS, Erlangen, Germany
+ * 
+ * --------------------------------------------------------------------
+ * 
+ * For NON-COMMERCIAL USE,
+ * the 'NewsService Journaline(R) Decoder' is free software;
+ * you can redistribute it and/or modify it under the terms of
+ * the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * The 'NewsService Journaline(R) Decoder' is distributed in the hope
+ * that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with the 'NewsService Journaline(R) Decoder';
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ * 
+ * If you use this software in a project with user interaction, please
+ * provide the following text to the user in an appropriate place:
+ * "Features NewsService Journaline(R) decoder technology by
+ * Fraunhofer IIS, Erlangen, Germany.
+ * For more information visit http://www.iis.fhg.de/dab"
+ * 
+ * --------------------------------------------------------------------
+ * 
+ * To use the 'NewsService Journaline(R) Decoder' software for
+ * COMMERCIAL purposes, please contact Fraunhofer IIS for a
+ * commercial license (see below for contact information)!
+ * 
+ * --------------------------------------------------------------------
+ * 
+ * Contact:
+ *   Fraunhofer IIS, Department 'Broadcast Applications'
+ *   Am Wolfsmantel 33, 91058 Erlangen, Germany
+ *   http://www.iis.fraunhofer.de/dab
+ *   mailto:bc-info at iis.fraunhofer.de
+ * 
+ */
+
+/**
+*** 			techidee GmbH
+*** Projekt:	NewsBox
+*** Autor:		Thomas Fruehwald
+***
+*** Compiler:	gcc
+*** Modul:
+		news object
+***
+***
+**/
+#include "newsobject.h"
+#include "cpplog.h"
+#include <cstdlib>
+#include <cstring>
+
+NewsObject::NewsObject(unsigned long len, const unsigned char *buf,
+	struct timeval *creation_time) :
+		d_creation_time(*creation_time),
+		d_reception_time(*creation_time),
+		d_obj_updated(false)
+{
+	d_object_id=(buf[0]<<8)+buf[1];
+#if 0
+	log_err << "insert id: " << d_object_id << "buf[0]: " <<
+	static_cast<unsigned int>(buf[0]) << "buf[1]: " << 
+	static_cast<unsigned int>(buf[1]) << endmsg;
+#endif
+
+	d_object_type=convertObjectType(static_cast<unsigned char>((buf[2]&0xE0)>>5));
+	d_static_flag=((buf[2]&0x10)!=0);
+	d_compressed_flag=((buf[2]&0x08)!=0);
+	d_revision_index=static_cast<unsigned char>(buf[2]&0x07);
+
+	if(len > MAX_NML_BYTES)
+	{
+		log_err << "length of nml too big:" << len << endmsg;
+	}
+	d_len=len;
+	memcpy(d_nml, buf, len);
+}
+
+NewsObject::~NewsObject()
+{
+}
+
+unsigned long NewsObject::getObjectId()
+{
+	return d_object_id;
+}
+
+struct timeval NewsObject::getReceptionTime()
+{
+	return d_reception_time;
+}
+
+struct timeval NewsObject::getCreationTime()
+{
+	return d_creation_time;
+}
+
+void NewsObject::setReceptionTime(struct timeval *time)
+{
+	d_reception_time=*time;
+}
+
+bool NewsObject::isStatic()
+{
+	return d_static_flag;
+}
+
+bool NewsObject::isCompressed()
+{
+	return d_compressed_flag;
+}
+
+bool NewsObject::isUpdated()
+{
+	return d_obj_updated;
+}
+
+void NewsObject::setUpdateFlag()
+{
+	d_obj_updated=true;
+}
+
+unsigned char NewsObject::getRevisionIndex()
+{
+	return d_revision_index;
+}
+
+NewsObject::object_type_id_t NewsObject::getObjectType()
+{
+	return d_object_type;
+}
+
+NewsObject::object_type_id_t NewsObject::convertObjectType(unsigned char in)
+{
+	switch(in)
+	{
+		case 0x01:
+			return MENU;
+
+		case 0x02:
+			return PLAIN_TEXT;
+
+		case 0x03:
+			return TITLE_ONLY;
+
+		case 0x04:
+			return LIST;
+
+		default:
+			log_err << "unknown object type: " <<
+			std::hex << static_cast<unsigned int>(in) << endmsg;
+	}
+	return PLAIN_TEXT;
+}
+
+void NewsObject::copyNml(unsigned long *len, unsigned char *nml)
+{
+	memcpy(nml, d_nml, d_len);
+	*len=d_len;
+}
+
diff --git a/src/datadecoding/journaline/newsobject.h b/src/datadecoding/journaline/newsobject.h
new file mode 100644
index 0000000..fd7901e
--- /dev/null
+++ b/src/datadecoding/journaline/newsobject.h
@@ -0,0 +1,121 @@
+/* 
+ *
+ * This file is part of the 'NewsService Journaline(R) Decoder'
+ * 
+ * Copyright (c) 2003, 2001-2014 by Fraunhofer IIS, Erlangen, Germany
+ * 
+ * --------------------------------------------------------------------
+ * 
+ * For NON-COMMERCIAL USE,
+ * the 'NewsService Journaline(R) Decoder' is free software;
+ * you can redistribute it and/or modify it under the terms of
+ * the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * The 'NewsService Journaline(R) Decoder' is distributed in the hope
+ * that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with the 'NewsService Journaline(R) Decoder';
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ * 
+ * If you use this software in a project with user interaction, please
+ * provide the following text to the user in an appropriate place:
+ * "Features NewsService Journaline(R) decoder technology by
+ * Fraunhofer IIS, Erlangen, Germany.
+ * For more information visit http://www.iis.fhg.de/dab"
+ * 
+ * --------------------------------------------------------------------
+ * 
+ * To use the 'NewsService Journaline(R) Decoder' software for
+ * COMMERCIAL purposes, please contact Fraunhofer IIS for a
+ * commercial license (see below for contact information)!
+ * 
+ * --------------------------------------------------------------------
+ * 
+ * Contact:
+ *   Fraunhofer IIS, Department 'Broadcast Applications'
+ *   Am Wolfsmantel 33, 91058 Erlangen, Germany
+ *   http://www.iis.fraunhofer.de/dab
+ *   mailto:bc-info at iis.fraunhofer.de
+ * 
+ */
+
+#ifndef __NEWS_OBJECT__
+#define __NEWS_OBJECT__
+/**
+*** 			techidee GmbH
+*** Projekt:	NewsBox
+*** Autor:		Thomas Fruehwald
+***
+*** Compiler:	gcc
+*** Modul:
+		news service decoder implementation
+***
+***
+**/
+#ifdef _MSC_VER
+# ifndef _WINSOCKAPI_
+#  include <winsock2.h>
+# endif
+#else
+# include <sys/time.h>
+#endif
+
+class NewsObject
+{
+public:
+	NewsObject(unsigned long len, const unsigned char *buf,
+		struct timeval *creation_time);
+	~NewsObject();
+
+	typedef enum
+	{
+		MENU,
+		PLAIN_TEXT,
+		TITLE_ONLY,
+		LIST
+	} object_type_id_t;
+
+	unsigned long getObjectId();
+	struct timeval getReceptionTime();	
+	struct timeval getCreationTime();	
+	void setReceptionTime(struct timeval *time);
+	bool isStatic();
+	bool isCompressed();
+	void setUpdateFlag();
+	bool isUpdated();
+	unsigned char getRevisionIndex();
+	object_type_id_t getObjectType();
+	void copyNml(unsigned long *len, unsigned char *nml);
+
+private:
+	enum { MAX_NML_BYTES=4092 };
+	unsigned long		d_object_id;
+	object_type_id_t	d_object_type;
+	bool			d_static_flag;
+	bool			d_compressed_flag;
+	unsigned char		d_revision_index;
+
+	unsigned long		d_len;
+	unsigned char		d_nml[MAX_NML_BYTES];
+
+	struct timeval		d_creation_time;
+	struct timeval		d_reception_time;
+
+	// that flag is set if an object with the same
+	// object id existed previously.
+	// It is needed to determine wether an object is
+	// first received or updated.
+	bool				d_obj_updated;
+
+	object_type_id_t convertObjectType(unsigned char in);
+};
+
+#endif
diff --git a/src/datadecoding/journaline/newssvcdec.h b/src/datadecoding/journaline/newssvcdec.h
new file mode 100644
index 0000000..12c064d
--- /dev/null
+++ b/src/datadecoding/journaline/newssvcdec.h
@@ -0,0 +1,352 @@
+/* 
+ *
+ * This file is part of the 'NewsService Journaline(R) Decoder'
+ * 
+ * Copyright (c) 2003, 2001-2014 by Fraunhofer IIS, Erlangen, Germany
+ * 
+ * --------------------------------------------------------------------
+ * 
+ * For NON-COMMERCIAL USE,
+ * the 'NewsService Journaline(R) Decoder' is free software;
+ * you can redistribute it and/or modify it under the terms of
+ * the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * The 'NewsService Journaline(R) Decoder' is distributed in the hope
+ * that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with the 'NewsService Journaline(R) Decoder';
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ * 
+ * If you use this software in a project with user interaction, please
+ * provide the following text to the user in an appropriate place:
+ * "Features NewsService Journaline(R) decoder technology by
+ * Fraunhofer IIS, Erlangen, Germany.
+ * For more information visit http://www.iis.fhg.de/dab"
+ * 
+ * --------------------------------------------------------------------
+ * 
+ * To use the 'NewsService Journaline(R) Decoder' software for
+ * COMMERCIAL purposes, please contact Fraunhofer IIS for a
+ * commercial license (see below for contact information)!
+ * 
+ * --------------------------------------------------------------------
+ * 
+ * Contact:
+ *   Fraunhofer IIS, Department 'Broadcast Applications'
+ *   Am Wolfsmantel 33, 91058 Erlangen, Germany
+ *   http://www.iis.fraunhofer.de/dab
+ *   mailto:bc-info at iis.fraunhofer.de
+ * 
+ */
+
+#ifndef __NEWS_SVC_DEC__
+#define __NEWS_SVC_DEC__
+
+/*!
+ * @brief Journaline(R) news service decoder interface
+ *
+ * @file newssvcdec.h
+ *
+ *         techidee GmbH
+ *
+ * Projekt:    NewsBox
+ *
+ * Autor:      Thomas Fruehwald
+ *
+ * Compiler:    gcc
+ *
+ * Modul: news service decoder
+ *
+ * Creation date:  2003-08-02
+ *
+ * Last modified:  2001-2014-02-16 (rbr)
+ *
+ * The Journaline(R) news service decoder will accept
+ * Journaline(R) objects conforming to the
+ * news service "Journaline(R)" specification and store them
+ * (subject to specified memory limits) for later retrieval by
+ * a Journaline(R) application.
+ *
+ * To use it, call createDec to create an instance,
+ * putData to put Journaline(R) objects into the decoder
+ * and in the end, use deleteDec to destroy the instance.
+ *
+ * To make use of the watch functionality for monitoring object availability
+ * information, you must implement the object availability callback and pass
+ * it to createDec.
+ *
+ * @attention
+ * The Journaline(R) news service decoder is not thread safe.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/*! @brief news service decoder instance type */
+typedef const void* NEWS_SVC_DEC_decoder_t;
+
+
+/*! @brief object availability status type */
+typedef enum
+{
+  NEWS_SVC_DEC_OBJ_NOT_YET_AVAILABLE, /*!< object is not yet available */
+  NEWS_SVC_DEC_OBJ_REMOVED,           /*!< object has been removed because
+                                           of memory restrictions */
+  NEWS_SVC_DEC_OBJ_RECEIVED,       /*!< object has been received */
+  NEWS_SVC_DEC_OBJ_UPDATED         /*!< update of already received object */
+} NEWS_SVC_DEC_obj_availability_status_t;
+
+/*! @brief object availability type */
+typedef struct
+{
+  unsigned short object_id;                      /*!< NML object id */
+  NEWS_SVC_DEC_obj_availability_status_t status; /*!< current availability
+                                                      status */
+} NEWS_SVC_DEC_obj_availability_t;
+
+
+/*!
+ * @brief object availability callback function
+ *
+ * The object availability callback function will be called when
+ * the object availability status of one or more of the objects
+ * in the watch list changes.
+ *
+ * @param number_of_elements
+ *   number of elements in change list
+ * @param chg_list
+ *   change list
+ * @param arg
+ *   user specified data pointer (as specified in createDec)
+ */
+typedef void(NEWS_SVC_DEC_cb)(
+    unsigned long number_of_elements,
+    NEWS_SVC_DEC_obj_availability_t *chg_list,
+    void *arg
+    );
+
+
+
+
+/****************************************************************************
+ *
+ * public function interface
+ *
+ ****************************************************************************/
+
+
+/*******************************************
+ * 1. object lifetime control              *
+ *******************************************/
+
+/*!
+ * @brief Create a news service decoder instance
+ *
+ * call this before anything else
+ *
+ * @param update
+ *   callback function (may be 0 to indicate watching is not used)
+ * @param max_memory
+ *   value in bytes for the news-service
+ *   the value is truncated to the nearest multiple
+ *   of the (internal) news object representation
+ *   approx. 2200 bytes (4092 bytes is the longest nml)
+ * @param max_objects
+ *   maximum number of objects.
+ *   if 0 the whole max_news_service_memory is used.
+ *   otherwise the sharper restriction limits the
+ *   object count (e.g. max_news_service_memory -> 10
+ *   objects, max_object_count=5 -> 5 objects)
+ * @param extended_header_len
+ *   length of NML extended header in bytes (signalled in SDC)
+ * @param arg
+ *   user specified data pointer (will only be passed to callback)
+ *
+ * @return created news service decoder instance
+ * @retval 0 on failure
+ */
+NEWS_SVC_DEC_decoder_t NEWS_SVC_DEC_createDec(
+    NEWS_SVC_DEC_cb update,
+    unsigned long max_memory,
+    unsigned long *max_objects, 
+    unsigned long extended_header_len,
+    void  *arg
+    );  
+
+/*!
+ * @brief Delete a news service decoder instance
+ *
+ * call this at shutdown time
+ *
+ * @param decoder
+ *   news service decoder instance
+ *   (as obtained by NEWS_SVC_DEC_createDec)
+ *   
+ * @retval 0 on failure
+ * @retval 1 on success
+ */
+void NEWS_SVC_DEC_deleteDec(
+    NEWS_SVC_DEC_decoder_t decoder
+    );
+
+
+/*******************************************
+ * 2. news service pull functions          *
+ *******************************************/
+
+/*!
+ * @brief Get a news object by id
+ * 
+ * The object with id object_id will be written to nml
+ * and len will be set to its actual length in bytes (at most 4092).
+ *
+ * @param decoder
+ *   news service decoder instance (as obtained by NEWS_SVC_DEC_createDec)
+ * @param object_id
+ *   NML object id (0000-FFFF)
+ * @param extended_header_len (out)
+ *   length in bytes of extended header field of this news service
+ *   (as signalled in SDC)
+ * @param len (out) 
+ *   length in bytes of NML object
+ * @param nml (out) 
+ *   the complete NML object (including NML header)
+ *
+ * @retval 0  on failure
+ */
+int NEWS_SVC_DEC_get_news_object(
+    NEWS_SVC_DEC_decoder_t decoder,
+    unsigned short object_id,
+    unsigned long *extended_header_len,
+    unsigned long *len,
+    unsigned char *nml
+    );
+
+
+/*!
+ * @brief Query the availability of objects
+ *
+ * Specify a list of objects (only the object ids have to be filled in)
+ * you want to query in query_list.
+ *
+ * on return the status field of query_list will be set.
+ *
+ * @param decoder
+ *   news service decoder instance (as obtained by NEWS_SVC_DEC_createDec)
+ * @param number_of_elements
+ *   length of SVCMGR_UI_object_availability_t array
+ * @param query_list
+ *   (inout) list of objects for which the status is queried
+ *
+ * @retval 0  on failure
+ */
+int NEWS_SVC_DEC_get_object_availability(
+    NEWS_SVC_DEC_decoder_t decoder,
+    unsigned long number_of_elements,
+    NEWS_SVC_DEC_obj_availability_t *query_list
+    );
+
+
+/*******************************************
+ * 3. data provision                       *
+ *******************************************/
+
+/*!
+ * @brief Put data into news decoder
+ * 
+ * The input for the news decoder consists of one complete Journaline(R) object.
+ *  
+ * @param decoder
+ *   news service decoder instance (as obtained by NEWS_SVC_DEC_createDec)
+ * @param len
+ *   length in bytes of Journaline(R) object
+ * @param buf
+ *   Journaline(R) object
+ *
+ * @retval 0  on failure
+ */
+unsigned long NEWS_SVC_DEC_putData(
+    NEWS_SVC_DEC_decoder_t  decoder,
+    const unsigned long  len,
+    const unsigned char *buf
+    );
+
+
+/*******************************************
+ * 4. watch and cache management           *
+ *******************************************/
+
+/*!
+ * @brief Set a watch on the specified objects
+ *
+ * When the status of an object with an id
+ * that is being watched on changes, a callback is done.
+ * To avoid nested upcalls the status at the calling
+ * time is returned in the watch_list's status field.
+ *
+ * @note Every call to this function overwrites the last watch list.
+ *
+ * @param number_of_elements
+ *   length of SVCMGR_UI_object_availability_t array
+ * @param decoder
+ *   news service decoder instance (as obtained by
+ *   NEWS_SVC_DEC_createDec)
+ * @param watch_list
+ *   (inout) list of objects for which a watch is set.
+ *
+ *   On input, the object_id field has to be specified.
+ *
+ *   On output, the status field will be filled.
+ *
+ * @retval 0  on failure
+ */
+int NEWS_SVC_DEC_watch_objects(
+    NEWS_SVC_DEC_decoder_t decoder,
+    unsigned long number_of_elements,
+    NEWS_SVC_DEC_obj_availability_t *watch_list
+    );
+
+/*!
+ * @brief Set ids of objects to be kept in cache
+ *
+ * Tell the memory management that the listed elements
+ * should be kept in memory (if possible).
+ * 
+ * Candidates for keeping in memory are (in order of importance):
+ *   -# currently viewed object
+ *   -# parents of currently viewed object
+ *   -# children of currently viewed (menu) object
+ *   -# "favorite" objects
+ *
+ * @note Every call to this function overwrites the last keep-in-memory list.
+ *
+ * @param decoder
+ *   news service decoder instance (as obtained by NEWS_SVC_DEC_createDec)
+ * @param number_of_elements
+ *   length of object_id array
+ * @param object_ids
+ *   list of ids of objects which should be kept in cache
+ *
+ * @retval 0  on failure
+ */
+int NEWS_SVC_DEC_keep_in_cache(
+    NEWS_SVC_DEC_decoder_t decoder,
+    unsigned long number_of_elements,
+    unsigned short *object_ids
+    );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __NEWS_SVC_DEC__ */
diff --git a/src/datadecoding/journaline/newssvcdec_impl.cpp b/src/datadecoding/journaline/newssvcdec_impl.cpp
new file mode 100644
index 0000000..8694c53
--- /dev/null
+++ b/src/datadecoding/journaline/newssvcdec_impl.cpp
@@ -0,0 +1,665 @@
+/*
+ *
+ * This file is part of the 'NewsService Journaline(R) Decoder'
+ *
+ * Copyright (c) 2003, 2001-2014 by Fraunhofer IIS, Erlangen, Germany
+ *
+ * --------------------------------------------------------------------
+ *
+ * For NON-COMMERCIAL USE,
+ * the 'NewsService Journaline(R) Decoder' is free software;
+ * you can redistribute it and/or modify it under the terms of
+ * the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * The 'NewsService Journaline(R) Decoder' is distributed in the hope
+ * that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with the 'NewsService Journaline(R) Decoder';
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ *
+ * If you use this software in a project with user interaction, please
+ * provide the following text to the user in an appropriate place:
+ * "Features NewsService Journaline(R) decoder technology by
+ * Fraunhofer IIS, Erlangen, Germany.
+ * For more information visit http://www.iis.fhg.de/dab"
+ *
+ * --------------------------------------------------------------------
+ *
+ * To use the 'NewsService Journaline(R) Decoder' software for
+ * COMMERCIAL purposes, please contact Fraunhofer IIS for a
+ * commercial license (see below for contact information)!
+ *
+ * --------------------------------------------------------------------
+ *
+ * Contact:
+ *   Fraunhofer IIS, Department 'Broadcast Applications'
+ *   Am Wolfsmantel 33, 91058 Erlangen, Germany
+ *   http://www.iis.fraunhofer.de/dab
+ *   mailto:bc-info at iis.fraunhofer.de
+ *
+ */
+
+/**
+*** 			techidee GmbH
+*** Projekt:	NewsBox
+*** Autor:		Thomas Fruehwald
+***
+*** Compiler:	gcc
+*** Modul:
+		dab datagroup decoder implementation
+***
+***
+**/
+
+
+#ifdef _MSC_VER
+#define TIM_DEF
+#include <wtypes.h>
+#undef min
+
+#pragma warning(disable: 4100)
+#pragma warning(disable: 4786)
+
+#endif
+
+#include <algorithm>
+#include <time.h>
+#ifdef _WIN32
+# include <windows.h> // for GetTickCount
+#endif
+
+#include "dabdatagroupdecoder.h"
+#include "cpplog.h"
+#include "newssvcdec_impl.h"
+
+using std::find;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+int showDdNewsSvcDecInfo;
+int showDdNewsSvcDecErr;
+#ifdef __cplusplus
+}
+#endif
+
+#ifdef __cplusplus
+extern "C"
+#endif
+NEWS_SVC_DEC_decoder_t NEWS_SVC_DEC_createDec(
+	NEWS_SVC_DEC_cb *update,
+	unsigned long max_memory,
+	unsigned long *max_objects,
+	unsigned long extended_header_len,
+	void	*arg
+	)
+{
+	NEWS_SVC_DEC_IMPL_t *dec=new NEWS_SVC_DEC_IMPL_t;
+	if(dec==0)
+	{
+		if(showDdNewsSvcDecErr)
+		{
+			log_err << "out of memory requesting "
+			<< sizeof(*dec) << " bytes" << endmsg;
+		}
+		return 0;
+	}
+
+	dec->d_magicId=NEWS_SVC_MAGIC_ID;
+	dec->d_update=update;
+	dec->d_arg=arg;
+	dec->d_extended_header_len=extended_header_len;
+	dec->d_max_memory=max_memory;
+
+	unsigned long obj_possible=max_memory / sizeof(NewsObject);
+	if(*max_objects==0)
+	{
+		*max_objects=obj_possible;
+	}
+	else
+	{
+		*max_objects=std::min(*max_objects, obj_possible);
+	}
+
+	if(showDdNewsSvcDecInfo)
+	{
+		log_info << "NEWS_SVC_DEC sizeof object: " << sizeof(NewsObject)
+		<< "max memory: " << max_memory << " max_objects: " << *max_objects
+		<< endmsg;
+	}
+
+	dec->d_max_objects=*max_objects;
+	dec->d_object_count=0;
+
+	dec->d_watch_list.clear();
+	dec->d_keep_in_cache_list.clear();
+
+	return (const NEWS_SVC_DEC_IMPL_t*)dec;
+}
+
+
+#ifdef __cplusplus
+extern "C"
+#endif
+void NEWS_SVC_DEC_deleteDec(
+		NEWS_SVC_DEC_decoder_t decoder
+		)
+{
+	NEWS_SVC_DEC_IMPL_t *dec=(NEWS_SVC_DEC_IMPL_t*)(decoder);
+	if(dec->d_magicId!=NEWS_SVC_MAGIC_ID)
+	{
+		if(showDdNewsSvcDecErr)
+		{
+			log_err << "not a news service decoder" << endmsg;
+		}
+		return;
+	}
+
+	delete dec;
+}
+
+#ifdef __cplusplus
+extern "C"
+#endif
+unsigned long NEWS_SVC_DEC_putData(
+		NEWS_SVC_DEC_decoder_t	decoder,
+		const unsigned long	len,
+		const unsigned char *buf
+	)
+{
+	if(showDdNewsSvcDecInfo)
+	{
+		log_info << "NEWS_SVC_DEC_putData" << endmsg;
+	}
+
+	NEWS_SVC_DEC_IMPL_t *dec=(NEWS_SVC_DEC_IMPL_t*)(decoder);
+	if(dec->d_magicId!=NEWS_SVC_MAGIC_ID)
+	{
+		if(showDdNewsSvcDecErr)
+		{
+			log_err << "not a news service decoder" << endmsg;
+		}
+		return 0;
+	}
+
+	if(showDdNewsSvcDecInfo)
+	{
+		log_info << "d_object_count: " << dec->d_object_count <<
+		" d_max_objects: " << dec->d_max_objects << endmsg;
+	}
+
+	struct timeval reception_time;
+
+#ifdef _WIN32
+	time((time_t *)&(reception_time.tv_sec));
+	reception_time.tv_usec=GetTickCount();
+#else
+	struct timezone tz;
+	if(gettimeofday(&reception_time, &tz))
+	{
+		if(showDdNewsSvcDecErr)
+		{
+			log_err << "gettimeofday failed" << endmsg;
+		}
+	}
+#endif
+
+#if 0
+	log_err << "received object at time:" << reception_time.tv_sec << ":"
+		<< reception_time.tv_usec << endmsg;
+#endif
+
+	// do not throw an exception when out of memory
+	NewsObject *obj=new(std::nothrow)NewsObject(len, buf, &reception_time);
+	if(obj==0)
+	{
+		if(showDdNewsSvcDecErr)
+		{
+			log_err << "out of memory requesting " << sizeof(*obj)
+			<< " bytes" << endmsg;
+		}
+		return 0;
+	}
+
+
+	unsigned long object_id=obj->getObjectId();
+	if(obj->isCompressed())
+	{
+		if(showDdNewsSvcDecInfo)
+		{
+			log_info << "object with id " << object_id << " is compressed"
+				<< endmsg;
+		}
+	}
+	if(showDdNewsSvcDecInfo)
+	{
+		log_info << "insert try got new object with id "
+		<< std::hex << object_id << " revision index: " <<
+		static_cast<unsigned int>(obj->getRevisionIndex())
+		<< endmsg;
+	}
+	if(dec->d_news_map.count(object_id)!=0)
+	{
+		if(showDdNewsSvcDecInfo)
+		{
+			log_info << "object already in map" << endmsg;
+		}
+		NewsObject *old=dec->d_news_map[object_id];
+		if(old->getRevisionIndex()==obj->getRevisionIndex())
+		{
+			// adjust reception time
+			old->setReceptionTime(&reception_time);
+			delete obj;
+			return 1;
+		}
+		else
+		{
+			if(showDdNewsSvcDecInfo)
+			{
+				log_info << "revision index changed" << endmsg;
+			}
+			// the object has a new revision index
+			// so set the updated flag
+			//
+			obj->setUpdateFlag();
+		}
+
+		// have new object -> delete the old one
+		//
+		dec->d_object_count--;
+		delete old;
+	}
+
+	if(dec->d_object_count >= dec->d_max_objects)
+	{
+		if(!NEWS_SVC_DEC_IMPL_garbage_collection(dec, 1))
+		{
+			if(showDdNewsSvcDecErr)
+			{
+				log_err << "garabage collection did not free memory" << endmsg;
+			}
+			return 0;
+		}
+	}
+
+
+	// check if we are watching for it
+	//
+	if(dec->d_update)
+	{
+		NEWS_SVC_DEC_IMPL_watch_list_t &l=dec->d_watch_list;
+		if(find(l.begin(), l.end(), object_id)!=l.end())
+		{
+			const unsigned long no_of_elem=1;
+			NEWS_SVC_DEC_obj_availability_t chg_list[no_of_elem];
+			chg_list[0].object_id=static_cast<unsigned short>(object_id);
+			if(obj->isUpdated())
+			{
+				chg_list[0].status=NEWS_SVC_DEC_OBJ_UPDATED;
+			}
+			else
+			{
+				chg_list[0].status=NEWS_SVC_DEC_OBJ_RECEIVED;
+			}
+
+			dec->d_update(
+				no_of_elem,
+				chg_list,
+				dec->d_arg);
+		}
+	}
+
+
+	// insert into map
+	if(showDdNewsSvcDecInfo)
+	{
+		log_info << "insert id: " << object_id << endmsg;
+	}
+	dec->d_news_map[object_id]=obj;
+	dec->d_object_count++;
+	return 1;
+}
+
+#ifdef __cplusplus
+extern "C"
+#endif
+int NEWS_SVC_DEC_IMPL_garbage_collection(NEWS_SVC_DEC_IMPL_t *dec,
+	unsigned long objs_to_free)
+{
+	for(unsigned long i=0;i<objs_to_free;++i)
+	{
+		if(dec->d_news_map.empty())
+		{
+			if(showDdNewsSvcDecErr)
+			{
+				log_err << "not enough elements in map" << endmsg;
+			}
+			break;
+		}
+
+		// find the oldest element
+		//
+		if(showDdNewsSvcDecInfo)
+		{
+			NEWS_SVC_DEC_IMPL_printObjList(dec);
+		}
+		FindMinFunctor min(dec);
+		NEWS_SVC_DEC_IMPL_map_t::iterator e=std::min_element(
+			dec->d_news_map.begin(), dec->d_news_map.end(),
+			min);
+		unsigned long obj_id=(e->second)->getObjectId();
+		NEWS_SVC_DEC_IMPL_keep_in_cache_list_t &l=dec->d_keep_in_cache_list;
+		if(find(l.begin(), l.end(), obj_id)!=l.end())
+		{
+			if(showDdNewsSvcDecInfo)
+			{
+				log_info << "should keep all elements in cache" << endmsg;
+			}
+			return 0;
+		}
+		if(showDdNewsSvcDecInfo)
+		{
+			log_info << "erase object with id: " << std::hex <<
+			obj_id << endmsg;
+		}
+
+		if(dec->d_update)
+		{
+			NEWS_SVC_DEC_IMPL_watch_list_t &l=dec->d_watch_list;
+			if(find(l.begin(), l.end(), obj_id)!=l.end())
+			{
+				const unsigned long no_of_elem=1;
+				NEWS_SVC_DEC_obj_availability_t chg_list[no_of_elem];
+				chg_list[0].object_id=static_cast<unsigned short>(obj_id);
+				chg_list[0].status=NEWS_SVC_DEC_OBJ_REMOVED;
+
+				dec->d_update(
+					no_of_elem,
+					chg_list,
+					dec->d_arg);
+			}
+		}
+
+		dec->d_news_map.erase(e);
+		--(dec->d_object_count);
+	}
+	return 1;
+}
+
+#ifdef __cplusplus
+extern "C"
+#endif
+int NEWS_SVC_DEC_get_news_object(
+		NEWS_SVC_DEC_decoder_t	decoder,
+		unsigned short object_id,
+		unsigned long *extended_header_len,
+		unsigned long *len,
+		unsigned char *nml)
+{
+	if(showDdNewsSvcDecInfo)
+	{
+		log_info << "NEWS_SVC_DEC_get_news_object object_id: " << object_id << endmsg;
+	}
+	NEWS_SVC_DEC_IMPL_t *dec=(NEWS_SVC_DEC_IMPL_t*)(decoder);
+	if(dec->d_magicId!=NEWS_SVC_MAGIC_ID)
+	{
+		if(showDdNewsSvcDecErr)
+		{
+			log_err << "not a news service decoder" << endmsg;
+		}
+		return 0;
+	}
+
+	if(dec->d_news_map.count(object_id)==0)
+	{
+		return 0;
+	}
+
+	dec->d_news_map[object_id]->copyNml(len, nml);
+	*extended_header_len=0;
+	return 1;
+}
+
+
+#ifdef __cplusplus
+extern "C"
+#endif
+int NEWS_SVC_DEC_watch_objects(
+	NEWS_SVC_DEC_decoder_t	decoder,
+	unsigned long number_of_elements,
+	NEWS_SVC_DEC_obj_availability_t *watch_list)
+{
+	NEWS_SVC_DEC_IMPL_t *dec=(NEWS_SVC_DEC_IMPL_t*)(decoder);
+	if(dec->d_magicId!=NEWS_SVC_MAGIC_ID)
+	{
+		if(showDdNewsSvcDecErr)
+		{
+			log_err << "not a news service decoder" << endmsg;
+		}
+		return 0;
+	}
+
+	if(showDdNewsSvcDecInfo)
+	{
+		log_info << "NEWS_SVC_DEC_watch_objects()" << endmsg;
+	}
+
+	dec->d_watch_list.clear();
+	if(number_of_elements==0)
+	{
+		// just clear the watch list
+		if(showDdNewsSvcDecInfo)
+		{
+			log_info << "NEWS_SVC_DEC_watch_objects(): clear watch list"
+			<< endmsg;
+		}
+
+		return 1;
+	}
+
+	for(unsigned long i=0;i<number_of_elements;++i)
+	{
+		if(showDdNewsSvcDecInfo)
+		{
+			log_info << "NEWS_SVC_DEC_watch_objects() add object " <<
+				watch_list[i].object_id << " to watch list" << endmsg;
+		}
+
+		dec->d_watch_list.push_back(watch_list[i].object_id);
+	}
+
+	if(!NEWS_SVC_DEC_get_object_availability(decoder,
+		number_of_elements, watch_list))
+	{
+		log_err << "NEWS_SVC_DEC_get_object_availability failed"
+			<< endmsg;
+		return 0;
+	}
+	return 1;
+}
+
+#ifdef __cplusplus
+extern "C"
+#endif
+int NEWS_SVC_DEC_get_object_availability(
+	NEWS_SVC_DEC_decoder_t	decoder,
+	unsigned long number_of_elements,
+	NEWS_SVC_DEC_obj_availability_t *query_list)
+{
+	NEWS_SVC_DEC_IMPL_t *dec=(NEWS_SVC_DEC_IMPL_t*)(decoder);
+	if(dec->d_magicId!=NEWS_SVC_MAGIC_ID)
+	{
+		if(showDdNewsSvcDecErr)
+		{
+			log_err << "not a news service decoder" << endmsg;
+		}
+		return 0;
+	}
+
+	if(showDdNewsSvcDecInfo)
+	{
+		log_info << "NEWS_SVC_DEC_get_object_availability()" << endmsg;
+	}
+	for(unsigned long i=0;i<number_of_elements;++i)
+	{
+		NEWS_SVC_DEC_obj_availability_t *e=query_list+i;
+		if(dec->d_news_map.count(e->object_id)==0)
+		{
+			e->status=NEWS_SVC_DEC_OBJ_NOT_YET_AVAILABLE;
+		}
+		else
+		{
+			NewsObject &obj=*dec->d_news_map[e->object_id];
+			if(obj.isUpdated())
+			{
+				e->status=NEWS_SVC_DEC_OBJ_UPDATED;
+			}
+			else
+			{
+				e->status=NEWS_SVC_DEC_OBJ_RECEIVED;
+			}
+		}
+
+	}
+	return 1;
+}
+
+#ifdef __cplusplus
+extern "C"
+#endif
+int NEWS_SVC_DEC_keep_in_cache(
+	NEWS_SVC_DEC_decoder_t	decoder,
+	unsigned long number_of_elements,
+	unsigned short *object_ids
+	)
+{
+	NEWS_SVC_DEC_IMPL_t *dec=(NEWS_SVC_DEC_IMPL_t*)(decoder);
+	if(dec->d_magicId!=NEWS_SVC_MAGIC_ID)
+	{
+		if(showDdNewsSvcDecErr)
+		{
+			log_err << "not a news service decoder" << endmsg;
+		}
+		return 0;
+	}
+
+	if(showDdNewsSvcDecInfo)
+	{
+		log_info << "NEWS_SVC_DEC_keep_in_cache()" << endmsg;
+	}
+
+	if(number_of_elements > dec->d_max_objects)
+	{
+		log_err << "keep-in-cache list too big: " << number_of_elements
+		<< " max objects: " << dec->d_max_objects << endmsg;
+		return 0;
+	}
+
+	dec->d_keep_in_cache_list.clear();
+	if(number_of_elements==0)
+	{
+		// just clear the keep_in_cache list
+		if(showDdNewsSvcDecInfo)
+		{
+			log_info << "NEWS_SVC_DEC_keep_in_cache(): clear keep-in-cache list"
+			<< endmsg;
+		}
+
+		return 1;
+	}
+
+	for(unsigned long i=0;i<number_of_elements;++i)
+	{
+		if(showDdNewsSvcDecInfo)
+		{
+			log_info << "NEWS_SVC_DEC_keep_in_cache() add object " <<
+				object_ids[i] << " to keep-in-cache list" << endmsg;
+		}
+
+		dec->d_keep_in_cache_list.push_back(object_ids[i]);
+	}
+
+	return 1;
+}
+
+void NEWS_SVC_DEC_IMPL_printObjList(NEWS_SVC_DEC_IMPL_t *dec)
+{
+	log_info << "print object map:" << std::endl << endmsg;
+	NEWS_SVC_DEC_IMPL_map_t::iterator e;
+	for(e=dec->d_news_map.begin();e!=dec->d_news_map.end();++e)
+	{
+		log_info_nots << "object id: " << (*e).first << std::endl << endmsg;
+	}
+}
+
+FindMinFunctor::FindMinFunctor(NEWS_SVC_DEC_IMPL_t *dec) :
+	d_dec(dec)
+{
+}
+
+FindMinFunctor::FindMinFunctor(const FindMinFunctor &rhs)
+{
+	d_dec=rhs.d_dec;
+}
+
+FindMinFunctor::~FindMinFunctor()
+{
+}
+
+bool FindMinFunctor::operator()(
+		std::pair<const unsigned long, NewsObject*> &rhs,
+		std::pair<const unsigned long, NewsObject*> &lhs)
+{
+	NewsObject *no1=rhs.second;
+	NewsObject *no2=lhs.second;
+
+	unsigned long obj_id1=no1->getObjectId();
+	unsigned long obj_id2=no2->getObjectId();
+#if 1
+	if(showDdNewsSvcDecInfo)
+	{
+		log_info << "compare " << obj_id1 << " with " << obj_id2 << endmsg;
+	}
+#endif
+
+	NEWS_SVC_DEC_IMPL_keep_in_cache_list_t &l=d_dec->d_keep_in_cache_list;
+	if(find(l.begin(), l.end(), obj_id1)!=l.end())
+	{
+		// special case root menu
+		if(showDdNewsSvcDecInfo)
+		{
+			log_info << "don't erase id " << obj_id1 <<
+			" from keep in cache list" << endmsg;
+		}
+		return false;
+	}
+	if(find(l.begin(), l.end(), obj_id2)!=l.end())
+	{
+		// special case root menu
+		if(showDdNewsSvcDecInfo)
+		{
+			log_info << "don't erase id " << obj_id2 <<
+			" from keep in cache list" << endmsg;
+		}
+		return true;
+	}
+
+	struct timeval t1=no1->getReceptionTime();
+	struct timeval t2=no2->getReceptionTime();
+
+	if(t1.tv_sec==t2.tv_sec)
+	{
+		return t1.tv_usec < t2.tv_usec;
+	}
+
+	return t1.tv_sec < t2.tv_sec;
+}
+
diff --git a/src/datadecoding/journaline/newssvcdec_impl.h b/src/datadecoding/journaline/newssvcdec_impl.h
new file mode 100644
index 0000000..7cd818f
--- /dev/null
+++ b/src/datadecoding/journaline/newssvcdec_impl.h
@@ -0,0 +1,137 @@
+/* 
+ *
+ * This file is part of the 'NewsService Journaline(R) Decoder'
+ * 
+ * Copyright (c) 2003, 2001-2014 by Fraunhofer IIS, Erlangen, Germany
+ * 
+ * --------------------------------------------------------------------
+ * 
+ * For NON-COMMERCIAL USE,
+ * the 'NewsService Journaline(R) Decoder' is free software;
+ * you can redistribute it and/or modify it under the terms of
+ * the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * The 'NewsService Journaline(R) Decoder' is distributed in the hope
+ * that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with the 'NewsService Journaline(R) Decoder';
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ * 
+ * If you use this software in a project with user interaction, please
+ * provide the following text to the user in an appropriate place:
+ * "Features NewsService Journaline(R) decoder technology by
+ * Fraunhofer IIS, Erlangen, Germany.
+ * For more information visit http://www.iis.fhg.de/dab"
+ * 
+ * --------------------------------------------------------------------
+ * 
+ * To use the 'NewsService Journaline(R) Decoder' software for
+ * COMMERCIAL purposes, please contact Fraunhofer IIS for a
+ * commercial license (see below for contact information)!
+ * 
+ * --------------------------------------------------------------------
+ * 
+ * Contact:
+ *   Fraunhofer IIS, Department 'Broadcast Applications'
+ *   Am Wolfsmantel 33, 91058 Erlangen, Germany
+ *   http://www.iis.fraunhofer.de/dab
+ *   mailto:bc-info at iis.fraunhofer.de
+ * 
+ */
+
+#ifndef __NEWS_SVC_DEC_IMPL__
+#define __NEWS_SVC_DEC_IMPL__
+/**
+*** 			techidee GmbH
+*** Projekt:	NewsBox
+*** Autor:		Thomas Fruehwald
+***
+*** Compiler:	gcc
+*** Modul:
+		news service decoder implementation
+***
+***
+**/
+#include "newsobject.h"
+#include "newssvcdec.h"
+
+
+#ifdef _MSC_VER
+#pragma warning(push,3)
+#pragma warning(disable:4100)
+#pragma warning(disable:4514)
+#endif
+
+#include <map>
+#include <list>
+
+#ifdef _MSC_VER
+#pragma warning(pop)
+#pragma warning(disable:4100)
+#endif
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int showDdNewsSvcDecInfo;
+extern int showDdNewsSvcDecErr;
+
+#define NEWS_SVC_MAGIC_ID	0x786245
+
+typedef std::map<unsigned long, NewsObject*> NEWS_SVC_DEC_IMPL_map_t;
+typedef std::list<unsigned short> NEWS_SVC_DEC_IMPL_watch_list_t;
+typedef std::list<unsigned short> NEWS_SVC_DEC_IMPL_keep_in_cache_list_t;
+
+typedef struct
+{
+	unsigned long	d_magicId;
+	NEWS_SVC_DEC_cb	*d_update;
+	void			*d_arg;
+	unsigned long	d_extended_header_len;
+	unsigned long	d_max_memory;
+	unsigned long	d_max_objects;
+	unsigned long	d_object_count;
+
+	NEWS_SVC_DEC_IMPL_map_t	d_news_map;
+
+	NEWS_SVC_DEC_IMPL_watch_list_t d_watch_list;
+	NEWS_SVC_DEC_IMPL_keep_in_cache_list_t d_keep_in_cache_list;
+} NEWS_SVC_DEC_IMPL_t;
+
+int NEWS_SVC_DEC_IMPL_garbage_collection(NEWS_SVC_DEC_IMPL_t *dec,
+	unsigned long objs_to_free);
+
+#ifdef __cplusplus
+}
+#endif
+
+/* internal functions */
+void NEWS_SVC_DEC_IMPL_printObjList(NEWS_SVC_DEC_IMPL_t *dec);
+
+class FindMinFunctor
+{
+public:
+	FindMinFunctor(NEWS_SVC_DEC_IMPL_t *dec);
+	FindMinFunctor(const FindMinFunctor &rhs);
+	~FindMinFunctor();
+
+	bool operator()(
+		std::pair<const unsigned long, NewsObject*> &rhs,
+		std::pair<const unsigned long, NewsObject*> &lhs);
+
+private:
+	NEWS_SVC_DEC_IMPL_t *d_dec;
+};
+
+
+#endif /* __NEWS_SVC_DEC_IMPL */
diff --git a/src/drmchannel/ChannelSimulation.cpp b/src/drmchannel/ChannelSimulation.cpp
new file mode 100644
index 0000000..cc39ede
--- /dev/null
+++ b/src/drmchannel/ChannelSimulation.cpp
@@ -0,0 +1,623 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer, Alexander Kurpiers
+ *
+ * Description:
+ *	DRM channel simulation
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "ChannelSimulation.h"
+
+
+/* Implementation *************************************************************/
+void CDRMChannel::ProcessDataInternal(CParameter&)
+{
+    int			i, j;
+    _COMPLEX	cCurTapSamp;
+
+    /* Save old values from the end of the vector */
+    for (i = 0; i < iMaxDelay; i++)
+        veccHistory[i] = veccHistory[i + iInputBlockSize];
+
+    /* Write new symbol in memory */
+    for (i = iMaxDelay; i < iLenHist; i++)
+        veccHistory[i] = (*pvecInputData)[i - iMaxDelay];
+
+    /* Delay signal using history buffer, add tap gain (fading), multiply with
+       exp-function (optimized implementation, see below) to implement
+       doppler shift */
+    /* Direct path */
+    for (i = 0; i < iInputBlockSize; i++)
+    {
+        cCurTapSamp = tap[0].Update() * cCurExp[0];
+
+        veccOutput[i] =	veccHistory[i + iMaxDelay /* - 0 */] * cCurTapSamp;
+
+        /* Rotate exp-pointer one step further by complex multiplication with
+           precalculated rotation vector cExpStep. This saves us from
+           calling sin() and cos() functions all the time (iterative
+           calculation of these functions) */
+        cCurExp[0] *= cExpStep[0];
+
+        /* Store the tap gain */
+        (*pvecOutputData)[i].veccTap[0] = cCurTapSamp;
+    }
+
+    /* Echos */
+    for (j = 1; j < iNumTaps; j++)
+    {
+        for (i = 0; i < iInputBlockSize; i++)
+        {
+            cCurTapSamp = tap[j].Update() * cCurExp[j];
+
+            veccOutput[i] +=
+                veccHistory[i + iMaxDelay - tap[j].GetDelay()] * cCurTapSamp;
+
+            /* See above */
+            cCurExp[j] *= cExpStep[j];
+
+            /* Store the tap gain */
+            (*pvecOutputData)[i].veccTap[j] = cCurTapSamp;
+        }
+    }
+
+    /* Get real output vector and correct global gain */
+    for (i = 0; i < iInputBlockSize; i++)
+        (*pvecOutputData)[i].tOut = veccOutput[i].real() * rGainCorr;
+
+    /* Additional white Gaussian noise (AWGN) */
+    for (i = 0; i < iInputBlockSize; i++)
+        (*pvecOutputData)[i].tOut += randn() * rNoisepwrFactor;
+
+
+    /* Reference signals for channel estimation evaluation ------------------ */
+    /* Input reference signal. "* 2" due to the real-valued signal */
+    for (i = 0; i < iInputBlockSize; i++)
+        (*pvecOutputData)[i].tIn = (*pvecInputData)[i].real() * 2;
+
+    /* Channel reference signal (without additional noise) */
+    for (i = 0; i < iInputBlockSize; i++)
+        (*pvecOutputData)[i].tRef = veccOutput[i].real() * rGainCorr;
+}
+
+void CDRMChannel::InitInternal(CParameter& Parameters)
+{
+    Parameters.Lock();
+    iSampleRate = Parameters.GetSigSampleRate();
+    /* Set channel parameter according to selected channel number (table B.1) */
+    switch (Parameters.iDRMChannelNum)
+    {
+    case 1:
+        /* AWGN */
+        iNumTaps = 1;
+
+        tap[0].Init(
+		/* Sample Rate */	iSampleRate,
+		/* Delay: */	(_REAL) 0.0,
+                /* Gain: */		(_REAL) 1.0,
+                /* Fshift: */	(_REAL) 0.0,
+                /* Fd: */		(_REAL) 0.0);
+        break;
+
+    case 2:
+        /* Rice with delay */
+        iNumTaps = 2;
+
+        tap[0].Init(
+		/* Sample Rate */	iSampleRate,
+/* Delay: */	(_REAL) 0.0,
+                                 /* Gain: */		(_REAL) 1.0,
+                                 /* Fshift: */	(_REAL) 0.0,
+                                 /* Fd: */		(_REAL) 0.0);
+
+        tap[1].Init(
+		/* Sample Rate */	iSampleRate,
+	/* Delay: */	(_REAL) 1.0,
+                                 /* Gain: */		(_REAL) 0.5,
+                                 /* Fshift: */	(_REAL) 0.0,
+                                 /* Fd: */		(_REAL) 0.1);
+        break;
+
+    case 3:
+        /* US Consortium */
+        iNumTaps = 4;
+
+        tap[0].Init(
+		/* Sample Rate */	iSampleRate,
+/* Delay: */	(_REAL) 0.0,
+                                 /* Gain: */		(_REAL) 1.0,
+                                 /* Fshift: */	(_REAL) 0.1,
+                                 /* Fd: */		(_REAL) 0.1);
+
+        tap[1].Init(
+		/* Sample Rate */	iSampleRate,
+/* Delay: */	(_REAL) 0.7,
+                                 /* Gain: */		(_REAL) 0.7,
+                                 /* Fshift: */	(_REAL) 0.2,
+                                 /* Fd: */		(_REAL) 0.5);
+
+        tap[2].Init(
+		/* Sample Rate */	iSampleRate,
+/* Delay: */	(_REAL) 1.5,
+                                 /* Gain: */		(_REAL) 0.5,
+                                 /* Fshift: */	(_REAL) 0.5,
+                                 /* Fd: */		(_REAL) 1.0);
+
+        tap[3].Init(
+		/* Sample Rate */	iSampleRate,
+/* Delay: */	(_REAL) 2.2,
+                                 /* Gain: */		(_REAL) 0.25,
+                                 /* Fshift: */	(_REAL) 1.0,
+                                 /* Fd: */		(_REAL) 2.0);
+        break;
+
+    case 4:
+        /* CCIR Poor */
+        iNumTaps = 2;
+
+        tap[0].Init(
+		/* Sample Rate */	iSampleRate,
+	/* Delay: */	(_REAL) 0.0,
+                                 /* Gain: */		(_REAL) 1.0,
+                                 /* Fshift: */	(_REAL) 0.0,
+                                 /* Fd: */		(_REAL) 1.0);
+
+        tap[1].Init(
+		/* Sample Rate */	iSampleRate,
+	/* Delay: */	(_REAL) 2.0,
+                                 /* Gain: */		(_REAL) 1.0,
+                                 /* Fshift: */	(_REAL) 0.0,
+                                 /* Fd: */		(_REAL) 1.0);
+        break;
+
+    case 5:
+        /* Channel no 5 */
+        iNumTaps = 2;
+
+        tap[0].Init(
+		/* Sample Rate */	iSampleRate,
+	/* Delay: */	(_REAL) 0.0,
+                                 /* Gain: */		(_REAL) 1.0,
+                                 /* Fshift: */	(_REAL) 0.0,
+                                 /* Fd: */		(_REAL) 2.0);
+
+        tap[1].Init(
+		/* Sample Rate */	iSampleRate,
+	/* Delay: */	(_REAL) 4.0,
+                                 /* Gain: */		(_REAL) 1.0,
+                                 /* Fshift: */	(_REAL) 0.0,
+                                 /* Fd: */		(_REAL) 2.0);
+        break;
+
+    case 6:
+        /* Channel #6 */
+        iNumTaps = 4;
+
+        tap[0].Init(
+		/* Sample Rate */	iSampleRate,
+	/* Delay: */	(_REAL) 0.0,
+                                 /* Gain: */		(_REAL) 0.5,
+                                 /* Fshift: */	(_REAL) 0.0,
+                                 /* Fd: */		(_REAL) 0.1);
+
+        tap[1].Init(
+		/* Sample Rate */	iSampleRate,
+	/* Delay: */	(_REAL) 2.0,
+                                 /* Gain: */		(_REAL) 1.0,
+                                 /* Fshift: */	(_REAL) 1.2,
+                                 /* Fd: */		(_REAL) 2.4);
+
+        tap[2].Init(
+		/* Sample Rate */	iSampleRate,
+	/* Delay: */	(_REAL) 4.0,
+                                 /* Gain: */		(_REAL) 0.25,
+                                 /* Fshift: */	(_REAL) 2.4,
+                                 /* Fd: */		(_REAL) 4.8);
+
+        tap[3].Init(
+		/* Sample Rate */	iSampleRate,
+	/* Delay: */	(_REAL) 6.0,
+                                 /* Gain: */		(_REAL) 0.0625,
+                                 /* Fshift: */	(_REAL) 3.6,
+                                 /* Fd: */		(_REAL) 7.2);
+        break;
+
+
+        /* My own test channels, NOT DEFINED IN THE DRM STANDARD! --------------- */
+    case 7:
+        /* Channel without fading and doppler shift */
+        iNumTaps = 4;
+
+        tap[0].Init(
+		/* Sample Rate */	iSampleRate,
+	/* Delay: */	(_REAL) 0.0,
+                                 /* Gain: */		(_REAL) 1.0,
+                                 /* Fshift: */	(_REAL) 0.0,
+                                 /* Fd: */		(_REAL) 0.0);
+
+        tap[1].Init(
+		/* Sample Rate */	iSampleRate,
+	/* Delay: */	(_REAL) 0.7,
+                                 /* Gain: */		(_REAL) 0.7,
+                                 /* Fshift: */	(_REAL) 0.0,
+                                 /* Fd: */		(_REAL) 0.0);
+
+        tap[2].Init(
+		/* Sample Rate */	iSampleRate,
+	/* Delay: */	(_REAL) 1.5,
+                                 /* Gain: */		(_REAL) 0.5,
+                                 /* Fshift: */	(_REAL) 0.0,
+                                 /* Fd: */		(_REAL) 0.0);
+
+        tap[3].Init(
+		/* Sample Rate */	iSampleRate,
+	/* Delay: */	(_REAL) 2.2,
+                                 /* Gain: */		(_REAL) 0.25,
+                                 /* Fshift: */	(_REAL) 0.0,
+                                 /* Fd: */		(_REAL) 0.0);
+        break;
+
+    case 8:
+        /* Only one fading path */
+        iNumTaps = 1;
+
+        tap[0].Init(
+		/* Sample Rate */	iSampleRate,
+	/* Delay: */	(_REAL) 0.0,
+                                 /* Gain: */		(_REAL) 1.0,
+                                 /* Fshift: */	(_REAL) 0.0,
+                                 /* Fd: */		(_REAL) Parameters.iSpecChDoppler);
+        break;
+
+    case 9:
+        /* Two moderate fading taps close to each other with equal gain */
+        iNumTaps = 2;
+
+        tap[0].Init(
+		/* Sample Rate */	iSampleRate,
+	/* Delay: */	(_REAL) 0.0,
+                                 /* Gain: */		(_REAL) 1.0,
+                                 /* Fshift: */	(_REAL) 0.0,
+                                 /* Fd: */		(_REAL) 1.0);
+
+        tap[1].Init(
+		/* Sample Rate */	iSampleRate,
+	/* Delay: */	(_REAL) 0.7,
+                                 /* Gain: */		(_REAL) 1.0,
+                                 /* Fshift: */	(_REAL) 0.0,
+                                 /* Fd: */		(_REAL) 1.0);
+        break;
+
+    case 10:
+        /* Frequency offset */
+        iNumTaps = 1;
+
+        tap[0].Init(
+		/* Sample Rate */	iSampleRate,
+	/* Delay: */	(_REAL) 0.0,
+                                 /* Gain: */		(_REAL) 1.0,
+                                 /* Fshift: */	(_REAL) Parameters.iSpecChDoppler,
+                                 /* Fd: */		(_REAL) 0.0);
+        break;
+
+    case 11:
+        /* Same as channel 5 but with variable Doppler */
+        iNumTaps = 2;
+
+        tap[0].Init(
+		/* Sample Rate */	iSampleRate,
+	/* Delay: */	(_REAL) 0.0,
+                                 /* Gain: */		(_REAL) 1.0,
+                                 /* Fshift: */	(_REAL) 0.0,
+                                 /* Fd: */		(_REAL) Parameters.iSpecChDoppler);
+
+        tap[1].Init(
+		/* Sample Rate */	iSampleRate,
+	/* Delay: */	(_REAL) 4.0,
+                                 /* Gain: */		(_REAL) 1.0,
+                                 /* Fshift: */	(_REAL) 0.0,
+                                 /* Fd: */		(_REAL) Parameters.iSpecChDoppler);
+        break;
+
+    case 12:
+        /* Same as 8 but we need to redefined because of OFDM.cpp module and
+           MMSE estimation */
+        iNumTaps = 1;
+
+        tap[0].Init(
+		/* Sample Rate */	iSampleRate,
+	/* Delay: */	(_REAL) 0.0,
+                                 /* Gain: */		(_REAL) 1.0,
+                                 /* Fshift: */	(_REAL) 0.0,
+                                 /* Fd: */		(_REAL) Parameters.iSpecChDoppler);
+        break;
+    }
+
+
+    /* Init exponent steps (for doppler shift) and gain correction ---------- */
+    rGainCorr = (_REAL) 0.0;
+    for (int i = 0; i < iNumTaps; i++)
+    {
+        /* Exponent function for shifting (doppler shift) */
+        cCurExp[i] = (_REAL) 1.0;
+
+        cExpStep[i] =
+            _COMPLEX(cos(tap[i].GetFShift()), sin(tap[i].GetFShift()));
+
+        /* Gain correction denominator */
+        rGainCorr += tap[i].GetGain() * tap[i].GetGain();
+
+        /* Get path delays for global struct */
+        Parameters.iPathDelay[i] = tap[i].GetDelay();
+    }
+
+    /* Final gain correction value. "* 2" due to the real-valued signals */
+    rGainCorr = (_REAL) 1.0 / sqrt(rGainCorr) * 2;
+
+    /* Set number of taps and gain correction in global struct */
+    Parameters.iNumTaps = iNumTaps;
+    Parameters.rGainCorr = rGainCorr / 2;
+
+
+    /* Memory allocation ---------------------------------------------------- */
+    /* Maximum delay */
+    iMaxDelay = tap[iNumTaps - 1].GetDelay();
+
+    /* Allocate memory for history, init vector with zeros. This history is used
+       for generating path delays */
+    iLenHist = Parameters.CellMappingTable.iSymbolBlockSize + iMaxDelay;
+    veccHistory.Init(iLenHist, _COMPLEX((_REAL) 0.0, (_REAL) 0.0));
+
+    /* Allocate memory for temporary output vector for complex values */
+    veccOutput.Init(Parameters.CellMappingTable.iSymbolBlockSize);
+
+
+    /* Calculate noise power factors for a given SNR ------------------------ */
+    /* Spectrum width (N / T_u) */
+    const _REAL rSpecOcc = (_REAL) Parameters.CellMappingTable.iNumCarrier /
+                           Parameters.CellMappingTable.iFFTSizeN * iSampleRate;
+
+    /* Bandwidth correction factor for noise (f_s / (2 * B))*/
+    const _REAL rBWFactor = (_REAL) iSampleRate / 2 / rSpecOcc;
+
+    /* Calculation of the gain factor for noise generator */
+    rNoisepwrFactor =
+        sqrt(pow((_REAL) 10.0, -Parameters.GetSystemSNRdB() / 10) *
+             Parameters.CellMappingTable.rAvPowPerSymbol * 2 * rBWFactor);
+
+
+    /* Set seed of random noise generator */
+    srand((unsigned) time(NULL));
+
+    /* Define block-sizes for input and output */
+    iInputBlockSize = Parameters.CellMappingTable.iSymbolBlockSize;
+    iOutputBlockSize = Parameters.CellMappingTable.iSymbolBlockSize;
+    Parameters.Unlock();
+}
+
+void CTapgain::Init(int iNewSampleRate, _REAL rNewDelay, _REAL rNewGain, _REAL rNewFshift,
+                    _REAL rNewFd)
+{
+    _REAL	s;
+    int		k;
+
+    /* Set internal parameters (convert units and normalize values) */
+
+    samplerate = iNewSampleRate;
+    delay = DelMs2Sam(rNewDelay);
+    gain = rNewGain;
+    fshift = NormShift(rNewFshift);
+    fd = rNewFd;
+
+    s = (_REAL) 0.5 * fd / samplerate;
+
+    /* If tap is not fading, return function */
+    if (s == (_REAL) 0.0)
+        return;
+
+    if (s > 0.03)
+    {
+        interpol = 0;
+        polyinterpol = 1;
+        phase = -1;
+    }
+    else
+    {
+        if (s > 0.017)
+        {
+            interpol = 0;
+            polyinterpol = 2;
+            phase = 0;
+        }
+        else
+        {
+            if (s > 0.0084)
+            {
+                interpol = 0;
+                polyinterpol = 4;
+                phase = 0;
+            }
+            else
+            {
+                if (s > 0.0042)
+                {
+                    interpol = 0;
+                    polyinterpol = 8;
+                    phase = 0;
+                }
+                else
+                {
+                    interpol = (int) (0.0042 / s + 1);
+                    polyinterpol = 8;
+                    s = s * interpol;
+                    phase = 0;
+                }
+            }
+        }
+    }
+
+    gausstp(taps, s, polyinterpol);
+
+    /* Initialize FIR buffer */
+    for (k = 0; k < FIRLENGTH; k++)
+    {
+        fir_buff[k][0] = randn();
+        fir_buff[k][1] = randn();
+    }
+
+    if (interpol)
+    {
+        /* Compute nextI and nextQ */
+        nextI = (_REAL) 0.0;
+        nextQ = (_REAL) 0.0;
+
+        /* FIR filter */
+        for (k = 0; k < FIRLENGTH; k++)
+        {
+            nextI += fir_buff[k][0] * taps[FIRLENGTH - k - 1];
+            nextQ += fir_buff[k][1] * taps[FIRLENGTH - k - 1];
+        }
+    }
+
+    over_cnt = 0;
+    fir_index = 0;
+}
+
+_COMPLEX CTapgain::Update()
+{
+    int			k;
+    _COMPLEX	out;
+
+    /* If tap is not fading, just return gain */
+    if (fd == (_REAL) 0.0)
+        return gain;
+
+    /* Over_cnt is always zero if no interpolation is used */
+    if (!over_cnt)
+    {
+        lastI = nextI;
+        lastQ = nextQ;
+
+        /* Get new noise sample */
+        if ((phase == -1) || (phase == 0))
+        {
+            fir_buff[fir_index][0] = randn();
+            fir_buff[fir_index][1] = randn();
+
+            fir_index = (fir_index - 1 + FIRLENGTH) % FIRLENGTH;
+        }
+
+        /* Compute new filter output */
+        nextI = (_REAL) 0.0;
+        nextQ = (_REAL) 0.0;
+
+        if (phase == -1)
+        {
+            /* FIR */
+            for (k = 0; k < FIRLENGTH; k++)
+            {
+                nextI +=
+                    fir_buff[(k + fir_index) % FIRLENGTH][0] *
+                    taps[FIRLENGTH - k - 1];
+                nextQ +=
+                    fir_buff[(k + fir_index) % FIRLENGTH][1] *
+                    taps[FIRLENGTH - k - 1];
+            }
+        }
+        else
+        {
+            /* Polyphase FIR with interpolation */
+            for (k = 0; k < FIRLENGTH; k++)
+            {
+                nextI +=
+                    fir_buff[(k + fir_index) % FIRLENGTH][0] *
+                    taps[polyinterpol * (FIRLENGTH - k) - phase - 1];
+                nextQ +=
+                    fir_buff[(k + fir_index) % FIRLENGTH][1] *
+                    taps[polyinterpol * (FIRLENGTH - k) - phase - 1];
+            }
+
+            phase = (phase + 1) % polyinterpol;
+        }
+    }
+
+    if (interpol)
+    {
+        /* Linear interpolation */
+        out  = _COMPLEX((nextI - lastI) * (_REAL) over_cnt /
+                        interpol + lastI,
+                        (nextQ - lastQ) * (_REAL) over_cnt /
+                        interpol + lastQ);
+
+        if (++over_cnt == interpol)
+            over_cnt = 0;
+    }
+    else
+        out = _COMPLEX(nextI, nextQ);
+
+    /* Weight with gain */
+    const _REAL ccGainCorr = sqrt((_REAL) 2.0);
+    return out * gain / ccGainCorr;
+}
+
+void CTapgain::gausstp(_REAL taps[], _REAL& s, int& over) const
+{
+    /* Calculate impulse response of FIR filter to implement
+    the Watterson modell (Gaussian PSD) */
+
+    /* "2 * s" is the doppler spread */
+    for (int n = 0; n < (FIRLENGTH * over); n++)
+    {
+        taps[n] = sqrt(sqrt(crPi * (_REAL) 8.0) * s * over) *
+                  exp(-fsqr((_REAL) 2.0 * crPi * s * (n - FIRLENGTH * over / 2)));
+    }
+}
+
+int CTapgain::DelMs2Sam(const _REAL rDelay) const
+{
+    /* Delay in samples. The channel taps are shifted to the taps that are
+       possible for the given sample rate -> approximation! */
+    return (int) (rDelay /* ms */ * samplerate / 1000);
+}
+
+_REAL CTapgain::NormShift(const _REAL rShift) const
+{
+    /* Normalize doppler shift */
+    return (_REAL) 2.0 * crPi / samplerate * rShift;
+}
+
+_REAL CChannelSim::randn() const
+{
+    const int iNoRand = 10;
+    const _REAL rFactor = (_REAL) sqrt((_REAL) 12.0 / iNoRand) / RAND_MAX;
+    const int iRandMaxHalf = RAND_MAX / 2;
+
+    /* Add some constant distributed random processes to get Gaussian
+       distribution */
+    _REAL rNoise = 0;
+    for (int i = 0; i < iNoRand; i++)
+        rNoise += rand() - iRandMaxHalf;
+
+    /* Apply amplification factor */
+    return rNoise * rFactor;
+}
diff --git a/src/drmchannel/ChannelSimulation.h b/src/drmchannel/ChannelSimulation.h
new file mode 100644
index 0000000..ea4c2e6
--- /dev/null
+++ b/src/drmchannel/ChannelSimulation.h
@@ -0,0 +1,118 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Alexander Kurpiers, Volker Fischer
+ *
+ * Description:
+ *	See ChannelSimulation.cpp
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#if !defined(DRMCHANNEL_H__3B0BA660_CA63_4344_BB2B_2OJVBEWJBWV_INCLUDED_)
+#define DRMCHANNEL_H__3B0BA660_CA63_4344_BB2B_2OJVBEWJBWV_INCLUDED_
+
+#include "../Parameter.h"
+#include "../util/Modul.h"
+#include <time.h>
+
+
+/* Definitions ****************************************************************/
+#define FIRLENGTH					24
+
+#define fsqr(a)						((a) * (a))
+
+
+/* Classes ********************************************************************/
+class CChannelSim
+{
+public:
+    inline _REAL randn() const;
+};
+
+class CTapgain : public CChannelSim
+{
+public:
+    void Init(int iNewSampleRate, _REAL rNewDelay, _REAL rNewGain, _REAL rNewFshift, _REAL rNewFd);
+    _COMPLEX Update();
+    _REAL GetGain() const {
+        return gain;
+    }
+    int GetDelay() const {
+        return delay;
+    }
+    _REAL GetFShift() const {
+        return fshift;
+    }
+
+
+protected:
+    _REAL		taps[FIRLENGTH * 8]; /* FIR filter coefficients */
+    int			over_cnt;		/* Counter for oversampling */
+    int			phase;			/* Phase for polyphase oversampling */
+    int			interpol;		/* interpolation factor for linear interpolation*/
+    int			polyinterpol;	/* interpolation factor for polyphase interpolation */
+    int			fir_index;		/* index to FIR buffer */
+    _REAL		fir_buff[FIRLENGTH][2]; /* FIR buffer */
+    _REAL		lastI, lastQ;	/* last FIR output, needed for interpolation */
+    _REAL		nextI, nextQ;	/* next FIR output */
+
+    _REAL fd;					/* Fading rate */
+    _REAL fshift;				/* Doppler shift */
+    _REAL gain;					/* Tap-gain */
+    int delay;					/* Path delay */
+    int samplerate;				/* Sound Card Sample Rate */
+
+    int		DelMs2Sam(const _REAL rDelay) const;
+    _REAL	NormShift(const _REAL rShift) const;
+    void	gausstp(_REAL taps[], _REAL& s, int& over) const;
+};
+
+class CDRMChannel :
+            /* The third template argument "_COMPLEX" is not used since this module
+               has only one input and one output buffer */
+            public CSimulationModul<_COMPLEX, CChanSimDataMod, _COMPLEX>, CChannelSim
+{
+public:
+    CDRMChannel() {}
+    virtual ~CDRMChannel() {}
+
+protected:
+    CTapgain			tap[4];
+    _COMPLEX			cCurExp[4];
+    _COMPLEX			cExpStep[4];
+
+    int					iSampleRate;
+    int					iNumTaps;
+    CVector<_COMPLEX>	veccHistory;
+    int					iMaxDelay;
+    int					iLenHist;
+    CVector<_COMPLEX>	veccOutput;
+    _REAL				rGainCorr;
+    _REAL				rNoisepwrFactor;
+
+    void InitTapgain(CTapgain& tapg);
+
+    virtual void InitInternal(CParameter& Parameters);
+    virtual void ProcessDataInternal(CParameter& Parameters);
+};
+
+
+#endif // !defined(DRMCHANNEL_H__3B0BA660_CA63_4344_BB2B_2OJVBEWJBWV_INCLUDED_)
diff --git a/src/interleaver/BlockInterleaver.cpp b/src/interleaver/BlockInterleaver.cpp
new file mode 100644
index 0000000..939cfcc
--- /dev/null
+++ b/src/interleaver/BlockInterleaver.cpp
@@ -0,0 +1,69 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later 
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT 
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "BlockInterleaver.h"
+
+
+/* Implementation *************************************************************/
+/******************************************************************************\
+* Block-interleaver base class												   *
+\******************************************************************************/
+void CBlockInterleaver::MakeTable(CVector<int>& veciIntTable, int iFrameSize, 
+								  int it_0)
+{
+	int i;
+	int	iHighestOne;
+	int is, iq;
+
+	/* The following equations are taken directly from the DRM-standard paper 
+	   (7.3.3 and 7.6) */
+	iHighestOne = iFrameSize;
+	/* s = 2 ^ ceil(log2(iFrameSize)), means: find the highest "1" of 
+	   iFrameSize. The result of the equation is only one "1" at position 
+	   "highest position of "1" in iFrameSize plus one". Therefore: 
+	   "1 << (16 + 1)".
+	   This implementation: shift bits in iHighestOne to the left until a 
+	   "1" reaches position 16. Simultaneously the bit in "is" is 
+	   right-shifted */
+	is = 1 << (16 + 1);
+	while (!(iHighestOne & (1 << 16)))
+	{
+		iHighestOne <<= 1;
+		is >>= 1;
+	}
+
+	iq = is / 4 - 1;
+
+	veciIntTable[0] = 0;
+
+	for (i = 1; i < iFrameSize; i++)
+	{
+		veciIntTable[i] = (it_0 * veciIntTable[i - 1] + iq) % is;
+		while (veciIntTable[i] >= iFrameSize)
+			veciIntTable[i] = (it_0 * veciIntTable[i] + iq) % is;
+	}
+}
diff --git a/src/interleaver/BlockInterleaver.h b/src/interleaver/BlockInterleaver.h
new file mode 100644
index 0000000..88bb34c
--- /dev/null
+++ b/src/interleaver/BlockInterleaver.h
@@ -0,0 +1,48 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *	See Blockinterleaver.cpp
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later 
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT 
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#if !defined(BLOCK_INTERL_H__3B0BA660_CA63_4344_BB2B_23E7A0D31912__INCLUDED_)
+#define BLOCK_INTERL_H__3B0BA660_CA63_4344_BB2B_23E7A0D31912__INCLUDED_
+
+#include "../GlobalDefinitions.h"
+#include "../util/Vector.h"
+
+
+/* Classes ********************************************************************/
+class CBlockInterleaver
+{
+public:
+	CBlockInterleaver() {}
+	virtual ~CBlockInterleaver() {}
+
+protected:
+	void MakeTable(CVector<int>& veciIntTable, int iFrameSize, int it_0);
+};
+
+
+#endif // !defined(BLOCK_INTERL_H__3B0BA660_CA63_4344_BB2B_23E7A0D31912__INCLUDED_)
diff --git a/src/interleaver/SymbolInterleaver.cpp b/src/interleaver/SymbolInterleaver.cpp
new file mode 100644
index 0000000..191b925
--- /dev/null
+++ b/src/interleaver/SymbolInterleaver.cpp
@@ -0,0 +1,216 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *	Symbol interleaver for MSC-symbols
+ *	We have to support long and short symbol interleaving. Long interleaving
+ *	spans over iD times iN_MUX interleaver blocks. To create a "block-wise 
+ *	cycle-buffer" we shift the indices (stored in a table) each time a complete
+ *	block was written. Thus, we dont need to copy data since we only modify
+ *	the indices. 
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later 
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT 
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "SymbolInterleaver.h"
+
+
+/* Implementation *************************************************************/
+/******************************************************************************\
+* Symbol interleaver														   *
+\******************************************************************************/
+void CSymbInterleaver::ProcessDataInternal(CParameter&)
+{
+	int i, j;
+
+	/* Write data in interleaver-memory (always index "0") */
+	for (i = 0; i < iInputBlockSize; i++)
+		matcInterlMemory[veciCurIndex[0]][i] = (*pvecInputData)[i];
+
+	/* Interleave data according to the interleaver table. Use the
+	   the interleaver-blocks described in the DRM-standard 
+	   (Ro(i) = i (mod D)  -> "i % iD") */
+	for (i = 0; i < iInputBlockSize; i++)
+		(*pvecOutputData)[i] = 
+			matcInterlMemory[veciCurIndex[i % iD]][veciIntTable[i]];
+
+	/* Set new indices. Move blocks (virtually) forward */
+	for (j = 0; j < iD; j++)
+	{
+		veciCurIndex[j]--;
+
+		if (veciCurIndex[j] < 0)
+			veciCurIndex[j] = iD - 1;
+	}
+}
+
+void CSymbInterleaver::InitInternal(CParameter& TransmParam)
+{
+	int i;
+
+	TransmParam.Lock(); 
+
+	/* Set internal parameters */
+	iN_MUX = TransmParam.CellMappingTable.iNumUsefMSCCellsPerFrame;
+
+	/* Allocate memory for table */
+	veciIntTable.Init(iN_MUX);
+
+	/* Make interleaver table */
+	MakeTable(veciIntTable, iN_MUX, SYMB_INTERL_CONST_T_0);
+
+	/* Set interleaver depth */
+	switch (TransmParam.eSymbolInterlMode)
+	{
+    case SI_LONG:
+		iD = D_LENGTH_LONG_INTERL;
+		break;
+
+    case SI_SHORT:
+		iD = D_LENGTH_SHORT_INTERL;
+		break;
+    case SI_MODE_E: // TODO
+		;
+	}
+
+	/* Always allocate memory for long interleaver case (interleaver memory) */
+	matcInterlMemory.Init(D_LENGTH_LONG_INTERL, iN_MUX);
+
+	/* Index for addressing the buffers */
+	veciCurIndex.Init(D_LENGTH_LONG_INTERL);
+	for (i = 0; i < D_LENGTH_LONG_INTERL; i++)
+		veciCurIndex[i] = i;
+
+	/* Define block-sizes for input and output */
+	iInputBlockSize = iN_MUX;
+	iOutputBlockSize = iN_MUX;
+
+	/* Since the MSC logical frames must not end at the end of one symbol
+	   (could be somewhere in the middle of the symbol), the output buffer must
+	   accept more cells than one logical MSC frame is long */
+	iMaxOutputBlockSize = 2 * iN_MUX;
+
+	TransmParam.Unlock(); 
+}
+
+
+/******************************************************************************\
+* Symbol deinterleaver														   *
+\******************************************************************************/
+void CSymbDeinterleaver::ProcessDataInternal(CParameter&)
+{
+	int i, j;
+
+	/* Deinterleave data according to the deinterleaver table. Use the
+	   the interleaver-blocks described in the DRM-standard 
+	   (Ro(i) = i (mod D)  -> "i % iD") */
+	for (i = 0; i < iInputBlockSize; i++)
+		matcDeinterlMemory[veciCurIndex[i % iD]][veciIntTable[i]] = 
+			(*pvecInputData)[i];
+
+	/* Read data from current block (index "iD - 1")*/
+	for (i = 0; i < iInputBlockSize; i++)
+		(*pvecOutputData)[i] = matcDeinterlMemory[veciCurIndex[iD - 1]][i];
+
+	/* Set new indices. Move blocks forward (virtually) */
+	for (j = 0; j < iD; j++)
+	{
+		veciCurIndex[j]--;
+
+		if (veciCurIndex[j] < 0)
+			veciCurIndex[j] = iD - 1;
+	}
+
+	/* Debar initialization phase */
+	if (iInitCnt > 0)
+	{
+		iInitCnt--;
+
+		/* Do not put out data in initialization phase */
+		iOutputBlockSize = 0;
+	}
+	else
+		iOutputBlockSize = iN_MUX; 
+}
+
+void CSymbDeinterleaver::InitInternal(CParameter& Parameters)
+{
+	int i;
+
+	Parameters.Lock(); 
+
+	/* Set internal parameters */
+	iN_MUX = Parameters.CellMappingTable.iNumUsefMSCCellsPerFrame;
+
+	/* Allocate memory for table */
+	veciIntTable.Init(iN_MUX);
+
+	/* Make interleaver table */
+	MakeTable(veciIntTable, iN_MUX, SYMB_INTERL_CONST_T_0);
+
+	/* Set interleaver depth */
+	switch (Parameters.eSymbolInterlMode)
+	{
+    case SI_LONG:
+		iD = D_LENGTH_LONG_INTERL;
+		break;
+
+    case SI_SHORT:
+		iD = D_LENGTH_SHORT_INTERL;
+		break;
+    case SI_MODE_E: // TODO
+		;
+	}
+
+	/* Always allocate memory for long interleaver case (interleaver memory) */
+	matcDeinterlMemory.Init(D_LENGTH_LONG_INTERL, iN_MUX
+#ifdef USE_ERASURE_FOR_FASTER_ACQ
+		, CEquSig(ERASURE_TAG_VALUE, ERASURE_TAG_VALUE) /* Init with erasures */
+#endif		
+		);
+
+	/* Index for addressing the buffers */
+	veciCurIndex.Init(D_LENGTH_LONG_INTERL);
+	for (i = 0; i < D_LENGTH_LONG_INTERL; i++)
+		veciCurIndex[i] = i;
+
+#ifdef USE_ERASURE_FOR_FASTER_ACQ
+	if (Parameters.eSimType == CParameter::ST_NONE)
+	{
+		/* Output right after the first block */
+		iInitCnt = (int) Min(1, iD);
+	}
+	else
+#endif
+	{
+		/* After an initialization we do not put out data befor the number
+		   symbols of the interleaver delay have been processed (this is
+		   also needed in any case for simulations) */
+		iInitCnt = iD - 1;
+	}
+
+	/* Define block-sizes for input and output */
+	iInputBlockSize = iN_MUX;
+	iMaxOutputBlockSize = iN_MUX;
+
+	Parameters.Unlock(); 
+}
diff --git a/src/interleaver/SymbolInterleaver.h b/src/interleaver/SymbolInterleaver.h
new file mode 100644
index 0000000..741f208
--- /dev/null
+++ b/src/interleaver/SymbolInterleaver.h
@@ -0,0 +1,85 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *	See SymbolInterleaver.cpp
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later 
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT 
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#if !defined(CONVINTERLEAVER_H__3B0BA660_CA63_4344_BB2B_23E7A0D31912__INCLUDED_)
+#define CONVINTERLEAVER_H__3B0BA660_CA63_4344_BB2B_23E7A0D31912__INCLUDED_
+
+#include "../GlobalDefinitions.h"
+#include "../Parameter.h"
+#include "../util/Modul.h"
+#include "BlockInterleaver.h"
+
+
+/* Definitions ****************************************************************/
+#define D_LENGTH_SHORT_INTERL		1
+#define D_LENGTH_LONG_INTERL		5
+
+/* This constant is defined in DRM-standard for MSC Cell Interleaving */
+#define SYMB_INTERL_CONST_T_0		5
+
+
+/* Classes ********************************************************************/
+class CSymbInterleaver : public CTransmitterModul<_COMPLEX, _COMPLEX>, 
+						 public CBlockInterleaver
+{
+public:
+	CSymbInterleaver() {}
+	virtual ~CSymbInterleaver() {}
+
+protected:
+	int					iN_MUX;
+	CMatrix<_COMPLEX>	matcInterlMemory;
+	CVector<int>		veciCurIndex;
+	CVector<int>		veciIntTable;
+	int					iD;
+
+	virtual void InitInternal(CParameter& TransmParam);
+	virtual void ProcessDataInternal(CParameter& TransmParam);
+};
+
+class CSymbDeinterleaver : public CReceiverModul<CEquSig, CEquSig>, 
+						   public CBlockInterleaver
+{
+public:
+	CSymbDeinterleaver() {}
+	virtual ~CSymbDeinterleaver() {}
+
+protected:
+	int					iN_MUX;
+	CMatrix<CEquSig>	matcDeinterlMemory;
+	CVector<int>		veciCurIndex;
+	CVector<int>		veciIntTable;
+	int					iD;
+	int					iInitCnt;
+
+	virtual void InitInternal(CParameter& Parameters);
+	virtual void ProcessDataInternal(CParameter& Parameters);
+};
+
+
+#endif // !defined(CONVINTERLEAVER_H__3B0BA660_CA63_4344_BB2B_23E7A0D31912__INCLUDED_)
diff --git a/src/linux/ConsoleIO.cpp b/src/linux/ConsoleIO.cpp
new file mode 100644
index 0000000..e755a46
--- /dev/null
+++ b/src/linux/ConsoleIO.cpp
@@ -0,0 +1,443 @@
+/******************************************************************************\
+ *
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *  David Flamand
+ *
+ * Description:
+ *  Module for interacting with console, no dependency to ncurses for
+ *  increased portability with various handheld devices and dev boards,
+ *  compatible with ANSI terminal.
+ *  For best results stderr should be redirected to file or /dev/null
+ *
+ * Defined Keys:
+ *  SPACEBAR  toggle display
+ *  I         toggle signal info
+ *  S         toggle service info
+ *  F         display signal info and service info
+ *  N         new acquisition
+ *  1 2 3 4   audio service selection
+ *  CTRL-C Q  quit
+ *
+ * Defined Signals:
+ *  SIGINT SIGHUP SIGTERM SIGQUIT  quit
+ *  SIGUSR1                        new acquisition
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <cstdio>
+#include "ConsoleIO.h"
+
+
+/* defines ANSI escape code */
+#define HIDECUR "\e[?25l"
+#define SHOWCUR "\e[?25h"
+#define HOME "\e[H"
+#define CLEAR "\e[2J"
+#define CLREND "\e[J"
+#define CL "\e[K" /* Clear Line */
+#define NL CL "\n" /* New Line */
+
+/* defines console output operation */
+#define cinit() do { screen_ptr=screen; screen_size=sizeof(screen); } while(0)
+#define cprintf(...) do { int ret = snprintf(screen_ptr, (size_t)screen_size, __VA_ARGS__); if (ret>0) { screen_ptr+=ret; screen_size-=ret; } } while(0)
+#define cflush() do { size_t ret = write(tty, screen, sizeof(screen)-screen_size); (void)ret; } while(0)
+#define cwrite(text) do { size_t ret = write(tty, text "", sizeof(text "")-1); (void)ret; } while(0)
+
+/* device for accessing the tty */
+#define TTY_DEVICE "/dev/tty"
+
+/* misc defines */
+#define MODE_SIGNAL 0x01
+#define MODE_SERVICE 0x02
+#define MODE_NODISPLAY 0x04
+#define DEFAULT_MODE (MODE_SIGNAL /*| MODE_SERVICE*/)
+
+#define REPLACE_CHAR(str, from, to) \
+	for (size_t pos=0;;) { \
+		pos = str.find(from, pos); \
+		if (pos == string::npos) break; \
+		str.replace(pos, 1, to ""); \
+		pos += sizeof(to "")-1; \
+	}
+#define REPLACE_STR(str, from, to) \
+	for (size_t pos=0;;) { \
+		pos = str.find(from "", pos); \
+		if (pos == string::npos) break; \
+		str.replace(pos, sizeof(from "")-1, to ""); \
+		pos += sizeof(to "")-1; \
+	}
+
+#define MINIMUM_IF_LEVEL -200.0
+
+#define NA "---"
+
+
+/* Implementation *************************************************************/
+
+CDRMReceiver* CConsoleIO::pDRMReceiver;
+unsigned long long CConsoleIO::time;
+int CConsoleIO::mode;
+int CConsoleIO::tty;
+int CConsoleIO::tty_setup;
+char CConsoleIO::screen[4096];
+char* CConsoleIO::screen_ptr;
+int CConsoleIO::screen_size;
+sigset_t CConsoleIO::sigset;
+struct termios CConsoleIO::old_tio;
+
+
+void
+CConsoleIO::Enter(CDRMReceiver* pDRMReceiver)
+{
+	mode = DEFAULT_MODE;
+
+	CConsoleIO::pDRMReceiver = pDRMReceiver;
+
+	/* Signals to ignore */
+	struct sigaction sigact;
+	sigact.sa_handler = SIG_IGN;
+	sigemptyset(&sigact.sa_mask);
+	sigact.sa_flags = 0;
+	sigaction(SIGPIPE, &sigact, NULL);
+	sigaction(SIGINT,  &sigact, NULL);
+	sigaction(SIGHUP,  &sigact, NULL);
+	sigaction(SIGTERM, &sigact, NULL);
+	sigaction(SIGQUIT, &sigact, NULL);
+	sigaction(SIGUSR1, &sigact, NULL);
+	sigaction(SIGUSR2, &sigact, NULL);
+
+	/* Signals to block */
+	sigemptyset(&sigset);
+	sigaddset(&sigset, SIGINT);
+	sigaddset(&sigset, SIGHUP);
+	sigaddset(&sigset, SIGTERM);
+	sigaddset(&sigset, SIGQUIT);
+	sigaddset(&sigset, SIGUSR1);
+	pthread_sigmask(SIG_BLOCK, &sigset, NULL);
+
+	/* TTY opening */
+	tty = open(TTY_DEVICE, O_RDWR | O_NONBLOCK);
+	if (tty != -1)
+	{
+		if (!tcgetattr(tty, &old_tio))
+		{
+			struct termios tio = old_tio;
+			tio.c_lflag &= ~(ECHO|ICANON);
+			tty_setup = tcsetattr(tty, TCSANOW, &tio);
+		}
+		else
+			tty_setup = -1;
+		cwrite(HIDECUR CLEAR HOME);
+	}
+}
+
+void
+CConsoleIO::Leave()
+{
+	if (tty != -1)
+	{
+		cwrite(CLEAR HOME SHOWCUR);
+		if (!tty_setup)
+			tcsetattr(tty, TCSANOW, &old_tio);
+		close(tty);
+		tty = -1;
+	}
+}
+
+void
+CConsoleIO::Update()
+{
+	/* Check for pending signals */
+	if (!sigpending(&sigset))
+	{
+		pthread_sigmask(SIG_UNBLOCK, &sigset, NULL);
+		pthread_sigmask(SIG_BLOCK,   &sigset, NULL);
+		if (sigismember(&sigset, SIGINT) ||
+			sigismember(&sigset, SIGHUP) ||
+			sigismember(&sigset, SIGTERM) ||
+			sigismember(&sigset, SIGQUIT)) {
+			pDRMReceiver->Stop();
+			return;
+		}
+		if (sigismember(&sigset, SIGUSR1))
+		{
+			pDRMReceiver->RequestNewAcquisition();
+		}
+	}
+
+	/* No TTY return */
+	if (tty < 0)
+		return;
+
+	CParameter& Parameters = *pDRMReceiver->GetParameters();
+	cinit();
+
+	/* Read key input */
+	for (;;)
+	{
+		unsigned char buffer[1];
+		int ret = read(tty, buffer, sizeof(buffer));
+		if (ret != sizeof(buffer))
+			break;
+		int key = buffer[0];
+		if (key == '\3' /* Control-C */ || key == 'q' || key == 'Q')
+		{
+			pDRMReceiver->Stop();
+			return;
+		}
+		if (key >= '1' && key <= '4')
+		{
+			Parameters.SetCurSelAudioService(key - '1');
+		}
+		if (key == ' ')
+		{
+			mode ^= MODE_NODISPLAY;
+			cwrite(CLEAR HOME);
+			time = 0;
+		}
+		if (key == 'f' || key == 'F')
+		{
+			mode &= ~MODE_NODISPLAY;
+			mode |= MODE_SIGNAL | MODE_SERVICE;
+			cwrite(CLEAR HOME);
+			time = 0;
+		}
+		if (key == 'i' || key == 'I')
+		{
+			if (mode & MODE_NODISPLAY)
+			{
+				mode &= ~MODE_NODISPLAY;
+				mode |= MODE_SIGNAL;
+			}
+			else
+				mode ^= MODE_SIGNAL;
+			cwrite(CLEAR);
+			time = 0;
+		}
+		if (key == 's' || key == 'S')
+		{
+			if (mode & MODE_NODISPLAY)
+			{
+				mode &= ~MODE_NODISPLAY;
+				mode |= MODE_SERVICE;
+			}
+			else
+				mode ^= MODE_SERVICE;
+			cwrite(CLEAR);
+			time = 0;
+		}
+		if (key == 'n' || key == 'N')
+		{
+			pDRMReceiver->RequestNewAcquisition();
+		}
+	}
+
+	if (mode & MODE_NODISPLAY)
+		return;
+
+	struct timespec ts;
+	if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1)
+		return;
+	unsigned long long curtime = (unsigned long long)ts.tv_sec*1000 + (unsigned long long)ts.tv_nsec/1000000;
+	if ((curtime - time) < GUI_CONTROL_UPDATE_TIME)
+		return;
+	time = curtime;
+
+	char msc = ETypeRxStatus2char(Parameters.ReceiveStatus.SLAudio.GetStatus());
+	char sdc = ETypeRxStatus2char(Parameters.ReceiveStatus.SDC.GetStatus());
+	char fac = ETypeRxStatus2char(Parameters.ReceiveStatus.FAC.GetStatus());
+	char time = ETypeRxStatus2char(Parameters.ReceiveStatus.TSync.GetStatus());
+	char frame = ETypeRxStatus2char(Parameters.ReceiveStatus.FSync.GetStatus());
+	ETypeRxStatus soundCardStatusI = Parameters.ReceiveStatus.InterfaceI.GetStatus(); /* Input */
+	ETypeRxStatus soundCardStatusO = Parameters.ReceiveStatus.InterfaceO.GetStatus(); /* Output */
+	char inter = ETypeRxStatus2char(soundCardStatusO == NOT_PRESENT ||
+		(soundCardStatusI != NOT_PRESENT && soundCardStatusI != RX_OK) ? soundCardStatusI : soundCardStatusO);
+	cprintf(HOME "        IO:%c  Time:%c  Frame:%c  FAC:%c  SDC:%c  MSC:%c" NL, inter, time, frame, fac, sdc, msc);
+
+	_REAL rIFLevel = Parameters.GetIFSignalLevel();
+	if (rIFLevel > MINIMUM_IF_LEVEL)
+		cprintf("                   IF Level: %.1f dB" NL, rIFLevel);
+	else
+		cprintf("                   IF Level: " NA NL);
+
+	if (mode & MODE_SIGNAL)
+	{
+		int signal = pDRMReceiver->GetAcquiState() == AS_WITH_SIGNAL;
+		if (signal)
+		{
+			_REAL rSNR = Parameters.GetSNR();
+			cprintf("                        SNR: %.1f dB" NL, rSNR);
+
+			_REAL rWMERMSC = Parameters.rWMERMSC;
+			_REAL rMER = Parameters.rMER;
+			cprintf("         MSC WMER / MSC MER: %.1f dB / %.1f dB" NL, rWMERMSC, rMER);
+
+			_REAL rDCFreq = pDRMReceiver->GetReceiveData()->ConvertFrequency(Parameters.GetDCFrequency());
+			cprintf(" DC Frequency of DRM Signal: %.2f Hz" NL, rDCFreq);
+
+		    _REAL rCurSamROffs = Parameters.rResampleOffset;
+			int iCurSamROffsPPM = (int)(rCurSamROffs / Parameters.GetSigSampleRate() * 1e6);
+			cprintf("    Sample Frequency Offset: %.2f Hz (%i ppm)" NL, rCurSamROffs, iCurSamROffsPPM);
+
+			_REAL rSigma = Parameters.rSigmaEstimate;
+			_REAL rMinDelay = Parameters.rMinDelay;
+			if (rSigma >= 0.0)
+			cprintf("            Doppler / Delay: %.2f Hz / %.2f ms" NL, rSigma, rMinDelay);
+			else
+			cprintf("            Doppler / Delay: " NA NL);
+
+			const char *strRob;
+			switch (Parameters.GetWaveMode()) {
+			case RM_ROBUSTNESS_MODE_A: strRob = "A"; break;
+			case RM_ROBUSTNESS_MODE_B: strRob = "B"; break;
+			case RM_ROBUSTNESS_MODE_C: strRob = "C"; break;
+			case RM_ROBUSTNESS_MODE_D: strRob = "D"; break;
+			default:                   strRob = "?"; }
+			const char *strOcc;
+			switch (Parameters.GetSpectrumOccup()) {
+			case SO_0: strOcc = "4.5 kHz"; break;
+			case SO_1: strOcc = "5 kHz";   break;
+			case SO_2: strOcc = "9 kHz";   break;
+	 		case SO_3: strOcc = "10 kHz";  break;
+			case SO_4: strOcc = "18 kHz";  break;
+			case SO_5: strOcc = "20 kHz";  break;
+			default:   strOcc = "?";       }
+			cprintf("       DRM Mode / Bandwidth: %s / %s" NL, strRob, strOcc);
+
+			const char *strInter;
+		    switch (Parameters.eSymbolInterlMode) {
+		    case SI_LONG:  strInter = "2 s";    break;
+		    case SI_SHORT: strInter = "400 ms"; break;
+		    default:       strInter = "?";      }
+			cprintf("          Interleaver Depth: %s" NL, strInter);
+
+			const char *strSDC;
+			switch (Parameters.eSDCCodingScheme) {
+			case CS_1_SM: strSDC = "4-QAM";  break;
+			case CS_2_SM: strSDC = "16-QAM"; break;
+			default:      strSDC = "?";      }
+			const char *strMSC;
+			switch (Parameters.eMSCCodingScheme) {
+			case CS_2_SM:    strMSC = "SM 16-QAM";    break;
+			case CS_3_SM:    strMSC = "SM 64-QAM";    break;
+			case CS_3_HMSYM: strMSC = "HMsym 64-QAM"; break;
+			case CS_3_HMMIX: strMSC = "HMmix 64-QAM"; break;
+			default:         strMSC = "?";            }
+			cprintf("             SDC / MSC Mode: %s / %s" NL, strSDC, strMSC);
+
+			int iPartB = Parameters.MSCPrLe.iPartB;
+			int iPartA = Parameters.MSCPrLe.iPartA;
+			cprintf("        Prot. Level (B / A): %i / %i" NL, iPartB, iPartA);
+
+			int iNumAudio = Parameters.iNumAudioService;
+			int iNumData = Parameters.iNumDataService;
+			cprintf("         Number of Services: Audio: %i / Data: %i" NL, (int)iNumAudio, (int)iNumData);
+
+			int iYear = Parameters.iYear;
+			int iMonth = Parameters.iMonth;
+			int iDay = Parameters.iDay;
+			int iUTCHour = Parameters.iUTCHour;
+			int iUTCMin = Parameters.iUTCMin;
+			if (iYear==0 && iMonth==0 && iDay==0 && iUTCHour==0 && iUTCMin==0)
+			cprintf("       Received time - date: Service not available" CL);
+			else
+			cprintf("       Received time - date: %04i-%02i-%02i %02i:%02i:00" CL, iYear, iMonth, iDay, iUTCHour, iUTCMin);
+
+		}
+		else {
+			cprintf("                        SNR: " NA NL
+					"         MSC WMER / MSC MER: " NA NL
+					" DC Frequency of DRM Signal: " NA NL
+					"    Sample Frequency Offset: " NA NL
+					"            Doppler / Delay: " NA NL
+					"       DRM Mode / Bandwidth: " NA NL
+					"          Interleaver Depth: " NA NL
+					"             SDC / MSC Mode: " NA NL
+					"        Prot. Level (B / A): " NA NL
+					"         Number of Services: " NA NL
+					"       Received time - date: " NA CL);
+		}
+	}
+	if (mode & MODE_SERVICE)
+	{
+		if (mode & MODE_SIGNAL)
+			cprintf(NL);
+		cprintf(NL "Service:" NL);
+		const char* strTextMessage = NULL;
+		int iCurAudService = Parameters.GetCurSelAudioService();
+		for (int i = 0; i < MAX_NUM_SERVICES; i++)
+		{
+			CService service = Parameters.Service[i];
+			if (service.IsActive())
+			{
+				const char *strLabel = service.strLabel.c_str();
+				int ID = service.iServiceID;
+				bool audio = service.eAudDataFlag == CService::SF_AUDIO;
+				cprintf("%c%i | %X | %s ", i==iCurAudService ? '>' : ' ', i+1, ID, strLabel);
+				_REAL rBitRate = Parameters.GetBitRateKbps(i, !audio);
+				_REAL rPartABLenRat = Parameters.PartABLenRatio(i);
+		        if (rPartABLenRat != (_REAL) 0.0)
+					cprintf("| UEP (%.1f%%) |", rPartABLenRat * 100);
+		        else
+					cprintf("| EEP |");
+				if (rBitRate > 0.0)
+					cprintf(" %s %.2f kbps", audio ? "Audio" : "Data", rBitRate);
+				if (audio && service.DataParam.iStreamID != STREAM_ID_NOT_USED)
+				{
+					_REAL rBitRate = Parameters.GetBitRateKbps(i, TRUE);
+					cprintf(" + Data %.2f kbps", rBitRate);
+				}
+				cprintf(NL);
+				if (i == iCurAudService)
+					strTextMessage = service.AudioParam.strTextMessage.c_str();
+			}
+			else
+				cprintf(" %i" NL, i+1);
+		}
+		if (strTextMessage != NULL)
+		{
+			string msg(strTextMessage);
+			REPLACE_STR(msg, "\r\n", "\r");  /* Windows CR-LF */
+			REPLACE_CHAR(msg, '\n', "\r");   /* New Line */
+			REPLACE_CHAR(msg, '\f', "\r");   /* Form Feed */
+			REPLACE_CHAR(msg, '\v', "\r");   /* Vertical Tab */
+			REPLACE_CHAR(msg, '\t', "    "); /* Horizontal Tab */
+			REPLACE_CHAR(msg, '\r', NL);     /* Carriage Return */
+			cprintf(NL "%s", msg.c_str());
+		}
+	}
+	cprintf(CLREND HOME);
+	cflush();
+}
+
+char
+CConsoleIO::ETypeRxStatus2char(ETypeRxStatus eTypeRxStatus)
+{
+	switch (eTypeRxStatus) {
+	case CRC_ERROR:  return 'X';
+	case DATA_ERROR: return '*';
+	case RX_OK:      return 'O';
+	default:         return ' '; }
+}
+
diff --git a/src/linux/ConsoleIO.h b/src/linux/ConsoleIO.h
new file mode 100644
index 0000000..cf56aef
--- /dev/null
+++ b/src/linux/ConsoleIO.h
@@ -0,0 +1,51 @@
+/******************************************************************************\
+ *
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *  David Flamand
+ *
+ * Description:
+ *  see ConsoleIO.cpp
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include <termios.h>
+#include <signal.h>
+#include "../DrmReceiver.h"
+
+class CConsoleIO
+{
+public:
+	static void Enter(CDRMReceiver* pDRMReceiver);
+	static void Leave();
+	static void Update();
+protected:
+	static char ETypeRxStatus2char(ETypeRxStatus eTypeRxStatus);
+	static CDRMReceiver* pDRMReceiver;
+	static unsigned long long time;
+	static int mode;
+	static int tty;
+	static int tty_setup;
+	static char screen[];
+	static char* screen_ptr;
+	static int screen_size;
+	static sigset_t sigset;
+	static struct termios old_tio;
+};
diff --git a/src/linux/Pacer.cpp b/src/linux/Pacer.cpp
new file mode 100644
index 0000000..bf1f904
--- /dev/null
+++ b/src/linux/Pacer.cpp
@@ -0,0 +1,60 @@
+
+#include "../util/Pacer.h"
+
+#include <sys/time.h>
+#include <signal.h>
+#include <unistd.h>
+#include <cstdio>
+#include <iostream>
+
+CPacer::CPacer(uint64_t ns)
+{
+    timespec now;
+#if _POSIX_TIMERS>0
+    int r = clock_gettime(CLOCK_REALTIME, &now);
+#else
+    timeval t;
+    int r = gettimeofday(&t, NULL);
+    now.tv_sec = t.tv_sec;
+    now.tv_nsec = 1000*t.tv_usec;
+#endif
+    if (r<0)
+        perror("time");
+    interval = ns;
+    timekeeper = 1000000000LL*now.tv_sec+now.tv_nsec;
+    timekeeper += interval;
+}
+
+CPacer::~CPacer()
+{
+}
+
+void CPacer::wait()
+{
+    uint64_t delay_ns = nstogo();
+    if (delay_ns>20000000ULL)
+    {
+        timespec delay;
+        delay.tv_sec = delay_ns / 1000000000ULL;
+        delay.tv_nsec = delay_ns % 1000000000ULL;
+        nanosleep(&delay, NULL);
+    }
+    timekeeper += interval;
+}
+
+uint64_t CPacer::nstogo()
+{
+    timespec now;
+#if _POSIX_TIMERS>0
+    (void)clock_gettime(CLOCK_REALTIME, &now);
+#else
+    timeval t;
+    (void)gettimeofday(&t, NULL);
+    now.tv_sec = t.tv_sec;
+    now.tv_nsec = 1000*t.tv_usec;
+#endif
+    uint64_t now_ns = 1000000000LL*now.tv_sec+now.tv_nsec;
+    if (timekeeper<=now_ns)
+        return 0;
+    return timekeeper - now_ns;
+}
diff --git a/src/linux/alsa.cpp b/src/linux/alsa.cpp
new file mode 100644
index 0000000..69b8896
--- /dev/null
+++ b/src/linux/alsa.cpp
@@ -0,0 +1,460 @@
+/******************************************************************************\
+* Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+* Copyright (c) 2001-2014
+*
+* Author(s):
+*	Alexander Kurpiers
+*
+*
+******************************************************************************
+*
+* This program is free software; you can redistribute it and/or modify it under
+* the terms of the GNU General Public License as published by the Free Software
+* Foundation; either version 2 of the License, or (at your option) any later
+* version.
+*
+* This program is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+* details.
+*
+* You should have received a copy of the GNU General Public License along with
+* this program; if not, write to the Free Software Foundation, Inc.,
+* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*
+\******************************************************************************/
+
+#include "soundin.h"
+#include "soundout.h"
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <iostream>
+#include <fstream>
+#include <sstream>
+#include <map>
+#include <algorithm>
+
+#define ALSA_PCM_NEW_HW_PARAMS_API
+#define ALSA_PCM_NEW_SW_PARAMS_API
+
+void CSoundIn::Init_HW() {
+
+    int err, dir=0;
+    snd_pcm_hw_params_t *hwparams;
+    snd_pcm_sw_params_t *swparams;
+    snd_pcm_uframes_t period_size = FRAGSIZE * NUM_IN_CHANNELS/2;
+    snd_pcm_uframes_t buffer_size;
+
+    /* Default ? */
+    if (iCurrentDevice < 0)
+        iCurrentDevice = int(devices.size())-1;
+
+    /* out of range ? (could happen from command line parameter or USB device unplugged */
+    if (iCurrentDevice >= int(devices.size()))
+        iCurrentDevice = int(devices.size())-1;
+
+    /* record device */
+    string recdevice = devices[iCurrentDevice];
+
+    if (handle != NULL)
+        return;
+
+    err = snd_pcm_open( &handle, recdevice.c_str(), SND_PCM_STREAM_CAPTURE, 0 );
+    if ( err != 0)
+    {
+        qDebug("open error: %s", snd_strerror(err));
+        throw CGenErr("alsa CSoundIn::Init_HW record, can't open "+recdevice+" ("+names[iCurrentDevice]+")");
+    }
+
+    snd_pcm_hw_params_alloca(&hwparams);
+    snd_pcm_sw_params_alloca(&swparams);
+
+    /* Choose all parameters */
+    err = snd_pcm_hw_params_any(handle, hwparams);
+    if (err < 0) {
+        qDebug("Broken configuration : no configurations available: %s", snd_strerror(err));
+        throw CGenErr("alsa CSoundIn::Init_HW ");
+    }
+    /* Set the interleaved read/write format */
+    err = snd_pcm_hw_params_set_access(handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED);
+
+    if (err < 0) {
+        qDebug("Access type not available : %s", snd_strerror(err));
+        throw CGenErr("alsa CSoundIn::Init_HW ");
+
+    }
+    /* Set the sample format */
+    err = snd_pcm_hw_params_set_format(handle, hwparams, SND_PCM_FORMAT_S16);
+    if (err < 0) {
+        qDebug("Sample format not available : %s", snd_strerror(err));
+        throw CGenErr("alsa CSoundIn::Init_HW ");
+    }
+    /* Set the count of channels */
+    err = snd_pcm_hw_params_set_channels(handle, hwparams, NUM_IN_CHANNELS);
+    if (err < 0) {
+        qDebug("Channels count (%i) not available s: %s", NUM_IN_CHANNELS, snd_strerror(err));
+        throw CGenErr("alsa CSoundIn::Init_HW ");
+    }
+    /* Set the stream rate */
+    dir=0;
+    err = snd_pcm_hw_params_set_rate(handle, hwparams, Parameters.GetSampleRate(), dir);
+    if (err < 0) {
+        qDebug("Rate %iHz not available : %s", Parameters.GetSampleRate(), snd_strerror(err));
+        throw CGenErr("alsa CSoundIn::Init_HW ");
+
+    }
+    dir=0;
+    unsigned int buffer_time = 500000;              /* ring buffer length in us */
+    /* set the buffer time */
+    err = snd_pcm_hw_params_set_buffer_time_near(handle, hwparams, &buffer_time, &dir);
+    if (err < 0) {
+        qDebug("Unable to set buffer time %i for playback: %s\n", buffer_time, snd_strerror(err));
+        throw CGenErr("alsa CSoundIn::Init_HW ");
+    }
+    err = snd_pcm_hw_params_get_buffer_size(hwparams, &buffer_size);
+    if (err < 0) {
+        qDebug("Unable to get buffer size for playback: %s\n", snd_strerror(err));
+        throw CGenErr("alsa CSoundIn::Init_HW ");
+    }
+    // qDebug("buffer size %d", buffer_size);
+    /* set the period time */
+    unsigned int period_time = 100000;              /* period time in us */
+    err = snd_pcm_hw_params_set_period_time_near(handle, hwparams, &period_time, &dir);
+    if (err < 0) {
+        qDebug("Unable to set period time %i for playback: %s\n", period_time, snd_strerror(err));
+        throw CGenErr("alsa CSoundIn::Init_HW ");
+    }
+    err = snd_pcm_hw_params_get_period_size_min(hwparams, &period_size, &dir);
+    if (err < 0) {
+        qDebug("Unable to get period size for playback: %s\n", snd_strerror(err));
+        throw CGenErr("alsa CSoundIn::Init_HW ");
+    }
+    // qDebug("period size %d", period_size);
+
+    /* Write the parameters to device */
+    err = snd_pcm_hw_params(handle, hwparams);
+    if (err < 0) {
+        qDebug("Unable to set hw params : %s", snd_strerror(err));
+        throw CGenErr("alsa CSoundIn::Init_HW ");
+    }
+    /* Get the current swparams */
+    err = snd_pcm_sw_params_current(handle, swparams);
+    if (err < 0) {
+        qDebug("Unable to determine current swparams : %s", snd_strerror(err));
+        throw CGenErr("alsa CSoundIn::Init_HW ");
+    }
+    /* Start the transfer when the buffer immediately */
+    err = snd_pcm_sw_params_set_start_threshold(handle, swparams, 0);
+    if (err < 0) {
+        qDebug("Unable to set start threshold mode : %s", snd_strerror(err));
+        throw CGenErr("alsa CSoundIn::Init_HW ");
+    }
+    /* Allow the transfer when at least period_size samples can be processed */
+    err = snd_pcm_sw_params_set_avail_min(handle, swparams, period_size);
+    if (err < 0) {
+        qDebug("Unable to set avail min : %s", snd_strerror(err));
+        throw CGenErr("alsa CSoundIn::Init_HW ");
+    }
+    /* Align all transfers to 1 sample */
+    err = snd_pcm_sw_params_set_xfer_align(handle, swparams, 1);
+    if (err < 0) {
+        qDebug("Unable to set transfer align : %s", snd_strerror(err));
+        throw CGenErr("alsa CSoundIn::Init_HW ");
+    }
+    /* Write the parameters to the record/playback device */
+    err = snd_pcm_sw_params(handle, swparams);
+    if (err < 0) {
+        qDebug("Unable to set sw params : %s", snd_strerror(err));
+        throw CGenErr("alsa CSoundIn::Init_HW ");
+    }
+    snd_pcm_start(handle);
+    qDebug("alsa init done");
+
+}
+
+int CSoundIn::read_HW( void * recbuf, int size) {
+
+    int ret = snd_pcm_readi(handle, recbuf, size);
+
+
+    if (ret < 0)
+    {
+        if (ret == -EPIPE)
+        {
+            qDebug("rpipe");
+            /* Under-run */
+            qDebug("rprepare");
+            ret = snd_pcm_prepare(handle);
+            if (ret < 0)
+                qDebug("Can't recover from underrun, prepare failed: %s", snd_strerror(ret));
+
+            ret = snd_pcm_start(handle);
+
+            if (ret < 0)
+                qDebug("Can't recover from underrun, start failed: %s", snd_strerror(ret));
+            return 0;
+
+        }
+        else if (ret == -ESTRPIPE)
+        {
+            qDebug("strpipe");
+
+            /* Wait until the suspend flag is released */
+            while ((ret = snd_pcm_resume(handle)) == -EAGAIN)
+                sleep(1);
+
+            if (ret < 0)
+            {
+                ret = snd_pcm_prepare(handle);
+
+                if (ret < 0)
+                    qDebug("Can't recover from suspend, prepare failed: %s", snd_strerror(ret));
+                throw CGenErr("CSound:Read");
+            }
+            return 0;
+        }
+        else
+        {
+            qDebug("CSoundIn::Read: %s", snd_strerror(ret));
+            throw CGenErr("CSound:Read");
+        }
+    } else
+        return ret;
+
+}
+
+void CSoundIn::close_HW( void ) {
+
+    if (handle != NULL)
+        snd_pcm_close( handle );
+
+    handle = NULL;
+}
+
+void CSoundOut::Init_HW()
+{
+
+    int err, dir;
+    snd_pcm_hw_params_t *hwparams;
+    snd_pcm_sw_params_t *swparams;
+    snd_pcm_uframes_t period_size = FRAGSIZE * NUM_OUT_CHANNELS/2;
+    snd_pcm_uframes_t buffer_size;
+
+    /* playback device */
+    if (devices.size()==0)
+        throw CGenErr("alsa CSoundOut::Init_HW no playback devices available!");
+
+    /* Default ? */
+    if (iCurrentDevice < 0)
+        iCurrentDevice = int(devices.size())-1;
+
+    /* out of range ? (could happen from command line parameter or USB device unplugged */
+    if (iCurrentDevice >= int(devices.size()))
+        iCurrentDevice = int(devices.size())-1;
+
+    string playdevice = devices[iCurrentDevice];
+
+    if (handle != NULL)
+        return;
+
+    err = snd_pcm_open( &handle, playdevice.c_str(), SND_PCM_STREAM_PLAYBACK, 0 );
+    if ( err != 0)
+    {
+        qDebug("open error: %s", snd_strerror(err));
+        throw CGenErr("alsa CSoundOut::Init_HW playback, can't open "+playdevice+" ("+names[iCurrentDevice]+")");
+    }
+
+    snd_pcm_hw_params_alloca(&hwparams);
+    snd_pcm_sw_params_alloca(&swparams);
+
+    /* Choose all parameters */
+    err = snd_pcm_hw_params_any(handle, hwparams);
+    if (err < 0) {
+        qDebug("Broken configuration : no configurations available: %s", snd_strerror(err));
+        throw CGenErr("alsa CSoundOut::Init_HW ");
+    }
+    /* Set the interleaved read/write format */
+    err = snd_pcm_hw_params_set_access(handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED);
+
+    if (err < 0) {
+        qDebug("Access type not available : %s", snd_strerror(err));
+        throw CGenErr("alsa CSoundOut::Init_HW ");
+
+    }
+    /* Set the sample format */
+    err = snd_pcm_hw_params_set_format(handle, hwparams, SND_PCM_FORMAT_S16);
+    if (err < 0) {
+        qDebug("Sample format not available : %s", snd_strerror(err));
+        throw CGenErr("alsa CSoundOut::Init_HW ");
+    }
+    /* Set the count of channels */
+    err = snd_pcm_hw_params_set_channels(handle, hwparams, NUM_OUT_CHANNELS);
+    if (err < 0) {
+        qDebug("Channels count (%i) not available s: %s", NUM_OUT_CHANNELS, snd_strerror(err));
+        throw CGenErr("alsa CSoundOut::Init_HW ");
+    }
+    /* Set the stream rate */
+    dir=0;
+    err = snd_pcm_hw_params_set_rate(handle, hwparams, Parameters.GetSampleRate(), dir);
+    if (err < 0) {
+        qDebug("Rate %iHz not available : %s", Parameters.GetSampleRate(), snd_strerror(err));
+        throw CGenErr("alsa CSoundOut::Init_HW ");
+    }
+    dir=0;
+    unsigned int buffer_time = 500000;              /* ring buffer length in us */
+    /* set the buffer time */
+    err = snd_pcm_hw_params_set_buffer_time_near(handle, hwparams, &buffer_time, &dir);
+    if (err < 0) {
+        qDebug("Unable to set buffer time %i for playback: %s\n", buffer_time, snd_strerror(err));
+        throw CGenErr("alsa CSoundOut::Init_HW ");
+    }
+    err = snd_pcm_hw_params_get_buffer_size(hwparams, &buffer_size);
+    if (err < 0) {
+        qDebug("Unable to get buffer size for playback: %s\n", snd_strerror(err));
+        throw CGenErr("alsa CSoundOut::Init_HW ");
+    }
+    // qDebug("buffer size %d", buffer_size);
+    /* set the period time */
+    unsigned int period_time = 100000;              /* period time in us */
+    err = snd_pcm_hw_params_set_period_time_near(handle, hwparams, &period_time, &dir);
+    if (err < 0) {
+        qDebug("Unable to set period time %i for playback: %s\n", period_time, snd_strerror(err));
+        throw CGenErr("alsa CSoundOut::Init_HW ");
+    }
+    err = snd_pcm_hw_params_get_period_size_min(hwparams, &period_size, &dir);
+    if (err < 0) {
+        qDebug("Unable to get period size for playback: %s\n", snd_strerror(err));
+        throw CGenErr("alsa CSoundOut::Init_HW ");
+    }
+    // qDebug("period size %d", period_size);
+
+    /* Write the parameters to device */
+    err = snd_pcm_hw_params(handle, hwparams);
+    if (err < 0) {
+        qDebug("Unable to set hw params : %s", snd_strerror(err));
+        throw CGenErr("alsa CSoundOut::Init_HW ");
+    }
+    /* Get the current swparams */
+    err = snd_pcm_sw_params_current(handle, swparams);
+    if (err < 0) {
+        qDebug("Unable to determine current swparams : %s", snd_strerror(err));
+        throw CGenErr("alsa CSoundOut::Init_HW ");
+    }
+    /* Write the parameters to the playback device */
+    err = snd_pcm_sw_params(handle, swparams);
+    if (err < 0) {
+        qDebug("Unable to set sw params : %s", snd_strerror(err));
+        throw CGenErr("alsa CSoundOut::Init_HW ");
+    }
+    snd_pcm_start(handle);
+    qDebug("alsa init done");
+
+}
+
+int CSoundOut::write_HW( _SAMPLE *playbuf, int size )
+{
+
+    int start = 0;
+    int ret;
+
+    while (size) {
+
+        ret = snd_pcm_writei(handle, &playbuf[start], size );
+        if (ret < 0) {
+            if (ret ==  -EAGAIN) {
+                if ((ret = snd_pcm_wait (handle, 100)) < 0) {
+                    qDebug ("poll failed (%s)", snd_strerror (ret));
+                    break;
+                }
+                continue;
+            } else
+                if (ret == -EPIPE) {    /* under-run */
+                    qDebug("underrun");
+                    ret = snd_pcm_prepare(handle);
+                    if (ret < 0)
+                        qDebug("Can't recover from underrun, prepare failed: %s", snd_strerror(ret));
+                    continue;
+                } else if (ret == -ESTRPIPE) {
+                    qDebug("strpipe");
+                    while ((ret = snd_pcm_resume(handle)) == -EAGAIN)
+                        sleep(1);       /* wait until the suspend flag is released */
+                    if (ret < 0) {
+                        ret = snd_pcm_prepare(handle);
+                        if (ret < 0)
+                            qDebug("Can't recover from suspend, prepare failed: %s", snd_strerror(ret));
+                    }
+                    continue;
+                } else {
+                    qDebug("Write error: %s", snd_strerror(ret));
+                    throw CGenErr("Write error");
+                }
+            break;  /* skip one period */
+        }
+        size -= ret;
+        start += ret;
+    }
+    return 0;
+}
+
+void CSoundOut::close_HW( void )
+{
+
+    if (handle != NULL)
+        snd_pcm_close( handle );
+
+    handle = NULL;
+}
+
+void
+getdevices(vector < string > &names, vector < string > &devices,
+           bool playback)
+{
+    vector < string > tmp;
+    names.clear();
+    devices.clear();
+    ifstream sndstat("/proc/asound/pcm");
+    if (sndstat.is_open())
+    {
+        while (!(sndstat.eof() || sndstat.fail()))
+        {
+            char s[200];
+            sndstat.getline(s, sizeof(s));
+            if (strlen(s) == 0)
+                break;
+            if (strstr(s, playback ? "playback" : "capture") != NULL)
+                tmp.push_back(s);
+        }
+        sndstat.close();
+    }
+    if (tmp.size() > 0)
+    {
+        sort(tmp.begin(), tmp.end());
+        for (size_t i = 0; i < tmp.size(); i++)
+        {
+            stringstream o(tmp[i]);
+            char p, n[200], d[200], cap[80];
+            int maj, min;
+            o >> maj >> p >> min;
+            o >> p;
+            o.getline(n, sizeof(n), ':');
+            o.getline(d, sizeof(d), ':');
+            o.getline(cap, sizeof(cap));
+            stringstream dev;
+            dev << "plughw:" << maj << "," << min;
+            devices.push_back(dev.str());
+            names.push_back(n);
+        }
+    }
+    if (playback)
+    {
+        names.push_back("Default Playback Device");
+        devices.push_back("dmix");
+    }
+    else
+    {
+        names.push_back("Default Capture Device");
+        devices.push_back("dsnoop");
+    }
+}
diff --git a/src/linux/alsa.h b/src/linux/alsa.h
new file mode 100644
index 0000000..95af14a
--- /dev/null
+++ b/src/linux/alsa.h
@@ -0,0 +1,73 @@
+/******************************************************************************\
+ * British Broadcasting Corporation
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Julian Cable
+ *
+ * Decription:
+ * ALSA sound interface
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#ifndef _ALSA_H
+#define _ALSA_H
+
+#include "../soundinterface.h"
+#include <alsa/asoundlib.h>
+
+class CAlsaSoundIn: public CSoundInInterface
+{
+public:
+    CAlsaSoundIn();
+    virtual 			~CAlsaSoundIn();
+
+    virtual void		Enumerate(vector<string>& choices);
+    virtual void		SetDev(int iNewDevice);
+    virtual int			GetDev();
+    virtual void		Init(int iNewBufferSize, _BOOLEAN bNewBlocking = TRUE);
+    virtual _BOOLEAN	Read(CVector<short>& psData);
+    virtual void		Close();
+protected:
+    snd_pcm_t *handle;
+    vector<string> names;
+    vector<string> devices;
+    int dev;
+};
+
+class CAlsaSoundOut: public CSoundOutInterface
+{
+public:
+    CAlsaSoundOut();
+    virtual 			~CAlsaSoundOut();
+
+    virtual void		Enumerate(vector<string>& choices);
+    virtual void		SetDev(int iNewDevice);
+    virtual int			GetDev();
+    virtual void		Init(int iNewBufferSize, _BOOLEAN bNewBlocking = TRUE);
+    virtual _BOOLEAN	Write(CVector<short>& psData);
+    virtual void		Close();
+protected:
+    snd_pcm_t *handle;
+    vector<string> names;
+    vector<string> devices;
+    int dev;
+};
+
+#endif
diff --git a/src/linux/jack.cpp b/src/linux/jack.cpp
new file mode 100644
index 0000000..af0827f
--- /dev/null
+++ b/src/linux/jack.cpp
@@ -0,0 +1,599 @@
+/******************************************************************************\
+* British Broadcasting Corporation
+* Copyright (c) 2001-2014
+*
+* Author(s):
+*	Julian Cable
+*
+* Description:
+*	Jack sound classes
+*
+******************************************************************************
+*
+* This program is free software; you can redistribute it and/or modify it under
+* the terms of the GNU General Public License as published by the Free Software
+* Foundation; either version 2 of the License, or (at your option) any later
+* version.
+*
+* This program is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+* details.
+*
+* You should have received a copy of the GNU General Public License along with
+* this program; if not, write to the Free Software Foundation, Inc.,
+* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#define _POSIX_C_SOURCE 199309
+#include <time.h>
+#include "jack.h"
+#include <sstream>
+#include <iostream>
+#include <cmath>
+#include <cstdlib>
+using namespace std;
+
+instance_data_t::instance_data_t():num_channels(2),
+        left(NULL), right(NULL), buff(NULL), underruns(0), overruns(0),
+        peer_left(),peer_right()
+{
+    buff =
+        jack_ringbuffer_create(
+            8 * sizeof(short) * 48 * 400 * num_channels
+        );
+}
+
+instance_data_t::~instance_data_t()
+{
+    jack_ringbuffer_free(buff);
+}
+
+struct CJackCommon
+{
+    CJackCommon():client(NULL),is_active(false),capture_data(NULL),play_data(NULL) {}
+    jack_client_t * client;
+    volatile bool is_active;
+    instance_data_t *capture_data;
+    instance_data_t *play_data;
+    void initialise();
+    void terminate();
+};
+
+static CJackCommon data;
+
+static int
+capture_stereo(jack_nframes_t nframes, void *arg)
+{
+    instance_data_t& data = *(instance_data_t *) arg;
+    if (arg==NULL)
+    {
+        return 0;
+    }
+    if (data.left==NULL || data.right == NULL)
+    {
+        return 0;
+    }
+    jack_default_audio_sample_t *in[2];
+    in[0] = (jack_default_audio_sample_t *) jack_port_get_buffer(data.left, nframes);
+    in[1] = (jack_default_audio_sample_t *) jack_port_get_buffer(data.right, nframes);
+    if (in[0]==NULL || in[1]==NULL)
+    {
+        return 0;
+    }
+    if (data.buff==NULL)
+    {
+        return 0;
+    }
+    for (jack_nframes_t i = 0; i < nframes; i++)
+    {
+        short sample[2];
+        size_t bytes = sizeof(short)*2;
+        /* interleave samples for encoder */
+        for (int chn = 0; chn < 2; chn++)
+            sample[chn] = short (32768.0 * in[chn][i]);
+        if (jack_ringbuffer_write (data.buff, (char *) sample, bytes) < bytes)
+            data.overruns++;
+    }
+    return 0;
+}
+
+pair< string, string>
+CJackPorts::get_ports(int dev)
+{
+    const size_t n = devices.size();
+    if (n==0)
+        return pair<string,string>("","");
+    if (dev<0 || dev>=int(n))
+        return ports[devices[n-1]];
+    return ports[devices[dev]];
+}
+
+void
+CJackPorts::load(jack_client_t * client, unsigned long flags)
+{
+    const char **port_names = jack_get_ports(client, ".*", NULL, flags);
+    string client_name = jack_get_client_name(client);
+    ports.clear();
+    devices.clear();
+    map<string, vector<string> > device_ports;
+    if (port_names)
+    {
+        for (size_t i=0; port_names[i]; i++)
+        {
+            string port = port_names[i];
+            if (port.substr(0, client_name.length())!=client_name)
+            {
+                size_t p = port.find(':');
+                string dev = port.substr(0, p);
+                device_ports[dev].push_back(port);
+            }
+            //free(port_names[i]);
+        }
+    }
+    free(port_names);
+    for (map<string, vector<string> >::iterator i = device_ports.begin(); i!=device_ports.end(); i++)
+    {
+        switch (i->second.size())
+        {
+        case 0:
+            break; // should not happen
+        case 1:
+            ports[i->first].first = i->second[0];
+            ports[i->first].second = i->second[0];
+            devices.push_back(i->first);
+            break;
+        case 2:
+            ports[i->first].first = i->second[0];
+            ports[i->first].second = i->second[1];
+            devices.push_back(i->first);
+            break;
+        default:
+            for (size_t j=0; j<i->second.size()/2; j++)
+            {
+                stringstream dev;
+                dev << i->first << "(" << 2*j << "," << 2*j+1 << ")";
+                ports[dev.str()].first = i->second[2*j];
+                ports[dev.str()].second = i->second[2*j+1];
+                devices.push_back(dev.str());
+            }
+            if (i->second.size() % 2 == 1)
+            {
+                size_t j = i->second.size()-1;
+                stringstream dev;
+                dev << i->first << "(" << j << ")";
+                ports[dev.str()].first = i->second[j];
+                ports[dev.str()].second = i->second[j];
+                devices.push_back(dev.str());
+            }
+        }
+    }
+}
+
+static int
+play_stereo(jack_nframes_t nframes, void *arg)
+{
+    if (arg==NULL)
+    {
+        return 0;
+    }
+    instance_data_t& data = *(instance_data_t *) arg;
+    if (data.left==NULL || data.right == NULL)
+    {
+        return 0;
+    }
+    jack_default_audio_sample_t *out[2];
+    out[0] = (jack_default_audio_sample_t *) jack_port_get_buffer(data.left, nframes);
+    out[1] = (jack_default_audio_sample_t *) jack_port_get_buffer(data.right, nframes);
+    if (out[0]==NULL || out[1]==NULL)
+    {
+        return 0;
+    }
+    if (data.buff==NULL)
+    {
+        return 0;
+    }
+    for (jack_nframes_t i = 0; i < nframes; i++)
+    {
+        short buffer[2];
+        size_t bytes = sizeof(short)*2;
+        size_t n = jack_ringbuffer_read(data.buff, (char*)buffer, bytes);
+        if (n < bytes)
+            data.underruns++;
+        /* de-interleave samples from decoder */
+        for (int chn = 0; chn < 2; chn++)
+            out[chn][i] = jack_default_audio_sample_t(double(buffer[chn])/32768.0);
+    }
+    return 0;
+}
+
+static int
+process_callback(jack_nframes_t nframes, void *arg)
+{
+    CJackCommon *This = (CJackCommon *) arg;
+    if (This->capture_data)
+        capture_stereo(nframes, This->capture_data);
+    if (This->play_data)
+        play_stereo(nframes, This->play_data);
+    return 0;
+}
+
+static void
+jack_shutdown(void *arg)
+{
+    cout << "jack shut down" << endl;
+}
+
+void CJackCommon::initialise()
+{
+    jack_options_t options = jack_options_t(JackNullOption | JackServerName);
+    jack_status_t status;
+    string server = "default";
+
+    /* open a client connection to the Jack server */
+
+    client = jack_client_open("dream", options, &status, server.c_str());
+    if (client == NULL)
+    {
+        cerr << "jack_client_open() failed, status = " << ((long unsigned)
+                status) << endl;
+        if (status & JackServerFailed)
+        {
+            throw "Unable to connect to Jack server";
+        }
+    }
+    if (status & JackServerStarted)
+    {
+        cout << "Jack server started" << endl;
+    }
+    if (status & JackNameNotUnique)
+    {
+        char *client_name = jack_get_client_name(client);
+        cout << "Jack unique name `" << client_name << "' assigned" << endl;
+    }
+
+    /* tell the CSoundInJack server to call `process()' whenever
+       there is work to be done.
+     */
+
+    jack_set_process_callback(client, process_callback, &data);
+
+    /* tell the Jack server to call `jack_shutdown()' if
+       it ever shuts down, either entirely, or if it
+       just decides to stop calling us.
+     */
+
+    jack_on_shutdown(client, jack_shutdown, 0);
+
+    if (jack_get_sample_rate(client) != Parameters.GetSampleRate())
+    {
+        throw "Jack: jack is running with the wrong sample rate";
+    }
+}
+
+void CJackCommon::terminate()
+{
+    jack_client_close(client);
+    client = NULL;
+}
+
+CSoundInJack::CSoundInJack():iBufferSize(0), bBlocking(TRUE), capture_data(), dev(-1),ports()
+{
+    if (data.client==NULL)
+        data.initialise();
+
+    if (data.is_active && jack_deactivate(data.client))
+    {
+        throw "Jack: cannot deactivate client";
+    }
+    data.is_active = false;
+
+    capture_data.left =
+        jack_port_register(data.client, "input_0", JACK_DEFAULT_AUDIO_TYPE,
+                           JackPortIsInput, 0);
+    capture_data.right =
+        jack_port_register(data.client, "input_1", JACK_DEFAULT_AUDIO_TYPE,
+                           JackPortIsInput, 0);
+
+    if ((capture_data.left == NULL) || (capture_data.right == NULL))
+    {
+        throw "Jack: no more ports available";
+    }
+
+    jack_ringbuffer_reset(capture_data.buff);
+
+    data.capture_data = &capture_data;
+
+    ports.load(data.client, JackPortIsOutput);
+
+    if (jack_activate(data.client))
+    {
+        throw "Jack: cannot activate client";
+    }
+    data.is_active = true;
+}
+
+CSoundInJack::CSoundInJack(const CSoundInJack & e):
+        iBufferSize(e.iBufferSize), bBlocking(e.bBlocking), device_changed(TRUE),
+        capture_data(e.capture_data), dev(e.dev), ports(e.ports)
+{
+}
+
+CSoundInJack & CSoundInJack::operator=(const CSoundInJack & e)
+{
+    iBufferSize = e.iBufferSize;
+    bBlocking = e.bBlocking;
+    capture_data = e.capture_data;
+    dev = e.dev;
+    ports = e.ports;
+    return *this;
+}
+
+CSoundInJack::~CSoundInJack()
+{
+    Close();
+    if (data.client==NULL)
+        return;
+
+    if (data.is_active && jack_deactivate(data.client))
+    {
+        throw "Jack: cannot deactivate client";
+    }
+    data.is_active = false;
+    data.capture_data = NULL;
+    if (jack_activate(data.client))
+    {
+        throw "Jack: cannot activate client";
+    }
+    data.is_active = true;
+}
+
+void
+CSoundInJack::Enumerate(vector<string>& choices)
+{
+    ports.load(data.client, JackPortIsOutput);
+    choices = ports.devices;
+}
+
+int
+CSoundInJack::GetDev()
+{
+    return dev;
+}
+
+void
+CSoundInJack::SetDev(int iNewDevice)
+{
+    if (dev != iNewDevice)
+    {
+        dev = iNewDevice;
+        device_changed = true;
+    }
+}
+
+void
+CSoundInJack::Init(int iNewBufferSize, _BOOLEAN bNewBlocking)
+{
+    if (device_changed == false)
+        return;
+
+    iBufferSize = iNewBufferSize;
+    bBlocking = bNewBlocking;
+
+    const char ** l = jack_port_get_connections(capture_data.left);
+    const char ** r = jack_port_get_connections(capture_data.right);
+    if (l || r)
+        Close();
+
+    if (l) free(l);
+    if (r) free(r);
+
+    pair<string,string> source = ports.get_ports(dev);
+
+    int err = jack_connect (data.client, source.first.c_str(), jack_port_name(capture_data.left));
+    if (err)
+    {
+        cout << "err " << err << " can't connect " << source.first << " to " << jack_port_name(capture_data.left) << endl;
+    }
+
+    err = jack_connect (data.client, source.second.c_str(), jack_port_name(capture_data.right));
+    if (err)
+    {
+        cout << "err " << err << " can't connect " << source.second << " to " << jack_port_name(capture_data.right) << endl;
+    }
+    device_changed = false;
+}
+
+_BOOLEAN
+CSoundInJack::Read(CVector<short>& psData)
+{
+    if (device_changed)
+        Init(iBufferSize, bBlocking);
+
+    size_t bytes = iBufferSize * sizeof(short);
+    const int delay_ms = 100;
+#ifdef _WIN32
+    while (jack_ringbuffer_read_space(capture_data.buff) < bytes)
+    {
+        Sleep(delay_ms);
+    }
+#else
+    timespec delay;
+    delay.tv_sec = 0;
+    const long one_ms = 1000000L; // nanoseconds
+    delay.tv_nsec = delay_ms*one_ms;
+    while (jack_ringbuffer_read_space(capture_data.buff) < bytes)
+    {
+        nanosleep(&delay, NULL);
+    }
+#endif
+    char *buffer = (char *) &psData[0];
+    //short buffer[16384];
+    size_t n = jack_ringbuffer_read(capture_data.buff, (char*)&buffer[0], bytes);
+    /*
+    short smax=-32767, smin=32767;
+    for(int i=0; i<iBufferSize; i++)
+    {
+    	if(smax<buffer[i]) smax = buffer[i];
+    	if(smin>buffer[i]) smin = buffer[i];
+    }
+    cout << iBufferSize << " " << setw(8) << smin << " " << setw(8) << smax << endl;
+    */
+    if (n != bytes)
+    {
+        capture_data.underruns++;
+        cerr << "jack read " << n << " wanted " << bytes << endl;
+        return TRUE;
+    }
+    return FALSE;
+}
+
+void
+CSoundInJack::Close()
+{
+    jack_port_disconnect(data.client, capture_data.left);
+    jack_port_disconnect(data.client, capture_data.right);
+    device_changed = true;
+}
+
+CSoundOutJack::CSoundOutJack():iBufferSize(0), bBlocking(TRUE), device_changed(TRUE),
+        play_data(), dev(-1), ports()
+{
+    if (data.client==NULL)
+        data.initialise();
+
+    if (data.is_active && jack_deactivate(data.client))
+    {
+        throw "Jack: cannot deactivate client";
+    }
+    data.is_active = false;
+
+    play_data.left =
+        jack_port_register(data.client, "output_0", JACK_DEFAULT_AUDIO_TYPE,
+                           JackPortIsOutput, 0);
+    play_data.right =
+        jack_port_register(data.client, "output_1", JACK_DEFAULT_AUDIO_TYPE,
+                           JackPortIsOutput, 0);
+
+    if ((play_data.left == NULL) || (play_data.right == NULL))
+    {
+        throw "Jack: no more ports available";
+    }
+
+    data.play_data = &play_data;
+    ports.load(data.client, JackPortIsInput);
+
+    if (jack_activate(data.client))
+    {
+        throw "Jack: cannot activate client";
+    }
+    data.is_active = true;
+}
+
+CSoundOutJack::~CSoundOutJack()
+{
+    Close();
+    if (data.is_active && jack_deactivate(data.client))
+    {
+        throw "Jack: cannot deactivate client";
+    }
+    data.is_active = false;
+    data.capture_data = NULL;
+    if (jack_activate(data.client))
+    {
+        throw "Jack: cannot activate client";
+    }
+    data.is_active = true;
+}
+
+CSoundOutJack::CSoundOutJack(const CSoundOutJack & e):
+        iBufferSize(e.iBufferSize), bBlocking(e.bBlocking),dev(e.dev)
+{
+}
+
+CSoundOutJack & CSoundOutJack::operator=(const CSoundOutJack & e)
+{
+    iBufferSize = e.iBufferSize;
+    bBlocking = e.bBlocking;
+    play_data = e.play_data;
+    dev = e.dev;
+    ports = e.ports;
+    return *this;
+}
+
+void
+CSoundOutJack::Enumerate(vector<string>& choices)
+{
+    ports.load(data.client, JackPortIsInput);
+    choices = ports.devices;
+}
+
+int
+CSoundOutJack::GetDev()
+{
+    return dev;
+}
+
+void
+CSoundOutJack::SetDev(int iNewDevice)
+{
+    if (dev != iNewDevice)
+    {
+        dev = iNewDevice;
+        device_changed = true;
+    }
+}
+
+void
+CSoundOutJack::Init(int iNewBufferSize, _BOOLEAN bNewBlocking)
+{
+    if (device_changed == false)
+        return;
+
+    iBufferSize = iNewBufferSize;
+    bBlocking = bNewBlocking;
+
+    const char ** l = jack_port_get_connections(play_data.left);
+    const char ** r = jack_port_get_connections(play_data.right);
+    if (l || r)
+        Close();
+
+    if (l) free(l);
+
+    pair<string,string> sink = ports.get_ports(dev);
+
+    int err = jack_connect (data.client, jack_port_name(play_data.left), sink.first.c_str());
+    if (err)
+    {
+        cout << "err " << err << " can't connect " << jack_port_name(play_data.left) << " to " << sink.first << endl;
+    }
+    err = jack_connect (data.client, jack_port_name(play_data.right), sink.second.c_str());
+    if (err)
+    {
+        cout << "err " << err << " can't connect " << jack_port_name(play_data.right) << " to " << sink.second << endl;
+    }
+    device_changed = false;
+}
+
+_BOOLEAN
+CSoundOutJack::Write(CVector<short>& psData)
+{
+    if (device_changed)
+        Init(iBufferSize, bBlocking);
+
+    size_t bytes = psData.Size()*sizeof(short);
+    if (jack_ringbuffer_write (play_data.buff, (char *) &psData[0], bytes) < bytes)
+    {
+        play_data.overruns++;
+        return TRUE;
+    }
+    return FALSE;
+}
+
+void
+CSoundOutJack::Close()
+{
+    jack_port_disconnect(data.client, play_data.left);
+    jack_port_disconnect(data.client, play_data.right);
+    device_changed = true;
+}
diff --git a/src/linux/jack.h b/src/linux/jack.h
new file mode 100644
index 0000000..512552c
--- /dev/null
+++ b/src/linux/jack.h
@@ -0,0 +1,114 @@
+/******************************************************************************\
+ * British Broadcasting Corporation
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Julian Cable
+ *
+ * Description:
+ *	Jack sound classes
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#ifndef _JACK_H
+#define _JACK_H
+
+#include "../soundinterface.h"
+
+#ifdef _WIN32
+# include <windows.h>
+	typedef HANDLE pthread_t;
+#endif
+#include <jack/jack.h>
+#include <jack/ringbuffer.h>
+#include <map>
+
+/* Classes ********************************************************************/
+
+struct instance_data_t
+{
+    instance_data_t();
+    ~instance_data_t();
+    int num_channels;
+    jack_port_t *left;
+    jack_port_t *right;
+    jack_ringbuffer_t* buff;
+    int underruns;
+    int overruns;
+    string peer_left, peer_right;
+};
+
+class CJackPorts
+{
+public:
+    CJackPorts():devices(),ports() {}
+    vector<string> devices;
+    void load(jack_client_t * client, unsigned long flags);
+    pair< string, string>get_ports(int dev);
+protected:
+    map<string, pair< string, string> > ports;
+};
+
+class CSoundInJack : public CSoundInInterface
+{
+public:
+    CSoundInJack();
+    virtual ~CSoundInJack();
+    CSoundInJack(const CSoundInJack& e);
+    CSoundInJack& operator=(const CSoundInJack& e);
+
+    virtual void		Init(int iNewBufferSize, _BOOLEAN bNewBlocking = TRUE);
+    virtual _BOOLEAN	Read(CVector<short>& psData);
+    virtual void		Enumerate(vector<string>&);
+    virtual int			GetDev();
+    virtual void		SetDev(int iNewDev);
+    virtual void		Close();
+protected:
+    int iBufferSize;
+    _BOOLEAN bBlocking;
+    _BOOLEAN device_changed;
+    instance_data_t capture_data;
+    int dev;
+    CJackPorts ports;
+};
+
+class CSoundOutJack : public CSoundOutInterface
+{
+public:
+    CSoundOutJack();
+    virtual ~CSoundOutJack();
+    CSoundOutJack(const CSoundOutJack& e);
+    CSoundOutJack& operator=(const CSoundOutJack& e);
+
+    virtual void		Init(int iNewBufferSize, _BOOLEAN bNewBlocking = TRUE);
+    virtual _BOOLEAN	Write(CVector<short>& psData);
+    virtual void		Enumerate(vector<string>&);
+    virtual int			GetDev();
+    virtual void		SetDev(int iNewDev);
+    virtual void		Close();
+protected:
+    int iBufferSize;
+    _BOOLEAN bBlocking;
+    _BOOLEAN device_changed;
+    instance_data_t play_data;
+    int dev;
+    CJackPorts ports;
+};
+
+#endif
diff --git a/src/linux/oss.cpp b/src/linux/oss.cpp
new file mode 100644
index 0000000..9757c35
--- /dev/null
+++ b/src/linux/oss.cpp
@@ -0,0 +1,302 @@
+/******************************************************************************\
+* Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+* Copyright (c) 2001-2014
+*
+* Author(s):
+*	Alexander Kurpiers
+*
+*
+******************************************************************************
+*
+* This program is free software; you can redistribute it and/or modify it under
+* the terms of the GNU General Public License as published by the Free Software
+* Foundation; either version 2 of the License, or (at your option) any later
+* version.
+*
+* This program is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+* details.
+*
+* You should have received a copy of the GNU General Public License along with
+* this program; if not, write to the Free Software Foundation, Inc.,
+* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*
+\******************************************************************************/
+
+#include "soundin.h"
+#include "soundout.h"
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <iostream>
+#include <fstream>
+#include <sstream>
+#include <sys/soundcard.h>
+#include <errno.h>
+
+map < string, COSSDev::devdata > COSSDev::dev;
+
+void
+COSSDev::devdata::open(const string & name, int mode)
+{
+    if (fd == 0)
+    {
+        fd =::open(name.c_str(), O_RDWR);
+        int
+        arg,
+        status;
+        /* Get ready for us.
+           ioctl(audio_fd, SNDCTL_DSP_SYNC, 0) can be used when application wants
+           to wait until last byte written to the device has been played (it doesn't
+           wait in recording mode). After that the call resets (stops) the device
+           and returns back to the calling program. Note that this call may take
+           several seconds to execute depending on the amount of data in the
+           buffers. close() calls SNDCTL_DSP_SYNC automaticly */
+        ioctl(fd, SNDCTL_DSP_SYNC, 0);
+
+        /* Set sampling parameters always so that number of channels (mono/stereo)
+           is set before selecting sampling rate! */
+        /* Set number of channels (0=mono, 1=stereo) */
+        arg = NUM_OUT_CHANNELS - 1;
+        status = ioctl(fd, SNDCTL_DSP_STEREO, &arg);
+        if (status == -1)
+            throw
+            CGenErr(string("SNDCTL_DSP_CHANNELS ioctl failed: ") +
+                    strerror(errno));
+
+        if (arg != (NUM_OUT_CHANNELS - 1))
+            throw
+            CGenErr("unable to set number of channels");
+
+        /* Sampling rate */
+        arg = Parameters.GetSampleRate();
+        status = ioctl(fd, SNDCTL_DSP_SPEED, &arg);
+        if (status == -1)
+            throw
+            CGenErr("SNDCTL_DSP_SPEED ioctl failed");
+        if (arg != Parameters.GetSampleRate())
+            throw
+            CGenErr("unable to set sample rate");
+
+        /* Sample size */
+        arg = (BITS_PER_SAMPLE == 16) ? AFMT_S16_LE : AFMT_U8;
+        status = ioctl(fd, SNDCTL_DSP_SAMPLESIZE, &arg);
+        if (status == -1)
+            throw
+            CGenErr("SNDCTL_DSP_SAMPLESIZE ioctl failed");
+        if (arg != ((BITS_PER_SAMPLE == 16) ? AFMT_S16_LE : AFMT_U8))
+            throw
+            CGenErr("unable to set sample size");
+        /* Check capabilities of the sound card */
+        status = ioctl(fd, SNDCTL_DSP_GETCAPS, &arg);
+        if (status == -1)
+            throw
+            CGenErr("SNDCTL_DSP_GETCAPS ioctl failed");
+        if ((arg & DSP_CAP_DUPLEX) == 0)
+            throw
+            CGenErr("Soundcard not full duplex capable!");
+    }
+    if (fd > 0)
+        count++;
+    else
+    {
+        fd = 0;
+    }
+}
+
+void
+COSSDev::devdata::close()
+{
+    if (fd && ((--count) == 0))
+    {
+        ::close(fd);
+        fd = 0;
+    }
+}
+
+int
+COSSDev::devdata::fildes()
+{
+    return fd;
+}
+
+void
+COSSDev::open(const string & devname, int mode)
+{
+    name = devname;
+    dev[name].open(name, mode);
+}
+
+void
+COSSDev::close()
+{
+    dev[name].close();
+}
+
+void
+getdevices(vector < string > &names, vector < string > &devices,
+           bool playback)
+{
+    vector < string > tmp;
+    names.clear();
+    devices.clear();
+    ifstream sndstat("/dev/sndstat");
+    if (!sndstat.is_open())
+    {
+        sndstat.close();
+        sndstat.clear();
+        sndstat.open("/proc/asound/oss/sndstat");
+    }
+
+    if (sndstat.is_open())
+    {
+        while (!(sndstat.eof() || sndstat.fail()))
+        {
+            char s[80];
+            sndstat.getline(s, sizeof(s));
+
+            if (strstr(s, "Audio devices:") != NULL)
+            {
+                while (true)
+                {
+                    sndstat.getline(s, sizeof(s));
+                    if (strlen(s) > 0)
+                        tmp.push_back(s);
+                    else
+                        break;
+                }
+            }
+        }
+    }
+    sndstat.close();
+
+    /* if there is more than one device, let the user chose */
+    if (tmp.size() > 0)
+    {
+        names.resize(tmp.size());
+        devices.resize(tmp.size());
+        size_t i;
+        for (i = 0; i < tmp.size(); i++)
+        {
+            stringstream o(tmp[i]);
+            char p, name[200];
+            int n;
+            o >> n >> p;
+            o.getline(name, sizeof(name), ':');
+            names[n] = name;
+        }
+        devices[0] = "/dev/dsp";
+        for (i = 1; i < names.size(); i++)
+        {
+            devices[i] = "/dev/dsp";
+            devices[i] += '0' + i;
+        }
+    }
+    else
+    {
+        if (playback)
+            names.push_back("Default Playback Device");
+        else
+            names.push_back("Default Capture Device");
+        devices.push_back("/dev/dsp");
+    }
+}
+
+void CSoundIn::Init_HW()
+{
+    /* Open sound device (Use O_RDWR only when writing a program which is
+       going to both record and play back digital audio) */
+    if (devices.size()==0)
+        throw CGenErr("no capture devices available");
+
+    /* Default ? */
+    if (iCurrentDevice < 0)
+        iCurrentDevice = devices.size()-1;
+
+    /* out of range ? (could happen from command line parameter or USB device unplugged */
+    if (iCurrentDevice >= int(devices.size()))
+        iCurrentDevice = devices.size()-1;
+
+    string devname = devices[iCurrentDevice];
+    dev.open(devname, O_RDONLY );
+    if (dev.fildes() < 0)
+        throw CGenErr("open of "+devname+" failed");
+}
+
+
+int CSoundIn::read_HW( void * recbuf, int size) {
+
+    int ret = read(dev.fildes(), recbuf, size * NUM_IN_CHANNELS * BYTES_PER_SAMPLE );
+    if (ret < 0) {
+        switch (errno)
+        {
+        case 0:
+            return 0;
+            break;
+        case EINTR:
+            return 0;
+            break;
+        case EAGAIN:
+            return 0;
+            break;
+        default:
+            qDebug("read error: %s", strerror(errno));
+            throw CGenErr("CSound:Read");
+        }
+    } else
+        return ret / (NUM_IN_CHANNELS * BYTES_PER_SAMPLE);
+}
+
+void CSoundIn::close_HW( void ) {
+    dev.close();
+}
+
+void CSoundOut::Init_HW()
+{
+    /* Open sound device (Use O_RDWR only when writing a program which is
+       going to both record and play back digital audio) */
+    if (devices.size()==0)
+        throw CGenErr("no playback devices available");
+
+    /* Default ? */
+    if (iCurrentDevice < 0)
+        iCurrentDevice = devices.size()-1;
+
+    /* out of range ? (could happen from command line parameter or USB device unplugged */
+    if (iCurrentDevice >= int(devices.size()))
+        iCurrentDevice = devices.size()-1;
+
+    string devname = devices[iCurrentDevice];
+    dev.open(devname, O_WRONLY );
+}
+
+int CSoundOut::write_HW( _SAMPLE *playbuf, int size )
+{
+
+    int start = 0;
+    int ret;
+
+    size *= BYTES_PER_SAMPLE * NUM_OUT_CHANNELS;
+
+    while (size)
+    {
+        ret = write(dev.fildes(), &playbuf[start], size);
+        if (ret < 0) {
+            if (errno == EINTR || errno == EAGAIN)
+            {
+                continue;
+            }
+            throw CGenErr("CSound:Write");
+        }
+        size -= ret;
+        start += ret / BYTES_PER_SAMPLE;
+    }
+    return 0;
+}
+
+void CSoundOut::close_HW( void )
+{
+    dev.close();
+}
diff --git a/src/linux/pa_shm_ringbuffer.c b/src/linux/pa_shm_ringbuffer.c
new file mode 100644
index 0000000..5924c4b
--- /dev/null
+++ b/src/linux/pa_shm_ringbuffer.c
@@ -0,0 +1,284 @@
+/*
+ * $Id: pa_shm_ringbuffer.c,v 1.4 2001-2014/09/30 10:33:58 jcable Exp $
+ * Portable Audio I/O Library
+ * Ring Buffer utility.
+ *
+ * Author: Phil Burk, http://www.softsynth.com
+ * modified for SMP safety on Mac OS X by Bjorn Roche
+ * modified for SMP safety on Linux by Leland Lucius
+ * also, allowed for const where possible
+ * Note that this is safe only for a single-thread reader and a
+ * single-thread writer.
+ *
+ * This program uses the PortAudio Portable Audio Library.
+ * For more information see: http://www.portaudio.com
+ * Copyright (c) 1999-2000 Ross Bencina and Phil Burk
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * The text above constitutes the entire PortAudio license; however,
+ * the PortAudio community also makes the following non-binding requests:
+ *
+ * Any person wishing to distribute modifications to the Software is
+ * requested to send the modifications to the original developer so that
+ * they can be incorporated into the canonical version. It is also
+ * requested that these non-binding requests be included along with the
+ * license above.
+ */
+
+/**
+ @file
+ @ingroup common_src
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include "pa_shm_ringbuffer.h"
+#include <string.h>
+
+/****************
+ * First, we'll define some memory barrier primitives based on the system.
+ * right now only OS X, FreeBSD, and Linux are supported. In addition to providing
+ * memory barriers, these functions should ensure that data cached in registers
+ * is written out to cache where it can be snooped by other CPUs. (ie, the volatile
+ * keyword should not be required)
+ *
+ * the primitives that must be defined are:
+ *
+ * PaUtil_FullMemoryBarrier()
+ * PaUtil_ReadMemoryBarrier()
+ * PaUtil_WriteMemoryBarrier()
+ *
+ ****************/
+
+#if defined(__APPLE__) || defined(__FreeBSD__)
+#   include <libkern/OSAtomic.h>
+/* Here are the memory barrier functions. Mac OS X and FreeBSD only provide
+   full memory barriers, so the three types of barriers are the same. */
+#   define PaUtil_FullMemoryBarrier()  OSMemoryBarrier()
+#   define PaUtil_ReadMemoryBarrier()  OSMemoryBarrier()
+#   define PaUtil_WriteMemoryBarrier() OSMemoryBarrier()
+#elif defined(__GNUC__)
+/* GCC understands volatile asm and "memory" to mean it
+ * should not reorder memory read/writes */
+#   if defined( __PPC__ )
+#      define PaUtil_FullMemoryBarrier()  asm volatile("sync":::"memory")
+#      define PaUtil_ReadMemoryBarrier()  asm volatile("sync":::"memory")
+#      define PaUtil_WriteMemoryBarrier() asm volatile("sync":::"memory")
+#   elif defined( __i386__ ) || defined( __i486__ ) || defined( __i586__ ) || defined( __i686__ ) || defined( __x86_64__ )
+#      define PaUtil_FullMemoryBarrier()  asm volatile("mfence":::"memory")
+#      define PaUtil_ReadMemoryBarrier()  asm volatile("lfence":::"memory")
+#      define PaUtil_WriteMemoryBarrier() asm volatile("sfence":::"memory")
+#   else
+#      ifdef ALLOW_SMP_DANGERS
+#         warning Memory barriers not defined on this system or system unknown
+#         warning For SMP safety, you should fix this.
+#         define PaUtil_FullMemoryBarrier()
+#         define PaUtil_ReadMemoryBarrier()
+#         define PaUtil_WriteMemoryBarrier()
+#      else
+#         error Memory barriers are not defined on this system. You can still compile by defining ALLOW_SMP_DANGERS, but SMP safety will not be guaranteed.
+#      endif
+#   endif
+#else
+#   ifdef ALLOW_SMP_DANGERS
+#      warning Memory barriers not defined on this system or system unknown
+#      warning For SMP safety, you should fix this.
+#      define PaUtil_FullMemoryBarrier()
+#      define PaUtil_ReadMemoryBarrier()
+#      define PaUtil_WriteMemoryBarrier()
+#   else
+#      error Memory barriers are not defined on this system. You can still compile by defining ALLOW_SMP_DANGERS, but SMP safety will not be guaranteed.
+#   endif
+#endif
+
+/***************************************************************************
+ * Initialize FIFO.
+ * numBytes must be power of 2, returns -1 if not.
+ */
+long PaUtil_InitializeShmRingBuffer( PaUtilShmRingBuffer *rbuf, long numBytes, void *dataPtr )
+{
+    (void)dataPtr;
+    if ( ((numBytes-1) & numBytes) != 0) return -1; /* Not Power of two. */
+    rbuf->bufferSize = numBytes;
+    //rbuf->buffer = (char *)dataPtr;
+    PaUtil_FlushShmRingBuffer( rbuf );
+    rbuf->bigMask = (numBytes*2)-1;
+    rbuf->smallMask = (numBytes)-1;
+    return 0;
+}
+
+/***************************************************************************
+** Return number of bytes available for reading. */
+long PaUtil_GetShmRingBufferReadAvailable( PaUtilShmRingBuffer *rbuf )
+{
+    PaUtil_ReadMemoryBarrier();
+    return ( (rbuf->writeIndex - rbuf->readIndex) & rbuf->bigMask );
+}
+/***************************************************************************
+** Return number of bytes available for writing. */
+long PaUtil_GetShmRingBufferWriteAvailable( PaUtilShmRingBuffer *rbuf )
+{
+    /* Since we are calling PaUtil_GetShmRingBufferReadAvailable, we don't need an aditional MB */
+    return ( rbuf->bufferSize - PaUtil_GetShmRingBufferReadAvailable(rbuf));
+}
+
+/***************************************************************************
+** Clear buffer. Should only be called when buffer is NOT being read. */
+void PaUtil_FlushShmRingBuffer( PaUtilShmRingBuffer *rbuf )
+{
+    rbuf->writeIndex = rbuf->readIndex = 0;
+}
+
+/***************************************************************************
+** Get address of region(s) to which we can write data.
+** If the region is contiguous, size2 will be zero.
+** If non-contiguous, size2 will be the size of second region.
+** Returns room available to be written or numBytes, whichever is smaller.
+*/
+long PaUtil_GetShmRingBufferWriteRegions( PaUtilShmRingBuffer *rbuf, long numBytes,
+        void **dataPtr1, long *sizePtr1,
+        void **dataPtr2, long *sizePtr2 )
+{
+    long   index;
+    long   available = PaUtil_GetShmRingBufferWriteAvailable( rbuf );
+    char *buffer = (char*)rbuf+sizeof(PaUtilShmRingBuffer);
+
+    if ( numBytes > available ) numBytes = available;
+    /* Check to see if write is not contiguous. */
+    index = rbuf->writeIndex & rbuf->smallMask;
+    if ( (index + numBytes) > rbuf->bufferSize )
+    {
+        /* Write data in two blocks that wrap the buffer. */
+        long   firstHalf = rbuf->bufferSize - index;
+        *dataPtr1 = &buffer[index];
+        *sizePtr1 = firstHalf;
+        *dataPtr2 = &buffer[0];
+        *sizePtr2 = numBytes - firstHalf;
+    }
+    else
+    {
+        *dataPtr1 = &buffer[index];
+        *sizePtr1 = numBytes;
+        *dataPtr2 = NULL;
+        *sizePtr2 = 0;
+    }
+    return numBytes;
+}
+
+
+/***************************************************************************
+*/
+long PaUtil_AdvanceShmRingBufferWriteIndex( PaUtilShmRingBuffer *rbuf, long numBytes )
+{
+    /* we need to ensure that previous writes are seen before we update the write index */
+    PaUtil_WriteMemoryBarrier();
+    return rbuf->writeIndex = (rbuf->writeIndex + numBytes) & rbuf->bigMask;
+}
+
+/***************************************************************************
+** Get address of region(s) from which we can read data.
+** If the region is contiguous, size2 will be zero.
+** If non-contiguous, size2 will be the size of second region.
+** Returns room available to be written or numBytes, whichever is smaller.
+*/
+long PaUtil_GetShmRingBufferReadRegions( PaUtilShmRingBuffer *rbuf, long numBytes,
+        void **dataPtr1, long *sizePtr1,
+        void **dataPtr2, long *sizePtr2 )
+{
+    long   index;
+    long   available = PaUtil_GetShmRingBufferReadAvailable( rbuf );
+    char *buffer = (char*)rbuf+sizeof(PaUtilShmRingBuffer);
+
+    if ( numBytes > available ) numBytes = available;
+    /* Check to see if read is not contiguous. */
+    index = rbuf->readIndex & rbuf->smallMask;
+    if ( (index + numBytes) > rbuf->bufferSize )
+    {
+        /* Write data in two blocks that wrap the buffer. */
+        long firstHalf = rbuf->bufferSize - index;
+        *dataPtr1 = &buffer[index];
+        *sizePtr1 = firstHalf;
+        *dataPtr2 = &buffer[0];
+        *sizePtr2 = numBytes - firstHalf;
+    }
+    else
+    {
+        *dataPtr1 = &buffer[index];
+        *sizePtr1 = numBytes;
+        *dataPtr2 = NULL;
+        *sizePtr2 = 0;
+    }
+    return numBytes;
+}
+/***************************************************************************
+*/
+long PaUtil_AdvanceShmRingBufferReadIndex( PaUtilShmRingBuffer *rbuf, long numBytes )
+{
+    /* we need to ensure that previous writes are always seen before updating the index. */
+    PaUtil_WriteMemoryBarrier();
+    return rbuf->readIndex = (rbuf->readIndex + numBytes) & rbuf->bigMask;
+}
+
+/***************************************************************************
+** Return bytes written. */
+long PaUtil_WriteShmRingBuffer( PaUtilShmRingBuffer *rbuf, const void *data, long numBytes )
+{
+    long size1, size2, numWritten;
+    void *data1, *data2;
+    numWritten = PaUtil_GetShmRingBufferWriteRegions( rbuf, numBytes, &data1, &size1, &data2, &size2 );
+    if ( size2 > 0 )
+    {
+
+        memcpy( data1, data, size1 );
+        data = ((char *)data) + size1;
+        memcpy( data2, data, size2 );
+    }
+    else
+    {
+        memcpy( data1, data, size1 );
+    }
+    PaUtil_AdvanceShmRingBufferWriteIndex( rbuf, numWritten );
+    return numWritten;
+}
+
+/***************************************************************************
+** Return bytes read. */
+long PaUtil_ReadShmRingBuffer( PaUtilShmRingBuffer *rbuf, void *data, long numBytes )
+{
+    long size1, size2, numRead;
+    void *data1, *data2;
+    numRead = PaUtil_GetShmRingBufferReadRegions( rbuf, numBytes, &data1, &size1, &data2, &size2 );
+    if ( size2 > 0 )
+    {
+        memcpy( data, data1, size1 );
+        data = ((char *)data) + size1;
+        memcpy( data, data2, size2 );
+    }
+    else
+    {
+        memcpy( data, data1, size1 );
+    }
+    PaUtil_AdvanceShmRingBufferReadIndex( rbuf, numRead );
+    return numRead;
+}
diff --git a/src/linux/pa_shm_ringbuffer.h b/src/linux/pa_shm_ringbuffer.h
new file mode 100644
index 0000000..a417411
--- /dev/null
+++ b/src/linux/pa_shm_ringbuffer.h
@@ -0,0 +1,197 @@
+#ifndef PA_SHM_RINGBUFFER_H
+#define PA_SHM_RINGBUFFER_H
+/*
+ * $Id: pa_shm_ringbuffer.h,v 1.3 2001-2014/12/23 14:37:22 jcable Exp $
+ * Portable Audio I/O Library
+ * Ring Buffer utility.
+ *
+ * Author: Phil Burk, http://www.softsynth.com
+ * modified for SMP safety on OS X by Bjorn Roche.
+ * also allowed for const where possible.
+ * Note that this is safe only for a single-thread reader
+ * and a single-thread writer.
+ *
+ * This program is distributed with the PortAudio Portable Audio Library.
+ * For more information see: http://www.portaudio.com
+ * Copyright (c) 1999-2000 Ross Bencina and Phil Burk
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * The text above constitutes the entire PortAudio license; however,
+ * the PortAudio community also makes the following non-binding requests:
+ *
+ * Any person wishing to distribute modifications to the Software is
+ * requested to send the modifications to the original developer so that
+ * they can be incorporated into the canonical version. It is also
+ * requested that these non-binding requests be included along with the
+ * license above.
+ */
+
+/** @file
+ @ingroup common_src
+*/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+    typedef struct PaUtilShmRingBuffer
+    {
+        long   bufferSize; /* Number of bytes in FIFO. Power of 2. Set by PaUtil_InitShmRingBuffer. */
+        long   writeIndex; /* Index of next writable byte. Set by PaUtil_AdvanceShmRingBufferWriteIndex. */
+        long   readIndex;  /* Index of next readable byte. Set by PaUtil_AdvanceShmRingBufferReadIndex. */
+        long   bigMask;    /* Used for wrapping indices with extra bit to distinguish full/empty. */
+        long   smallMask;  /* Used for fitting indices to buffer. */
+    } PaUtilShmRingBuffer;
+
+    /** Initialize Ring Buffer.
+
+     @param rbuf The ring buffer.
+
+     @param numBytes The number of bytes in the buffer and must be power of 2.
+
+     @param dataPtr A pointer to a previously allocated area where the data
+     will be maintained.  It must be numBytes long.
+
+     @return -1 if numBytes is not a power of 2, otherwise 0.
+    */
+    long PaUtil_InitializeShmRingBuffer( PaUtilShmRingBuffer *rbuf, long numBytes, void *dataPtr );
+
+    /** Clear buffer. Should only be called when buffer is NOT being read.
+
+     @param rbuf The ring buffer.
+    */
+    void PaUtil_FlushShmRingBuffer( PaUtilShmRingBuffer *rbuf );
+
+    /** Retrieve the number of bytes available in the ring buffer for writing.
+
+     @param rbuf The ring buffer.
+
+     @return The number of bytes available for writing.
+    */
+    long PaUtil_GetShmRingBufferWriteAvailable( PaUtilShmRingBuffer *rbuf );
+
+    /** Retrieve the number of bytes available in the ring buffer for reading.
+
+     @param rbuf The ring buffer.
+
+     @return The number of bytes available for reading.
+    */
+    long PaUtil_GetShmRingBufferReadAvailable( PaUtilShmRingBuffer *rbuf );
+
+    /** Write data to the ring buffer.
+
+     @param rbuf The ring buffer.
+
+     @param data The address of new data to write to the buffer.
+
+     @param numBytes The number of bytes to be written.
+
+     @return The number of bytes written.
+    */
+    long PaUtil_WriteShmRingBuffer( PaUtilShmRingBuffer *rbuf, const void *data, long numBytes );
+
+    /** Read data from the ring buffer.
+
+     @param rbuf The ring buffer.
+
+     @param data The address where the data should be stored.
+
+     @param numBytes The number of bytes to be read.
+
+     @return The number of bytes read.
+    */
+    long PaUtil_ReadShmRingBuffer( PaUtilShmRingBuffer *rbuf, void *data, long numBytes );
+
+    /** Get address of region(s) to which we can write data.
+
+     @param rbuf The ring buffer.
+
+     @param numBytes The number of bytes desired.
+
+     @param dataPtr1 The address where the first (or only) region pointer will be
+     stored.
+
+     @param sizePtr1 The address where the first (or only) region length will be
+     stored.
+
+     @param dataPtr2 The address where the second region pointer will be stored if
+     the first region is too small to satisfy numBytes.
+
+     @param sizePtr2 The address where the second region length will be stored if
+     the first region is too small to satisfy numBytes.
+
+     @return The room available to be written or numBytes, whichever is smaller.
+    */
+    long PaUtil_GetShmRingBufferWriteRegions( PaUtilShmRingBuffer *rbuf, long numBytes,
+            void **dataPtr1, long *sizePtr1,
+            void **dataPtr2, long *sizePtr2 );
+
+    /** Advance the write index to the next location to be written.
+
+     @param rbuf The ring buffer.
+
+     @param numBytes The number of bytes to advance.
+
+     @return The new position.
+    */
+    long PaUtil_AdvanceShmRingBufferWriteIndex( PaUtilShmRingBuffer *rbuf, long numBytes );
+
+    /** Get address of region(s) from which we can write data.
+
+     @param rbuf The ring buffer.
+
+     @param numBytes The number of bytes desired.
+
+     @param dataPtr1 The address where the first (or only) region pointer will be
+     stored.
+
+     @param sizePtr1 The address where the first (or only) region length will be
+     stored.
+
+     @param dataPtr2 The address where the second region pointer will be stored if
+     the first region is too small to satisfy numBytes.
+
+     @param sizePtr2 The address where the second region length will be stored if
+     the first region is too small to satisfy numBytes.
+
+     @return The number of bytes available for reading.
+    */
+    long PaUtil_GetShmRingBufferReadRegions( PaUtilShmRingBuffer *rbuf, long numBytes,
+            void **dataPtr1, long *sizePtr1,
+            void **dataPtr2, long *sizePtr2 );
+
+    /** Advance the read index to the next location to be read.
+
+     @param rbuf The ring buffer.
+
+     @param numBytes The number of bytes to advance.
+
+     @return The new position.
+    */
+    long PaUtil_AdvanceShmRingBufferReadIndex( PaUtilShmRingBuffer *rbuf, long numBytes );
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* PA_RINGBUFFER_H */
diff --git a/src/linux/shmsoundin.cpp b/src/linux/shmsoundin.cpp
new file mode 100644
index 0000000..6ab0eea
--- /dev/null
+++ b/src/linux/shmsoundin.cpp
@@ -0,0 +1,159 @@
+/******************************************************************************\
+ * British Broadcasting Corporation
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Julian Cable
+ *
+ * Decription:
+ * Sound in interface using POSIX shared memory
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#define _POSIX_C_SOURCE 199309
+#include <time.h>
+#include <sys/types.h>
+#include <iostream>
+# include <sys/mman.h>
+# include <fcntl.h>
+# include <unistd.h>
+# include <sys/stat.h>
+# include "shmsoundin.h"
+
+CShmSoundIn::CShmSoundIn():ringBuffer(NULL),
+        shmid(-1),shm(NULL),shm_path(),name("shm input"),shmChannels(1),wantedChannels(2)
+{
+}
+
+CShmSoundIn::~CShmSoundIn()
+{
+    Close();
+}
+
+/* iNewBufferSize is the number of samples to read, e.g. stereo is
+ * 2 samples per frame
+ */
+void
+CShmSoundIn::Init(int iNewBufferSize, _BOOLEAN bNewBlocking)
+{
+    // TODO decide if we should use the parameters
+    (void)iNewBufferSize;
+    (void)bNewBlocking;
+    shmid = shm_open(shm_path.c_str(), O_RDWR, 0666);
+    if (shmid == -1)
+    {
+        perror("shm_open");
+        return;
+    }
+    struct stat s;
+    fstat(shmid, &s);
+    shm = mmap(0, s.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, shmid, 0);
+    if ((void*)shm == (void*)-1)
+    {
+        perror("mmap");
+        return;
+    }
+    ringBuffer = (PaUtilShmRingBuffer*)shm;
+}
+
+void
+CShmSoundIn::Enumerate(vector < string > &choices)
+{
+    choices.clear();
+    if (shmid==-1)
+        return;
+    choices.push_back(name);
+}
+
+void
+CShmSoundIn::SetDev(int iNewDevice)
+{
+    (void)iNewDevice;
+}
+
+int
+CShmSoundIn::GetDev()
+{
+    if (shmid==-1)
+        return -1;
+    return 0;
+}
+
+_BOOLEAN
+CShmSoundIn::Read(CVector<short>& psData)
+{
+    if (ringBuffer==NULL)
+        return FALSE;
+
+    size_t frames;
+    if (wantedChannels==2)
+        frames = psData.Size()/2;
+    else
+        frames = psData.Size();
+
+    size_t samples,bytes;
+    if (shmChannels==2)
+        samples = 2*frames;
+    else
+        samples = frames;
+    bytes = sizeof(short)*samples;
+
+
+    while (PaUtil_GetShmRingBufferReadAvailable(ringBuffer)<int(bytes))
+    {
+        timespec ts;
+        ts.tv_sec=0;
+        ts.tv_nsec = 10000000; // 10 ms
+        nanosleep(&ts, NULL);
+    }
+
+    if (shmChannels==wantedChannels)
+    {
+        PaUtil_ReadShmRingBuffer(ringBuffer, &psData[0], bytes);
+    }
+    else
+    {
+        short buf[samples];
+        PaUtil_ReadShmRingBuffer(ringBuffer, &buf[0], bytes);
+        for (size_t i=0; i<frames; i++)
+        {
+            if (wantedChannels==2) /* mono to stereo */
+            {
+                psData[2*i] = buf[i]/2;
+                psData[2*i+1] = buf[i]/2;
+            }
+            else /* stereo to mono */
+            {
+                psData[i] = (buf[2*i] + buf[2*i+1])/2;
+            }
+        }
+    }
+
+    return TRUE;
+}
+
+void
+CShmSoundIn::Close()
+{
+    struct stat s;
+    fstat(shmid, &s);
+    munmap(shm, s.st_size);
+    shm_unlink(shm_path.c_str());
+    cout << "capture close" << endl;
+}
diff --git a/src/linux/shmsoundin.h b/src/linux/shmsoundin.h
new file mode 100644
index 0000000..eb17b9b
--- /dev/null
+++ b/src/linux/shmsoundin.h
@@ -0,0 +1,72 @@
+/******************************************************************************\
+ * British Broadcasting Corporation
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Julian Cable
+ *
+ * Decription:
+ * Winradio G313 sound interface
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#ifndef _SHMSOUNDIN_H
+#define _SHMSOUNDIN_H
+
+#include "../soundinterface.h"
+#include "pa_shm_ringbuffer.h"
+
+class CShmSoundIn: public CSoundInInterface
+{
+public:
+    CShmSoundIn();
+    virtual 			~CShmSoundIn();
+    virtual void		Enumerate(vector<string>& choices);
+    virtual void		SetDev(int);
+    virtual int			GetDev();
+
+    virtual void		Init(int iNewBufferSize, _BOOLEAN bNewBlocking = TRUE);
+    virtual void		Close();
+    virtual _BOOLEAN	Read(CVector<short>& psData);
+
+    void				SetShmPath(const string& p) {
+        shm_path = p;
+    }
+    void				SetShmChannels(int n) {
+        shmChannels = n;
+    }
+    void				SetWantedChannels(int n) {
+        wantedChannels = n;
+    }
+    void				SetName(const string& n) {
+        name = n;
+    }
+
+protected:
+
+    PaUtilShmRingBuffer *ringBuffer;
+    int		shmid;
+    void*	shm;
+    string	shm_path;
+    string	name;
+    int		shmChannels;
+    int		wantedChannels;
+};
+
+#endif
diff --git a/src/linux/sound.h b/src/linux/sound.h
new file mode 100644
index 0000000..45f692f
--- /dev/null
+++ b/src/linux/sound.h
@@ -0,0 +1,60 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Alexander Kurpiers
+ *
+ * Decription:
+ * Linux sound interface
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#ifndef _SOUND_H
+#define _SOUND_H
+
+#ifdef USE_OSS
+# include "soundin.h"
+# include "soundout.h"
+#endif
+
+#ifdef USE_ALSA
+# include "soundin.h"
+# include "soundout.h"
+#endif
+
+#ifdef USE_JACK
+# include "jack.h"
+typedef CSoundInJack CSoundIn;
+typedef CSoundOutJack CSoundOut;
+#endif
+
+#ifdef USE_PORTAUDIO
+# include "portaudio.h"
+typedef CPaIn CSoundIn;
+typedef CPaOut CSoundOut;
+#endif
+
+#if !defined(USE_OSS) && !defined(USE_ALSA) && !defined(USE_JACK) && !defined(USE_PORTAUDIO)
+# include "../soundnull.h"
+typedef CSoundInNull CSoundIn;
+typedef CSoundOutNull CSoundOut;
+#endif
+
+#endif
diff --git a/src/linux/soundcommon.cpp b/src/linux/soundcommon.cpp
new file mode 100644
index 0000000..dd236b2
--- /dev/null
+++ b/src/linux/soundcommon.cpp
@@ -0,0 +1,352 @@
+/******************************************************************************\
+* Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+* Copyright (c) 2001-2014
+*
+* Author(s):
+*	Alexander Kurpiers
+*
+*
+******************************************************************************
+*
+* This program is free software; you can redistribute it and/or modify it under
+* the terms of the GNU General Public License as published by the Free Software
+* Foundation; either version 2 of the License, or (at your option) any later
+* version.
+*
+* This program is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+* details.
+*
+* You should have received a copy of the GNU General Public License along with
+* this program; if not, write to the Free Software Foundation, Inc.,
+* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*
+\******************************************************************************/
+
+#include "soundin.h"
+#include "soundout.h"
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <iostream>
+#include <fstream>
+#include <sstream>
+
+/* ************************************************************************* */
+
+CSoundIn::CSoundIn():devices(),names(),iCurrentDevice(-1)
+#ifdef USE_OSS
+        ,dev()
+#endif
+#ifdef USE_ALSA
+        ,handle(NULL)
+#endif
+{
+    RecThread.pSoundIn = this;
+    getdevices(names, devices, false);
+    /* Set flag to open devices */
+    bChangDev = TRUE;
+}
+
+void
+CSoundIn::CRecThread::run()
+{
+    while (SoundBuf.keep_running) {
+
+        int fill;
+
+        SoundBuf.lock();
+        fill = SoundBuf.GetFillLevel();
+        SoundBuf.unlock();
+
+        if (  (SOUNDBUFLEN - fill) > (FRAGSIZE * NUM_IN_CHANNELS) ) {
+            // enough space in the buffer
+
+            int size = pSoundIn->read_HW( tmprecbuf, FRAGSIZE);
+
+            // common code
+            if (size > 0) {
+                CVectorEx<_SAMPLE>*	ptarget;
+
+                /* Copy data from temporary buffer in output buffer */
+                SoundBuf.lock();
+
+                ptarget = SoundBuf.QueryWriteBuffer();
+
+                for (int i = 0; i < size * NUM_IN_CHANNELS; i++)
+                    (*ptarget)[i] = tmprecbuf[i];
+
+                SoundBuf.Put( size * NUM_IN_CHANNELS );
+                SoundBuf.unlock();
+            }
+        } else {
+            msleep( 1 );
+        }
+    }
+    qDebug("Rec Thread stopped");
+}
+
+
+/* Wave in ********************************************************************/
+
+void CSoundIn::Init(int iNewBufferSize, _BOOLEAN bNewBlocking)
+{
+    qDebug("initrec %d", iNewBufferSize);
+
+    /* Save < */
+    RecThread.SoundBuf.lock();
+    iInBufferSize = iNewBufferSize;
+    bBlockingRec = bNewBlocking;
+    RecThread.SoundBuf.unlock();
+
+    /* Check if device must be opened or reinitialized */
+    if (bChangDev == TRUE)
+    {
+
+        Init_HW( );
+
+        /* Reset flag */
+        bChangDev = FALSE;
+    }
+
+    if ( RecThread.running() == FALSE ) {
+        RecThread.SoundBuf.lock();
+        RecThread.SoundBuf.Init( SOUNDBUFLEN );
+        RecThread.SoundBuf.unlock();
+        RecThread.start();
+    }
+
+}
+
+
+_BOOLEAN CSoundIn::Read(CVector< _SAMPLE >& psData)
+{
+    CVectorEx<_SAMPLE>*	p;
+
+    /* Check if device must be opened or reinitialized */
+    if (bChangDev == TRUE)
+    {
+        /* Reinit sound interface */
+        Init(iBufferSize, bBlockingRec);
+
+        /* Reset flag */
+        bChangDev = FALSE;
+    }
+
+    RecThread.SoundBuf.lock();	// we need exclusive access
+
+    if (iCurrentDevice == -1)
+        iCurrentDevice = names.size()-1;
+
+    while ( RecThread.SoundBuf.GetFillLevel() < iInBufferSize ) {
+
+
+        // not enough data, sleep a little
+        RecThread.SoundBuf.unlock();
+        usleep(1000); //1ms
+        RecThread.SoundBuf.lock();
+    }
+
+    // copy data
+
+    p = RecThread.SoundBuf.Get( iInBufferSize );
+    for (int i=0; i<iInBufferSize; i++)
+        psData[i] = (*p)[i];
+
+    RecThread.SoundBuf.unlock();
+
+    return FALSE;
+}
+
+void CSoundIn::Close()
+{
+    qDebug("stoprec");
+
+    // stop the recording threads
+
+    if (RecThread.running() ) {
+        RecThread.SoundBuf.keep_running = FALSE;
+        // wait 1sec max. for the threads to terminate
+        RecThread.wait(1000);
+    }
+
+    close_HW();
+
+    /* Set flag to open devices the next time it is initialized */
+    bChangDev = TRUE;
+}
+
+void CSoundIn::SetDev(int iNewDevice)
+{
+    /* Change only in case new device id is not already active */
+    if (iNewDevice != iCurrentDevice)
+    {
+        iCurrentDevice = iNewDevice;
+        bChangDev = TRUE;
+    }
+}
+
+int CSoundIn::GetDev()
+{
+    return iCurrentDevice;
+}
+
+CSoundOut::CSoundOut():devices(),names(),iCurrentDevice(-1)
+#ifdef USE_OSS
+        ,dev()
+#endif
+#ifdef USE_ALSA
+        ,handle(NULL)
+#endif
+{
+    PlayThread.pSoundOut = this;
+    getdevices(names, devices, true);
+    /* Set flag to open devices */
+    bChangDev = TRUE;
+}
+
+void CSoundOut::CPlayThread::run()
+{
+    while ( SoundBuf.keep_running ) {
+        int fill;
+
+        SoundBuf.lock();
+        fill = SoundBuf.GetFillLevel();
+        SoundBuf.unlock();
+
+        if ( fill > (FRAGSIZE * NUM_OUT_CHANNELS) ) {
+
+            // enough data in the buffer
+
+            CVectorEx<_SAMPLE>*	p;
+
+            SoundBuf.lock();
+            p = SoundBuf.Get( FRAGSIZE * NUM_OUT_CHANNELS );
+
+            for (int i=0; i < FRAGSIZE * NUM_OUT_CHANNELS; i++)
+                tmpplaybuf[i] = (*p)[i];
+
+            SoundBuf.unlock();
+
+            pSoundOut->write_HW( tmpplaybuf, FRAGSIZE );
+
+        } else {
+
+            do {
+                msleep( 1 );
+
+                SoundBuf.lock();
+                fill = SoundBuf.GetFillLevel();
+                SoundBuf.unlock();
+
+            } while ((SoundBuf.keep_running) && ( fill < SOUNDBUFLEN/2 ));	// wait until buffer is at least half full
+        }
+    }
+    qDebug("Play Thread stopped");
+}
+
+void CSoundOut::Init(int iNewBufferSize, _BOOLEAN bNewBlocking)
+{
+    qDebug("initplay %d", iNewBufferSize);
+
+    /* Save buffer size */
+    PlayThread.SoundBuf.lock();
+    iBufferSize = iNewBufferSize;
+    bBlockingPlay = bNewBlocking;
+    PlayThread.SoundBuf.unlock();
+
+    /* Check if device must be opened or reinitialized */
+    if (bChangDev == TRUE)
+    {
+
+        Init_HW( );
+
+        /* Reset flag */
+        bChangDev = FALSE;
+    }
+
+    if ( PlayThread.running() == FALSE ) {
+        PlayThread.SoundBuf.lock();
+        PlayThread.SoundBuf.Init( SOUNDBUFLEN );
+        PlayThread.SoundBuf.unlock();
+        PlayThread.start();
+    }
+}
+
+_BOOLEAN CSoundOut::Write(CVector< _SAMPLE >& psData)
+{
+    /* Check if device must be opened or reinitialized */
+    if (bChangDev == TRUE)
+    {
+        /* Reinit sound interface */
+        Init(iBufferSize, bBlockingPlay);
+
+        /* Reset flag */
+        bChangDev = FALSE;
+    }
+
+    if ( bBlockingPlay ) {
+        // blocking write
+        while ( PlayThread.SoundBuf.keep_running ) {
+            PlayThread.SoundBuf.lock();
+            int fill = SOUNDBUFLEN - PlayThread.SoundBuf.GetFillLevel();
+            PlayThread.SoundBuf.unlock();
+            if ( fill > iBufferSize) break;
+        }
+    }
+
+    PlayThread.SoundBuf.lock();	// we need exclusive access
+
+    if ( ( SOUNDBUFLEN - PlayThread.SoundBuf.GetFillLevel() ) > iBufferSize) {
+
+        CVectorEx<_SAMPLE>*	ptarget;
+
+        // data fits, so copy
+        ptarget = PlayThread.SoundBuf.QueryWriteBuffer();
+        for (int i=0; i < iBufferSize; i++)
+        {
+            (*ptarget)[i] = psData[i];
+        }
+
+        PlayThread.SoundBuf.Put( iBufferSize );
+    }
+
+    PlayThread.SoundBuf.unlock();
+
+    return FALSE;
+}
+
+void CSoundOut::Close()
+{
+    qDebug("stopplay");
+
+    // stop the playback thread
+    if (PlayThread.running() ) {
+        PlayThread.SoundBuf.keep_running = FALSE;
+        PlayThread.wait(1000);
+    }
+
+    close_HW();
+
+    /* Set flag to open devices the next time it is initialized */
+    bChangDev = TRUE;
+}
+
+void CSoundOut::SetDev(int iNewDevice)
+{
+    /* Change only in case new device id is not already active */
+    if (iNewDevice != iCurrentDevice)
+    {
+        iCurrentDevice = iNewDevice;
+        bChangDev = TRUE;
+    }
+}
+
+int CSoundOut::GetDev()
+{
+    return iCurrentDevice;
+}
+
diff --git a/src/linux/soundcommon.h b/src/linux/soundcommon.h
new file mode 100644
index 0000000..ae9b13c
--- /dev/null
+++ b/src/linux/soundcommon.h
@@ -0,0 +1,118 @@
+/******************************************************************************\
+* Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+* Copyright (c) 2001-2014
+*
+* Author(s):
+*	Alexander Kurpiers
+*
+*
+******************************************************************************
+*
+* This program is free software; you can redistribute it and/or modify it under
+* the terms of the GNU General Public License as published by the Free Software
+* Foundation; either version 2 of the License, or (at your option) any later
+* version.
+*
+* This program is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+* details.
+*
+* You should have received a copy of the GNU General Public License along with
+* this program; if not, write to the Free Software Foundation, Inc.,
+* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*
+\******************************************************************************/
+
+
+#ifndef _SOUND_COMMON_H
+#define _SOUND_COMMON_H
+
+#ifdef QT_CORE_LIB
+# include <qmutex.h>
+# include <qthread.h>
+#endif
+#include "../util/Buffer.h"
+#ifdef USE_ALSA
+#include <alsa/asoundlib.h>
+#endif
+
+/* Definitions ****************************************************************/
+#define	NUM_IN_CHANNELS			2		/* Stereo recording (but we only
+use one channel for recording) */
+#define	NUM_OUT_CHANNELS		2		/* Stereo Playback */
+#define	BITS_PER_SAMPLE			16		/* Use all bits of the D/A-converter */
+#define BYTES_PER_SAMPLE		2		/* Number of bytes per sample */
+
+#ifdef USE_OSS
+#include <map>
+
+class COSSDev
+{
+    public:
+COSSDev():name() {}
+void open(const string& devname, int mode);
+int fildes() {
+    return dev[name].fildes();
+}
+void close();
+protected:
+class devdata
+{
+public:
+    devdata():count(0),fd(0) {}
+    void open(const string&, int);
+    void close();
+    int fildes();
+protected:
+    int count;
+    int fd;
+};
+static map<string,devdata> dev;
+string name;
+};
+#endif
+
+class CSoundBuf : public CCyclicBuffer<_SAMPLE> {
+
+    public:
+    CSoundBuf() : keep_running(TRUE)
+#ifdef QT_CORE_LIB
+            , data_accessed()
+#endif
+{}
+bool keep_running;
+#ifdef QT_CORE_LIB
+void lock () {
+    data_accessed.lock();
+}
+void unlock () {
+    data_accessed.unlock();
+}
+
+protected:
+QMutex	data_accessed;
+#else
+void lock () { }
+void unlock () { }
+#endif
+};
+
+#ifdef QT_CORE_LIB
+typedef QThread CThread;
+#else
+class CThread {
+    public:
+void run() {}
+void start() {}
+void wait(int) {}
+void msleep(int) {}
+bool running() {
+    return true;
+}
+};
+#endif
+
+void getdevices(vector<string>& names, vector<string>& devices, bool playback);
+
+#endif
diff --git a/src/linux/soundin.cpp b/src/linux/soundin.cpp
new file mode 100644
index 0000000..a2c7b96
--- /dev/null
+++ b/src/linux/soundin.cpp
@@ -0,0 +1,502 @@
+/******************************************************************************\
+* Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+* Copyright (c) 2001-2014
+*
+* Author(s):
+*	Alexander Kurpiers
+*
+*
+******************************************************************************
+*
+* This program is free software; you can redistribute it and/or modify it under
+* the terms of the GNU General Public License as published by the Free Software
+* Foundation; either version 2 of the License, or (at your option) any later
+* version.
+*
+* This program is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+* details.
+*
+* You should have received a copy of the GNU General Public License along with
+* this program; if not, write to the Free Software Foundation, Inc.,
+* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*
+\******************************************************************************/
+
+#include "soundin.h"
+
+#ifdef WITH_SOUND
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <iostream>
+#include <fstream>
+#include <sstream>
+
+/*****************************************************************************/
+
+#ifdef USE_OSS
+
+#include <sys/soundcard.h>
+#include <errno.h>
+
+CSoundIn::CSoundIn():devices(),dev(),names(),iCurrentDevice(-1)
+{
+    RecThread.pSoundIn = this;
+    getdevices(names, devices, false);
+    /* Set flag to open devices */
+    bChangDev = TRUE;
+}
+
+void CSoundIn::Init_HW()
+{
+    /* Open sound device (Use O_RDWR only when writing a program which is
+       going to both record and play back digital audio) */
+    if (devices.size()==0)
+        throw CGenErr("no capture devices available");
+
+    /* Default ? */
+    if (iCurrentDevice < 0)
+        iCurrentDevice = devices.size()-1;
+
+    /* out of range ? (could happen from command line parameter or USB device unplugged */
+    if (iCurrentDevice >= int(devices.size()))
+        iCurrentDevice = devices.size()-1;
+
+    string devname = devices[iCurrentDevice];
+    dev.open(devname, O_RDONLY );
+    if (dev.fildes() < 0)
+        throw CGenErr("open of "+devname+" failed");
+
+#if 0
+    /* Get ready for us.
+       ioctl(audio_fd, SNDCTL_DSP_SYNC, 0) can be used when application wants
+       to wait until last byte written to the device has been played (it doesn't
+       wait in recording mode). After that the call resets (stops) the device
+       and returns back to the calling program. Note that this call may take
+       several seconds to execute depending on the amount of data in the
+       buffers. close() calls SNDCTL_DSP_SYNC automaticly */
+    ioctl(dev.fildes(), SNDCTL_DSP_SYNC, 0);
+
+    /* Set sampling parameters always so that number of channels (mono/stereo)
+       is set before selecting sampling rate! */
+    /* Set number of channels (0=mono, 1=stereo) */
+    arg = NUM_IN_CHANNELS - 1;
+    status = ioctl(dev.fildes(), SNDCTL_DSP_STEREO, &arg);
+    if (status == -1)
+        throw CGenErr("SNDCTL_DSP_CHANNELS ioctl failed");
+
+    if (arg != (NUM_IN_CHANNELS - 1))
+        throw CGenErr("unable to set number of channels");
+
+
+    /* Sampling rate */
+    arg = Parameters.GetSampleRate();
+    status = ioctl(dev.fildes(), SNDCTL_DSP_SPEED, &arg);
+    if (status == -1)
+        throw CGenErr("SNDCTL_DSP_SPEED ioctl failed");
+    if (arg != Parameters.GetSampleRate())
+        throw CGenErr("unable to set sample rate");
+
+
+    /* Sample size */
+    arg = (BITS_PER_SAMPLE == 16) ? AFMT_S16_LE : AFMT_U8;
+    status = ioctl(dev.fildes(), SNDCTL_DSP_SAMPLESIZE, &arg);
+    if (status == -1)
+        throw CGenErr("SNDCTL_DSP_SAMPLESIZE ioctl failed");
+    if (arg != ((BITS_PER_SAMPLE == 16) ? AFMT_S16_LE : AFMT_U8))
+        throw CGenErr("unable to set sample size");
+#endif
+}
+
+
+int CSoundIn::read_HW( void * recbuf, int size) {
+
+    int ret = read(dev.fildes(), recbuf, size * NUM_IN_CHANNELS * BYTES_PER_SAMPLE );
+    if (ret < 0) {
+        switch (errno)
+        {
+        case 0:
+            return 0;
+            break;
+        case EINTR:
+            return 0;
+            break;
+        case EAGAIN:
+            return 0;
+            break;
+        default:
+            qDebug("read error: %s", strerror(errno));
+            throw CGenErr("CSound:Read");
+        }
+    } else
+        return ret / (NUM_IN_CHANNELS * BYTES_PER_SAMPLE);
+}
+
+void CSoundIn::close_HW( void ) {
+    dev.close();
+}
+#endif
+
+/*****************************************************************************/
+
+#ifdef USE_ALSA
+
+#define ALSA_PCM_NEW_HW_PARAMS_API
+#define ALSA_PCM_NEW_SW_PARAMS_API
+
+CSoundIn::CSoundIn(): devices(), handle(NULL), names(),bChangDev(TRUE), iCurrentDevice(-1)
+{
+    RecThread.pSoundIn = this;
+    getdevices(names, devices, false);
+}
+
+void CSoundIn::Init_HW() {
+
+    int err, dir=0;
+    snd_pcm_hw_params_t *hwparams;
+    snd_pcm_sw_params_t *swparams;
+    snd_pcm_uframes_t period_size = FRAGSIZE * NUM_IN_CHANNELS/2;
+    snd_pcm_uframes_t buffer_size;
+
+    /* Default ? */
+    if (iCurrentDevice < 0)
+        iCurrentDevice = int(devices.size())-1;
+
+    /* out of range ? (could happen from command line parameter or USB device unplugged */
+    if (iCurrentDevice >= int(devices.size()))
+        iCurrentDevice = int(devices.size())-1;
+
+    /* record device */
+    string recdevice = devices[iCurrentDevice];
+
+    if (handle != NULL)
+        return;
+
+    err = snd_pcm_open( &handle, recdevice.c_str(), SND_PCM_STREAM_CAPTURE, 0 );
+    if ( err != 0)
+    {
+        qDebug("open error: %s", snd_strerror(err));
+        throw CGenErr("alsa CSoundIn::Init_HW record, can't open "+recdevice+" ("+names[iCurrentDevice]+")");
+    }
+
+    snd_pcm_hw_params_alloca(&hwparams);
+    snd_pcm_sw_params_alloca(&swparams);
+
+    /* Choose all parameters */
+    err = snd_pcm_hw_params_any(handle, hwparams);
+    if (err < 0) {
+        qDebug("Broken configuration : no configurations available: %s", snd_strerror(err));
+        throw CGenErr("alsa CSoundIn::Init_HW ");
+    }
+    /* Set the interleaved read/write format */
+    err = snd_pcm_hw_params_set_access(handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED);
+
+    if (err < 0) {
+        qDebug("Access type not available : %s", snd_strerror(err));
+        throw CGenErr("alsa CSoundIn::Init_HW ");
+
+    }
+    /* Set the sample format */
+    err = snd_pcm_hw_params_set_format(handle, hwparams, SND_PCM_FORMAT_S16);
+    if (err < 0) {
+        qDebug("Sample format not available : %s", snd_strerror(err));
+        throw CGenErr("alsa CSoundIn::Init_HW ");
+    }
+    /* Set the count of channels */
+    err = snd_pcm_hw_params_set_channels(handle, hwparams, NUM_IN_CHANNELS);
+    if (err < 0) {
+        qDebug("Channels count (%i) not available s: %s", NUM_IN_CHANNELS, snd_strerror(err));
+        throw CGenErr("alsa CSoundIn::Init_HW ");
+    }
+    /* Set the stream rate */
+    dir=0;
+    err = snd_pcm_hw_params_set_rate(handle, hwparams, Parameters.GetSampleRate(), dir);
+    if (err < 0) {
+        qDebug("Rate %iHz not available : %s", Parameters.GetSampleRate(), snd_strerror(err));
+        throw CGenErr("alsa CSoundIn::Init_HW ");
+
+    }
+    dir=0;
+    unsigned int buffer_time = 500000;              /* ring buffer length in us */
+    /* set the buffer time */
+    err = snd_pcm_hw_params_set_buffer_time_near(handle, hwparams, &buffer_time, &dir);
+    if (err < 0) {
+        qDebug("Unable to set buffer time %i for playback: %s\n", buffer_time, snd_strerror(err));
+        throw CGenErr("alsa CSoundIn::Init_HW ");
+    }
+    err = snd_pcm_hw_params_get_buffer_size(hwparams, &buffer_size);
+    if (err < 0) {
+        qDebug("Unable to get buffer size for playback: %s\n", snd_strerror(err));
+        throw CGenErr("alsa CSoundIn::Init_HW ");
+    }
+    // qDebug("buffer size %d", buffer_size);
+    /* set the period time */
+    unsigned int period_time = 100000;              /* period time in us */
+    err = snd_pcm_hw_params_set_period_time_near(handle, hwparams, &period_time, &dir);
+    if (err < 0) {
+        qDebug("Unable to set period time %i for playback: %s\n", period_time, snd_strerror(err));
+        throw CGenErr("alsa CSoundIn::Init_HW ");
+    }
+    err = snd_pcm_hw_params_get_period_size_min(hwparams, &period_size, &dir);
+    if (err < 0) {
+        qDebug("Unable to get period size for playback: %s\n", snd_strerror(err));
+        throw CGenErr("alsa CSoundIn::Init_HW ");
+    }
+    // qDebug("period size %d", period_size);
+
+    /* Write the parameters to device */
+    err = snd_pcm_hw_params(handle, hwparams);
+    if (err < 0) {
+        qDebug("Unable to set hw params : %s", snd_strerror(err));
+        throw CGenErr("alsa CSoundIn::Init_HW ");
+    }
+    /* Get the current swparams */
+    err = snd_pcm_sw_params_current(handle, swparams);
+    if (err < 0) {
+        qDebug("Unable to determine current swparams : %s", snd_strerror(err));
+        throw CGenErr("alsa CSoundIn::Init_HW ");
+    }
+    /* Start the transfer when the buffer immediately */
+    err = snd_pcm_sw_params_set_start_threshold(handle, swparams, 0);
+    if (err < 0) {
+        qDebug("Unable to set start threshold mode : %s", snd_strerror(err));
+        throw CGenErr("alsa CSoundIn::Init_HW ");
+    }
+    /* Allow the transfer when at least period_size samples can be processed */
+    err = snd_pcm_sw_params_set_avail_min(handle, swparams, period_size);
+    if (err < 0) {
+        qDebug("Unable to set avail min : %s", snd_strerror(err));
+        throw CGenErr("alsa CSoundIn::Init_HW ");
+    }
+    /* Align all transfers to 1 sample */
+    err = snd_pcm_sw_params_set_xfer_align(handle, swparams, 1);
+    if (err < 0) {
+        qDebug("Unable to set transfer align : %s", snd_strerror(err));
+        throw CGenErr("alsa CSoundIn::Init_HW ");
+    }
+    /* Write the parameters to the record/playback device */
+    err = snd_pcm_sw_params(handle, swparams);
+    if (err < 0) {
+        qDebug("Unable to set sw params : %s", snd_strerror(err));
+        throw CGenErr("alsa CSoundIn::Init_HW ");
+    }
+    snd_pcm_start(handle);
+    qDebug("alsa init done");
+
+}
+
+int CSoundIn::read_HW( void * recbuf, int size) {
+
+    int ret = snd_pcm_readi(handle, recbuf, size);
+
+
+    if (ret < 0)
+    {
+        if (ret == -EPIPE)
+        {
+            qDebug("rpipe");
+            /* Under-run */
+            qDebug("rprepare");
+            ret = snd_pcm_prepare(handle);
+
+            if (ret < 0)
+                qDebug("Can't recover from underrun, prepare failed: %s", snd_strerror(ret));
+
+            ret = snd_pcm_start(handle);
+
+            if (ret < 0)
+                qDebug("Can't recover from underrun, start failed: %s", snd_strerror(ret));
+            return 0;
+
+        }
+        else if (ret == -ESTRPIPE)
+        {
+            qDebug("strpipe");
+
+            /* Wait until the suspend flag is released */
+            while ((ret = snd_pcm_resume(handle)) == -EAGAIN)
+                sleep(1);
+
+            if (ret < 0)
+            {
+                ret = snd_pcm_prepare(handle);
+
+                if (ret < 0)
+                    qDebug("Can't recover from suspend, prepare failed: %s", snd_strerror(ret));
+                throw CGenErr("CSound:Read");
+            }
+            return 0;
+        }
+        else
+        {
+            qDebug("CSoundIn::Read: %s", snd_strerror(ret));
+            throw CGenErr("CSound:Read");
+        }
+    } else
+        return ret;
+
+}
+
+void CSoundIn::close_HW( void ) {
+
+    if (handle != NULL)
+        snd_pcm_close( handle );
+
+    handle = NULL;
+}
+
+#endif
+
+
+/* ************************************************************************* */
+
+
+void
+CSoundIn::CRecThread::run()
+{
+    while (SoundBuf.keep_running) {
+
+        int fill;
+
+        SoundBuf.lock();
+        fill = SoundBuf.GetFillLevel();
+        SoundBuf.unlock();
+
+        if (  (SOUNDBUFLEN - fill) > (FRAGSIZE * NUM_IN_CHANNELS) ) {
+            // enough space in the buffer
+
+            int size = pSoundIn->read_HW( tmprecbuf, FRAGSIZE);
+
+            // common code
+            if (size > 0) {
+                CVectorEx<_SAMPLE>*	ptarget;
+
+                /* Copy data from temporary buffer in output buffer */
+                SoundBuf.lock();
+
+                ptarget = SoundBuf.QueryWriteBuffer();
+
+                for (int i = 0; i < size * NUM_IN_CHANNELS; i++)
+                    (*ptarget)[i] = tmprecbuf[i];
+
+                SoundBuf.Put( size * NUM_IN_CHANNELS );
+                SoundBuf.unlock();
+            }
+        } else {
+            msleep( 1 );
+        }
+    }
+    qDebug("Rec Thread stopped");
+}
+
+
+/* Wave in ********************************************************************/
+
+void CSoundIn::Init(int iNewBufferSize, _BOOLEAN bNewBlocking)
+{
+    qDebug("initrec %d", iNewBufferSize);
+
+    /* Save < */
+    RecThread.SoundBuf.lock();
+    iInBufferSize = iNewBufferSize;
+    bBlockingRec = bNewBlocking;
+    RecThread.SoundBuf.unlock();
+
+    /* Check if device must be opened or reinitialized */
+    if (bChangDev == TRUE)
+    {
+
+        Init_HW( );
+
+        /* Reset flag */
+        bChangDev = FALSE;
+    }
+
+    if ( RecThread.running() == FALSE ) {
+        RecThread.SoundBuf.lock();
+        RecThread.SoundBuf.Init( SOUNDBUFLEN );
+        RecThread.SoundBuf.unlock();
+        RecThread.start();
+    }
+
+}
+
+
+_BOOLEAN CSoundIn::Read(CVector< _SAMPLE >& psData)
+{
+    CVectorEx<_SAMPLE>*	p;
+
+    /* Check if device must be opened or reinitialized */
+    if (bChangDev == TRUE)
+    {
+        /* Reinit sound interface */
+        Init(iBufferSize, bBlockingRec);
+
+        /* Reset flag */
+        bChangDev = FALSE;
+    }
+
+    RecThread.SoundBuf.lock();	// we need exclusive access
+
+    if (iCurrentDevice == -1)
+        iCurrentDevice = names.size()-1;
+
+    while ( RecThread.SoundBuf.GetFillLevel() < iInBufferSize ) {
+
+
+        // not enough data, sleep a little
+        RecThread.SoundBuf.unlock();
+        usleep(1000); //1ms
+        RecThread.SoundBuf.lock();
+    }
+
+    // copy data
+
+    p = RecThread.SoundBuf.Get( iInBufferSize );
+    for (int i=0; i<iInBufferSize; i++)
+        psData[i] = (*p)[i];
+
+    RecThread.SoundBuf.unlock();
+
+    return FALSE;
+}
+
+void CSoundIn::Close()
+{
+    qDebug("stoprec");
+
+    // stop the recording threads
+
+    if (RecThread.running() ) {
+        RecThread.SoundBuf.keep_running = FALSE;
+        // wait 1sec max. for the threads to terminate
+        RecThread.wait(1000);
+    }
+
+    close_HW();
+
+    /* Set flag to open devices the next time it is initialized */
+    bChangDev = TRUE;
+}
+
+#endif
+
+void CSoundIn::SetDev(int iNewDevice)
+{
+    /* Change only in case new device id is not already active */
+    if (iNewDevice != iCurrentDevice)
+    {
+        iCurrentDevice = iNewDevice;
+        bChangDev = TRUE;
+    }
+}
+
+
+int CSoundIn::GetDev()
+{
+    return iCurrentDevice;
+}
+
diff --git a/src/linux/soundin.h b/src/linux/soundin.h
new file mode 100644
index 0000000..57a62a7
--- /dev/null
+++ b/src/linux/soundin.h
@@ -0,0 +1,94 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Alexander Kurpiers
+ *
+ * Decription:
+ * Linux sound interface
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#ifndef _SOUNDIN_H
+#define _SOUNDIN_H
+
+#include "../soundinterface.h"
+#include "../util/Buffer.h"
+#include "soundcommon.h"
+
+/* Definitions ****************************************************************/
+#define RECORDING_CHANNEL		0		/* 0: Left, 1: Right */
+
+#define SOUNDBUFLEN 102400
+
+#define FRAGSIZE 8192
+//#define FRAGSIZE 1024
+
+/* Classes ********************************************************************/
+class CSoundIn : public CSoundInInterface
+{
+public:
+    CSoundIn();
+    virtual ~CSoundIn() {}
+
+    virtual void				Enumerate(vector<string>& choices) {
+        choices = names;
+    }
+    virtual void				SetDev(int iNewDevice);
+    virtual int					GetDev();
+
+    void Init(int iNewBufferSize, _BOOLEAN bNewBlocking = TRUE);
+    _BOOLEAN Read(CVector<short>& psData);
+    void Close();
+
+protected:
+    void Init_HW();
+    int read_HW( void * recbuf, int size);
+    void close_HW( void );
+
+    int 	iBufferSize, iInBufferSize;
+    short int *tmprecbuf;
+    _BOOLEAN	bBlockingRec;
+    vector<string> devices;
+
+    class CRecThread : public CThread
+    {
+    public:
+        virtual ~CRecThread() {}
+        virtual void run();
+        CSoundBuf SoundBuf;
+        CSoundIn*	pSoundIn;
+    protected:
+        _SAMPLE	tmprecbuf[NUM_IN_CHANNELS * FRAGSIZE];
+    } RecThread;
+
+protected:
+    vector<string> names;
+    _BOOLEAN bChangDev;
+    int	iCurrentDevice;
+#ifdef USE_ALSA
+    snd_pcm_t *handle;
+#endif
+#ifdef USE_OSS
+    COSSDev dev;
+#endif
+};
+
+#endif
diff --git a/src/linux/soundout.cpp b/src/linux/soundout.cpp
new file mode 100644
index 0000000..6b061b2
--- /dev/null
+++ b/src/linux/soundout.cpp
@@ -0,0 +1,489 @@
+/******************************************************************************\
+* Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+* Copyright (c) 2001-2014
+*
+* Author(s):
+*	Alexander Kurpiers
+*
+*
+******************************************************************************
+*
+* This program is free software; you can redistribute it and/or modify it under
+* the terms of the GNU General Public License as published by the Free Software
+* Foundation; either version 2 of the License, or (at your option) any later
+* version.
+*
+* This program is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+* details.
+*
+* You should have received a copy of the GNU General Public License along with
+* this program; if not, write to the Free Software Foundation, Inc.,
+* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*
+\******************************************************************************/
+
+#include "soundout.h"
+
+#ifdef WITH_SOUND
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <iostream>
+#include <fstream>
+#include <sstream>
+#include <map>
+
+/*****************************************************************************/
+
+#ifdef USE_OSS
+
+#include <sys/soundcard.h>
+#include <errno.h>
+
+CSoundOut::CSoundOut():devices(),dev(),names(),iCurrentDevice(-1)
+{
+    PlayThread.pSoundOut = this;
+    getdevices(names, devices, true);
+    /* Set flag to open devices */
+    bChangDev = TRUE;
+}
+
+void CSoundOut::Init_HW()
+{
+    /* Open sound device (Use O_RDWR only when writing a program which is
+       going to both record and play back digital audio) */
+    if (devices.size()==0)
+        throw CGenErr("no playback devices available");
+
+    /* Default ? */
+    if (iCurrentDevice < 0)
+        iCurrentDevice = devices.size()-1;
+
+    /* out of range ? (could happen from command line parameter or USB device unplugged */
+    if (iCurrentDevice >= int(devices.size()))
+        iCurrentDevice = devices.size()-1;
+
+    string devname = devices[iCurrentDevice];
+    dev.open(devname, O_WRONLY );
+#if 0
+    if (dev.fildes() < 0)
+        throw CGenErr("open of "+devname+" failed");
+    /* Get ready for us.
+       ioctl(audio_fd, SNDCTL_DSP_SYNC, 0) can be used when application wants
+       to wait until last byte written to the device has been played (it doesn't
+       wait in recording mode). After that the call resets (stops) the device
+       and returns back to the calling program. Note that this call may take
+       several seconds to execute depending on the amount of data in the
+       buffers. close() calls SNDCTL_DSP_SYNC automaticly */
+    ioctl(dev.fildes(), SNDCTL_DSP_SYNC, 0);
+
+    /* Set sampling parameters always so that number of channels (mono/stereo)
+       is set before selecting sampling rate! */
+    /* Set number of channels (0=mono, 1=stereo) */
+    arg = NUM_OUT_CHANNELS - 1;
+    status = ioctl(dev.fildes(), SNDCTL_DSP_STEREO, &arg);
+    if (status == -1)
+        throw CGenErr(string("SNDCTL_DSP_CHANNELS ioctl failed: ")+strerror(errno));
+
+    if (arg != (NUM_OUT_CHANNELS - 1))
+        throw CGenErr("unable to set number of channels");
+
+
+    /* Sampling rate */
+    arg = Parameters.GetSampleRate();
+    status = ioctl(dev.fildes(), SNDCTL_DSP_SPEED, &arg);
+    if (status == -1)
+        throw CGenErr("SNDCTL_DSP_SPEED ioctl failed");
+    if (arg != Parameters.GetSampleRate())
+        throw CGenErr("unable to set sample rate");
+
+
+    /* Sample size */
+    arg = (BITS_PER_SAMPLE == 16) ? AFMT_S16_LE : AFMT_U8;
+    status = ioctl(dev.fildes(), SNDCTL_DSP_SAMPLESIZE, &arg);
+    if (status == -1)
+        throw CGenErr("SNDCTL_DSP_SAMPLESIZE ioctl failed");
+    if (arg != ((BITS_PER_SAMPLE == 16) ? AFMT_S16_LE : AFMT_U8))
+        throw CGenErr("unable to set sample size");
+#if 0
+    /* Check capabilities of the sound card */
+    status = ioctl(dev.fildes(), SNDCTL_DSP_GETCAPS, &arg);
+    if (status ==  -1)
+        throw CGenErr("SNDCTL_DSP_GETCAPS ioctl failed");
+    if ((arg & DSP_CAP_DUPLEX) == 0)
+        throw CGenErr("Soundcard not full duplex capable!");
+#endif
+#endif
+}
+
+int CSoundOut::write_HW( _SAMPLE *playbuf, int size )
+{
+
+    int start = 0;
+    int ret;
+
+    size *= BYTES_PER_SAMPLE * NUM_OUT_CHANNELS;
+
+    while (size)
+    {
+        ret = write(dev.fildes(), &playbuf[start], size);
+        if (ret < 0) {
+            if (errno == EINTR || errno == EAGAIN)
+            {
+                continue;
+            }
+            throw CGenErr("CSound:Write");
+        }
+        size -= ret;
+        start += ret / BYTES_PER_SAMPLE;
+    }
+    return 0;
+}
+
+void CSoundOut::close_HW( void )
+{
+    dev.close();
+}
+#endif
+
+/*****************************************************************************/
+
+#ifdef USE_ALSA
+
+#define ALSA_PCM_NEW_HW_PARAMS_API
+#define ALSA_PCM_NEW_SW_PARAMS_API
+
+#include <alsa/asoundlib.h>
+
+CSoundOut::CSoundOut() : devices(), handle(NULL),names(),bChangDev(TRUE), iCurrentDevice(-1)
+{
+    PlayThread.pSoundOut = this;
+    getdevices(names, devices, true);
+}
+
+void CSoundOut::Init_HW()
+{
+
+    int err, dir;
+    snd_pcm_hw_params_t *hwparams;
+    snd_pcm_sw_params_t *swparams;
+    snd_pcm_uframes_t period_size = FRAGSIZE * NUM_OUT_CHANNELS/2;
+    snd_pcm_uframes_t buffer_size;
+
+    /* playback device */
+    if (devices.size()==0)
+        throw CGenErr("alsa CSoundOut::Init_HW no playback devices available!");
+
+    /* Default ? */
+    if (iCurrentDevice < 0)
+        iCurrentDevice = int(devices.size())-1;
+
+    /* out of range ? (could happen from command line parameter or USB device unplugged */
+    if (iCurrentDevice >= int(devices.size()))
+        iCurrentDevice = int(devices.size())-1;
+
+    string playdevice = devices[iCurrentDevice];
+
+    if (handle != NULL)
+        return;
+
+    err = snd_pcm_open( &handle, playdevice.c_str(), SND_PCM_STREAM_PLAYBACK, 0 );
+    if ( err != 0)
+    {
+        qDebug("open error: %s", snd_strerror(err));
+        throw CGenErr("alsa CSoundOut::Init_HW playback, can't open "+playdevice+" ("+names[iCurrentDevice]+")");
+    }
+
+    snd_pcm_hw_params_alloca(&hwparams);
+    snd_pcm_sw_params_alloca(&swparams);
+
+    /* Choose all parameters */
+    err = snd_pcm_hw_params_any(handle, hwparams);
+    if (err < 0) {
+        qDebug("Broken configuration : no configurations available: %s", snd_strerror(err));
+        throw CGenErr("alsa CSoundOut::Init_HW ");
+    }
+    /* Set the interleaved read/write format */
+    err = snd_pcm_hw_params_set_access(handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED);
+
+    if (err < 0) {
+        qDebug("Access type not available : %s", snd_strerror(err));
+        throw CGenErr("alsa CSoundOut::Init_HW ");
+
+    }
+    /* Set the sample format */
+    err = snd_pcm_hw_params_set_format(handle, hwparams, SND_PCM_FORMAT_S16);
+    if (err < 0) {
+        qDebug("Sample format not available : %s", snd_strerror(err));
+        throw CGenErr("alsa CSoundOut::Init_HW ");
+    }
+    /* Set the count of channels */
+    err = snd_pcm_hw_params_set_channels(handle, hwparams, NUM_OUT_CHANNELS);
+    if (err < 0) {
+        qDebug("Channels count (%i) not available s: %s", NUM_OUT_CHANNELS, snd_strerror(err));
+        throw CGenErr("alsa CSoundOut::Init_HW ");
+    }
+    /* Set the stream rate */
+    dir=0;
+    err = snd_pcm_hw_params_set_rate(handle, hwparams, Parameters.GetSampleRate(), dir);
+    if (err < 0) {
+        qDebug("Rate %iHz not available : %s", Parameters.GetSampleRate(), snd_strerror(err));
+        throw CGenErr("alsa CSoundOut::Init_HW ");
+    }
+    dir=0;
+    unsigned int buffer_time = 500000;              /* ring buffer length in us */
+    /* set the buffer time */
+    err = snd_pcm_hw_params_set_buffer_time_near(handle, hwparams, &buffer_time, &dir);
+    if (err < 0) {
+        qDebug("Unable to set buffer time %i for playback: %s\n", buffer_time, snd_strerror(err));
+        throw CGenErr("alsa CSoundOut::Init_HW ");
+    }
+    err = snd_pcm_hw_params_get_buffer_size(hwparams, &buffer_size);
+    if (err < 0) {
+        qDebug("Unable to get buffer size for playback: %s\n", snd_strerror(err));
+        throw CGenErr("alsa CSoundOut::Init_HW ");
+    }
+    // qDebug("buffer size %d", buffer_size);
+    /* set the period time */
+    unsigned int period_time = 100000;              /* period time in us */
+    err = snd_pcm_hw_params_set_period_time_near(handle, hwparams, &period_time, &dir);
+    if (err < 0) {
+        qDebug("Unable to set period time %i for playback: %s\n", period_time, snd_strerror(err));
+        throw CGenErr("alsa CSoundOut::Init_HW ");
+    }
+    err = snd_pcm_hw_params_get_period_size_min(hwparams, &period_size, &dir);
+    if (err < 0) {
+        qDebug("Unable to get period size for playback: %s\n", snd_strerror(err));
+        throw CGenErr("alsa CSoundOut::Init_HW ");
+    }
+    // qDebug("period size %d", period_size);
+
+    /* Write the parameters to device */
+    err = snd_pcm_hw_params(handle, hwparams);
+    if (err < 0) {
+        qDebug("Unable to set hw params : %s", snd_strerror(err));
+        throw CGenErr("alsa CSoundOut::Init_HW ");
+    }
+    /* Get the current swparams */
+    err = snd_pcm_sw_params_current(handle, swparams);
+    if (err < 0) {
+        qDebug("Unable to determine current swparams : %s", snd_strerror(err));
+        throw CGenErr("alsa CSoundOut::Init_HW ");
+    }
+    /* Write the parameters to the playback device */
+    err = snd_pcm_sw_params(handle, swparams);
+    if (err < 0) {
+        qDebug("Unable to set sw params : %s", snd_strerror(err));
+        throw CGenErr("alsa CSoundOut::Init_HW ");
+    }
+    snd_pcm_start(handle);
+    qDebug("alsa init done");
+
+}
+
+int CSoundOut::write_HW( _SAMPLE *playbuf, int size )
+{
+
+    int start = 0;
+    int ret;
+
+    while (size) {
+
+        ret = snd_pcm_writei(handle, &playbuf[start], size );
+        if (ret < 0) {
+            if (ret ==  -EAGAIN) {
+                if ((ret = snd_pcm_wait (handle, 100)) < 0) {
+                    qDebug ("poll failed (%s)", snd_strerror (ret));
+                    break;
+                }
+                continue;
+            } else
+                if (ret == -EPIPE) {    /* under-run */
+                    qDebug("underrun");
+                    ret = snd_pcm_prepare(handle);
+                    if (ret < 0)
+                        qDebug("Can't recover from underrun, prepare failed: %s", snd_strerror(ret));
+                    continue;
+                } else if (ret == -ESTRPIPE) {
+                    qDebug("strpipe");
+                    while ((ret = snd_pcm_resume(handle)) == -EAGAIN)
+                        sleep(1);       /* wait until the suspend flag is released */
+                    if (ret < 0) {
+                        ret = snd_pcm_prepare(handle);
+                        if (ret < 0)
+                            qDebug("Can't recover from suspend, prepare failed: %s", snd_strerror(ret));
+                    }
+                    continue;
+                } else {
+                    qDebug("Write error: %s", snd_strerror(ret));
+                    throw CGenErr("Write error");
+                }
+            break;  /* skip one period */
+        }
+        size -= ret;
+        start += ret;
+    }
+    return 0;
+}
+
+void CSoundOut::close_HW( void )
+{
+
+    if (handle != NULL)
+        snd_pcm_close( handle );
+
+    handle = NULL;
+}
+
+#endif
+
+void CSoundOut::CPlayThread::run()
+{
+    while ( SoundBuf.keep_running ) {
+        int fill;
+
+        SoundBuf.lock();
+        fill = SoundBuf.GetFillLevel();
+        SoundBuf.unlock();
+
+        if ( fill > (FRAGSIZE * NUM_OUT_CHANNELS) ) {
+
+            // enough data in the buffer
+
+            CVectorEx<_SAMPLE>*	p;
+
+            SoundBuf.lock();
+            p = SoundBuf.Get( FRAGSIZE * NUM_OUT_CHANNELS );
+
+            for (int i=0; i < FRAGSIZE * NUM_OUT_CHANNELS; i++)
+                tmpplaybuf[i] = (*p)[i];
+
+            SoundBuf.unlock();
+
+            pSoundOut->write_HW( tmpplaybuf, FRAGSIZE );
+
+        } else {
+
+            do {
+                msleep( 1 );
+
+                SoundBuf.lock();
+                fill = SoundBuf.GetFillLevel();
+                SoundBuf.unlock();
+
+            } while ((SoundBuf.keep_running) && ( fill < SOUNDBUFLEN/2 ));	// wait until buffer is at least half full
+        }
+    }
+    qDebug("Play Thread stopped");
+}
+
+void CSoundOut::Init(int iNewBufferSize, _BOOLEAN bNewBlocking)
+{
+    qDebug("initplay %d", iNewBufferSize);
+
+    /* Save buffer size */
+    PlayThread.SoundBuf.lock();
+    iBufferSize = iNewBufferSize;
+    bBlockingPlay = bNewBlocking;
+    PlayThread.SoundBuf.unlock();
+
+    /* Check if device must be opened or reinitialized */
+    if (bChangDev == TRUE)
+    {
+
+        Init_HW( );
+
+        /* Reset flag */
+        bChangDev = FALSE;
+    }
+
+    if ( PlayThread.running() == FALSE ) {
+        PlayThread.SoundBuf.lock();
+        PlayThread.SoundBuf.Init( SOUNDBUFLEN );
+        PlayThread.SoundBuf.unlock();
+        PlayThread.start();
+    }
+}
+
+
+_BOOLEAN CSoundOut::Write(CVector< _SAMPLE >& psData)
+{
+    /* Check if device must be opened or reinitialized */
+    if (bChangDev == TRUE)
+    {
+        /* Reinit sound interface */
+        Init(iBufferSize, bBlockingPlay);
+
+        /* Reset flag */
+        bChangDev = FALSE;
+    }
+
+    if ( bBlockingPlay ) {
+        // blocking write
+        while ( PlayThread.SoundBuf.keep_running ) {
+            PlayThread.SoundBuf.lock();
+            int fill = SOUNDBUFLEN - PlayThread.SoundBuf.GetFillLevel();
+            PlayThread.SoundBuf.unlock();
+            if ( fill > iBufferSize) break;
+        }
+    }
+
+    PlayThread.SoundBuf.lock();	// we need exclusive access
+
+    if ( ( SOUNDBUFLEN - PlayThread.SoundBuf.GetFillLevel() ) > iBufferSize) {
+
+        CVectorEx<_SAMPLE>*	ptarget;
+
+        // data fits, so copy
+        ptarget = PlayThread.SoundBuf.QueryWriteBuffer();
+        for (int i=0; i < iBufferSize; i++)
+        {
+            (*ptarget)[i] = psData[i];
+        }
+
+        PlayThread.SoundBuf.Put( iBufferSize );
+    }
+
+    PlayThread.SoundBuf.unlock();
+
+    return FALSE;
+}
+
+void CSoundOut::Close()
+{
+    qDebug("stopplay");
+
+    // stop the playback thread
+    if (PlayThread.running() ) {
+        PlayThread.SoundBuf.keep_running = FALSE;
+        PlayThread.wait(1000);
+    }
+
+    close_HW();
+
+    /* Set flag to open devices the next time it is initialized */
+    bChangDev = TRUE;
+}
+
+#else
+CSoundOut::CSoundOut():names(),iCurrentDevice(-1) {}
+#endif
+
+void CSoundOut::SetDev(int iNewDevice)
+{
+    /* Change only in case new device id is not already active */
+    if (iNewDevice != iCurrentDevice)
+    {
+        iCurrentDevice = iNewDevice;
+        bChangDev = TRUE;
+    }
+}
+
+int CSoundOut::GetDev()
+{
+    return iCurrentDevice;
+}
+
diff --git a/src/linux/soundout.h b/src/linux/soundout.h
new file mode 100644
index 0000000..c10c546
--- /dev/null
+++ b/src/linux/soundout.h
@@ -0,0 +1,93 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Alexander Kurpiers
+ *
+ * Decription:
+ * Linux sound interface
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#ifndef _SOUNDOUT_H
+#define _SOUNDOUT_H
+
+#include "../soundinterface.h"
+#include "../util/Buffer.h"
+#include "soundcommon.h"
+
+/* Definitions ****************************************************************/
+#define SOUNDBUFLEN 102400
+
+#define FRAGSIZE 8192
+//#define FRAGSIZE 1024
+
+/* Classes ********************************************************************/
+class CSoundOut : public CSoundOutInterface
+{
+public:
+    CSoundOut();
+    virtual ~CSoundOut() {}
+
+    virtual void				Enumerate(vector<string>& choices) {
+        choices = names;
+    }
+    virtual void				SetDev(int iNewDevice);
+    virtual int					GetDev();
+
+    void Init(int iNewBufferSize, _BOOLEAN bNewBlocking = FALSE);
+    _BOOLEAN Write(CVector<short>& psData);
+
+    void Close();
+
+protected:
+    void Init_HW();
+    int write_HW( _SAMPLE *playbuf, int size );
+    void close_HW( void );
+
+    int 	iBufferSize, iInBufferSize;
+    short int *tmpplaybuf;
+    _BOOLEAN	bBlockingPlay;
+    vector<string> devices;
+
+    class CPlayThread : public CThread
+    {
+    public:
+        virtual ~CPlayThread() {}
+        virtual void run();
+        CSoundBuf SoundBuf;
+        CSoundOut*	pSoundOut;
+    protected:
+        _SAMPLE	tmpplaybuf[NUM_OUT_CHANNELS * FRAGSIZE];
+    } PlayThread;
+
+    vector<string> names;
+    _BOOLEAN bChangDev;
+    int	iCurrentDevice;
+#ifdef USE_ALSA
+    snd_pcm_t *handle;
+#endif
+#ifdef USE_OSS
+    COSSDev dev;
+#endif
+
+};
+
+#endif
diff --git a/src/matlib/Matlib.h b/src/matlib/Matlib.h
new file mode 100644
index 0000000..8a00cb0
--- /dev/null
+++ b/src/matlib/Matlib.h
@@ -0,0 +1,867 @@
+/******************************************************************************\
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *	C++ Mathematic Library (Matlib)
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#ifndef _MATLIB_H_
+#define _MATLIB_H_
+
+#include <cstdlib>
+#include <math.h>
+#include <complex>
+using namespace std;
+#include "../GlobalDefinitions.h"
+
+
+/* Definitions ****************************************************************/
+/* Two different types: constant and temporary buffer */
+enum EVecTy {VTY_CONST, VTY_TEMP};
+
+
+/* These definitions save a lot of redundant code */
+#define _VECOP(TYPE, LENGTH, FCT)	const int iL = LENGTH; \
+									CMatlibVector<TYPE> vecRet(iL, VTY_TEMP); \
+									for (int i = 0; i < iL; i++) \
+										vecRet[i] = FCT; \
+									return vecRet
+
+#define _VECOPCL(FCT)				for (int i = 0; i < iVectorLength; i++) \
+										operator[](i) FCT; \
+									return *this
+
+#define _MATOP(TYPE, LENGTHROW, LENGTHCOL, FCT) \
+									const int iRL = LENGTHROW; \
+									CMatlibMatrix<TYPE> matRet(iRL, LENGTHCOL, VTY_TEMP); \
+									for (int i = 0; i < iRL; i++) \
+										matRet[i] = FCT; \
+									return matRet
+
+#define _MATOPCL(FCT)				for (int i = 0; i < iRowSize; i++) \
+										operator[](i) FCT; \
+									return *this
+
+
+/* In debug mode, test input parameters */
+#ifdef _DEBUG_
+#define _TESTRNGR(POS)		if ((POS >= iVectorLength) || (POS < 0)) \
+								DebugError("MatLibrRead", "POS", POS, \
+								"iVectorLength", iVectorLength)
+#define _TESTRNGW(POS)		if ((POS >= iVectorLength) || (POS < 0)) \
+								DebugError("MatLibrWrite", "POS", POS, \
+								"iVectorLength", iVectorLength)
+#define _TESTSIZE(INP)		if (INP != iVectorLength) \
+								DebugError("SizeCheck", "INP", INP, \
+								"iVectorLength", iVectorLength)
+#define _TESTRNGRM(POS)		if ((POS >= iRowSize) || (POS < 0)) \
+								DebugError("MatLibrReadMatrix", "POS", POS, \
+								"iRowSize", iRowSize)
+#define _TESTRNGWM(POS)		if ((POS >= iRowSize) || (POS < 0)) \
+								DebugError("MatLibrWriteMatrix", "POS", POS, \
+								"iRowSize", iRowSize)
+#define _TESTSIZEM(INP)		if (INP != iRowSize) \
+								DebugError("MatLibOperatorMatrix=()", "INP", INP, \
+								"iRowSize", iRowSize)
+#else
+
+// On Visual c++ 2005 Express Edition there is a segmentation fault if these macros are empty
+// TODO: FIX this with a better solution
+#if _MSC_VER && (_MSC_VER == 1400)
+#define _TESTRNGR(POS) if (POS != POS) int idummy=0
+#define _TESTRNGW(POS) if (POS != POS) int idummy=0
+#define _TESTSIZE(INP) if (INP != INP) int idummy=0
+#define _TESTRNGRM(POS) if (POS != POS) int idummy=0
+#define _TESTRNGWM(POS) if (POS != POS) int idummy=0
+#define _TESTSIZEM(INP) if (INP != INP) int idummy=0
+#else
+#define _TESTRNGR(POS)
+#define _TESTRNGW(POS)
+#define _TESTSIZE(INP)
+#define _TESTRNGRM(POS)
+#define _TESTRNGWM(POS)
+#define _TESTSIZEM(INP)
+#endif
+#endif
+
+
+/* Classes ********************************************************************/
+/* Prototypes */
+template<class T> class			CMatlibVector;
+template<class T> class			CMatlibMatrix;
+
+/* Here we can choose the precision of the Matlib calculations */
+typedef _REAL					CReal;
+typedef complex<CReal>			CComplex;
+typedef CMatlibVector<CReal>	CRealVector;
+typedef CMatlibVector<CComplex>	CComplexVector;
+typedef CMatlibMatrix<CReal>	CRealMatrix;
+typedef CMatlibMatrix<CComplex>	CComplexMatrix;
+
+
+/******************************************************************************/
+/* CMatlibVector class ********************************************************/
+/******************************************************************************/
+template<class T>
+class CMatlibVector
+{
+public:
+	/* Construction, Destruction -------------------------------------------- */
+	CMatlibVector() : eVType(VTY_CONST), iVectorLength(0), pData(NULL) {}
+	CMatlibVector(const int iNLen, const EVecTy eNTy = VTY_CONST) :
+		eVType(eNTy), iVectorLength(0), pData(NULL) {Init(iNLen);}
+	CMatlibVector(const int iNLen, const T tIniVal) :
+		eVType(VTY_CONST), iVectorLength(0), pData(NULL) {Init(iNLen, tIniVal);}
+#ifndef _MSC_VER
+	CMatlibVector(CMatlibVector<T>& vecI);
+#endif
+	CMatlibVector(const CMatlibVector<T>& vecI);
+	virtual ~CMatlibVector() {if (pData != NULL) delete[] pData;}
+
+	CMatlibVector(const CMatlibVector<CReal>& fvReal, const CMatlibVector<CReal>& fvImag) :
+		eVType(VTY_CONST/*VTY_TEMP*/), iVectorLength(fvReal.GetSize()), pData(NULL)
+	{
+		/* Allocate data block for vector */
+		pData = new CComplex[iVectorLength];
+
+		/* Copy data from real-vectors in complex vector */
+		for (int i = 0; i < iVectorLength; i++)
+			pData[i] = CComplex(fvReal[i], fvImag[i]);
+	}
+
+	/* Operator[] (Regular indices!!!) */
+	inline T& operator[](int const iPos) const
+		{_TESTRNGR(iPos); return pData[iPos];}
+	inline T& operator[](int const iPos)
+		{_TESTRNGW(iPos); return pData[iPos];} // For use as l value
+
+	/* Operator() */
+	inline T& operator()(int const iPos) const
+		{_TESTRNGR(iPos - 1); return pData[iPos - 1];}
+	inline T& operator()(int const iPos)
+		{_TESTRNGW(iPos - 1); return pData[iPos - 1];} // For use as l value
+
+	CMatlibVector<T> operator()(const int iFrom, const int iTo) const;
+	CMatlibVector<T> operator()(const int iFrom, const int iStep, const int iTo) const;
+
+	inline int GetSize() const {return iVectorLength;}
+	void Init(const int iIniLen, const T tIniVal = 0);
+	inline CMatlibVector<T>& Reset(const T tResVal = 0) {_VECOPCL(= tResVal);}
+	CMatlibVector<T>& PutIn(const int iFrom, const int iTo, CMatlibVector<T>& fvA);
+	CMatlibVector<T>& Merge(const CMatlibVector<T>& vecA, T& tB);
+	CMatlibVector<T>& Merge(const CMatlibVector<T>& vecA, const CMatlibVector<T>& vecB);
+	CMatlibVector<T>& Merge(const CMatlibVector<T>& vecA, const CMatlibVector<T>& vecB,
+		const CMatlibVector<T>& vecC);
+
+
+	/* operator= */
+	inline CMatlibVector<T>&		operator=(const CMatlibVector<CReal>& vecI)
+	{
+		Init(vecI.GetSize());
+		for (int i = 0; i < iVectorLength; i++) 
+			operator[](i) = vecI[i]; 
+		
+		return *this;
+	}
+
+	inline CMatlibVector<CComplex>&	operator=(const CMatlibVector<CComplex>& vecI)
+	{
+		Init(vecI.GetSize());
+		for (int i = 0; i < iVectorLength; i++) 
+			operator[](i) = vecI[i]; 
+		
+		return *this;
+	}
+
+	/* operator*= */
+	inline CMatlibVector<T>&		operator*=(const CReal& rI)
+		{_VECOPCL(*= rI);}
+	inline CMatlibVector<CComplex>&	operator*=(const CComplex& cI)
+		{_VECOPCL(*= cI);}
+	inline CMatlibVector<T>&		operator*=(const CMatlibVector<CReal>& vecI)
+		{_VECOPCL(*= vecI[i]);}
+	inline CMatlibVector<CComplex>&	operator*=(const CMatlibVector<CComplex>& vecI)
+		{_VECOPCL(*= vecI[i]);}
+
+	/* operator/= */
+	inline CMatlibVector<T>&		operator/=(const CReal& rI)
+		{_VECOPCL(/= rI);}
+	inline CMatlibVector<CComplex>&	operator/=(const CComplex& cI)
+		{_VECOPCL(/= cI);}
+	inline CMatlibVector<T>&		operator/=(const CMatlibVector<CReal>& vecI)
+		{_VECOPCL(/= vecI[i]);}
+	inline CMatlibVector<CComplex>&	operator/=(const CMatlibVector<CComplex>& vecI)
+		{_VECOPCL(/= vecI[i]);}
+
+	/* operator+= */
+	inline CMatlibVector<T>&		operator+=(const CReal& rI)
+		{_VECOPCL(+= rI);}
+	inline CMatlibVector<CComplex>&	operator+=(const CComplex& cI)
+		{_VECOPCL(+= cI);}
+	inline CMatlibVector<T>&		operator+=(const CMatlibVector<CReal>& vecI)
+		{_VECOPCL(+= vecI[i]);}
+	inline CMatlibVector<CComplex>&	operator+=(const CMatlibVector<CComplex>& vecI)
+		{_VECOPCL(+= vecI[i]);}
+
+	/* operator-= */
+	inline CMatlibVector<T>&		operator-=(const CReal& rI)
+		{_VECOPCL(-= rI);}
+	inline CMatlibVector<CComplex>&	operator-=(const CComplex& cI)
+		{_VECOPCL(-= cI);}
+	inline CMatlibVector<T>&		operator-=(const CMatlibVector<CReal>& vecI)
+		{_VECOPCL(-= vecI[i]);}
+	inline CMatlibVector<CComplex>&	operator-=(const CMatlibVector<CComplex>& vecI)
+		{_VECOPCL(-= vecI[i]);}
+
+protected:
+	EVecTy	eVType;
+	int		iVectorLength;
+	T*		pData;
+};
+
+/* operator* ---------------------------------------------------------------- */
+inline CMatlibVector<CComplex> // cv, cv
+	operator*(const CMatlibVector<CComplex>& cvA, const CMatlibVector<CComplex>& cvB)
+	{_VECOP(CComplex, cvA.GetSize(), cvA[i] * cvB[i]);}
+inline CMatlibVector<CReal> // rv, rv
+	operator*(const CMatlibVector<CReal>& rvA, const CMatlibVector<CReal>& rvB)
+	{_VECOP(CReal, rvA.GetSize(), rvA[i] * rvB[i]);}
+
+inline CMatlibVector<CComplex> // cv, rv
+	operator*(const CMatlibVector<CComplex>& cvA, const CMatlibVector<CReal>& rvB)
+	{_VECOP(CComplex, cvA.GetSize(), cvA[i] * rvB[i]);}
+inline CMatlibVector<CComplex> // rv, cv
+	operator*(const CMatlibVector<CReal>& rvB, const CMatlibVector<CComplex>& cvA)
+	{_VECOP(CComplex, cvA.GetSize(), cvA[i] * rvB[i]);}
+
+template<class T> inline
+CMatlibVector<T> // Tv, r
+	operator*(const CMatlibVector<T>& vecA, const CReal& rB)
+	{_VECOP(T, vecA.GetSize(), vecA[i] * rB);}
+template<class T> inline
+CMatlibVector<T> // r, Tv
+	operator*(const CReal& rA, const CMatlibVector<T>& vecB)
+	{_VECOP(T, vecB.GetSize(), rA * vecB[i]);}
+
+template<class T> inline
+CMatlibVector<CComplex> // Tv, c
+	operator*(const CMatlibVector<T>& vecA, const CComplex& cB)
+	{_VECOP(CComplex, vecA.GetSize(), vecA[i] * cB);}
+template<class T> inline
+CMatlibVector<CComplex> // c, Tv
+	operator*(const CComplex& cA, const CMatlibVector<T>& vecB)
+	{_VECOP(CComplex, vecB.GetSize(), cA * vecB[i]);}
+
+
+/* operator/ ---------------------------------------------------------------- */
+inline CMatlibVector<CComplex> // cv, cv
+	operator/(const CMatlibVector<CComplex>& cvA, const CMatlibVector<CComplex>& cvB)
+	{_VECOP(CComplex, cvA.GetSize(), cvA[i] / cvB[i]);}
+inline CMatlibVector<CReal> // rv, rv
+	operator/(const CMatlibVector<CReal>& rvA, const CMatlibVector<CReal>& rvB)
+	{_VECOP(CReal, rvA.GetSize(), rvA[i] / rvB[i]);}
+
+inline CMatlibVector<CComplex> // cv, rv
+	operator/(const CMatlibVector<CComplex>& cvA, const CMatlibVector<CReal>& rvB)
+	{_VECOP(CComplex, cvA.GetSize(), cvA[i] / rvB[i]);}
+inline CMatlibVector<CComplex> // rv, cv
+	operator/(const CMatlibVector<CReal>& rvA, const CMatlibVector<CComplex>& cvB)
+	{_VECOP(CComplex, rvA.GetSize(), rvA[i] / cvB[i]);}
+
+template<class T> inline
+CMatlibVector<T> // Tv, r
+	operator/(const CMatlibVector<T>& vecA, const CReal& rB)
+	{_VECOP(T, vecA.GetSize(), vecA[i] / rB);}
+template<class T> inline
+CMatlibVector<T> // r, Tv
+	operator/(const CReal& rA, const CMatlibVector<T>& vecB)
+	{_VECOP(T, vecB.GetSize(), rA / vecB[i]);}
+
+template<class T> inline
+CMatlibVector<CComplex> // Tv, c
+	operator/(const CMatlibVector<T>& vecA, const CComplex& cB)
+	{_VECOP(CComplex, vecA.GetSize(), vecA[i] / cB);}
+template<class T> inline
+CMatlibVector<CComplex> // c, Tv
+	operator/(const CComplex& cA, const CMatlibVector<T>& vecB)
+	{_VECOP(CComplex, vecB.GetSize(), cA / vecB[i]);}
+
+
+/* operator+ ---------------------------------------------------------------- */
+inline CMatlibVector<CComplex> // cv, cv
+	operator+(const CMatlibVector<CComplex>& cvA, const CMatlibVector<CComplex>& cvB)
+	{_VECOP(CComplex, cvA.GetSize(), cvA[i] + cvB[i]);}
+inline CMatlibVector<CReal> // rv, rv
+	operator+(const CMatlibVector<CReal>& rvA, const CMatlibVector<CReal>& rvB)
+	{_VECOP(CReal, rvA.GetSize(), rvA[i] + rvB[i]);}
+
+inline CMatlibVector<CComplex> // cv, rv
+	operator+(const CMatlibVector<CComplex>& cvA, const CMatlibVector<CReal>& rvB)
+	{_VECOP(CComplex, cvA.GetSize(), cvA[i] + rvB[i]);}
+inline CMatlibVector<CComplex> // rv, cv
+	operator+(const CMatlibVector<CReal>& rvA, const CMatlibVector<CComplex>& cvB)
+	{_VECOP(CComplex, rvA.GetSize(), rvA[i] + cvB[i]);}
+
+template<class T> inline
+CMatlibVector<T> // Tv, r
+	operator+(const CMatlibVector<T>& vecA, const CReal& rB)
+	{_VECOP(T, vecA.GetSize(), vecA[i] + rB);}
+template<class T> inline
+CMatlibVector<T> // r, Tv
+	operator+(const CReal& rA, const CMatlibVector<T>& vecB)
+	{_VECOP(T, vecB.GetSize(), rA + vecB[i]);}
+
+template<class T> inline
+CMatlibVector<CComplex> // Tv, c
+	operator+(const CMatlibVector<T>& vecA, const CComplex& cB)
+	{_VECOP(CComplex, vecA.GetSize(), vecA[i] + cB);}
+template<class T> inline
+CMatlibVector<CComplex> // c, Tv
+	operator+(const CComplex& cA, const CMatlibVector<T>& vecB)
+	{_VECOP(CComplex, vecB.GetSize(), cA + vecB[i]);}
+
+
+/* operator- ---------------------------------------------------------------- */
+inline CMatlibVector<CComplex> // cv, cv
+	operator-(const CMatlibVector<CComplex>& cvA, const CMatlibVector<CComplex>& cvB)
+	{_VECOP(CComplex, cvA.GetSize(), cvA[i] - cvB[i]);}
+inline CMatlibVector<CReal> // rv, rv
+	operator-(const CMatlibVector<CReal>& rvA, const CMatlibVector<CReal>& rvB)
+	{_VECOP(CReal, rvA.GetSize(), rvA[i] - rvB[i]);}
+
+inline CMatlibVector<CComplex> // cv, rv
+	operator-(const CMatlibVector<CComplex>& cvA, const CMatlibVector<CReal>& rvB)
+	{_VECOP(CComplex, cvA.GetSize(), cvA[i] - rvB[i]);}
+inline CMatlibVector<CComplex> // rv, cv
+	operator-(const CMatlibVector<CReal>& rvA, const CMatlibVector<CComplex>& cvB)
+	{_VECOP(CComplex, rvA.GetSize(), rvA[i] - cvB[i]);}
+
+template<class T> inline
+CMatlibVector<T> // Tv, r
+	operator-(const CMatlibVector<T>& vecA, const CReal& rB)
+	{_VECOP(T, vecA.GetSize(), vecA[i] - rB);}
+template<class T> inline
+CMatlibVector<T> // r, Tv
+	operator-(const CReal& rA, const CMatlibVector<T>& vecB)
+	{_VECOP(T, vecB.GetSize(), rA - vecB[i]);}
+
+template<class T> inline
+CMatlibVector<CComplex> // Tv, c
+	operator-(const CMatlibVector<T>& vecA, const CComplex& cB)
+	{_VECOP(CComplex, vecA.GetSize(), vecA[i] - cB);}
+template<class T> inline
+CMatlibVector<CComplex> // c, Tv
+	operator-(const CComplex& cA, const CMatlibVector<T>& vecB)
+	{_VECOP(CComplex, vecB.GetSize(), cA - vecB[i]);}
+
+
+/* Implementation **************************************************************
+   (the implementation of template classes must be in the header file!) */
+
+#ifndef _MSC_VER
+template<class T>
+CMatlibVector<T>::CMatlibVector(CMatlibVector<T>& vecI) :
+	 eVType(VTY_CONST/*VTY_TEMP*/), iVectorLength(vecI.GetSize()), pData(NULL)
+{
+	/* The copy constructor for the constant vector is a real copying
+	   task. But in the case of a temporary buffer only the pointer
+	   of the temporary buffer is used. The buffer of the temporary
+	   vector is then destroyed!!! Therefore the usage of "VTY_TEMP"
+	   should be done if the vector IS NOT USED IN A FUNCTION CALL,
+	   otherwise this vector will be destroyed afterwards (if the
+	   function argument is not declared with "&") */
+	if (iVectorLength > 0)
+	{
+		if (vecI.eVType == VTY_CONST)
+		{
+			/* Allocate data block for vector */
+			pData = new T[iVectorLength];
+
+			/* Copy vector */
+			for (int i = 0; i < iVectorLength; i++)
+				pData[i] = vecI[i];
+		}
+		else
+		{
+			/* We can define the copy constructor as a destroying operator of
+			   the input vector for performance reasons. This
+			   saves us from always copy the entire vector */
+			/* Take data pointer from input vector (steal it) */
+			pData = vecI.pData;
+
+			/* Destroy other vector (temporary vectors only) */
+			vecI.pData = NULL;
+		}
+	}
+}
+#endif
+
+/* Copy constructor for constant Matlib vectors */
+template<class T>
+CMatlibVector<T>::CMatlibVector(const CMatlibVector<T>& vecI) :
+	eVType(VTY_CONST), iVectorLength(vecI.GetSize()), pData(NULL)
+{
+	if (iVectorLength > 0)
+	{
+		/* Allocate data block for vector */
+		pData = new T[iVectorLength];
+
+		/* Copy vector */
+		for (int i = 0; i < iVectorLength; i++)
+			pData[i] = vecI[i];
+	}
+}
+
+template<class T>
+void CMatlibVector<T>::Init(const int iIniLen, const T tIniVal)
+{
+	iVectorLength = iIniLen;
+
+	/* Allocate data block for vector */
+	if (iVectorLength > 0)
+	{
+		if (pData != NULL)
+			delete[] pData;
+
+		pData = new T[iVectorLength];
+
+		/* Init with init value */
+		for (int i = 0; i < iVectorLength; i++)
+			pData[i] = tIniVal;
+	}
+}
+
+template<class T> inline
+CMatlibVector<T> CMatlibVector<T>::operator()(const int iFrom,
+											  const int iTo) const
+{
+	/* This is also capable of "wrap around" blocks (if the value in "iFrom" is
+	   larger then the "iTo" value) */
+	int			i;
+	const int	iStartVal = iFrom - 1;
+
+	if (iFrom > iTo)
+	{
+		/* Wrap around case */
+		CMatlibVector<T> vecRet(iVectorLength - iStartVal + iTo, VTY_TEMP);
+
+		int iCurPos = 0;
+
+		for (i = iStartVal; i < iVectorLength; i++)
+			vecRet[iCurPos++] = operator[](i);
+
+		for (i = 0; i < iTo; i++)
+			vecRet[iCurPos++] = operator[](i);
+
+		return vecRet;
+	}
+	else
+	{
+		CMatlibVector<T> vecRet(iTo - iStartVal, VTY_TEMP);
+
+		for (i = iStartVal; i < iTo; i++)
+			vecRet[i - iStartVal] = operator[](i);
+
+		return vecRet;
+	}
+}
+
+template<class T> inline
+CMatlibVector<T> CMatlibVector<T>::operator()(const int iFrom,
+											  const int iStep,
+											  const int iTo) const
+{
+	CMatlibVector<T> vecRet(size_t(abs(float(iTo - iFrom)) / abs(float(iStep))) + 1, VTY_TEMP);
+	int iOutPos = 0;
+	int i;
+
+	if (iFrom > iTo)
+	{
+		const int iEnd = iTo - 2;
+		for (i = iFrom - 1; i > iEnd; i += iStep)
+		{
+			vecRet[iOutPos] = operator[](i);
+			iOutPos++;
+		}
+	}
+	else
+	{
+		for (i = iFrom - 1; i < iTo; i += iStep)
+		{
+			vecRet[iOutPos] = operator[](i);
+			iOutPos++;
+		}
+	}
+
+	return vecRet;
+}
+
+template<class T> inline
+CMatlibVector<T>& CMatlibVector<T>::PutIn(const int iFrom,
+										  const int iTo,
+										  CMatlibVector<T>& vecI)
+{
+	const int iStart = iFrom - 1;
+	const int iEnd = iTo - iStart;
+
+	for (int i = 0; i < iEnd; i++)
+		operator[](i + iStart) = vecI[i];
+
+	return *this;
+}
+
+template<class T> inline
+CMatlibVector<T>& CMatlibVector<T>::Merge(const CMatlibVector<T>& vecA, T& tB)
+{
+	const int iSizeA = vecA.GetSize();
+
+	for (int i = 0; i < iSizeA; i++)
+		operator[](i) = vecA[i];
+	
+	operator[](iSizeA) = tB;
+
+	return *this;
+}
+
+template<class T> inline
+CMatlibVector<T>& CMatlibVector<T>::Merge(const CMatlibVector<T>& vecA,
+										  const CMatlibVector<T>& vecB)
+{
+	int i;
+	const int iSizeA = vecA.GetSize();
+	const int iSizeB = vecB.GetSize();
+
+	/* Put first vector */
+	for (i = 0; i < iSizeA; i++)
+		operator[](i) = vecA[i];
+	
+	/* Put second vector behind the first one, both
+	   together must have length of *this */
+	for (i = 0; i < iSizeB; i++)
+		operator[](i + iSizeA) = vecB[i];
+
+	return *this;
+}
+
+template<class T> inline
+CMatlibVector<T>& CMatlibVector<T>::Merge(const CMatlibVector<T>& vecA,
+										  const CMatlibVector<T>& vecB,
+										  const CMatlibVector<T>& vecC)
+{
+	int i;
+	const int iSizeA = vecA.GetSize();
+	const int iSizeB = vecB.GetSize();
+	const int iSizeC = vecC.GetSize();
+	const int iSizeAB = iSizeA + iSizeB;
+
+	/* Put first vector */
+	for (i = 0; i < iSizeA; i++)
+		operator[](i) = vecA[i];
+	
+	/* Put second vector behind the first one */
+	for (i = 0; i < iSizeB; i++)
+		operator[](i + iSizeA) = vecB[i];
+
+	/* Put third vector behind previous put vectors */
+	for (i = 0; i < iSizeC; i++)
+		operator[](i + iSizeAB) = vecC[i];
+
+	return *this;
+}
+
+
+/******************************************************************************/
+/* CMatlibMatrix class ********************************************************/
+/******************************************************************************/
+/*
+	We define: Matrix[row][column]
+*/
+template<class T>
+class CMatlibMatrix
+{
+public:
+	/* Construction, Destruction -------------------------------------------- */
+	CMatlibMatrix() : eVType(VTY_CONST), iRowSize(0), ppData(NULL) {}
+	CMatlibMatrix(const int iNRowLen, const int iNColLen,
+		const EVecTy eNTy = VTY_CONST) :  eVType(eNTy),
+		iRowSize(0), ppData(NULL) {Init(iNRowLen, iNColLen);}
+	CMatlibMatrix(const int iNRowLen, const int iNColLen, const T tIniVal) :
+		eVType(VTY_CONST), iRowSize(0), ppData(NULL)
+		{Init(iNRowLen, iNColLen, tIniVal);}
+	CMatlibMatrix(const CMatlibMatrix<T>& matI);
+
+	virtual ~CMatlibMatrix() {if (ppData != NULL) delete[] ppData;}
+
+	void Init(const int iNRowLen, const int iNColLen, const T tIniVal = 0);
+	inline int GetRowSize() const {return iRowSize;}
+	inline int GetColSize() const
+		{if (iRowSize > 0) return ppData[0].GetSize(); else return 0;}
+
+	/* Operator[] (Regular indices!!!) */
+	inline CMatlibVector<T>& operator[](int const iPos) const
+		{_TESTRNGRM(iPos); return ppData[iPos];}
+	inline CMatlibVector<T>& operator[](int const iPos)
+		{_TESTRNGWM(iPos); return ppData[iPos];} // For use as l value
+
+	/* Operator() */
+	inline CMatlibVector<T>& operator()(int const iPos) const 
+		{_TESTRNGRM(iPos - 1); return ppData[iPos - 1];}
+	inline CMatlibVector<T>& operator()(int const iPos) 
+		{_TESTRNGWM(iPos - 1); return ppData[iPos - 1];} // For use as l value
+
+	CMatlibMatrix<T> operator()(const int iRowFrom, const int iRowTo,
+		const int iColFrom, const int iColTo) const;
+
+	/* operator= */
+	inline CMatlibMatrix<T>& operator=(const CMatlibMatrix<CReal>& matI)
+		{_TESTSIZEM(matI.GetRowSize()); _MATOPCL(= matI[i]);}
+	inline CMatlibMatrix<CComplex>& operator=(const CMatlibMatrix<CComplex>& matI)
+		{_TESTSIZEM(matI.GetRowSize()); _MATOPCL(= matI[i]);}
+
+	/* operator+= */
+	inline CMatlibMatrix<T>& operator+=(const CMatlibMatrix<CReal>& matI)
+		{_MATOPCL(+= matI[i]);}
+	inline CMatlibMatrix<CComplex>& operator+=(const CMatlibMatrix<CComplex>& matI)
+		{_MATOPCL(+= matI[i]);}
+
+	/* operator-= */
+	inline CMatlibMatrix<T>& operator-=(const CMatlibMatrix<CReal>& matI)
+		{_MATOPCL(-= matI[i]);}
+	inline CMatlibMatrix<CComplex>& operator-=(const CMatlibMatrix<CComplex>& matI)
+		{_MATOPCL(-= matI[i]);}
+
+	/* operator*= */
+	inline CMatlibMatrix<T>& operator*=(const CReal& rI)
+		{_MATOPCL(*= rI);}
+	inline CMatlibMatrix<CComplex>& operator*=(const CComplex& cI)
+		{_MATOPCL(*= cI);}
+
+	/* operator/= */
+	inline CMatlibMatrix<T>& operator/=(const CReal& rI)
+		{_MATOPCL(/= rI);}
+	inline CMatlibMatrix<CComplex>& operator/=(const CComplex& cI)
+		{_MATOPCL(/= cI);}
+
+protected:
+	EVecTy				eVType;
+	int					iRowSize;
+	CMatlibVector<T>*	ppData;
+};
+
+
+/* Help functions *************************************************************/
+/* operator+ */
+inline CMatlibMatrix<CComplex> // cm, cm
+operator+(const CMatlibMatrix<CComplex>& cmA, const CMatlibMatrix<CComplex>& cmB)
+{
+	const int iRowSizeA = cmA.GetRowSize();
+	const int iColSizeA = cmA.GetColSize();
+	CMatlibMatrix<CComplex> matRet(iRowSizeA, iColSizeA, VTY_TEMP);
+
+	for (int j = 0; j < iRowSizeA; j++)
+	{
+		for (int i = 0; i < iColSizeA; i++)
+			matRet[j][i] = cmA[j][i] + cmB[j][i];
+	}
+
+	return matRet;
+}
+
+/* operator- */
+inline CMatlibMatrix<CComplex> // cm, cm
+operator-(const CMatlibMatrix<CComplex>& cmA, const CMatlibMatrix<CComplex>& cmB)
+{
+	const int iRowSizeA = cmA.GetRowSize();
+	const int iColSizeA = cmA.GetColSize();
+	CMatlibMatrix<CComplex> matRet(iRowSizeA, iColSizeA, VTY_TEMP);
+
+	for (int j = 0; j < iRowSizeA; j++)
+	{
+		for (int i = 0; i < iColSizeA; i++)
+			matRet[j][i] = cmA[j][i] - cmB[j][i];
+	}
+
+	return matRet;
+}
+
+/* operator* */
+inline CMatlibVector<CComplex> // cm, cv
+operator*(const CMatlibMatrix<CComplex>& cmA, const CMatlibVector<CComplex>& cvB)
+{
+	const int iRowSizeA = cmA.GetRowSize();
+	const int iSizeB = cvB.GetSize();
+	CMatlibVector<CComplex> vecRet(iSizeB, VTY_TEMP);
+
+	for (int j = 0; j < iRowSizeA; j++)
+	{
+		vecRet[j] = (CReal) 0.0;
+
+		for (int i = 0; i < iSizeB; i++)
+			vecRet[j] += cmA[j][i] * cvB[i];
+	}
+
+	return vecRet;
+}
+
+/* operator* */
+inline CMatlibVector<CReal> // rm, rv
+operator*(const CMatlibMatrix<CReal>& rmA, const CMatlibVector<CReal>& rvB)
+{
+	const int iRowSizeA = rmA.GetRowSize();
+	const int iSizeB = rvB.GetSize();
+	CMatlibVector<CReal> vecRet(iSizeB, VTY_TEMP);
+
+	for (int j = 0; j < iRowSizeA; j++)
+	{
+		vecRet[j] = (CReal) 0.0;
+
+		for (int i = 0; i < iSizeB; i++)
+			vecRet[j] += rmA[j][i] * rvB[i];
+	}
+
+	return vecRet;
+}
+
+/* operator* */
+inline CMatlibMatrix<CComplex> // cm, cm
+operator*(const CMatlibMatrix<CComplex>& cmA, const CMatlibMatrix<CComplex>& cmB)
+{
+	const int iRowSizeA = cmA.GetRowSize();
+	const int iRowSizeB = cmB.GetRowSize();
+	const int iColSizeB = cmB.GetColSize();
+	CMatlibMatrix<CComplex> matRet(iRowSizeA, iColSizeB, VTY_TEMP);
+
+	for (int k = 0; k < iColSizeB; k++)
+	{
+		for (int j = 0; j < iRowSizeA; j++)
+		{
+			matRet[j][k] = (CReal) 0.0;
+
+			for (int i = 0; i < iRowSizeB; i++)
+				matRet[j][k] += cmA[j][i] * cmB[i][k];
+		}
+	}
+
+	return matRet;
+}
+
+/* operator* */
+inline CMatlibMatrix<CComplex> // c, cm
+operator*(const CComplex& cA, const CMatlibMatrix<CComplex>& cmB)
+{
+	const int iRowSizeB = cmB.GetRowSize();
+	const int iColSizeB = cmB.GetColSize();
+	CMatlibMatrix<CComplex> matRet(iRowSizeB, iColSizeB, VTY_TEMP);
+
+	for (int k = 0; k < iColSizeB; k++)
+	{
+		for (int j = 0; j < iRowSizeB; j++)
+			matRet[j][k] = cA * cmB[j][k];
+	}
+
+	return matRet;
+}
+
+/* operator* */
+inline CMatlibMatrix<CReal> // r, rm
+operator*(const CReal& rA, const CMatlibMatrix<CReal>& rmB)
+{
+	const int iRowSizeB = rmB.GetRowSize();
+	const int iColSizeB = rmB.GetColSize();
+	CMatlibMatrix<CReal> matRet(iRowSizeB, iColSizeB, VTY_TEMP);
+
+	for (int k = 0; k < iColSizeB; k++)
+	{
+		for (int j = 0; j < iRowSizeB; j++)
+			matRet[j][k] = rA * rmB[j][k];
+	}
+
+	return matRet;
+}
+
+
+/* Implementation **************************************************************
+   (the implementation of template classes must be in the header file!) */
+template<class T>
+CMatlibMatrix<T>::CMatlibMatrix(const CMatlibMatrix<T>& matI) :
+	eVType(VTY_CONST), iRowSize(matI.GetRowSize()), ppData(NULL)
+{
+	if (iRowSize > 0)
+	{
+		/* Allocate data block for vector */
+		ppData = new CMatlibVector<T>[iRowSize];
+
+		/* Init column vectors and copy */
+		for (int i = 0; i < iRowSize; i++)
+		{
+			ppData[i].Init(matI.GetColSize());
+
+			/* Copy entire vector */
+			ppData[i] = matI[i];
+		}
+	}
+}
+
+template<class T>
+void CMatlibMatrix<T>::Init(const int iNRowLen, const int iNColLen, const T tIniVal)
+{
+	iRowSize = iNRowLen;
+
+	/* Allocate data block for vector */
+	if (iRowSize > 0)
+	{
+		if (ppData != NULL)
+			delete[] ppData;
+
+		ppData = new CMatlibVector<T>[iRowSize];
+
+		/* Init column vectors and set to init value */
+		for (int i = 0; i < iRowSize; i++)
+			ppData[i].Init(iNColLen, tIniVal);
+	}
+}
+
+template<class T> inline
+CMatlibMatrix<T> CMatlibMatrix<T>::operator()(const int iRowFrom, const int iRowTo,
+											  const int iColFrom, const int iColTo) const
+{
+	const int iStartRow = iRowFrom - 1;
+	const int iStartCol = iColFrom - 1;
+	CMatlibMatrix<T> matRet(iRowTo - iStartRow, iColTo - iStartCol, VTY_TEMP);
+
+	for (int j = iStartRow; j < iRowTo; j++)
+	{
+		for (int i = iStartCol; i < iColTo; i++)
+			matRet[j - iStartRow][i - iStartCol] = operator[](j)[i];
+	}
+
+	return matRet;
+}
+
+
+/* Include toolboxes after all type definitions */
+#include "MatlibStdToolbox.h"
+#include "MatlibSigProToolbox.h"
+
+
+#endif /* _MATLIB_H_ */
diff --git a/src/matlib/MatlibSigProToolbox.cpp b/src/matlib/MatlibSigProToolbox.cpp
new file mode 100644
index 0000000..77f4123
--- /dev/null
+++ b/src/matlib/MatlibSigProToolbox.cpp
@@ -0,0 +1,606 @@
+/******************************************************************************\
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *	c++ Mathematic Library (Matlib), signal processing toolbox
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later 
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT 
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "MatlibSigProToolbox.h"
+
+
+/* Implementation *************************************************************/
+CMatlibVector<CReal> Hann(const int iLen)
+{
+	int iHalf, i;
+	CMatlibVector<CReal> fvRet(iLen, VTY_TEMP);
+
+	if (iLen % 2)
+	{
+		/* Odd length window */
+		iHalf = (iLen + 1) / 2;
+
+		/* Hanning window */
+		CMatlibVector<CReal> vecTemp(iHalf);
+		CMatlibVector<CReal> w(iHalf);
+		for (i = 0; i < iHalf; i++)
+			vecTemp[i] = (CReal) i;
+
+		w = (CReal) 0.5 * (1 - Cos((CReal) 2.0 * crPi * vecTemp / (iLen - 1)));
+
+		/* Make symmetric window */
+		return fvRet.Merge(w, w(iHalf - 1, -1, 1));
+	}
+	else
+	{
+		/* Even length window */
+		iHalf = iLen / 2;
+
+		/* Hanning window */
+		CMatlibVector<CReal> vecTemp(iHalf);
+		CMatlibVector<CReal> w(iHalf);
+		for (i = 0; i < iHalf; i++)
+			vecTemp[i] = (CReal) i;
+
+		w = (CReal) 0.5 * (1 - Cos((CReal) 2.0 * crPi * vecTemp / (iLen - 1)));
+
+		/* Make symmetric window */
+		return fvRet.Merge(w, w(iHalf, -1, 1));
+	}
+}
+
+CMatlibVector<CReal> Hamming(const int iLen)
+{
+	int iHalf, i;
+	CMatlibVector<CReal> fvRet(iLen, VTY_TEMP);
+
+	if (iLen % 2)
+	{
+		/* Odd length window */
+		iHalf = (iLen + 1) / 2;
+
+		/* Hanning window */
+		CMatlibVector<CReal> vecTemp(iHalf);
+		CMatlibVector<CReal> w(iHalf);
+		for (i = 0; i < iHalf; i++)
+			vecTemp[i] = (CReal) i;
+
+		w = (CReal) 0.54 - (CReal) 0.46 * 
+			Cos((CReal) 2.0 * crPi * vecTemp / (iLen - 1));
+
+		/* Make symmetric window */
+		return fvRet.Merge(w, w(iHalf - 1, -1, 1));
+	}
+	else
+	{
+		/* Even length window */
+		iHalf = iLen / 2;
+
+		/* Hanning window */
+		CMatlibVector<CReal> vecTemp(iHalf);
+		CMatlibVector<CReal> w(iHalf);
+		for (i = 0; i < iHalf; i++)
+			vecTemp[i] = (CReal) i;
+
+		w = (CReal) 0.54 - (CReal) 0.46 * 
+			Cos((CReal) 2.0 * crPi * vecTemp / (iLen - 1));
+
+		/* Make symmetric window */
+		return fvRet.Merge(w, w(iHalf, -1, 1));
+	}
+}
+
+CMatlibVector<CReal> Nuttallwin(const int iLen)
+{
+	CMatlibVector<CReal> fvRet(iLen, VTY_TEMP);
+
+	/* Nuttall coefficients */
+	const CReal rA0 = (CReal) 0.3635819;
+	const CReal rA1 = (CReal) 0.4891775;
+	const CReal rA2 = (CReal) 0.1365995;
+	const CReal rA3 = (CReal) 0.0106411;
+
+	const CReal rArg = (CReal) 2.0 * crPi / (iLen - 1);
+
+	for (int i = 0; i < iLen; i++)
+	{
+		fvRet[i] = rA0 - rA1 * Cos(rArg * i) +
+			rA2 * Cos(rArg * i * 2) - rA3 * Cos(rArg * i * 3);
+	}
+
+	return fvRet;
+}
+
+CMatlibVector<CReal> Bartlett(const int iLen)
+{
+	const int iHalf = (int) Ceil((CReal) iLen / 2);
+	CMatlibVector<CReal> fvHalfWin(iHalf);
+	CMatlibVector<CReal> fvRet(iLen, VTY_TEMP);
+
+	for (int i = 0; i < iHalf; i++)
+		fvHalfWin[i] = (CReal) 2.0 * i / (iLen - 1);
+
+	/* Build complete output vector depending on odd or even input length */
+	if (iLen % 2)
+		fvRet.Merge(fvHalfWin, fvHalfWin(iHalf - 1, -1, 1)); /* Odd */
+	else
+		fvRet.Merge(fvHalfWin, fvHalfWin(iHalf, -1, 1)); /* Even */
+
+	return fvRet;
+}
+
+CMatlibVector<CReal> Triang(const int iLen)
+{
+	const int iHalf = (int) Ceil((CReal) iLen / 2);
+	CMatlibVector<CReal> fvHalfWin(iHalf);
+	CMatlibVector<CReal> fvRet(iLen, VTY_TEMP);
+
+	/* Build complete output vector depending on odd or even input length */
+	if (iLen % 2)
+	{
+		for (int i = 0; i < iHalf; i++)
+			fvHalfWin[i] = (CReal) 2.0 * (i + 1) / (iLen + 1);
+
+		fvRet.Merge(fvHalfWin, fvHalfWin(iHalf - 1, -1, 1)); /* Odd */
+	}
+	else
+	{
+		for (int i = 0; i < iHalf; i++)
+			fvHalfWin[i] = ((CReal) 2.0 * (i + 1) - 1) / iLen;
+
+		fvRet.Merge(fvHalfWin, fvHalfWin(iHalf, -1, 1)); /* Even */
+	}
+
+	return fvRet;
+}
+
+CMatlibVector<CReal> Kaiser(const int iLen, const CReal rBeta)
+{
+	CReal		rX;
+	const int	iIsOdd = iLen % 2;
+	const int	n = (iLen + 1) / 2; /* Half vector size, round up */
+	CMatlibVector<CReal> fvRet(iLen);
+	CMatlibVector<CReal> fvW(n);
+
+	const CReal rNorm = Abs(Besseli((CReal) 0.0, rBeta));
+	const CReal rXind = (iLen - 1) * (iLen - 1);
+
+	if (iIsOdd == 0)
+		rX = (CReal) 0.5;
+	else
+		rX = (CReal) 0.0;
+
+	for (int i = 0; i < n; i++)
+	{
+		fvW[i] = Besseli((CReal) 0.0, rBeta * Sqrt((CReal) 1.0 -
+			(CReal) 4.0 * rX * rX / rXind)) / rNorm;
+		rX += (CReal) 1.0;
+	}
+
+	/* Symmetrical window */
+	fvRet.Merge(fvW(n, -1, iIsOdd + 1), fvW);
+
+	return Abs(fvRet);
+}
+
+CReal Besseli(const CReal rNu, const CReal rZ)
+{
+	const CReal	rEp = (CReal) 10e-9; /* Define accuracy */
+	const CReal	rY = rZ / (CReal) 2.0;
+	CReal		rReturn = (CReal) 1.0;
+	CReal		rD = (CReal) 1.0;
+	CReal		rS = (CReal) 1.0;
+
+	/* Only nu = 0 is supported right now! */
+	if (rNu != (CReal) 0.0)
+	{
+#ifdef _DEBUG_
+		DebugError("MatLibr: Besseli function", "The nu = ", rNu, \
+			" is not supported, only nu = ", 0);
+#endif
+	}
+
+	for (int i = 1; i <= 25 && rReturn * rEp <= rS; i++)
+	{
+		rD *= rY / i;
+		rS = rD * rD;
+		rReturn += rS;
+	}
+
+	return rReturn;
+}
+
+CMatlibVector<CReal> Randn(const int iLen)
+{
+	/* Add some constant distributed random processes together */
+	_VECOP(CReal, iLen, 
+		(CReal) ((((CReal) 
+		rand() + rand() + rand() + rand() + rand() + rand() + rand()) 
+		/ RAND_MAX - 0.5) * /* sqrt(3) * 2 / sqrt(7) */ 1.3093));
+}
+
+CMatlibVector<CReal> Filter(const CMatlibVector<CReal>& fvB,
+							const CMatlibVector<CReal>& fvA,
+							const CMatlibVector<CReal>& fvX,
+							CMatlibVector<CReal>& fvZ)
+{
+	int						m, n, iLenCoeff;
+	const int				iSizeA = fvA.GetSize();
+	const int				iSizeB = fvB.GetSize();
+	const int				iSizeX = fvX.GetSize();
+	const int				iSizeZ = fvZ.GetSize();
+	CMatlibVector<CReal>	fvY(iSizeX, VTY_TEMP);
+	CMatlibVector<CReal>	fvANew, fvBNew;
+
+	if ((iSizeA == 1) && (fvA[0] == (CReal) 1.0))
+	{
+		/* FIR filter ------------------------------------------------------- */
+		const int				iSizeXNew = iSizeX + iSizeZ;
+		CMatlibVector<CReal>	rvXNew(iSizeXNew);
+
+		/* Add old values to input vector */
+		rvXNew.Merge(fvZ, fvX);
+
+		/* Actual convolution */
+		for (m = 0; m < iSizeX; m++)
+		{
+			fvY[m] = (CReal) 0.0;
+
+			for (n = 0; n < iSizeB; n++)
+				fvY[m] += fvB[n] * rvXNew[m + iSizeB - n];
+		}
+
+		/* Save last samples in state vector */
+		fvZ = rvXNew(iSizeXNew - iSizeZ + 1, iSizeXNew);
+	}
+	else
+	{
+		/* IIR filter ------------------------------------------------------- */
+		/* Length of coefficients */
+		iLenCoeff = (int) Max((CReal) iSizeB, (CReal) iSizeA);
+
+		/* Make fvB and fvA the same length (zero padding) */
+		if (iSizeB > iSizeA)
+		{
+			fvBNew.Init(iSizeB);
+			fvANew.Init(iSizeB);
+
+			fvBNew = fvB;
+			fvANew.Merge(fvA, Zeros(iSizeB - iSizeA));
+		}
+		else
+		{
+			fvBNew.Init(iSizeA);
+			fvANew.Init(iSizeA);
+
+			fvANew = fvA;
+			fvBNew.Merge(fvB, Zeros(iSizeA - iSizeB));
+		}
+
+		/* Filter is implemented as a transposed direct form II structure */
+		for (m = 0; m < iSizeX; m++)
+		{
+			/* y(m) = (b(1) x(m) + z_1(m - 1)) / a(1) */
+			fvY[m] = (fvBNew[0] * fvX[m] + fvZ[0]) / fvANew[0];
+
+			for (n = 1; n < iLenCoeff; n++)
+			{
+				/* z_{n - 2}(m) = b(n - 1) x(m) + z_{n - 1}(m - 1) -
+				   a(n - 1) y(m) */
+				fvZ[n - 1] = fvBNew[n] * fvX[m] + fvZ[n] - fvANew[n] * fvY[m];
+			}
+		}
+	}
+
+	return fvY;
+}
+
+CMatlibVector<CReal> FirLP(const CReal rNormBW,
+						   const CMatlibVector<CReal>& rvWin)
+{
+/*
+	Lowpass filter design using windowing method
+*/
+	const int				iLen = rvWin.GetSize();
+	const int				iHalfLen = (int) Floor((CReal) iLen / 2);
+	CMatlibVector<CReal>	fvRet(iLen, VTY_TEMP);
+
+	/* Generate truncuated ideal response */
+	for (int i = 0; i < iLen; i++)
+		fvRet[i] = rNormBW * Sinc(rNormBW * (i - iHalfLen));
+
+	/* Apply window */
+	fvRet *= rvWin;
+
+	return fvRet;
+}
+
+CMatlibVector<CComplex> FirFiltDec(const CMatlibVector<CComplex>& cvB,
+								   const CMatlibVector<CComplex>& cvX,
+								   CMatlibVector<CComplex>& cvZ,
+								   const int iDecFact)
+{
+	int			m, n, iCurPos;
+	const int	iSizeX = cvX.GetSize();
+	const int	iSizeZ = cvZ.GetSize();
+	const int	iSizeB = cvB.GetSize();
+	const int	iSizeXNew = iSizeX + iSizeZ;
+	const int	iSizeFiltHist = iSizeB - 1;
+
+	int iNewLenZ;
+	int iDecSizeY;
+
+	if (iSizeFiltHist >= iSizeXNew)
+	{
+		 /* Special case if no new output can be calculated */
+		iDecSizeY = 0;
+
+		iNewLenZ = iSizeXNew;
+	}
+	else
+	{
+		/* Calculate the number of output bits which can be generated from the
+		   provided input vector */
+		iDecSizeY = 
+				(int) (((CReal) iSizeXNew - iSizeFiltHist - 1) / iDecFact + 1);
+
+		/* Since the input vector length must not be a multiple of "iDecFact",
+		   some input bits will be unused. To store this number, the size of
+		   the state vector "Z" is adapted */
+		iNewLenZ = iSizeFiltHist - 
+			(iDecSizeY * iDecFact - (iSizeXNew - iSizeFiltHist));
+	}
+
+	CMatlibVector<CComplex>	cvY(iDecSizeY, VTY_TEMP);
+	CMatlibVector<CComplex>	cvXNew(iSizeXNew);
+
+	/* Add old values to input vector */
+	cvXNew.Merge(cvZ, cvX);
+
+	/* FIR filter */
+	for (m = 0; m < iDecSizeY; m++)
+	{
+		iCurPos = m * iDecFact + iSizeFiltHist;
+
+		cvY[m] = (CReal) 0.0;
+
+		for (n = 0; n < iSizeB; n++)
+			cvY[m] += cvB[n] * cvXNew[iCurPos - n];
+	}
+
+	/* Save last samples in state vector */
+	cvZ.Init(iNewLenZ);
+	cvZ = cvXNew(iSizeXNew - iNewLenZ + 1, iSizeXNew);
+
+	return cvY;
+}
+
+CMatlibVector<CReal> Levinson(const CMatlibVector<CReal>& vecrRx,
+							  const CMatlibVector<CReal>& vecrB)
+{
+/* 
+	The levinson recursion [S. Haykin]
+
+	This algorithm solves the following equations:
+	Rp ap = ep u1,
+	Rp Xp = b, where Rp is a Toepliz-matrix of vector prRx and b = prB 
+	is an arbitrary correlation-vector. The Result is ap = prA.
+
+	Parts of the following code are taken from Ptolemy
+	(http://ptolemy.eecs.berkeley.edu/)
+*/
+	const int	iLength = vecrRx.GetSize();
+	CRealVector vecrX(iLength, VTY_TEMP);
+
+	CReal		rGamma;
+	CReal		rGammaCap;
+	CReal		rDelta;
+	CReal		rE;
+	CReal		rQ;
+	int			i, j;
+	CRealVector vecraP(iLength);
+	CRealVector vecrA(iLength);
+
+	/* Initialize the recursion --------------------------------------------- */
+	// (a) First coefficient is always unity
+	vecrA[0] = (CReal) 1.0;
+	vecraP[0] = (CReal) 1.0;
+
+	// (b) 
+	vecrX[0] = vecrB[0] / vecrRx[0];
+
+	// (c) Initial prediction error is simply the zero-lag of
+	// of the autocorrelation, or the signal power estimate.
+	rE = vecrRx[0];
+
+
+	/* Main loop ------------------------------------------------------------ */
+	// The order recurrence
+	for (j = 0; j < iLength - 1; j++)
+	{
+		const int iNextInd = j + 1;
+
+		// (a) Compute the new gamma
+		rGamma = vecrRx[iNextInd];
+		for (i = 1; i < iNextInd; i++) 
+			rGamma += vecrA[i] * vecrRx[iNextInd - i];
+
+		// (b), (d) Compute and output the reflection coefficient
+		// (which is also equal to the last AR parameter)
+		vecrA[j + 1] = rGammaCap = - rGamma / rE;
+
+		// (c)
+		for (i = 1; i < iNextInd; i++) 
+			vecraP[i] = vecrA[i] + rGammaCap * vecrA[iNextInd - i];
+
+		// Swap a and aP for next order recurrence
+		for (i = 1; i < iNextInd; i++)
+			vecrA[i] = vecraP[i];
+
+		// (e) Update the prediction error power
+		rE = rE * ((CReal) 1.0 - rGammaCap * rGammaCap);
+
+		// (f)
+		rDelta = (CReal) 0.0;
+		for (i = 0; i < iNextInd; i++) 
+			rDelta += vecrX[i] * vecrRx[iNextInd - i];
+
+		// (g), (i) 
+		vecrX[iNextInd] = rQ = (vecrB[iNextInd] - rDelta) / rE;
+
+		// (h)
+		for (i = 0; i < iNextInd; i++) 
+			vecrX[i] = vecrX[i] + rQ * vecrA[iNextInd - i];
+	}
+
+	return vecrX;
+}
+
+CMatlibVector<CComplex> Levinson(const CMatlibVector<CComplex>& veccRx,
+								 const CMatlibVector<CComplex>& veccB)
+{
+/* 
+	The levinson recursion [S. Haykin]
+	COMPLEX version!
+
+	This algorithm solves the following equations:
+	Rp ap = ep u1,
+	Rp Xp = b, where Rp is a Toepliz-matrix of vector prRx and b = prB 
+	is an arbitrary correlation-vector. The Result is ap = prA.
+
+	Parts of the following code are taken from Ptolemy
+	(http://ptolemy.eecs.berkeley.edu/)
+*/
+	const int		iLength = veccRx.GetSize();
+	CComplexVector	veccX(iLength, VTY_TEMP);
+
+	CComplex		cGamma;
+	CComplex		cGammaCap;
+	CComplex		cDelta;
+	CReal			rE;
+	CComplex		cQ;
+	int				i, j;
+	CComplexVector	veccaP(iLength);
+	CComplexVector	veccA(iLength);
+
+	/* Initialize the recursion --------------------------------------------- */
+	// (a) First coefficient is always unity
+	veccA[0] = (CReal) 1.0;
+	veccaP[0] = (CReal) 1.0;
+
+	// (b) 
+	veccX[0] = veccB[0] / veccRx[0];
+
+	// (c) Initial prediction error is simply the zero-lag of
+	// of the autocorrelation, or the signal power estimate.
+	rE = Real(veccRx[0]);
+
+
+	/* Main loop ------------------------------------------------------------ */
+	// The order recurrence
+	for (j = 0; j < iLength - 1; j++)
+	{
+		const int iNextInd = j + 1;
+
+		// (a) Compute the new gamma
+		cGamma = veccRx[iNextInd];
+		for (i = 1; i < iNextInd; i++) 
+			cGamma += veccA[i] * veccRx[iNextInd - i];
+
+		// (b), (d) Compute and output the reflection coefficient
+		// (which is also equal to the last AR parameter)
+		veccA[iNextInd] = cGammaCap = - cGamma / rE;
+
+		// (c)
+		for (i = 1; i < iNextInd; i++) 
+			veccaP[i] = veccA[i] + cGammaCap * Conj(veccA[iNextInd - i]);
+
+		// Swap a and aP for next order recurrence
+		for (i = 1; i < iNextInd; i++)
+			veccA[i] = veccaP[i];
+
+		// (e) Update the prediction error power
+		rE = rE * ((CReal) 1.0 - SqMag(cGammaCap));
+
+		// (f)
+		cDelta = (CReal) 0.0;
+		for (i = 0; i < iNextInd; i++) 
+			cDelta += veccX[i] * veccRx[iNextInd - i];
+
+		// (g), (i) 
+		veccX[iNextInd] = cQ = (veccB[iNextInd] - cDelta) / rE;
+
+		// (h)
+		for (i = 0; i < iNextInd; i++) 
+			veccX[i] = veccX[i] + cQ * Conj(veccA[iNextInd - i]);
+	}
+
+	return veccX;
+}
+
+CMatlibVector<CReal> DomEig(const CMatlibMatrix<CReal>& rmI,
+							const CReal rEpsilon)
+{
+	const int				iMaxNumIt = 150; /* Maximum number of iterations */
+	const int				iSize = rmI.GetColSize();
+	CMatlibVector<CReal>	vecrV(iSize, VTY_TEMP);
+	CMatlibVector<CReal>	vecrVold(iSize);
+	CMatlibVector<CReal>	vecrY(iSize);
+	CReal					rLambda, rLambdaold, rError;
+
+	/* Implementing the power method for getting the dominant eigenvector */
+	/* Start value for eigenvector */
+	vecrV = Ones(iSize);
+	rLambda = rLambdaold = (CReal) 1.0;
+	rError = _MAXREAL;
+	int iItCnt = iMaxNumIt;
+
+	while ((iItCnt > 0) && (rError > rEpsilon))
+	{
+		/* Save old values needed error calculation */
+		vecrVold = vecrV;
+		rLambdaold = rLambda;
+
+		/* Actual power method calculations */
+		rLambda = Max(Abs(vecrV));
+		vecrV = (CReal) 1.0 / rLambda * rmI * vecrV;
+
+		/* Take care of number of iterations and error calculations */
+		iItCnt--;
+		rError =
+			Max(Abs(rLambda - rLambdaold), Max(Abs(vecrV - vecrVold)));
+	}
+
+	return vecrV;
+}
+
+CReal LinRegr(const CMatlibVector<CReal>& rvX, const CMatlibVector<CReal>& rvY)
+{
+	/* Linear regression */
+	CReal Xm(Mean(rvX));
+	CReal Ym(Mean(rvY));
+
+	CRealVector Xmrem(rvX - Xm); /* Remove mean of W */
+
+	/* Return only the gradient, we do not calculate and return the offset */
+	return Sum(Xmrem * (rvY - Ym)) / Sum(Xmrem * Xmrem);
+}
diff --git a/src/matlib/MatlibSigProToolbox.h b/src/matlib/MatlibSigProToolbox.h
new file mode 100644
index 0000000..94fbfb4
--- /dev/null
+++ b/src/matlib/MatlibSigProToolbox.h
@@ -0,0 +1,136 @@
+/******************************************************************************\
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *	c++ Mathematic Library (Matlib), signal processing toolbox
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later 
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT 
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#ifndef _MATLIB_SIGNAL_PROC_TOOLBOX_H_
+#define _MATLIB_SIGNAL_PROC_TOOLBOX_H_
+
+#include "Matlib.h"
+#include "MatlibStdToolbox.h"
+#include <cstdlib>
+
+
+/* Helpfunctions **************************************************************/
+/* Randomize functions */
+CMatlibVector<CReal>	Randn(const int iLen);
+inline
+CMatlibVector<CReal>	Rand(const int iLen)
+							{_VECOP(CReal, iLen, (CReal) rand() / RAND_MAX);}
+
+
+/* Window functions */
+CMatlibVector<CReal>	Hann(const int iLen);
+CMatlibVector<CReal>	Hamming(const int iLen);
+CMatlibVector<CReal>	Nuttallwin(const int iLen);
+CMatlibVector<CReal>	Bartlett(const int iLen);
+CMatlibVector<CReal>	Triang(const int iLen);
+CMatlibVector<CReal>	Kaiser(const int iLen, const CReal rBeta);
+
+
+/* Bessel function */
+CReal					Besseli(const CReal rNu, const CReal rZ);
+
+
+/* Filter data with a recursive (IIR) or nonrecursive (FIR) filter */
+CMatlibVector<CReal>	Filter(const CMatlibVector<CReal>& fvB, 
+							   const CMatlibVector<CReal>& fvA, 
+							   const CMatlibVector<CReal>& fvX, 
+							   CMatlibVector<CReal>& fvZ);
+
+
+/* Levinson durbin recursion */
+CMatlibVector<CReal>	Levinson(const CMatlibVector<CReal>& vecrRx, 
+								 const CMatlibVector<CReal>& vecrB);
+CMatlibVector<CComplex>	Levinson(const CMatlibVector<CComplex>& veccRx, 
+								 const CMatlibVector<CComplex>& veccB);
+
+
+/* Sinc-function */
+inline CReal			Sinc(const CReal& rI)
+							{return rI == (CReal) 0.0 ? (CReal) 1.0 : sin(crPi * rI) / (crPi * rI);}
+inline
+CMatlibVector<CReal>	Sinc(const CMatlibVector<CReal>& fvI)
+							{_VECOP(CReal, fvI.GetSize(), Sinc(fvI[i]));}
+
+
+/* My own functions --------------------------------------------------------- */
+/* Dominant eigenvector */
+CMatlibVector<CReal>	DomEig(const CMatlibMatrix<CReal>& rmI, const CReal rEpsilon = 1e-5);
+
+/* Linear regression */
+CReal					LinRegr(const CMatlibVector<CReal>& rvX, const CMatlibVector<CReal>& rvY);
+
+/* Lowpass filter design using windowing method */
+CMatlibVector<CReal>	FirLP(const CReal rNormBW,
+							  const CMatlibVector<CReal>& rvWin);
+
+/* Complex FIR filter with decimation */
+CMatlibVector<CComplex>	FirFiltDec(const CMatlibVector<CComplex>& cvB,
+								   const CMatlibVector<CComplex>& cvX,
+								   CMatlibVector<CComplex>& cvZ,
+								   const int iDecFact);
+
+/* Squared magnitude */
+inline CReal			SqMag(const CComplex& cI)
+							{return cI.real() * cI.real() + cI.imag() * cI.imag();}
+inline CReal			SqMag(const CReal& rI)
+							{return rI * rI;}
+inline
+CMatlibVector<CReal>	SqMag(const CMatlibVector<CComplex>& veccI)
+							{_VECOP(CReal, veccI.GetSize(), SqMag(veccI[i]));}
+inline
+CMatlibVector<CReal>	SqMag(const CMatlibVector<CReal>& vecrI)
+							{_VECOP(CReal, vecrI.GetSize(), SqMag(vecrI[i]));}
+
+/* One pole recursion (first order IIR)
+   y_n = lambda * y_{n - 1} + (1 - lambda) * x_n */
+inline void				IIR1(CReal& rY, const CReal& rX, const CReal rLambda)
+							{rY = rLambda * (rY - rX) + rX;}
+
+inline void				IIR1(CComplex& cY, const CComplex& cX, const CReal rLambda)
+							{cY = rLambda * (cY - cX) + cX;}
+
+inline void				IIR1(CMatlibVector<CReal>& rY,
+							 const CMatlibVector<CReal>& rX,
+							 const CReal rLambda)
+{
+	const int iSize = rY.GetSize();
+
+	for (int i = 0; i < iSize; i++)
+		IIR1(rY[i], rX[i], rLambda);
+}
+
+/* Two-sided one pole recursion */
+inline void				IIR1TwoSided(CReal& rY, const CReal& rX,
+									 const CReal rLamUp, const CReal rLamDown)
+							{rX > rY ? IIR1(rY, rX, rLamUp) : IIR1(rY, rX, rLamDown);}
+
+/* Get lambda for one-pole recursion from time constant */
+inline CReal			IIR1Lam(const CReal& rTau, const CReal& rFs)
+							{return exp((CReal) -1.0 / (rTau * rFs));}
+
+
+#endif	/* _MATLIB_SIGNAL_PROC_TOOLBOX_H_ */
diff --git a/src/matlib/MatlibStdToolbox.cpp b/src/matlib/MatlibStdToolbox.cpp
new file mode 100644
index 0000000..cc07678
--- /dev/null
+++ b/src/matlib/MatlibStdToolbox.cpp
@@ -0,0 +1,799 @@
+/******************************************************************************\
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *	c++ Mathematic Library (Matlib)
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "MatlibStdToolbox.h"
+#include "../GlobalDefinitions.h"
+
+/* The mutex need to be application wide,
+   only the execution routines are thread-safe */
+static CMutex* mutex = NULL;
+#define MUTEX_LOCK() mutex->Lock()
+#define MUTEX_UNLOCK() mutex->Unlock()
+
+# define PLANNER_FLAGS (FFTW_ESTIMATE | FFTW_DESTROY_INPUT)
+/* Warning: for testing purpose only */
+//# define PLANNER_FLAGS FFTW_EXHAUSTIVE
+
+
+/* Implementation *************************************************************/
+CReal Min(const CMatlibVector<CReal>& rvI)
+{
+	const int iSize = rvI.GetSize();
+	CReal rMinRet = rvI[0];
+	for (int i = 1; i < iSize; i++)
+	{
+		if (rvI[i] < rMinRet)
+			rMinRet = rvI[i];
+	}
+
+	return rMinRet;
+}
+
+void Min(CReal& rMinVal, int& iMinInd, const CMatlibVector<CReal>& rvI)
+{
+	const int iSize = rvI.GetSize();
+	rMinVal = rvI[0]; /* Init actual minimum value */
+	iMinInd = 0; /* Init index of minimum */
+	for (int i = 1; i < iSize; i++)
+	{
+		if (rvI[i] < rMinVal)
+		{
+			rMinVal = rvI[i];
+			iMinInd = i;
+		}
+	}
+}
+
+CReal Max(const CMatlibVector<CReal>& rvI)
+{
+	CReal rMaxRet;
+	int iMaxInd; /* Not used by this function */
+	Max(rMaxRet, iMaxInd, rvI);
+
+	return rMaxRet;
+}
+
+void Max(CReal& rMaxVal, int& iMaxInd, const CMatlibVector<CReal>& rvI)
+{
+	const int iSize = rvI.GetSize();
+	rMaxVal = rvI[0]; /* Init actual maximum value */
+	iMaxInd = 0; /* Init index of maximum */
+	for (int i = 1; i < iSize; i++)
+	{
+		if (rvI[i] > rMaxVal)
+		{
+			rMaxVal = rvI[i];
+			iMaxInd = i;
+		}
+	}
+}
+
+CMatlibVector<CReal> Sort(const CMatlibVector<CReal>& rvI)
+{
+	const int iSize = rvI.GetSize();
+	const int iEnd = iSize - 1;
+	CMatlibVector<CReal> fvRet(iSize, VTY_TEMP);
+
+	/* Copy input vector in output vector */
+	fvRet = rvI;
+
+	/* Loop through the array one less than its total cell count */
+	for (int i = 0; i < iEnd; i++)
+	{
+		/* Loop through every cell (value) in array */
+		for (int j = 0; j < iEnd; j++)
+		{
+			/* Compare the values and switch if necessary */
+			if (fvRet[j] > fvRet[j + 1])
+			{
+				const CReal rSwap = fvRet[j];
+				fvRet[j] = fvRet[j + 1];
+				fvRet[j + 1] = rSwap;
+			}
+		}
+	}
+
+	return fvRet;
+}
+
+CMatlibMatrix<CReal> Eye(const int iLen)
+{
+	CMatlibMatrix<CReal> matrRet(iLen, iLen, VTY_TEMP);
+
+	/* Set all values except of the diagonal to zero, diagonal entries = 1 */
+	for (int i = 0; i < iLen; i++)
+	{
+		for (int j = 0; j < iLen; j++)
+		{
+			if (i == j)
+				matrRet[i][j] = (CReal) 1.0;
+			else
+				matrRet[i][j] = (CReal) 0.0;
+		}
+	}
+
+	return matrRet;
+}
+
+CMatlibMatrix<CComplex> Diag(const CMatlibVector<CComplex>& cvI)
+{
+	const int iSize = cvI.GetSize();
+	CMatlibMatrix<CComplex> matcRet(iSize, iSize, VTY_TEMP);
+
+	/* Set the diagonal to the values of the input vector */
+	for (int i = 0; i < iSize; i++)
+	{
+		for (int j = 0; j < iSize; j++)
+		{
+			if (i == j)
+				matcRet[i][j] = cvI[i];
+			else
+				matcRet[i][j] = (CReal) 0.0;
+		}
+	}
+
+	return matcRet;
+}
+
+CReal Trace(const CMatlibMatrix<CReal>& rmI)
+{
+	const int iSize = rmI.GetRowSize(); /* matrix must be square */
+	CReal rReturn = (CReal) 0.0;
+
+	for (int i = 0; i < iSize; i++)
+		rReturn += rmI[i][i];
+
+	return rReturn;
+}
+
+CMatlibMatrix<CComplex> Toeplitz(const CMatlibVector<CComplex>& cvI)
+{
+	const int				iSize = cvI.GetSize();
+	CMatlibMatrix<CComplex>	matcRet(iSize, iSize, VTY_TEMP);
+
+	/* Create Toeplitz matrix */
+	for (int i = 0; i < iSize; i++)
+	{
+		for (int j = 0; j < iSize; j++)
+		{
+			if (i < j)
+				matcRet[i][j] = cvI[j - i];
+			else
+				matcRet[i][j] = Conj(cvI[i - j]);
+		}
+	}
+
+	return matcRet;
+}
+
+CMatlibMatrix<CComplex> Transp(const CMatlibMatrix<CComplex>& cmI)
+{
+	const int iRowSize = cmI.GetRowSize();
+	const int iColSize = cmI.GetColSize();
+
+	/* Swaped row and column size due to transpose operation */
+	CMatlibMatrix<CComplex> matcRet(iColSize, iRowSize, VTY_TEMP);
+
+	/* Transpose matrix */
+	for (int i = 0; i < iRowSize; i++)
+	{
+		for (int j = 0; j < iColSize; j++)
+			matcRet[j][i] = cmI[i][j];
+	}
+
+	return matcRet;
+}
+
+CMatlibMatrix<CComplex> Inv(const CMatlibMatrix<CComplex>& matrI)
+{
+/*
+	Parts of the following code are taken from Ptolemy
+	(http://ptolemy.eecs.berkeley.edu/)
+
+	The input matrix must be square, this is NOT checked here!
+*/
+	_COMPLEX	temp;
+	int			row, col, i;
+
+	const int iSize = matrI.GetColSize();
+	CMatlibMatrix<CComplex> matrRet(iSize, iSize, VTY_TEMP);
+
+	/* Make a working copy of input matrix */
+	CMatlibMatrix<CComplex> work(matrI);
+
+	/* Set result to be the identity matrix */
+	matrRet = Eye(iSize);
+
+	for (i = 0; i < iSize; i++) 
+	{
+		/* Check that the element in (i,i) is not zero */
+		if ((Real(work[i][i]) == 0) && (Imag(work[i][i]) == 0))
+		{
+			/* Swap with a row below this one that has a non-zero element
+			   in the same column */
+			for (row = i + 1; row < iSize; row++)
+			{
+				if ((Real(work[i][i]) != 0) || (Imag(work[i][i]) != 0))
+					break;
+			}
+
+// TEST
+if (row == iSize)
+{
+	fprintf(stderr, "couldn't invert matrix, possibly singular.\n");
+	matrRet = Eye(iSize);
+	return matrRet;
+}
+
+			/* Swap rows */
+			for (col = 0; col < iSize; col++)
+			{
+				temp = work[i][col];
+				work[i][col] = work[row][col];
+				work[row][col] = temp;
+				temp = matrRet[i][col];
+				matrRet[i][col] = matrRet[row][col];
+				matrRet[row][col] = temp;
+			}
+		}
+
+		/* Divide every element in the row by element (i,i) */
+		temp = work[i][i];
+		for (col = 0; col < iSize; col++)
+		{
+			work[i][col] /= temp;
+			matrRet[i][col] /= temp;
+		}
+
+		/* Zero out the rest of column i */
+		for (row = 0; row < iSize; row++)
+		{
+			if (row != i)
+			{
+				temp = work[row][i];
+				for (col = iSize - 1; col >= 0; col--)
+				{
+					work[row][col] -= (temp * work[i][col]);
+					matrRet[row][col] -= (temp * matrRet[i][col]);
+				}
+			}
+		}
+	}
+
+	return matrRet;
+}
+
+/* This function is not listed in the header file. It shall be used only for
+   Matlib internal calculations */
+CComplex _integral(MATLIB_CALLBACK_QAUD f, const CReal a, const CReal b,
+				   const CReal errorBound, CReal& integralBound,
+				   _BOOLEAN& integralError, const CReal ru)
+{
+/*
+	The following code (inclusive the actual Quad() function) is based on a
+	JavaScript Example written by Lucio Tavernini. The code is hosted at
+	http://tavernini.com/integral.shtml.
+
+	Description: Adaptive Simpson's Quadrature
+
+	_integral(f, a, b, errorBound) attempts to integrate f from
+	a to b while keeping the asymptotic error estimate below
+	errorBound using an adaptive implementation of Simpson's rule.
+
+	Notes: Instead of NaN we use _MAXREAL. Infinite bounds are not allowed! The
+	lower bound must always be smaller than the higher bound!
+*/
+
+	CReal		left, right, h, h6, bound;
+	CComplex	fa, fb, v1, v2, error, value;
+	int			m1, jend, mstart, j;
+
+	if (integralError)
+		return _MAXREAL; /* NaN */
+
+	/* Integrate over [a,b]. Initialize */
+	const int max = 1024;
+	CRealVector x(max);
+	CComplexVector f1(max);
+	CComplexVector f2(max);
+	CComplexVector f3(max);
+	CComplexVector v(max);
+
+	int step = 1;
+	int m = 1;
+	bound = errorBound;
+	value = 0;
+	h = b - a;
+	x[0] = a;
+	f1[0] = f(a);
+	f2[0] = f((CReal) 0.5 * (a + b));
+	f3[0] = f(b);
+	v[0] = h * (f1[0] + (CReal) 4.0 * f2[0] + f3[0]) / (CReal) 6.0;
+
+	do
+	{
+		/* Are we going to go forward or backward? */
+		if (step == -1)
+		{
+			/* Forward: j = m,...,max */
+			step = 1;
+			j = m + 1;
+			jend = max;
+			m = 0;
+			mstart = 0;
+		}
+		else
+		{
+			/* Backward: j = m,...,1 */
+			step = -1;
+			j = m - 1;
+			jend = -1;
+			m = max - 1;
+			mstart = max - 1;
+		}
+		
+		h = (CReal) 0.5 * h;
+		h6 = h / 6;
+		bound = (CReal) 0.5 * bound;
+		
+		do
+		{
+			left = x[j];
+			right = x[j] + (CReal) 0.5 * h;
+
+			/* Complete loss of significance? */
+			if (left >= right)
+			{
+				fprintf(stderr, "integral: Error 1\n");
+				return value;
+			}
+
+			fa = f(x[j] + (CReal) 0.5 * h);
+			fb = f(x[j] + (CReal) 1.5 * h);
+			v1 = h6 * (f1[j] + (CReal) 4.0 * fa + f2[j]);
+			v2 = h6 * (f2[j] + (CReal) 4.0 * fb + f3[j]);
+			error = (v[j] - v1 - v2) / (CReal) 15.0;
+
+			if ((Abs(error) <= bound) || (Abs(v1 + v2) < Abs(value) * ru))
+				value = ((v1 + v2) + value) - error;
+			else
+			{
+				if (integralError)
+					return _MAXREAL; /* NaN */
+				
+				/* Are we out of memory? */
+				if (m == j)
+				{
+					left = x[j];
+					right = x[j] + (CReal) 0.5 * h;
+
+					/* Complete loss of significance? */
+					if (left >= right)
+					{
+						fprintf(stderr, "integral: Error 2\n");
+						return value;
+					}
+
+					value += _integral(f, left, x[j] + 2 * h, bound,
+						integralBound, integralError, ru);
+				}
+				else 
+				{
+					/* No, we are not */
+					left = x[j];
+					right = x[j] + (CReal) 0.125 * h;
+
+					if (left >= right)
+					{
+						/* The error bound specified is too small! */
+						integralError = TRUE;
+						return _MAXREAL; /* NaN */
+					}
+
+					m1 = m + step;
+					x[m] = x[j];
+					x[m1] = x[j] + h;
+					v[m] = v1;
+					v[m1] = v2;
+					f1[m] = f1[j];
+					f2[m] = fa;
+					f3[m] = f2[j];
+					f1[m1] = f2[j];
+					f2[m1] = fb;
+					f3[m1] = f3[j];
+					m += 2 * step;
+				}
+			}
+			j += step;
+		}
+		while (j != jend);
+	}
+	while (m != mstart);
+
+	if (integralError)
+		return _MAXREAL; /* NaN */
+	else
+		return value;
+}
+
+CComplex Quad(MATLIB_CALLBACK_QAUD f, const CReal a, const CReal b,
+			  const CReal errorBound)
+{
+	/* Set globals */
+	/* Generate rounding unit */
+	CReal value;
+	CReal ru = (CReal) 1.0;
+	do
+	{
+		ru = (CReal) 0.5 * ru;
+		value = (CReal) 1.0 + ru;
+	}
+	while (value != (CReal) 1.0);
+
+	ru *= 2;
+
+	CReal integralBound = errorBound;
+	_BOOLEAN integralError = FALSE;
+
+	/* Compute */
+	return _integral(f, a, b, errorBound, integralBound, integralError, ru);
+}
+
+CMatlibVector<CComplex> Fft(const CMatlibVector<CComplex>& cvI,
+							CFftPlans& FftPlans)
+{
+	int				i;
+	fftw_complex*	pFftwComplexIn;
+	fftw_complex*	pFftwComplexOut;
+
+	const int				n(cvI.GetSize());
+
+	CMatlibVector<CComplex>	cvReturn(n, VTY_TEMP);
+
+	/* If input vector has zero length, return */
+	if (n == 0)
+		return cvReturn;
+
+	/* Init the plan */
+	FftPlans.Init(n, CFftPlans::FP_FFTPlForw);
+
+	pFftwComplexIn = FftPlans.pFftwComplexIn;
+	pFftwComplexOut = FftPlans.pFftwComplexOut;
+
+	/* fftw (Homepage: http://www.fftw.org/) */
+	for (i = 0; i < n; i++)
+	{
+		pFftwComplexIn[i][0] = cvI[i].real();
+		pFftwComplexIn[i][1] = cvI[i].imag();
+	}
+
+	/* Actual fftw call */
+	fftw_execute(FftPlans.FFTPlForw);
+
+	for (i = 0; i < n; i++)
+		cvReturn[i] = CComplex(pFftwComplexOut[i][0], pFftwComplexOut[i][1]);
+
+	return cvReturn;
+}
+
+CMatlibVector<CComplex> Ifft(const CMatlibVector<CComplex>& cvI,
+							 CFftPlans& FftPlans)
+{
+	int				i;
+	fftw_complex*	pFftwComplexIn;
+	fftw_complex*	pFftwComplexOut;
+
+	const int		n(cvI.GetSize());
+
+	CMatlibVector<CComplex>	cvReturn(n, VTY_TEMP);
+
+	/* If input vector has zero length, return */
+	if (n == 0)
+		return cvReturn;
+
+	/* Init the plan */
+	FftPlans.Init(n, CFftPlans::FP_FFTPlBackw);
+
+	pFftwComplexIn = FftPlans.pFftwComplexIn;
+	pFftwComplexOut = FftPlans.pFftwComplexOut;
+
+	/* fftw (Homepage: http://www.fftw.org/) */
+	for (i = 0; i < n; i++)
+	{
+		pFftwComplexIn[i][0] = cvI[i].real();
+		pFftwComplexIn[i][1] = cvI[i].imag();
+	}
+
+	/* Actual fftw call */
+	fftw_execute(FftPlans.FFTPlBackw);
+	
+	const CReal scale = (CReal) 1.0 / n;
+	for (i = 0; i < n; i++)
+	{
+		cvReturn[i] = CComplex(pFftwComplexOut[i][0] * scale,
+			pFftwComplexOut[i][1] * scale);
+	}
+
+	return cvReturn;
+}
+
+CMatlibVector<CComplex> rfft(const CMatlibVector<CReal>& fvI,
+							 CFftPlans& FftPlans)
+{
+	int			i;
+	double* 	pFftwRealIn;
+	double* 	pFftwRealOut;
+
+	const int	iSizeI = fvI.GetSize();
+	const int	iLongLength(iSizeI);
+	const int	iShortLength(iLongLength / 2);
+	const int	iUpRoundShortLength((iLongLength + 1) / 2);
+	
+	CMatlibVector<CComplex>	cvReturn(iShortLength
+		/* Include Nyquist frequency in case of even N */ + 1, VTY_TEMP);
+
+	/* If input vector has zero length, return */
+	if (iLongLength == 0)
+		return cvReturn;
+
+	/* Init the plan */
+	FftPlans.Init(iLongLength, CFftPlans::FP_RFFTPlForw);
+
+	pFftwRealIn = FftPlans.pFftwRealIn;
+	pFftwRealOut = FftPlans.pFftwRealOut;
+
+	/* fftw (Homepage: http://www.fftw.org/) */
+	for (i = 0; i < iSizeI; i++)
+		pFftwRealIn[i] = fvI[i];
+
+	/* Actual fftw call */
+	fftw_execute(FftPlans.RFFTPlForw);
+
+	/* Now build complex output vector */
+	/* Zero frequency */
+	cvReturn[0] = pFftwRealOut[0];
+	for (i = 1; i < iUpRoundShortLength; i++)
+		cvReturn[i] = CComplex(pFftwRealOut[i], pFftwRealOut[iLongLength - i]);
+
+	/* If N is even, include Nyquist frequency */
+	if ((iLongLength & 1) == 0)
+		cvReturn[iShortLength] = pFftwRealOut[iShortLength];
+
+	return cvReturn;
+}
+
+CMatlibVector<CReal> rifft(const CMatlibVector<CComplex>& cvI,
+						   CFftPlans& FftPlans)
+{
+/*
+	This function only works with EVEN N!
+*/
+	int			i;
+	double*		pFftwRealIn;
+	double*		pFftwRealOut;
+
+	const int	iShortLength(cvI.GetSize() - 1); /* Nyquist frequency! */
+	const int	iLongLength(iShortLength * 2);
+
+	CMatlibVector<CReal> fvReturn(iLongLength, VTY_TEMP);
+
+	/* If input vector is too short, return */
+	if (iShortLength <= 0)
+		return fvReturn;
+
+	/* Init the plan */
+	FftPlans.Init(iLongLength, CFftPlans::FP_RFFTPlBackw);
+
+	pFftwRealIn = FftPlans.pFftwRealIn;
+	pFftwRealOut = FftPlans.pFftwRealOut;
+
+	/* Now build half-complex-vector */
+	pFftwRealIn[0] = cvI[0].real();
+	for (i = 1; i < iShortLength; i++)
+	{
+		pFftwRealIn[i] = cvI[i].real();
+		pFftwRealIn[iLongLength - i] = cvI[i].imag();
+	}
+	/* Nyquist frequency */
+	pFftwRealIn[iShortLength] = cvI[iShortLength].real(); 
+
+	/* Actual fftw call */
+	fftw_execute(FftPlans.RFFTPlBackw);
+
+	/* Scale output vector */
+	const CReal scale = (CReal) 1.0 / iLongLength;
+	for (i = 0; i < iLongLength; i++) 
+		fvReturn[i] = pFftwRealOut[i] * scale;
+
+	return fvReturn;
+}
+
+CMatlibVector<CReal> FftFilt(const CMatlibVector<CComplex>& rvH,
+							 const CMatlibVector<CReal>& rvI,
+							 CMatlibVector<CReal>& rvZ,
+							 CFftPlans& FftPlans)
+{
+/*
+	This function only works with EVEN N!
+*/
+	const int				iL(rvH.GetSize() - 1); /* Nyquist frequency! */
+	const int				iL2(2 * iL);
+	CMatlibVector<CReal>	rvINew(iL2);
+	CMatlibVector<CReal>	rvOutTMP(iL2);
+
+	/* Init the plan */
+	FftPlans.Init(iL2);
+
+	/* Update history of input signal */
+	rvINew.Merge(rvZ, rvI);
+
+	rvOutTMP = rifft(rfft(rvINew, FftPlans) * rvH, FftPlans);
+
+	/* Save old input signal vector for next block */
+	rvZ = rvI;
+
+	/* Cut out correct samples (to get from cyclic convolution to linear
+	   convolution) */
+	return rvOutTMP(iL + 1, iL2);
+}
+
+
+/* FftPlans implementation -------------------------------------------------- */
+CFftPlans::CFftPlans(const int iFftSize) :
+	RFFTPlForw(NULL), RFFTPlBackw(NULL), pFftwRealIn(NULL), pFftwRealOut(NULL),
+	FFTPlForw(NULL), FFTPlBackw(NULL), pFftwComplexIn(NULL), pFftwComplexOut(NULL),
+	bInitialized(FALSE), bFixedSizeInit(FALSE), fftw_n(0)
+{
+	/* Static initialization of CMutex not working on Mac OS X */
+	if (!mutex)
+		mutex = new CMutex();
+
+	/* If iFftSize is non zero then proceed to initialization */
+	if (iFftSize)
+		Init(iFftSize);
+}
+
+CFftPlans::~CFftPlans()
+{
+	/* This one is obvious, no need to comment! */
+	Clean();
+}
+
+void CFftPlans::Init(const int iFSi, EFFTPlan eFFTPlan)
+{
+	/* Init some flags */
+	_BOOLEAN bNeedPlanInit = FALSE;
+	_BOOLEAN bSizeChanged = FALSE;
+
+	/* If Init(const int iFSi) as been previously called
+	   then the fft size can't be changed here
+	   (not reelly needed but keep the original behaviour) */
+	if (!bFixedSizeInit)
+		bSizeChanged = InitInternal(iFSi);
+
+	/* The fft size has changed so we don't need to check for plan init */
+	if (!bSizeChanged)
+	{
+		/* Check if the requested plan need an initialization */
+		switch (eFFTPlan)
+		{
+		case FP_RFFTPlForw:  bNeedPlanInit = !RFFTPlForw;  break;
+		case FP_RFFTPlBackw: bNeedPlanInit = !RFFTPlBackw; break;
+		case FP_FFTPlForw:   bNeedPlanInit = !FFTPlForw;   break;
+		case FP_FFTPlBackw:  bNeedPlanInit = !FFTPlBackw;  break;
+		}
+	}
+
+	/* The following fftw_ call might be cpu intensive, they must be called only when needed */
+	if (bSizeChanged || bNeedPlanInit)
+	{
+//		fprintf(stderr, "CFftPlans::Init() bSizeChanged=%i bNeedPlanInit=%i iFSi=%i fftw_n=%i\n", bSizeChanged, bNeedPlanInit, iFSi, fftw_n);
+		MUTEX_LOCK();
+		switch (eFFTPlan)
+		{
+		case FP_RFFTPlForw:
+			RFFTPlForw = fftw_plan_r2r_1d(fftw_n, pFftwRealIn, pFftwRealOut, FFTW_R2HC, PLANNER_FLAGS);
+			break;
+		case FP_RFFTPlBackw:
+			RFFTPlBackw = fftw_plan_r2r_1d(fftw_n, pFftwRealIn, pFftwRealOut, FFTW_HC2R, PLANNER_FLAGS);
+			break;
+		case FP_FFTPlForw:
+			FFTPlForw = fftw_plan_dft_1d(fftw_n, pFftwComplexIn, pFftwComplexOut, FFTW_FORWARD, PLANNER_FLAGS);
+			break;
+		case FP_FFTPlBackw:
+			FFTPlBackw = fftw_plan_dft_1d(fftw_n, pFftwComplexIn, pFftwComplexOut, FFTW_BACKWARD, PLANNER_FLAGS);
+			break;
+		}
+		MUTEX_UNLOCK();
+	}
+}
+
+void CFftPlans::Init(const int iFSi)
+{
+	/* The bFixedSizeInit flag isn't really needed,
+	   it only keep the original Init() behaviour */
+	bFixedSizeInit = TRUE;
+	InitInternal(iFSi);
+}
+
+_BOOLEAN CFftPlans::InitInternal(const int iFSi)
+{
+	if (bInitialized)
+	{
+		/* No change, so return */
+		if (fftw_n == iFSi)
+			return FALSE; /* The fft size is the same */
+
+		/* Delete old plans and intermediate buffers */
+		Clean();
+	}
+
+// TODO intermediate buffers should be created only when needed
+    /* Create new intermediate buffers */
+	pFftwRealIn = new double[iFSi];
+	pFftwRealOut = new double[iFSi];
+	pFftwComplexIn = new fftw_complex[iFSi];
+	pFftwComplexOut = new fftw_complex[iFSi];
+
+	fftw_n = iFSi;
+	bInitialized = TRUE;
+	return TRUE; /* The fft size has changed */
+}
+
+void CFftPlans::Clean()
+{
+	if (bInitialized)
+	{
+		/* Delete old plans and intermediate buffers */
+		MUTEX_LOCK();
+		if (RFFTPlForw)  fftw_destroy_plan(RFFTPlForw);
+		if (RFFTPlBackw) fftw_destroy_plan(RFFTPlBackw);
+		if (FFTPlForw)   fftw_destroy_plan(FFTPlForw);
+		if (FFTPlBackw)  fftw_destroy_plan(FFTPlBackw);
+		MUTEX_UNLOCK();
+
+		delete[] pFftwRealIn;
+		delete[] pFftwRealOut;
+		delete[] pFftwComplexIn;
+		delete[] pFftwComplexOut;
+
+		pFftwRealIn = NULL;
+		pFftwRealOut = NULL;
+		pFftwComplexIn = NULL;
+		pFftwComplexOut = NULL;
+
+		RFFTPlForw = NULL;
+		RFFTPlBackw = NULL;
+		FFTPlForw = NULL;
+		FFTPlBackw = NULL;
+
+		fftw_n = 0;
+
+		bInitialized = FALSE;
+	}
+}
+
diff --git a/src/matlib/MatlibStdToolbox.h b/src/matlib/MatlibStdToolbox.h
new file mode 100644
index 0000000..0878dc2
--- /dev/null
+++ b/src/matlib/MatlibStdToolbox.h
@@ -0,0 +1,294 @@
+/******************************************************************************\
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *	c++ Mathematic Library (Matlib), standard toolbox
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#ifndef _MATLIB_STD_TOOLBOX_H_
+#define _MATLIB_STD_TOOLBOX_H_
+
+#include "Matlib.h"
+
+/* fftw (Homepage: http://www.fftw.org) */
+#include <fftw3.h>
+
+/* Classes ********************************************************************/
+class CFftPlans
+{
+public:
+	CFftPlans(const int iFftSize = 0);
+	~CFftPlans();
+
+	enum EFFTPlan { FP_RFFTPlForw, FP_RFFTPlBackw, FP_FFTPlForw, FP_FFTPlBackw };
+
+	void Init(const int iFSi);
+	void Init(const int iFSi, EFFTPlan eFFTPlan);
+
+	fftw_plan	RFFTPlForw;
+	fftw_plan	RFFTPlBackw;
+	double*		pFftwRealIn;
+	double*		pFftwRealOut;
+	fftw_plan	FFTPlForw;
+	fftw_plan	FFTPlBackw;
+
+	fftw_complex*	pFftwComplexIn;
+	fftw_complex*	pFftwComplexOut;
+
+protected:
+	void			Clean();
+	_BOOLEAN		InitInternal(const int iFSi);
+	_BOOLEAN		bInitialized;
+	_BOOLEAN		bFixedSizeInit;
+	int				fftw_n;
+};
+
+
+/* Helpfunctions **************************************************************/
+inline CReal				Min(const CReal& rA, const CReal& rB)
+								{return rA < rB ? rA : rB;}
+inline CMatlibVector<CReal>	Min(const CMatlibVector<CReal>& rvA, const CMatlibVector<CReal>& rvB)
+								{_VECOP(CReal, rvA.GetSize(), Min(rvA[i], rvB[i]));}
+CReal						Min(const CMatlibVector<CReal>& rvI);
+void						Min(CReal& rMinVal /* out */, int& iMinInd /* out */,
+								const CMatlibVector<CReal>& rvI /* in */);
+
+inline CReal				Min(const CReal& r1, const CReal& r2, const CReal& r3, const CReal& r4)
+								{return Min(Min(Min(r1, r2), r3), r4);}
+inline CReal				Min(const CReal& r1, const CReal& r2, const CReal& r3, const CReal& r4,
+								const CReal& r5, const CReal& r6, const CReal& r7, const CReal& r8)
+								{return Min(Min(Min(Min(Min(Min(Min(r1, r2), r3), r4), r5), r6), r7), r8);}
+
+
+inline CReal				Max(const CReal& rA, const CReal& rB)
+								{return rA > rB ? rA : rB;}
+inline CMatlibVector<CReal>	Max(const CMatlibVector<CReal>& rvA, const CMatlibVector<CReal>& rvB)
+								{_VECOP(CReal, rvA.GetSize(), Max(rvA[i], rvB[i]));}
+CReal						Max(const CMatlibVector<CReal>& rvI);
+void						Max(CReal& rMaxVal /* out */, int& iMaxInd /* out */,
+								const CMatlibVector<CReal>& rvI /* in */);
+
+inline CReal				Max(const CReal& r1, const CReal& r2, const CReal& r3)
+								{return Max(Max(r1, r2), r3);}
+inline CReal				Max(const CReal& r1, const CReal& r2, const CReal& r3, const CReal& r4,
+								const CReal& r5, const CReal& r6, const CReal& r7)
+								{return Max(Max(Max(Max(Max(Max(r1, r2), r3), r4), r5), r6), r7);}
+
+
+inline CMatlibVector<CReal>	Ones(const int iLen)
+								{_VECOP(CReal, iLen, (CReal) 1.0);}
+inline CMatlibVector<CReal>	Zeros(const int iLen)
+								{_VECOP(CReal, iLen, (CReal) 0.0);}
+
+
+inline CReal				Real(const CComplex& cI) {return cI.real();}
+inline CMatlibVector<CReal>	Real(const CMatlibVector<CComplex>& cvI)
+								{_VECOP(CReal, cvI.GetSize(), Real(cvI[i]));}
+
+inline CReal				Imag(const CComplex& cI) {return cI.imag();}
+inline CMatlibVector<CReal>	Imag(const CMatlibVector<CComplex>& cvI)
+								{_VECOP(CReal, cvI.GetSize(), Imag(cvI[i]));}
+
+inline CComplex					Conj(const CComplex& cI) {return conj(cI);}
+inline CMatlibVector<CComplex>	Conj(const CMatlibVector<CComplex>& cvI)
+									{_VECOP(CComplex, cvI.GetSize(), Conj(cvI[i]));}
+inline CMatlibMatrix<CComplex>	Conj(const CMatlibMatrix<CComplex>& cmI)
+									{_MATOP(CComplex, cmI.GetRowSize(), cmI.GetColSize(), Conj(cmI[i]));}
+
+
+/* Absolute and angle (argument) functions */
+inline CReal				Abs(const CReal& rI) {return fabs(rI);}
+inline CMatlibVector<CReal>	Abs(const CMatlibVector<CReal>& fvI)
+								{_VECOP(CReal, fvI.GetSize(), Abs(fvI[i]));}
+
+inline CReal				Abs(const CComplex& cI) {return abs(cI);}
+inline CMatlibVector<CReal>	Abs(const CMatlibVector<CComplex>& cvI)
+								{_VECOP(CReal, cvI.GetSize(), Abs(cvI[i]));}
+
+inline CReal				Angle(const CComplex& cI) {return arg(cI);}
+inline CMatlibVector<CReal>	Angle(const CMatlibVector<CComplex>& cvI)
+								{_VECOP(CReal, cvI.GetSize(), Angle(cvI[i]));}
+
+
+/* Trigonometric functions */
+inline CReal				Sin(const CReal& fI) {return sin(fI);}
+template<class T> inline
+CMatlibVector<T>			Sin(const CMatlibVector<T>& vecI) 
+								{_VECOP(T, vecI.GetSize(), sin(vecI[i]));}
+
+inline CReal				Cos(const CReal& fI) {return cos(fI);}
+template<class T> inline
+CMatlibVector<T>			Cos(const CMatlibVector<T>& vecI)
+								{_VECOP(T, vecI.GetSize(), cos(vecI[i]));}
+
+inline CReal				Tan(const CReal& fI) {return tan(fI);}
+template<class T> inline
+CMatlibVector<T>			Tan(const CMatlibVector<T>& vecI)
+								{_VECOP(T, vecI.GetSize(), tan(vecI[i]));}
+
+inline CReal				Sinh(const CReal& fI) {return sinh(fI);}
+template<class T> inline
+CMatlibVector<T>			Sinh(const CMatlibVector<T>& vecI) 
+								{_VECOP(T, vecI.GetSize(), sinh(vecI[i]));}
+
+inline CReal				Cosh(const CReal& fI) {return cosh(fI);}
+template<class T> inline
+CMatlibVector<T>			Cosh(const CMatlibVector<T>& vecI)
+								{_VECOP(T, vecI.GetSize(), cosh(vecI[i]));}
+
+inline CReal				Tanh(const CReal& fI) {return tanh(fI);}
+template<class T> inline
+CMatlibVector<T>			Tanh(const CMatlibVector<T>& vecI)
+								{_VECOP(T, vecI.GetSize(), tanh(vecI[i]));}
+
+
+/* Square root */
+inline CReal				Sqrt(const CReal& fI) {return sqrt(fI);}
+template<class T> inline
+CMatlibVector<T>			Sqrt(const CMatlibVector<T>& vecI)
+								{_VECOP(T, vecI.GetSize(), sqrt(vecI[i]));}
+
+
+/* Exponential function */
+inline CReal				Exp(const CReal& fI) {return exp(fI);}
+template<class T> inline
+CMatlibVector<T>			Exp(const CMatlibVector<T>& vecI)
+								{_VECOP(T, vecI.GetSize(), exp(vecI[i]));}
+
+
+/* Logarithm */
+inline CReal				Log(const CReal& fI) {return log(fI);}
+template<class T> inline
+CMatlibVector<T>			Log(const CMatlibVector<T>& vecI)
+								{_VECOP(T, vecI.GetSize(), log(vecI[i]));}
+
+inline CReal				Log10(const CReal& fI) {return log10(fI);}
+template<class T> inline
+CMatlibVector<T>			Log10(const CMatlibVector<T>& vecI)
+								{_VECOP(T, vecI.GetSize(), log10(vecI[i]));}
+
+
+/* Mean, variance and standard deviation */
+template<class T> inline T	Mean(const CMatlibVector<T>& vecI)
+								{return Sum(vecI) / vecI.GetSize();}
+template<class T> inline T	Std(CMatlibVector<T>& vecI) 
+								{return Sqrt(Var(vecI));}
+template<class T> T			Var(const CMatlibVector<T>& vecI);
+
+
+/* Rounding functions */
+inline CReal				Fix(const CReal& fI) {return (int) fI;}
+inline CMatlibVector<CReal>	Fix(const CMatlibVector<CReal>& fvI)
+								{_VECOP(CReal, fvI.GetSize(), Fix(fvI[i]));}
+
+inline CReal				Floor(const CReal& fI) {return floor(fI);}
+inline CMatlibVector<CReal>	Floor(const CMatlibVector<CReal>& fvI)
+								{_VECOP(CReal, fvI.GetSize(), Floor(fvI[i]));}
+
+inline CReal				Ceil(const CReal& fI) {return ceil(fI);}
+inline CMatlibVector<CReal>	Ceil(const CMatlibVector<CReal>& fvI)
+								{_VECOP(CReal, fvI.GetSize(), Ceil(fvI[i]));}
+
+inline CReal				Round(const CReal& fI)
+								{return Floor(fI + (CReal) 0.5);}
+inline CMatlibVector<CReal>	Round(const CMatlibVector<CReal>& fvI)
+								{_VECOP(CReal, fvI.GetSize(), Round(fvI[i]));}
+
+inline CReal				Sign(const CReal& rI)
+								{return rI == 0 ? 0 : rI > 0 ? 1 : -1;}
+
+inline int					Mod(const int ix, const int iy)
+								{return ix < 0 ? (ix % iy + iy) % iy : ix % iy;}
+
+template<class T> T			Sum(const CMatlibVector<T>& vecI);
+
+CMatlibVector<CReal>		Sort(const CMatlibVector<CReal>& rvI);
+
+
+/* Matrix inverse */
+CMatlibMatrix<CComplex>		Inv(const CMatlibMatrix<CComplex>& matrI);
+
+/* Identity matrix */
+CMatlibMatrix<CReal>		Eye(const int iLen);
+
+CMatlibMatrix<CComplex>		Diag(const CMatlibVector<CComplex>& cvI);
+
+CReal						Trace(const CMatlibMatrix<CReal>& rmI);
+
+CMatlibMatrix<CComplex>		Toeplitz(const CMatlibVector<CComplex>& cvI);
+
+/* Matrix transpose */
+CMatlibMatrix<CComplex>		Transp(const CMatlibMatrix<CComplex>& cmI);
+inline
+CMatlibMatrix<CComplex>		TranspH(const CMatlibMatrix<CComplex>& cmI)
+								{return Conj(Transp(cmI));} /* With conjugate complex */
+
+/* Fourier transformations (also included: real FFT) */
+CMatlibVector<CComplex>		Fft(const CMatlibVector<CComplex>& cvI, CFftPlans& FftPlans);
+CMatlibVector<CComplex>		Ifft(const CMatlibVector<CComplex>& cvI, CFftPlans& FftPlans);
+CMatlibVector<CComplex>		rfft(const CMatlibVector<CReal>& fvI, CFftPlans& FftPlans);
+CMatlibVector<CReal>		rifft(const CMatlibVector<CComplex>& cvI, CFftPlans& FftPlans);
+
+CMatlibVector<CReal>		FftFilt(const CMatlibVector<CComplex>& rvH,
+									const CMatlibVector<CReal>& rvI,
+									CMatlibVector<CReal>& rvZ,
+									CFftPlans& FftPlans);
+
+
+/* Numerical integration */
+typedef CComplex(MATLIB_CALLBACK_QAUD)(CReal rX); /* Callback function definition */
+CComplex					Quad(MATLIB_CALLBACK_QAUD f, const CReal a,
+								 const CReal b, const CReal errorBound = 1.e-6);
+
+
+/* Implementation **************************************************************
+   (the implementation of template classes must be in the header file!) */
+template<class T> inline
+T Sum(const CMatlibVector<T>& vecI)
+{
+	const int iSize = vecI.GetSize();
+	T SumRet = 0;
+	for (int i = 0; i < iSize; i++)
+		SumRet += vecI[i];
+
+	return SumRet;
+}
+
+template<class T> inline
+T Var(const CMatlibVector<T>& vecI)
+{
+	const int iSize = vecI.GetSize();
+
+	/* First calculate mean */
+	T tMean = Mean(vecI);
+
+	/* Now variance (sum formula) */
+	T tRet = 0;
+	for (int i = 0; i < iSize; i++)
+		tRet += (vecI[i] - tMean) * (vecI[i] - tMean);
+
+	return tRet / (iSize - 1); /* Normalizing */
+}
+
+
+#endif	/* _MATLIB_STD_TOOLBOX_H_ */
diff --git a/src/mlc/BitInterleaver.cpp b/src/mlc/BitInterleaver.cpp
new file mode 100644
index 0000000..d8621e6
--- /dev/null
+++ b/src/mlc/BitInterleaver.cpp
@@ -0,0 +1,145 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *
+ * The two parts with different protection levels shall not overlap in the
+ * interleaving process. Therefore the interleaved lower protected part shall
+ * be appended to the interleaved higher protected part.
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "BitInterleaver.h"
+
+
+/* Implementation *************************************************************/
+/******************************************************************************\
+* Bit interleaver															   *
+\******************************************************************************/
+void CBitInterleaver::Interleave(CVector<_DECISION>& InputData)
+{
+    int i;
+
+    /* Block 1 -------------------------------------------------------------- */
+    /* Interleave data according the interleaver table */
+    for (i = 0; i < ix_in1; i++)
+        vecInterlMemory1[i] = InputData[veciIntTable1[i]];
+
+    /* Copy result in input-vector */
+    for (i = 0; i < ix_in1; i++)
+        InputData[i] = vecInterlMemory1[i];
+
+    /* Block 2 -------------------------------------------------------------- */
+    /* Interleave data according the interleaver table */
+    for (i = 0; i < ix_in2; i++)
+        vecInterlMemory2[i] = InputData[veciIntTable2[i] + ix_in1];
+
+    /* Copy result in input-vector */
+    for (i = 0; i < ix_in2; i++)
+        InputData[i + ix_in1] = vecInterlMemory2[i];
+}
+
+void CBitInterleaver::Init(int iNewx_in1, int iNewx_in2, int it_0)
+{
+    /* Set internal parameters */
+    ix_in1 = iNewx_in1;
+    ix_in2 = iNewx_in2;
+
+    /* ix_in1 can be 0 but ix_in2 is always greater than "0" */
+    if (ix_in1 > 0)
+    {
+        /* Allocate memory for table */
+        veciIntTable1.Init(ix_in1);
+
+        /* Make interleaver table */
+        MakeTable(veciIntTable1, ix_in1, it_0);
+
+        /* Allocate memory for interleaver */
+        vecInterlMemory1.Init(ix_in1);
+    }
+
+    /* Allocate memory for table */
+    veciIntTable2.Init(ix_in2);
+
+    /* Make interleaver table */
+    MakeTable(veciIntTable2, ix_in2, it_0);
+
+    /* Allocate memory for interleaver */
+    vecInterlMemory2.Init(ix_in2);
+}
+
+
+/******************************************************************************\
+* Bit deinterleaver															   *
+\******************************************************************************/
+void CBitDeinterleaver::Deinterleave(CVector<CDistance>& vecInput)
+{
+    int i;
+
+    /* Block 1 -------------------------------------------------------------- */
+    /* Deinterleave data according the deinterleaver table */
+    for (i = 0; i < ix_in1; i++)
+        vecDeinterlMemory1[veciIntTable1[i]] = vecInput[i];
+
+    /* Copy result in input-vector */
+    for (i = 0; i < ix_in1; i++)
+        vecInput[i] = vecDeinterlMemory1[i];
+
+    /* Block 2 -------------------------------------------------------------- */
+    /* Deinterleave data according the deinterleaver table */
+    for (i = 0; i < ix_in2; i++)
+        vecDeinterlMemory2[veciIntTable2[i]] = vecInput[i + ix_in1];
+
+    /* Copy result in input-vector */
+    for (i = 0; i < ix_in2; i++)
+        vecInput[i + ix_in1] = vecDeinterlMemory2[i];
+}
+
+void CBitDeinterleaver::Init(int iNewx_in1, int iNewx_in2, int it_0)
+{
+    /* Set internal parameters */
+    ix_in1 = iNewx_in1;
+    ix_in2 = iNewx_in2;
+
+    /* ix_in1 can be 0 but ix_in2 is always greater than "0" */
+    if (ix_in1 > 0)
+    {
+        /* Allocate memory for table */
+        veciIntTable1.Init(ix_in1);
+
+        /* Make interleaver table */
+        MakeTable(veciIntTable1, ix_in1, it_0);
+
+        /* Allocate memory for interleaver */
+        vecDeinterlMemory1.Init(ix_in1);
+    }
+
+    /* Allocate memory for table */
+    veciIntTable2.Init(ix_in2);
+
+    /* Make interleaver table */
+    MakeTable(veciIntTable2, ix_in2, it_0);
+
+    /* Allocate memory for interleaver */
+    vecDeinterlMemory2.Init(ix_in2);
+}
diff --git a/src/mlc/BitInterleaver.h b/src/mlc/BitInterleaver.h
new file mode 100644
index 0000000..5c86841
--- /dev/null
+++ b/src/mlc/BitInterleaver.h
@@ -0,0 +1,75 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#if !defined(BIT_INTERLEAVER_H__3B0BA660_CA63_4344_BB2B_23E7A0D31912__INCLUDED_)
+#define BIT_INTERLEAVER_H__3B0BA660_CA63_4344_BB2B_23E7A0D31912__INCLUDED_
+
+#include "../GlobalDefinitions.h"
+#include "../interleaver/BlockInterleaver.h"
+#include "../util/Vector.h"
+
+
+/* Classes ********************************************************************/
+class CBitInterleaver: public CBlockInterleaver
+{
+public:
+    CBitInterleaver() {}
+    virtual ~CBitInterleaver() {}
+
+    void Init(int iNewx_in1, int iNewx_in2, int it_0);
+    void Interleave(CVector<_DECISION>& InputData);
+
+protected:
+    int					ix_in1;
+    int					ix_in2;
+    CVector<int>		veciIntTable1;
+    CVector<int>		veciIntTable2;
+    CVector<_DECISION>	vecInterlMemory1;
+    CVector<_DECISION>	vecInterlMemory2;
+};
+
+class CBitDeinterleaver: public CBlockInterleaver
+{
+public:
+    CBitDeinterleaver() {}
+    virtual ~CBitDeinterleaver() {}
+
+    void Init(int iNewx_in1, int iNewx_in2, int it_0);
+    void Deinterleave(CVector<CDistance>& vecInput);
+
+protected:
+    int					ix_in1;
+    int					ix_in2;
+    CVector<int>		veciIntTable1;
+    CVector<int>		veciIntTable2;
+    CVector<CDistance>	vecDeinterlMemory1;
+    CVector<CDistance>	vecDeinterlMemory2;
+};
+
+
+#endif // !defined(BIT_INTERLEAVER_H__3B0BA660_CA63_4344_BB2B_23E7A0D31912__INCLUDED_)
diff --git a/src/mlc/ChannelCode.cpp b/src/mlc/ChannelCode.cpp
new file mode 100644
index 0000000..cc1f379
--- /dev/null
+++ b/src/mlc/ChannelCode.cpp
@@ -0,0 +1,189 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "ChannelCode.h"
+
+
+/* Implementation *************************************************************/
+CVector<int> CChannelCode::GenPuncPatTable(ECodScheme eNewCodingScheme,
+        EChanType eNewChannelType,
+        int iN1, int iN2,
+        int iNewNumOutBitsPartA,
+        int iNewNumOutBitsPartB,
+        int iPunctPatPartA, int iPunctPatPartB,
+        int iLevel)
+{
+    int				i;
+    int				iNumOutBits;
+    int				iNumOutBitsWithMemory;
+    int				iTailbitPattern;
+    int				iTailbitParamL0;
+    int				iTailbitParamL1;
+    int				iPartAPatLen;
+    int				iPartBPatLen;
+    int				iPunctCounter;
+    CVector<int>	veciPuncPatPartA;
+    CVector<int>	veciPuncPatPartB;
+    CVector<int>	veciTailBitPat;
+    CVector<int>	veciReturn;
+
+    /* Number of bits out is the sum of all protection levels */
+    iNumOutBits = iNewNumOutBitsPartA + iNewNumOutBitsPartB;
+
+    /* Number of out bits including the state memory */
+    iNumOutBitsWithMemory = iNumOutBits + MC_CONSTRAINT_LENGTH - 1;
+
+    /* Init vector, storing table for puncturing pattern */
+    veciReturn.Init(iNumOutBitsWithMemory);
+
+
+    /* Set tail-bit pattern ------------------------------------------------- */
+    /* We have to consider two cases because in HSYM "N1 + N2" is used
+       instead of only "N2" to calculate the tailbit pattern */
+    switch (eNewCodingScheme)
+    {
+    case CS_3_HMMIX:
+        iTailbitParamL0 = iN1 + iN2;
+        iTailbitParamL1 = iN2;
+        break;
+
+    case CS_3_HMSYM:
+        iTailbitParamL0 = 2 * (iN1 + iN2);
+        iTailbitParamL1 = 2 * iN2;
+        break;
+
+    default:
+        iTailbitParamL0 = 2 * iN2;
+        iTailbitParamL1 = 2 * iN2;
+    }
+
+    /* Tailbit pattern calculated according DRM-standard. We have to consider
+       two cases because in HSYM "N1 + N2" is used instead of only "N2" */
+    if (iLevel == 0)
+        iTailbitPattern =
+            iTailbitParamL0 - 12 - iPuncturingPatterns[iPunctPatPartB][1] *
+            (int) ((iTailbitParamL0 - 12) /
+                   iPuncturingPatterns[iPunctPatPartB][1]);
+    else
+        iTailbitPattern =
+            iTailbitParamL1 - 12 - iPuncturingPatterns[iPunctPatPartB][1] *
+            (int) ((iTailbitParamL1 - 12) /
+                   iPuncturingPatterns[iPunctPatPartB][1]);
+
+
+    /* Set puncturing bit patterns and lengths ------------------------------ */
+    /* Lengths */
+    iPartAPatLen = iPuncturingPatterns[iPunctPatPartA][0];
+    iPartBPatLen = iPuncturingPatterns[iPunctPatPartB][0];
+
+    /* Vector, storing patterns for part A. Patterns begin at [][2 + x] */
+    veciPuncPatPartA.Init(iPartAPatLen);
+    for (i = 0; i < iPartAPatLen; i++)
+        veciPuncPatPartA[i] = iPuncturingPatterns[iPunctPatPartA][2 + i];
+
+    /* Vector, storing patterns for part B. Patterns begin at [][2 + x] */
+    veciPuncPatPartB.Init(iPartBPatLen);
+    for (i = 0; i < iPartBPatLen; i++)
+        veciPuncPatPartB[i] = iPuncturingPatterns[iPunctPatPartB][2 + i];
+
+    /* Vector, storing patterns for tailbit pattern */
+    veciTailBitPat.Init(LENGTH_TAIL_BIT_PAT);
+    for (i = 0; i < LENGTH_TAIL_BIT_PAT; i++)
+        veciTailBitPat[i] = iPunctPatTailbits[iTailbitPattern][i];
+
+
+    /* Generate actual table for puncturing pattern ------------------------- */
+    /* Reset counter for puncturing */
+    iPunctCounter = 0;
+
+    for (i = 0; i < iNumOutBitsWithMemory; i++)
+    {
+        if (i < iNewNumOutBitsPartA)
+        {
+            /* Puncturing patterns part A */
+            /* Get current pattern */
+            veciReturn[i] = veciPuncPatPartA[iPunctCounter];
+
+            /* Increment index and take care of wrap around */
+            iPunctCounter++;
+            if (iPunctCounter == iPartAPatLen)
+                iPunctCounter = 0;
+        }
+        else
+        {
+            /* In case of FAC do not use special tailbit-pattern! */
+            if ((i < iNumOutBits) || (eNewChannelType == CT_FAC))
+            {
+                /* Puncturing patterns part B */
+                /* Reset counter when beginning of part B is reached */
+                if (i == iNewNumOutBitsPartA)
+                    iPunctCounter = 0;
+
+                /* Get current pattern */
+                veciReturn[i] = veciPuncPatPartB[iPunctCounter];
+
+                /* Increment index and take care of wrap around */
+                iPunctCounter++;
+                if (iPunctCounter == iPartBPatLen)
+                    iPunctCounter = 0;
+            }
+            else
+            {
+                /* Tailbits */
+                /* Check when tailbit pattern starts */
+                if (i == iNumOutBits)
+                    iPunctCounter = 0;
+
+                /* Set tailbit pattern */
+                veciReturn[i] = veciTailBitPat[iPunctCounter];
+
+                /* No test for wrap around needed, since there ist only one
+                   cycle of this pattern */
+                iPunctCounter++;
+            }
+        }
+    }
+
+    return veciReturn;
+}
+
+CChannelCode::CChannelCode()
+{
+    /* Create table for parity bit */
+    for (int j = 0; j < 1 << SIZEOF__BYTE; j++)
+    {
+        /* XOR all bits in byResult.
+           We observe always the LSB by masking using operator "& 1". To get
+           access to all bits in "byResult" we shift the current bit so long
+           until it reaches the mask (at zero) by using operator ">> i". The
+           actual XOR operation is done by "^=" */
+        vecbiParity[j] = 0;
+        for (int i = 0; i < MC_CONSTRAINT_LENGTH; i++)
+            vecbiParity[j] ^= (j >> i) & 1;
+    }
+}
diff --git a/src/mlc/ChannelCode.h b/src/mlc/ChannelCode.h
new file mode 100644
index 0000000..a5cd9b1
--- /dev/null
+++ b/src/mlc/ChannelCode.h
@@ -0,0 +1,70 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#if !defined(CHANNEL_CODE_H__3B0BA660_CA63345347A0D31912__INCLUDED_)
+#define CHANNEL_CODE_H__3B0BA660_CA63345347A0D31912__INCLUDED_
+
+#include "../GlobalDefinitions.h"
+#include "../tables/TableMLC.h"
+#include "../util/Vector.h"
+#include "../Parameter.h"
+
+
+/* Classes ********************************************************************/
+class CChannelCode
+{
+public:
+    CChannelCode();
+    virtual ~CChannelCode() {}
+
+    inline _BINARY Convolution(const _BYTE byNewStateShiftReg,
+                               const int iGenPolyn) const
+    {
+        /* Mask bits with generator polynomial and get convolution result from
+           pre-calculated table (speed optimization). Since we have a AND
+           operation on the "byGeneratorMatrix", the index of the convolution
+           table cannot exceed the size of the table (although the value in
+           "byNewStateShiftReg" can be larger) */
+        return vecbiParity[byNewStateShiftReg & byGeneratorMatrix[iGenPolyn]];
+    }
+
+    CVector<int> GenPuncPatTable(ECodScheme eNewCodingScheme,
+                                 EChanType eNewChannelType,
+                                 int iN1, int iN2,
+                                 int iNewNumOutBitsPartA,
+                                 int iNewNumOutBitsPartB,
+                                 int iPunctPatPartA, int iPunctPatPartB,
+                                 int iLevel);
+
+
+private:
+    _BINARY vecbiParity[1 << SIZEOF__BYTE];
+};
+
+
+#endif // !defined(CHANNEL_CODE_H__3B0BA660_CA63345347A0D31912__INCLUDED_)
diff --git a/src/mlc/ConvEncoder.cpp b/src/mlc/ConvEncoder.cpp
new file mode 100644
index 0000000..a4d621c
--- /dev/null
+++ b/src/mlc/ConvEncoder.cpp
@@ -0,0 +1,236 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *
+ *	Note: We always shift the bits towards the MSB
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "ConvEncoder.h"
+
+
+/* Implementation *************************************************************/
+int CConvEncoder::Encode(CVector<_DECISION>& vecInputData,
+                         CVector<_DECISION>& vecOutputData)
+{
+    /* Set output size to zero, increment it each time a new bit is encoded */
+    int iOutputCnt = 0;
+
+    /* Reset counter for puncturing and state-register */
+    _BYTE byStateShiftReg = 0;
+#ifdef USE_MAX_LOG_MAP
+    /* We know the initial state of the shift registers, therefore a very
+       high soft information value */
+    vecStateMem.Reset(ML_SOFT_INF_MAX_VALUE);
+#endif
+
+    for (int i = 0; i < iNumInBitsWithMemory; i++)
+    {
+        /* Update shift-register (state information) ------------------------ */
+        /* Shift bits in state-shift-register */
+        byStateShiftReg <<= 1;
+
+        /* Tailbits are calculated in this loop. Check when end of vector is
+           reached and no more bits must be added */
+        if (i < iNumInBits)
+        {
+            /* Add new bit at the beginning */
+            if (ExtractBit(vecInputData[i]) != 0)
+                byStateShiftReg |= 1;
+
+#ifdef USE_MAX_LOG_MAP
+            /* Update shift register for soft information. We assume here that
+               the decision type is some floating point type -> we use
+               fabs() function */
+            vecStateMem.AddBegin(fabs(vecInputData[i]));
+#endif
+        }
+
+
+        /* Puncturing ------------------------------------------------------- */
+        /* Depending on the current puncturing pattern, different numbers of
+           output bits are generated. The state shift register "byStateShiftReg"
+           is convoluted with the respective patterns for this bit (is done
+           inside the convolution function) */
+#ifdef USE_MAX_LOG_MAP
+        switch (veciTablePuncPat[i])
+        {
+        case PP_TYPE_0001:
+            /* Pattern 0001 */
+            vecOutputData[iOutputCnt++] =
+                SoftConvolution(byStateShiftReg, vecStateMem, 0);
+            break;
+
+        case PP_TYPE_0101:
+            /* Pattern 0101 */
+            vecOutputData[iOutputCnt++] =
+                SoftConvolution(byStateShiftReg, vecStateMem, 0);
+
+            vecOutputData[iOutputCnt++] =
+                SoftConvolution(byStateShiftReg, vecStateMem, 2);
+            break;
+
+        case PP_TYPE_0011:
+            /* Pattern 0011 */
+            vecOutputData[iOutputCnt++] =
+                SoftConvolution(byStateShiftReg, vecStateMem, 0);
+
+            vecOutputData[iOutputCnt++] =
+                SoftConvolution(byStateShiftReg, vecStateMem, 1);
+            break;
+
+        case PP_TYPE_0111:
+            /* Pattern 0111 */
+            vecOutputData[iOutputCnt++] =
+                SoftConvolution(byStateShiftReg, vecStateMem, 0);
+
+            vecOutputData[iOutputCnt++] =
+                SoftConvolution(byStateShiftReg, vecStateMem, 1);
+
+            vecOutputData[iOutputCnt++] =
+                SoftConvolution(byStateShiftReg, vecStateMem, 2);
+            break;
+
+        case PP_TYPE_1111:
+            /* Pattern 1111 */
+            vecOutputData[iOutputCnt++] =
+                SoftConvolution(byStateShiftReg, vecStateMem, 0);
+
+            vecOutputData[iOutputCnt++] =
+                SoftConvolution(byStateShiftReg, vecStateMem, 1);
+
+            vecOutputData[iOutputCnt++] =
+                SoftConvolution(byStateShiftReg, vecStateMem, 2);
+
+            vecOutputData[iOutputCnt++] =
+                SoftConvolution(byStateShiftReg, vecStateMem, 3);
+            break;
+        }
+#else
+        switch (veciTablePuncPat[i])
+        {
+        case PP_TYPE_0001:
+            /* Pattern 0001 */
+            vecOutputData[iOutputCnt++] = Convolution(byStateShiftReg, 0);
+            break;
+
+        case PP_TYPE_0101:
+            /* Pattern 0101 */
+            vecOutputData[iOutputCnt++] = Convolution(byStateShiftReg, 0);
+            vecOutputData[iOutputCnt++] = Convolution(byStateShiftReg, 2);
+            break;
+
+        case PP_TYPE_0011:
+            /* Pattern 0011 */
+            vecOutputData[iOutputCnt++] = Convolution(byStateShiftReg, 0);
+            vecOutputData[iOutputCnt++] = Convolution(byStateShiftReg, 1);
+            break;
+
+        case PP_TYPE_0111:
+            /* Pattern 0111 */
+            vecOutputData[iOutputCnt++] = Convolution(byStateShiftReg, 0);
+            vecOutputData[iOutputCnt++] = Convolution(byStateShiftReg, 1);
+            vecOutputData[iOutputCnt++] = Convolution(byStateShiftReg, 2);
+            break;
+
+        case PP_TYPE_1111:
+            /* Pattern 1111 */
+            vecOutputData[iOutputCnt++] = Convolution(byStateShiftReg, 0);
+            vecOutputData[iOutputCnt++] = Convolution(byStateShiftReg, 1);
+            vecOutputData[iOutputCnt++] = Convolution(byStateShiftReg, 2);
+            vecOutputData[iOutputCnt++] = Convolution(byStateShiftReg, 3);
+            break;
+        }
+#endif
+    }
+
+    /* Return number of encoded bits */
+    return iOutputCnt;
+}
+
+#ifdef USE_MAX_LOG_MAP
+_DECISION CConvEncoder::SoftConvolution(const _BYTE byNewStateShiftReg,
+                                        CShiftRegister<_DECISION>& vecStateMem,
+                                        const int iGenPolyn)
+{
+    _DECISION decSoftOut;
+
+    /* Search for minimum norm value of input soft-informations.
+       Here we implement the convolution of the soft information independent of
+       the poylnoms stored in "byGeneratorMatrix[]"! When changing the polynoms,
+       it has to be changed here, too */
+    switch (iGenPolyn)
+    {
+    case 0:
+    case 3:
+        /* oct: 0155 -> 1101101 */
+        decSoftOut = Min(Min(Min(Min(vecStateMem[0], vecStateMem[2]),
+                                 vecStateMem[3]), vecStateMem[5]), vecStateMem[6]);
+        break;
+
+    case 1:
+        /* oct: 0117 -> 1001111 */
+        decSoftOut = Min(Min(Min(Min(vecStateMem[0], vecStateMem[1]),
+                                 vecStateMem[2]), vecStateMem[3]), vecStateMem[6]);
+        break;
+
+    case 2:
+        /* oct: 0123 -> 1010011 */
+        decSoftOut = Min(Min(Min(vecStateMem[0], vecStateMem[1]),
+                             vecStateMem[4]), vecStateMem[6]);
+        break;
+    }
+
+    /* Hard decision defines the sign, the norm is defined by the minimum of
+       input norms of soft informations using max-log approximation */
+    if (Convolution(byNewStateShiftReg, iGenPolyn) == 0)
+        return -decSoftOut;
+    else
+        return decSoftOut;
+}
+#endif
+
+void CConvEncoder::Init(ECodScheme eNewCodingScheme,
+                        EChanType eNewChannelType, int iN1,
+                        int iN2, int iNewNumInBitsPartA,
+                        int iNewNumInBitsPartB, int iPunctPatPartA,
+                        int iPunctPatPartB, int iLevel)
+{
+    /* Number of bits out is the sum of all protection levels */
+    iNumInBits = iNewNumInBitsPartA + iNewNumInBitsPartB;
+
+    /* Number of out bits including the state memory */
+    iNumInBitsWithMemory = iNumInBits + MC_CONSTRAINT_LENGTH - 1;
+
+    /* Init vector, storing table for puncturing pattern and generate pattern */
+    veciTablePuncPat.Init(iNumInBitsWithMemory);
+
+    veciTablePuncPat = GenPuncPatTable(eNewCodingScheme, eNewChannelType, iN1,
+                                       iN2, iNewNumInBitsPartA, iNewNumInBitsPartB, iPunctPatPartA,
+                                       iPunctPatPartB, iLevel);
+
+#ifdef USE_MAX_LOG_MAP
+    vecStateMem.Init(MC_CONSTRAINT_LENGTH);
+#endif
+}
diff --git a/src/mlc/ConvEncoder.h b/src/mlc/ConvEncoder.h
new file mode 100644
index 0000000..e1be55f
--- /dev/null
+++ b/src/mlc/ConvEncoder.h
@@ -0,0 +1,71 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#if !defined(CONNVOL_ENC_H__3B0BA660_CA63_4344_BB2B_23E7A0D31912__INCLUDED_)
+#define CONNVOL_ENC_H__3B0BA660_CA63_4344_BB2B_23E7A0D31912__INCLUDED_
+
+#include "../GlobalDefinitions.h"
+#include "../tables/TableMLC.h"
+#include "../util/Vector.h"
+#include "../Parameter.h"
+#include "ChannelCode.h"
+
+
+/* Classes ********************************************************************/
+class CConvEncoder : public CChannelCode
+{
+public:
+    CConvEncoder() {}
+    virtual ~CConvEncoder() {}
+
+    int		Encode(CVector<_DECISION>& vecInputData,
+                CVector<_DECISION>& vecOutputData);
+
+    void	Init(ECodScheme eNewCodingScheme, EChanType eNewChannelType,
+              int iN1, int iN2, int iNewNumInBitsPartA,
+              int iNewNumInBitsPartB, int iPunctPatPartA, int iPunctPatPartB,
+              int iLevel);
+
+protected:
+    int						iNumInBits;
+    int						iNumInBitsWithMemory;
+
+    CVector<int>			veciTablePuncPat;
+
+    EChanType	eChannelType;
+
+#ifdef USE_MAX_LOG_MAP
+    CShiftRegister<_DECISION>	vecStateMem;
+    _DECISION SoftConvolution(const _BYTE byNewStateShiftReg,
+                              CShiftRegister<_DECISION>& vecStateMem,
+                              const int iGenPolyn);
+#endif
+};
+
+
+#endif // !defined(CONNVOL_ENC_H__3B0BA660_CA63_4344_BB2B_23E7A0D31912__INCLUDED_)
diff --git a/src/mlc/EnergyDispersal.cpp b/src/mlc/EnergyDispersal.cpp
new file mode 100644
index 0000000..b4837da
--- /dev/null
+++ b/src/mlc/EnergyDispersal.cpp
@@ -0,0 +1,90 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *
+ * Note:
+ * Input data stream is divided into a regluar stream and the VSPP stream.
+ * Both stream are treated independently. The respective positions of the
+ * two streams are requested in the init-routine.
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "EnergyDispersal.h"
+
+
+/* Implementation *************************************************************/
+void CEngergyDispersal::ProcessData(CVector<_BINARY>* pbiData)
+{
+    int			i;
+    uint32_t	iTempShiftRegister;
+    _BINARY		biPRBSbit;
+
+    /* Init shift register and set all registers to "1" with bit-wise
+       not-operation */
+    iShiftRegisterSPP = ~uint32_t(0);
+    iShiftRegisterVSPP = ~uint32_t(0);
+
+    /* Main routine */
+    for (i = 0; i < iNumInBits; i++)
+    {
+        if (i < iEndIndVSPP)
+        {
+            /* Calculate new PRBS bit */
+            iTempShiftRegister = iShiftRegisterVSPP;
+
+            /* P(X) = X^9 + X^5 + 1,
+               in this implementation we have to shift n-1! */
+            biPRBSbit = _BINARY(((iTempShiftRegister >> 4) & 1) ^
+                                ((iTempShiftRegister >> 8) & 1));
+
+            /* Shift bits in shift register and add new bit */
+            iShiftRegisterVSPP <<= 1;
+            iShiftRegisterVSPP |= (biPRBSbit & 1);
+        }
+        else
+        {
+            /* Calculate new PRBS bit */
+            iTempShiftRegister = iShiftRegisterSPP;
+
+            /* P(X) = X^9 + X^5 + 1,
+               in this implementation we have to shift n-1! */
+            biPRBSbit = _BINARY(((iTempShiftRegister >> 4) & 1) ^
+                                ((iTempShiftRegister >> 8) & 1));
+
+            /* Shift bits in shift register and add new bit */
+            iShiftRegisterSPP <<= 1;
+            iShiftRegisterSPP |= (biPRBSbit & 1);
+        }
+
+        /* Apply PRBS to the data-stream */
+        (*pbiData)[i] ^= biPRBSbit;
+    }
+}
+
+void CEngergyDispersal::Init(int iNewNumInBits, int iNewLengthVSPP)
+{
+    /* Set the internal parameters */
+    iNumInBits = iNewNumInBits;
+    iEndIndVSPP = iNewLengthVSPP;
+}
diff --git a/src/mlc/EnergyDispersal.h b/src/mlc/EnergyDispersal.h
new file mode 100644
index 0000000..16b6176
--- /dev/null
+++ b/src/mlc/EnergyDispersal.h
@@ -0,0 +1,55 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#if !defined(ENERGYDISPERSAL_H__3B0BA660_CA63_4344_2B_23453E7A0D31912__INCLUDED_)
+#define ENERGYDISPERSAL_H__3B0BA660_CA63_4344_2B_23453E7A0D31912__INCLUDED_
+
+#include "../GlobalDefinitions.h"
+#include "../util/Vector.h"
+
+
+/* Classes ********************************************************************/
+class CEngergyDispersal
+{
+public:
+    CEngergyDispersal() {}
+    virtual ~CEngergyDispersal() {}
+
+    void ProcessData(CVector<_BINARY>* pbiData);
+    void Init(int iNewNumInBits, int iNewLengthVSPP);
+
+protected:
+    int			iNumInBits;
+    int			iStartIndVSPP;
+    int			iEndIndVSPP;
+    uint32_t	iShiftRegisterSPP;
+    uint32_t	iShiftRegisterVSPP;
+};
+
+
+#endif // !defined(ENERGYDISPERSAL_H__3B0BA660_CA63_4344_2B_23453E7A0D31912__INCLUDED_)
diff --git a/src/mlc/MLC.cpp b/src/mlc/MLC.cpp
new file mode 100644
index 0000000..edbc960
--- /dev/null
+++ b/src/mlc/MLC.cpp
@@ -0,0 +1,1013 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *	Multi-level-channel (de)coder (MLC)
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "MLC.h"
+
+
+/* Implementation *************************************************************/
+/******************************************************************************\
+* MLC-encoder                                                                  *
+\******************************************************************************/
+void CMLCEncoder::ProcessDataInternal(CParameter&)
+{
+    int	i, j;
+    int iElementCounter;
+
+    /* Energy dispersal ----------------------------------------------------- */
+    /* VSPP is treated as a separate part for energy dispersal */
+    EnergyDisp.ProcessData(pvecInputData);
+
+
+    /* Partitioning of input-stream ----------------------------------------- */
+    iElementCounter = 0;
+
+    if (iL[2] == 0)
+    {
+        /* Standard departitioning */
+        /* Protection level A */
+        for (j = 0; j < iLevels; j++)
+        {
+            /* Bits */
+            for (i = 0; i < iM[j][0]; i++)
+            {
+                vecEncInBuffer[j][i] =
+                    BitToSoft((*pvecInputData)[iElementCounter]);
+
+                iElementCounter++;
+            }
+        }
+
+        /* Protection level B */
+        for (j = 0; j < iLevels; j++)
+        {
+            /* Bits */
+            for (i = 0; i < iM[j][1]; i++)
+            {
+                vecEncInBuffer[j][iM[j][0] + i] =
+                    BitToSoft((*pvecInputData)[iElementCounter]);
+
+                iElementCounter++;
+            }
+        }
+    }
+    else
+    {
+        /* Special partitioning with hierarchical modulation. First set
+           hierarchical bits at the beginning, then append the rest */
+        /* Hierarchical frame (always "iM[0][1]"). "iM[0][0]" is always "0" in
+           this case */
+        for (i = 0; i < iM[0][1]; i++)
+        {
+            vecEncInBuffer[0][i] =
+                BitToSoft((*pvecInputData)[iElementCounter]);
+
+            iElementCounter++;
+        }
+
+
+        /* Protection level A (higher protected part) */
+        for (j = 1; j < iLevels; j++)
+        {
+            /* Bits */
+            for (i = 0; i < iM[j][0]; i++)
+            {
+                vecEncInBuffer[j][i] =
+                    BitToSoft((*pvecInputData)[iElementCounter]);
+
+                iElementCounter++;
+            }
+        }
+
+        /* Protection level B  (lower protected part) */
+        for (j = 1; j < iLevels; j++)
+        {
+            /* Bits */
+            for (i = 0; i < iM[j][1]; i++)
+            {
+                vecEncInBuffer[j][iM[j][0] + i] =
+                    BitToSoft((*pvecInputData)[iElementCounter]);
+
+                iElementCounter++;
+            }
+        }
+    }
+
+
+    /* Convolutional encoder ------------------------------------------------ */
+    for (j = 0; j < iLevels; j++)
+        ConvEncoder[j].Encode(vecEncInBuffer[j], vecEncOutBuffer[j]);
+
+
+    /* Bit interleaver ------------------------------------------------------ */
+    for (j = 0; j < iLevels; j++)
+        if (piInterlSequ[j] != -1)
+            BitInterleaver[piInterlSequ[j]].Interleave(vecEncOutBuffer[j]);
+
+
+    /* QAM mapping ---------------------------------------------------------- */
+    QAMMapping.Map(vecEncOutBuffer[0],
+                   vecEncOutBuffer[1],
+                   vecEncOutBuffer[2],
+                   vecEncOutBuffer[3],
+                   vecEncOutBuffer[4],
+                   vecEncOutBuffer[5], pvecOutputData);
+}
+
+void CMLCEncoder::InitInternal(CParameter& TransmParam)
+{
+    int i;
+    int	iNumInBits;
+
+    TransmParam.Lock();
+    CalculateParam(TransmParam, eChannelType);
+    TransmParam.Unlock();
+
+    iNumInBits = iL[0] + iL[1] + iL[2];
+
+
+    /* Init modules --------------------------------------------------------- */
+    /* Energy dispersal */
+    EnergyDisp.Init(iNumInBits, iL[2]);
+
+    /* Encoder */
+    for (i = 0; i < iLevels; i++)
+        ConvEncoder[i].Init(eCodingScheme, eChannelType, iN[0], iN[1],
+                            iM[i][0], iM[i][1], iCodeRate[i][0], iCodeRate[i][1], i);
+
+    /* Bit interleaver */
+    /* First init all possible interleaver (According table "TableMLC.h" ->
+       "Interleaver sequence") */
+    if (eCodingScheme == CS_3_HMMIX)
+    {
+        BitInterleaver[0].Init(iN[0], iN[1], 13);
+        BitInterleaver[1].Init(iN[0], iN[1], 21);
+    }
+    else
+    {
+        BitInterleaver[0].Init(2 * iN[0], 2 * iN[1], 13);
+        BitInterleaver[1].Init(2 * iN[0], 2 * iN[1], 21);
+    }
+
+    /* QAM-mapping */
+    QAMMapping.Init(iN_mux, eCodingScheme);
+
+
+    /* Allocate memory for internal bit-buffers ----------------------------- */
+    for (i = 0; i < iLevels; i++)
+    {
+        /* Buffers for each encoder on all different levels */
+        /* Add bits from higher protected and lower protected part */
+        vecEncInBuffer[i].Init(iM[i][0] + iM[i][1]);
+
+        /* Encoder output buffers for all levels. Must have the same length */
+        vecEncOutBuffer[i].Init(iNumEncBits);
+    }
+
+    /* Define block-size for input and output */
+    iInputBlockSize = iNumInBits;
+    iOutputBlockSize = iN_mux;
+}
+
+
+/******************************************************************************\
+* MLC-decoder                                                                  *
+\******************************************************************************/
+void CMLCDecoder::ProcessDataInternal(CParameter&)
+{
+    int			i, j, k;
+    int			iElementCounter;
+    _BOOLEAN	bIteration;
+
+    /* Save input signal for signal constellation. We cannot use the copy
+       operator of vector because the input vector is not of the same size as
+       our intermediate buffer, therefore the "for"-loop */
+    for (i = 0; i < iInputBlockSize; i++)
+        vecSigSpacBuf[i] = (*pvecInputData)[i].cSig;
+
+
+
+#if 0
+// TEST
+    static FILE* pFile = fopen("test/constellation.dat", "w");
+    if (eChannelType == CParameter::CT_MSC) {
+        for (i = 0; i < iInputBlockSize; i++)
+            fprintf(pFile, "%e %e\n", vecSigSpacBuf[i].real(), vecSigSpacBuf[i].imag());
+        fflush(pFile);
+    }
+// close all;load constellation.dat;constellation=complex(constellation(:,1),constellation(:,2));plot(constellation,'.')
+#endif
+
+
+
+
+    /* Iteration loop */
+    for (k = 0; k < iNumIterations + 1; k++)
+    {
+        for (j = 0; j < iLevels; j++)
+        {
+            /* Metric ------------------------------------------------------- */
+            if (k > 0)
+                bIteration = TRUE;
+            else
+                bIteration = FALSE;
+
+            MLCMetric.CalculateMetric(pvecInputData, vecMetric,
+                                      vecSubsetDef[0], vecSubsetDef[1], vecSubsetDef[2],
+                                      vecSubsetDef[3], vecSubsetDef[4], vecSubsetDef[5],
+                                      j, bIteration);
+
+
+            /* Bit deinterleaver -------------------------------------------- */
+            if (piInterlSequ[j] != -1)
+                BitDeinterleaver[piInterlSequ[j]].Deinterleave(vecMetric);
+
+
+            /* Viterbi decoder ---------------------------------------------- */
+            rAccMetric = ViterbiDecoder[j].Decode(vecMetric, vecDecOutBits[j]);
+
+            /* The last branch of encoding and interleaving must not be used at
+               the very last loop */
+            /* "iLevels - 1" for iLevels = 1, 2, 3
+               "iLevels - 2" for iLevels = 6 */
+            if ((k < iNumIterations) ||
+                    ((k == iNumIterations) && !(j >= iIndexLastBranch)))
+            {
+                /* Convolutional encoder ------------------------------------ */
+                ConvEncoder[j].Encode(vecDecOutBits[j], vecSubsetDef[j]);
+
+
+                /* Bit interleaver ------------------------------------------ */
+                if (piInterlSequ[j] != -1)
+                {
+                    BitInterleaver[piInterlSequ[j]].
+                    Interleave(vecSubsetDef[j]);
+                }
+            }
+        }
+    }
+
+
+    /* De-partitioning of input-stream -------------------------------------- */
+    iElementCounter = 0;
+
+    if (iL[2] == 0)
+    {
+        /* Standard departitioning */
+        /* Protection level A (higher protected part) */
+        for (j = 0; j < iLevels; j++)
+        {
+            /* Bits */
+            for (i = 0; i < iM[j][0]; i++)
+            {
+                (*pvecOutputData)[iElementCounter] =
+                    ExtractBit(vecDecOutBits[j][i]);
+
+                iElementCounter++;
+            }
+        }
+
+        /* Protection level B (lower protected part) */
+        for (j = 0; j < iLevels; j++)
+        {
+            /* Bits */
+            for (i = 0; i < iM[j][1]; i++)
+            {
+                (*pvecOutputData)[iElementCounter] =
+                    ExtractBit(vecDecOutBits[j][iM[j][0] + i]);
+
+                iElementCounter++;
+            }
+        }
+    }
+    else
+    {
+        /* Special departitioning with hierarchical modulation. First set
+           hierarchical bits at the beginning, then append the rest */
+        /* Hierarchical frame (always "iM[0][1]"). "iM[0][0]" is always "0" in
+           this case */
+        for (i = 0; i < iM[0][1]; i++)
+        {
+            (*pvecOutputData)[iElementCounter] =
+                ExtractBit(vecDecOutBits[0][i]);
+
+            iElementCounter++;
+        }
+
+        /* Protection level A (higher protected part) */
+        for (j = 1; j < iLevels; j++)
+        {
+            /* Bits */
+            for (i = 0; i < iM[j][0]; i++)
+            {
+                (*pvecOutputData)[iElementCounter] =
+                    ExtractBit(vecDecOutBits[j][i]);
+
+                iElementCounter++;
+            }
+        }
+
+        /* Protection level B (lower protected part) */
+        for (j = 1; j < iLevels; j++)
+        {
+            /* Bits */
+            for (i = 0; i < iM[j][1]; i++)
+            {
+                (*pvecOutputData)[iElementCounter] =
+                    ExtractBit(vecDecOutBits[j][iM[j][0] + i]);
+
+                iElementCounter++;
+            }
+        }
+    }
+
+
+    /* Energy dispersal ----------------------------------------------------- */
+    /* VSPP is treated as a separate part for energy dispersal (7.2.2) */
+    EnergyDisp.ProcessData(pvecOutputData);
+}
+
+void CMLCDecoder::InitInternal(CParameter& Parameters)
+{
+    int i;
+
+
+    /* First, calculate all necessary parameters for decoding process */
+    Parameters.Lock();
+    CalculateParam(Parameters, eChannelType);
+    Parameters.Unlock();
+
+    /* Reasonable number of iterations depends on coding scheme. With a
+       4-QAM no iteration is possible */
+    if (eCodingScheme == CS_1_SM)
+        iNumIterations = 0;
+    else
+        iNumIterations = iInitNumIterations;
+
+    /* Set this parameter to identify the last level of coder (important for
+       very last loop */
+    if (eCodingScheme == CS_3_HMMIX)
+        iIndexLastBranch = iLevels - 2;
+    else
+        iIndexLastBranch = iLevels - 1;
+
+    iNumOutBits = iL[0] + iL[1] + iL[2];
+
+    /* Reset accumulated metric for reliability test of transmission */
+    rAccMetric = (_REAL) 0.0;
+
+
+    /* Init modules --------------------------------------------------------- */
+    /* Energy dispersal */
+    EnergyDisp.Init(iNumOutBits, iL[2]);
+
+    /* Viterby decoder */
+    for (i = 0; i < iLevels; i++)
+        ViterbiDecoder[i].Init(eCodingScheme, eChannelType, iN[0], iN[1],
+                               iM[i][0], iM[i][1], iCodeRate[i][0], iCodeRate[i][1], i);
+
+    /* Encoder */
+    for (i = 0; i < iLevels; i++)
+        ConvEncoder[i].Init(eCodingScheme, eChannelType, iN[0], iN[1],
+                            iM[i][0], iM[i][1], iCodeRate[i][0], iCodeRate[i][1], i);
+
+    /* Bit interleaver */
+    /* First init all possible interleaver (According table "TableMLC.h" ->
+       "Interleaver sequence") */
+    if (eCodingScheme == CS_3_HMMIX)
+    {
+        BitDeinterleaver[0].Init(iN[0], iN[1], 13);
+        BitDeinterleaver[1].Init(iN[0], iN[1], 21);
+        BitInterleaver[0].Init(iN[0], iN[1], 13);
+        BitInterleaver[1].Init(iN[0], iN[1], 21);
+    }
+    else
+    {
+        BitDeinterleaver[0].Init(2 * iN[0], 2 * iN[1], 13);
+        BitDeinterleaver[1].Init(2 * iN[0], 2 * iN[1], 21);
+        BitInterleaver[0].Init(2 * iN[0], 2 * iN[1], 13);
+        BitInterleaver[1].Init(2 * iN[0], 2 * iN[1], 21);
+    }
+
+    /* Metric */
+    MLCMetric.Init(iN_mux, eCodingScheme);
+
+
+    /* Allocate memory for internal bit (metric) -buffers ------------------- */
+    vecMetric.Init(iNumEncBits);
+
+    /* Decoder output buffers for all levels. Have different length */
+    for (i = 0; i < iLevels; i++)
+        vecDecOutBits[i].Init(iM[i][0] + iM[i][1]);
+
+    /* Buffers for subset definition (always number of encoded bits long) */
+    for (i = 0; i < MC_MAX_NUM_LEVELS; i++)
+        vecSubsetDef[i].Init(iNumEncBits);
+
+    /* Init buffer for signal space */
+    vecSigSpacBuf.Init(iN_mux);
+
+    /* Define block-size for input and output */
+    iInputBlockSize = iN_mux;
+    iOutputBlockSize = iNumOutBits;
+}
+
+void CMLCDecoder::GetVectorSpace(CVector<_COMPLEX>& veccData)
+{
+    /* Init output vectors */
+    veccData.Init(iN_mux);
+
+    /* Do copying of data only if vector is of non-zero length which means that
+       the module was already initialized */
+    if (iN_mux != 0)
+    {
+        /* Lock resources */
+        Lock();
+
+        /* Copy vectors */
+        for (int i = 0; i < iN_mux; i++)
+            veccData[i] = vecSigSpacBuf[i];
+
+        /* Release resources */
+        Unlock();
+    }
+}
+
+
+/******************************************************************************\
+* MLC base class                                                               *
+\******************************************************************************/
+void CMLC::CalculateParam(CParameter& Parameter, int iNewChannelType)
+{
+    int i;
+    int iMSCDataLenPartA;
+
+    switch (iNewChannelType)
+    {
+        /* FAC ********************************************************************/
+    case CT_FAC:
+        eCodingScheme = CS_1_SM;
+        iN_mux = NUM_FAC_CELLS;
+
+        iNumEncBits = NUM_FAC_CELLS * 2;
+
+        iLevels = 1;
+
+        /* Code rates for prot.-Level A and B for each level */
+        /* Protection Level A */
+        iCodeRate[0][0] = 0;
+
+        /* Protection Level B */
+        iCodeRate[0][1] = iCodRateCombFDC4SM;
+
+        /* Define interleaver sequence for all levels */
+        piInterlSequ = iInterlSequ4SM;
+
+
+        /* iN: Number of OFDM-cells of each protection level ---------------- */
+        iN[0] = 0;
+        iN[1] = iN_mux;
+
+
+        /* iM: Number of bits each level ------------------------------------ */
+        iM[0][0] = 0;
+        iM[0][1] = Parameter.iNumFACBitsPerBlock;
+
+
+        /* iL: Number of bits each protection level ------------------------- */
+        /* Higher protected part */
+        iL[0] = 0;
+
+        /* Lower protected part */
+        iL[1] = iM[0][1];
+
+        /* Very strong protected part (VSPP) */
+        iL[2] = 0;
+        break;
+
+
+        /* SDC ********************************************************************/
+    case CT_SDC:
+        eCodingScheme = Parameter.eSDCCodingScheme;
+        iN_mux = Parameter.CellMappingTable.iNumSDCCellsPerSFrame;
+
+        iNumEncBits = iN_mux * 2;
+
+        switch (eCodingScheme)
+        {
+        case CS_1_SM:
+            iLevels = 1;
+
+            /* Code rates for prot.-Level A and B for each level */
+            /* Protection Level A */
+            iCodeRate[0][0] = 0;
+
+            /* Protection Level B */
+            iCodeRate[0][1] = iCodRateCombSDC4SM;
+
+            /* Define interleaver sequence for all levels */
+            piInterlSequ = iInterlSequ4SM;
+
+
+            /* iN: Number of OFDM-cells of each protection level ------------ */
+            iN[0] = 0;
+            iN[1] = iN_mux;
+
+
+            /* iM: Number of bits each level -------------------------------- */
+            iM[0][0] = 0;
+
+            /* M_0,2 = RX_0 * floor((2 * N_SDC - 12) / RY_0) */
+            iM[0][1] = iPuncturingPatterns[iCodRateCombSDC4SM][0] *
+                       (int) ((_REAL) (2 * iN_mux - 12) /
+                              iPuncturingPatterns[iCodRateCombSDC4SM][1]);
+
+
+            /* iL: Number of bits each protection level --------------------- */
+            /* Higher protected part */
+            iL[0] = 0;
+
+            /* Lower protected part */
+            iL[1] = iM[0][1];
+
+            /* Very strong protected part (VSPP) */
+            iL[2] = 0;
+            break;
+
+        case CS_2_SM:
+            iLevels = 2;
+
+            /* Code rates for prot.-Level A and B for each level */
+            for (i = 0; i < 2; i++)
+            {
+                /* Protection Level A */
+                iCodeRate[i][0] = 0;
+
+                /* Protection Level B */
+                iCodeRate[i][1] = iCodRateCombSDC16SM[i];
+            }
+
+            /* Define interleaver sequence for all levels */
+            piInterlSequ = iInterlSequ16SM;
+
+
+            /* iN: Number of OFDM-cells of each protection level ------------ */
+            iN[0] = 0;
+            iN[1] = iN_mux;
+
+
+            /* iM: Number of bits each level -------------------------------- */
+            /* M_p,2 = RX_p * floor((N_2 - 6) / RY_p) */
+            for (i = 0; i < 2; i++)
+            {
+                iM[i][0] = 0;
+
+                /* M_p,2 = RX_p * floor((2 * N_SDC - 12) / RY_p) */
+                iM[i][1] = iPuncturingPatterns[iCodRateCombSDC16SM[i]][0] *
+                           (int) ((_REAL) (2 * iN[1] - 12) /
+                                  iPuncturingPatterns[iCodRateCombSDC16SM[i]][1]);
+            }
+
+
+            /* iL: Number of bits each protection level --------------------- */
+            /* Higher protected part */
+            iL[0] = 0;
+
+            /* Lower protected part */
+            iL[1] = iM[0][1] + iM[1][1];
+
+            /* Very strong protected part (VSPP) */
+            iL[2] = 0;
+            break;
+
+        default:
+            break;
+        }
+
+        /* Set number of bits for one SDC-block */
+        Parameter.SetNumDecodedBitsSDC(iL[1]);
+        break;
+
+
+        /* MSC ********************************************************************/
+    case CT_MSC:
+        eCodingScheme = Parameter.eMSCCodingScheme;
+        iN_mux = Parameter.CellMappingTable.iNumUsefMSCCellsPerFrame;
+
+        /* Data length for part A is the sum of all lengths of the streams */
+        iMSCDataLenPartA = Parameter.Stream[0].iLenPartA +
+                           Parameter.Stream[1].iLenPartA +
+                           Parameter.Stream[2].iLenPartA +
+                           Parameter.Stream[3].iLenPartA;
+
+        switch (eCodingScheme)
+        {
+        case CS_2_SM:
+            iLevels = 2;
+
+            /* Code rates for prot.-Level A and B for each level */
+            for (i = 0; i < 2; i++)
+            {
+                /* Protection Level A */
+                iCodeRate[i][0] =
+                    iCodRateCombMSC16SM[Parameter.MSCPrLe.iPartA][i];
+
+                /* Protection Level B */
+                iCodeRate[i][1] =
+                    iCodRateCombMSC16SM[Parameter.MSCPrLe.iPartB][i];
+            }
+
+            /* Define interleaver sequence for all levels */
+            piInterlSequ = iInterlSequ16SM;
+
+            iNumEncBits = iN_mux * 2;
+
+
+            /* iN: Number of OFDM-cells of each protection level ------------ */
+            /* N_1 = ceil(8 * X / (2 * RY_Icm * sum(R_p)) * RY_Icm */
+            iN[0] = (int) ceil(8 * (_REAL) iMSCDataLenPartA / (2 *
+                               /* RY_Icm */
+                               (_REAL) iCodRateCombMSC16SM[Parameter.MSCPrLe.iPartA][2] *
+                               (
+                                   /* R_0 */
+                                   (_REAL) iPuncturingPatterns[iCodRateCombMSC16SM[
+                                                                   Parameter.MSCPrLe.iPartA][0]][0] /
+                                   iPuncturingPatterns[iCodRateCombMSC16SM[
+                                                           Parameter.MSCPrLe.iPartA][0]][1] +
+                                   /* R_1 */
+                                   (_REAL) iPuncturingPatterns[iCodRateCombMSC16SM[
+                                                                   Parameter.MSCPrLe.iPartA][1]][0] /
+                                   iPuncturingPatterns[iCodRateCombMSC16SM[
+                                                           Parameter.MSCPrLe.iPartA][1]][1]))) *
+                    /* RY_Icm */
+                    iCodRateCombMSC16SM[Parameter.MSCPrLe.iPartA][2];
+
+            /* Check if result can be possible, if not -> correct. This can
+               happen, if a wrong number is in "Param.Stream[x].iLenPartA" */
+            if (iN[0] > iN_mux)
+                iN[0] = 0;
+
+            iN[1] = iN_mux - iN[0];
+
+
+            /* iM: Number of bits each level -------------------------------- */
+            for (i = 0; i < 2; i++)
+            {
+                /* M_p,1 = 2 * N_1 * R_p */
+                iM[i][0] = (int) (2 * iN[0] *
+                                  (_REAL) iPuncturingPatterns[iCodRateCombMSC16SM[
+                                                                  Parameter.MSCPrLe.iPartA][i]][0] /
+                                  iPuncturingPatterns[iCodRateCombMSC16SM[
+                                                          Parameter.MSCPrLe.iPartA][i]][1]);
+
+                /* M_p,2 = RX_p * floor((2 * N_2 - 12) / RY_p) */
+                iM[i][1] =
+                    iPuncturingPatterns[iCodRateCombMSC16SM[
+                                            Parameter.MSCPrLe.iPartB][i]][0] *
+                    (int) ((_REAL) (2 * iN[1] - 12) /
+                           iPuncturingPatterns[iCodRateCombMSC16SM[
+                                                   Parameter.MSCPrLe.iPartB][i]][1]);
+            }
+
+
+            /* iL: Number of bits each protection level --------------------- */
+            /* Higher protected part */
+            iL[0] = iM[0][0] + iM[1][0];
+
+            /* Lower protected part */
+            iL[1] = iM[0][1] + iM[1][1];
+
+            /* Very strong protected part (VSPP) */
+            iL[2] = 0;
+            break;
+
+        case CS_3_SM:
+            iLevels = 3;
+
+            /* Code rates for prot.-Level A and B for each level */
+            for (i = 0; i < 3; i++)
+            {
+                /* Protection Level A */
+                iCodeRate[i][0] =
+                    iCodRateCombMSC64SM[Parameter.MSCPrLe.iPartA][i];
+
+                /* Protection Level B */
+                iCodeRate[i][1] =
+                    iCodRateCombMSC64SM[Parameter.MSCPrLe.iPartB][i];
+            }
+
+            /* Define interleaver sequence for all levels */
+            piInterlSequ = iInterlSequ64SM;
+
+            iNumEncBits = iN_mux * 2;
+
+
+            /* iN: Number of OFDM-cells of each protection level ------------ */
+            /* N_1 = ceil(8 * X / (2 * RY_Icm * sum(R_p)) * RY_Icm */
+            iN[0] = (int) ceil(8 * (_REAL) iMSCDataLenPartA / (2 *
+                               /* RY_Icm */
+                               (_REAL) iCodRateCombMSC64SM[Parameter.MSCPrLe.iPartA][3] *
+                               (
+                                   /* R_0 */
+                                   (_REAL) iPuncturingPatterns[iCodRateCombMSC64SM[
+                                                                   Parameter.MSCPrLe.iPartA][0]][0] /
+                                   iPuncturingPatterns[iCodRateCombMSC64SM[
+                                                           Parameter.MSCPrLe.iPartA][0]][1] +
+                                   /* R_1 */
+                                   (_REAL) iPuncturingPatterns[iCodRateCombMSC64SM[
+                                                                   Parameter.MSCPrLe.iPartA][1]][0] /
+                                   iPuncturingPatterns[iCodRateCombMSC64SM[
+                                                           Parameter.MSCPrLe.iPartA][1]][1] +
+                                   /* R_2 */
+                                   (_REAL) iPuncturingPatterns[iCodRateCombMSC64SM[
+                                                                   Parameter.MSCPrLe.iPartA][2]][0] /
+                                   iPuncturingPatterns[iCodRateCombMSC64SM[
+                                                           Parameter.MSCPrLe.iPartA][2]][1]))) *
+                    /* RY_Icm */
+                    iCodRateCombMSC64SM[Parameter.MSCPrLe.iPartA][3];
+
+            /* Check if result can be possible, if not -> correct. This can
+               happen, if a wrong number is in "Param.Stream[x].iLenPartA" */
+            if (iN[0] > iN_mux)
+                iN[0] = 0;
+
+            iN[1] = iN_mux - iN[0];
+
+
+            /* iM: Number of bits each level -------------------------------- */
+            for (i = 0; i < 3; i++)
+            {
+                /* M_p,1 = 2 * N_1 * R_p */
+                iM[i][0] = (int) (2 * iN[0] *
+                                  (_REAL) iPuncturingPatterns[iCodRateCombMSC64SM[
+                                                                  Parameter.MSCPrLe.iPartA][i]][0] /
+                                  iPuncturingPatterns[iCodRateCombMSC64SM[
+                                                          Parameter.MSCPrLe.iPartA][i]][1]);
+
+                /* M_p,2 = RX_p * floor((2 * N_2 - 12) / RY_p) */
+                iM[i][1] =
+                    iPuncturingPatterns[iCodRateCombMSC64SM[
+                                            Parameter.MSCPrLe.iPartB][i]][0] *
+                    (int) ((_REAL) (2 * iN[1] - 12) /
+                           iPuncturingPatterns[iCodRateCombMSC64SM[
+                                                   Parameter.MSCPrLe.iPartB][i]][1]);
+            }
+
+
+            /* iL: Number of bits each protection level --------------------- */
+            /* Higher protected part */
+            iL[0] = iM[0][0] + iM[1][0] + iM[2][0];
+
+            /* Lower protected part */
+            iL[1] = iM[0][1] + iM[1][1] + iM[2][1];
+
+            /* Very strong protected part (VSPP) */
+            iL[2] = 0;
+            break;
+
+        case CS_3_HMSYM:
+            iLevels = 3;
+
+            /* Code rates for prot.-Level A and B for each level */
+            /* VSPP (Hierachical) */
+            iCodeRate[0][0] = 0;
+            iCodeRate[0][1] =
+                iCodRateCombMSC64HMsym[Parameter.MSCPrLe.iHierarch][0];
+
+            for (i = 1; i < 3; i++)
+            {
+                /* Protection Level A */
+                iCodeRate[i][0] =
+                    iCodRateCombMSC64HMsym[Parameter.MSCPrLe.iPartA][i];
+
+                /* Protection Level B */
+                iCodeRate[i][1] =
+                    iCodRateCombMSC64HMsym[Parameter.MSCPrLe.iPartB][i];
+            }
+
+            /* Define interleaver sequence for all levels */
+            piInterlSequ = iInterlSequ64HMsym;
+
+            iNumEncBits = iN_mux * 2;
+
+
+            /* iN: Number of OFDM-cells of each protection level ------------ */
+            /* N_1 = ceil(8 * X / (2 * RY_Icm * sum(R_p)) * RY_Icm */
+            iN[0] = (int) ceil(8 * (_REAL) iMSCDataLenPartA / (2 *
+                               /* RY_Icm */
+                               (_REAL) iCodRateCombMSC64HMsym[Parameter.MSCPrLe.iPartA][3] *
+                               (
+                                   /* R_1 */
+                                   (_REAL) iPuncturingPatterns[iCodRateCombMSC64HMsym[
+                                                                   Parameter.MSCPrLe.iPartA][1]][0] /
+                                   iPuncturingPatterns[iCodRateCombMSC64HMsym[
+                                                           Parameter.MSCPrLe.iPartA][1]][1] +
+                                   /* R_2 */
+                                   (_REAL) iPuncturingPatterns[iCodRateCombMSC64HMsym[
+                                                                   Parameter.MSCPrLe.iPartA][2]][0] /
+                                   iPuncturingPatterns[iCodRateCombMSC64HMsym[
+                                                           Parameter.MSCPrLe.iPartA][2]][1]))) *
+                    /* RY_Icm */
+                    iCodRateCombMSC64HMsym[Parameter.MSCPrLe.iPartA][3];
+
+            /* Check if result can be possible, if not -> correct. This can
+               happen, if a wrong number is in "Param.Stream[x].iLenPartA" */
+            if (iN[0] > iN_mux)
+                iN[0] = 0;
+
+            iN[1] = iN_mux - iN[0];
+
+
+            /* iM: Number of bits each level -------------------------------- */
+            /* Level 0, contains the VSPP, treated differently */
+            /* M_0,1 */
+            iM[0][0] = 0;
+
+            /* M_0,2 = RX_0 * floor((2 * (N_1 + N_2) - 12) / RY_0) */
+            iM[0][1] =
+                iPuncturingPatterns[iCodRateCombMSC64HMsym[
+                                        Parameter.MSCPrLe.iHierarch][0]][0] *
+                (int) ((_REAL) (2 * (iN[0] + iN[1]) - 12) /
+                       iPuncturingPatterns[iCodRateCombMSC64HMsym[
+                                               Parameter.MSCPrLe.iHierarch][0]][1]);
+
+            for (i = 1; i < 3; i++)
+            {
+                /* M_p,1 = 2 * N_1 * R_p */
+                iM[i][0] = (int) (2 * iN[0] *
+                                  (_REAL) iPuncturingPatterns[iCodRateCombMSC64HMsym[
+                                                                  Parameter.MSCPrLe.iPartA][i]][0] /
+                                  iPuncturingPatterns[iCodRateCombMSC64HMsym[
+                                                          Parameter.MSCPrLe.iPartA][i]][1]);
+
+                /* M_p,2 = RX_p * floor((2 * N_2 - 12) / RY_p) */
+                iM[i][1] =
+                    iPuncturingPatterns[iCodRateCombMSC64HMsym[
+                                            Parameter.MSCPrLe.iPartB][i]][0] *
+                    (int) ((_REAL) (2 * iN[1] - 12) /
+                           iPuncturingPatterns[iCodRateCombMSC64HMsym[
+                                                   Parameter.MSCPrLe.iPartB][i]][1]);
+            }
+
+
+            /* iL: Number of bits each protection level --------------------- */
+            /* Higher protected part */
+            iL[0] = iM[1][0] + iM[2][0];
+
+            /* Lower protected part */
+            iL[1] = iM[1][1] + iM[2][1];
+
+            /* Very strong protected part (VSPP) */
+            iL[2] = iM[0][1];
+            break;
+
+        case CS_3_HMMIX:
+            iLevels = 6;
+
+            /* Code rates for prot.-Level A and B for each level */
+            /* VSPP (Hierachical) */
+            iCodeRate[0][0] = 0;
+            iCodeRate[0][1] =
+                iCodRateCombMSC64HMmix[Parameter.MSCPrLe.iHierarch][0];
+
+            for (i = 1; i < 6; i++)
+            {
+                /* Protection Level A */
+                iCodeRate[i][0] =
+                    iCodRateCombMSC64HMmix[Parameter.MSCPrLe.iPartA][i];
+
+                /* Protection Level B */
+                iCodeRate[i][1] =
+                    iCodRateCombMSC64HMmix[Parameter.MSCPrLe.iPartB][i];
+            }
+
+            /* Define interleaver sequence for all levels */
+            piInterlSequ = iInterlSequ64HMmix;
+
+            iNumEncBits = iN_mux;
+
+
+            /* iN: Number of OFDM-cells of each protection level ------------ */
+            /* N_1 = ceil(8 * X / (RY_Icm * sum(R_p)) * RY_Icm */
+            iN[0] = (int) ceil(8 * (_REAL) iMSCDataLenPartA / (
+                                   /* RY_Icm */
+                                   (_REAL) iCodRateCombMSC64HMmix[Parameter.MSCPrLe.iPartA][6] *
+                                   (
+                                       /* R_1 */
+                                       (_REAL) iPuncturingPatterns[iCodRateCombMSC64HMmix[
+                                                                       Parameter.MSCPrLe.iPartA][1]][0] /
+                                       iPuncturingPatterns[iCodRateCombMSC64HMmix[
+                                                               Parameter.MSCPrLe.iPartA][1]][1] +
+                                       /* R_2 */
+                                       (_REAL) iPuncturingPatterns[iCodRateCombMSC64HMmix[
+                                                                       Parameter.MSCPrLe.iPartA][2]][0] /
+                                       iPuncturingPatterns[iCodRateCombMSC64HMmix[
+                                                               Parameter.MSCPrLe.iPartA][2]][1] +
+                                       /* R_3 */
+                                       (_REAL) iPuncturingPatterns[iCodRateCombMSC64HMmix[
+                                                                       Parameter.MSCPrLe.iPartA][3]][0] /
+                                       iPuncturingPatterns[iCodRateCombMSC64HMmix[
+                                                               Parameter.MSCPrLe.iPartA][3]][1] +
+                                       /* R_4 */
+                                       (_REAL) iPuncturingPatterns[iCodRateCombMSC64HMmix[
+                                                                       Parameter.MSCPrLe.iPartA][4]][0] /
+                                       iPuncturingPatterns[iCodRateCombMSC64HMmix[
+                                                               Parameter.MSCPrLe.iPartA][4]][1] +
+                                       /* R_5 */
+                                       (_REAL) iPuncturingPatterns[iCodRateCombMSC64HMmix[
+                                                                       Parameter.MSCPrLe.iPartA][5]][0] /
+                                       iPuncturingPatterns[iCodRateCombMSC64HMmix[
+                                                               Parameter.MSCPrLe.iPartA][5]][1]))) *
+                    /* RY_Icm */
+                    iCodRateCombMSC64HMmix[Parameter.MSCPrLe.iPartA][6];
+
+            /* Check if result can be possible, if not -> correct. This can
+               happen, if a wrong number is in "Param.Stream[x].iLenPartA" */
+            if (iN[0] > iN_mux)
+                iN[0] = 0;
+
+            iN[1] = iN_mux - iN[0];
+
+
+            /* iM: Number of bits each level -------------------------------- */
+            /* Real-parts of level 0, they contain the VSPP and treated
+               differently */
+            /* M_0,1Re */
+            iM[0][0] = 0;
+
+            /* M_0,2Re = RX_0Re * floor((N_1 + N_2 - 12) / RY_0Re) */
+            iM[0][1] =
+                iPuncturingPatterns[iCodRateCombMSC64HMmix[
+                                        Parameter.MSCPrLe.iHierarch][0]][0] *
+                (int) ((_REAL) (iN[0] + iN[1] - 12) /
+                       iPuncturingPatterns[iCodRateCombMSC64HMmix[
+                                               Parameter.MSCPrLe.iHierarch][0]][1]);
+
+            for (i = 1; i < 6; i++)
+            {
+                /* M_p,1Re;Im = 2 * N_1 * R_pRe;Im */
+                iM[i][0] = (int) (iN[0] *
+                                  (_REAL) iPuncturingPatterns[iCodRateCombMSC64HMmix[
+                                                                  Parameter.MSCPrLe.iPartA][i]][0] /
+                                  iPuncturingPatterns[iCodRateCombMSC64HMmix[
+                                                          Parameter.MSCPrLe.iPartA][i]][1]);
+
+                /* M_p,2Re;Im =
+                   RX_pRe;Im * floor((2 * N_2 - 12) / RY_pRe;Im) */
+                iM[i][1] =
+                    iPuncturingPatterns[iCodRateCombMSC64HMmix[
+                                            Parameter.MSCPrLe.iPartB][i]][0] *
+                    (int) ((_REAL) (iN[1] - 12) /
+                           iPuncturingPatterns[iCodRateCombMSC64HMmix[
+                                                   Parameter.MSCPrLe.iPartB][i]][1]);
+            }
+
+
+            /* iL: Number of bits each protection level --------------------- */
+            /* Higher protected part */
+            iL[0] = iM[1][0] + iM[2][0] + iM[3][0] + iM[4][0] + iM[5][0];
+
+            /* Lower protected part */
+            iL[1] = iM[1][1] + iM[2][1] + iM[3][1] + iM[4][1] + iM[5][1];
+
+            /* Very strong protected part (VSPP) */
+            iL[2] = iM[0][1];
+            break;
+
+        default:
+            break;
+        }
+
+        /* Set number of output bits for next module */
+        Parameter.SetNumDecodedBitsMSC(iL[0] + iL[1] + iL[2]);
+
+        /* Set total number of bits for hiearchical frame (needed for MSC
+           demultiplexer module) */
+        Parameter.SetNumBitsHieraFrTot(iL[2]);
+        break;
+    }
+}
diff --git a/src/mlc/MLC.h b/src/mlc/MLC.h
new file mode 100644
index 0000000..180fb26
--- /dev/null
+++ b/src/mlc/MLC.h
@@ -0,0 +1,229 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *	See MLC.cpp
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#if !defined(MLC_H__3B0BA660_CA63_4344_BB2B_23E7A0D31912__INCLUDED_)
+#define MLC_H__3B0BA660_CA63_4344_BB2B_23E7A0D31912__INCLUDED_
+
+#include "../GlobalDefinitions.h"
+#include "../util/Modul.h"
+#include "../Parameter.h"
+#include "../tables/TableMLC.h"
+#include "../tables/TableCarMap.h"
+#include "ConvEncoder.h"
+#include "ViterbiDecoder.h"
+#include "Metric.h"
+#include "BitInterleaver.h"
+#include "QAMMapping.h"
+#include "EnergyDispersal.h"
+
+
+/* Classes ********************************************************************/
+class CMLC
+{
+public:
+    CMLC() : iN_mux(0), eChannelType(CT_MSC) {}
+    virtual ~CMLC() {}
+
+    void CalculateParam(CParameter& Parameter, int iNewChannelType);
+
+protected:
+    int	iLevels;
+    /* No input bits for each level. First index: Level, second index:
+       Protection level.
+       For three levels: [M_0,l  M_1,l  M2,l]
+       For six levels: [M_0,lRe  M_0,lIm  M_1,lRe  M_1,lIm  M_2,lRe  ...  ] */
+    int	iM[MC_MAX_NUM_LEVELS][2];
+    int iN[2];
+    int iL[3];
+    int iN_mux;
+    int iCodeRate[MC_MAX_NUM_LEVELS][2];
+
+    const int* piInterlSequ;
+
+    int	iNumEncBits;
+
+    EChanType	eChannelType;
+    ECodScheme	eCodingScheme;
+};
+
+class CMLCEncoder : public CTransmitterModul<_BINARY, _COMPLEX>,
+            public CMLC
+{
+public:
+    CMLCEncoder() {}
+    virtual ~CMLCEncoder() {}
+
+protected:
+    CConvEncoder		ConvEncoder[MC_MAX_NUM_LEVELS];
+    /* Two different types of interleaver table */
+    CBitInterleaver		BitInterleaver[2];
+    CQAMMapping			QAMMapping;
+    CEngergyDispersal	EnergyDisp;
+
+    /* Internal buffers */
+    CVector<_DECISION>	vecEncInBuffer[MC_MAX_NUM_LEVELS];
+    CVector<_DECISION>	vecEncOutBuffer[MC_MAX_NUM_LEVELS];
+
+    virtual void InitInternal(CParameter& TransmParam);
+    virtual void ProcessDataInternal(CParameter& Parameter);
+};
+
+class CMLCDecoder : public CReceiverModul<CEquSig, _BINARY>,
+            public CMLC
+{
+public:
+    CMLCDecoder() : iInitNumIterations(MC_NUM_ITERATIONS) {}
+    virtual ~CMLCDecoder() {}
+
+    _REAL GetAccMetric() const {
+        return 10 * log10(rAccMetric);
+    }
+    void GetVectorSpace(CVector<_COMPLEX>& veccData);
+    void SetNumIterations(int iNewNumIterations)
+    {
+        iInitNumIterations = iNewNumIterations;
+        SetInitFlag();
+    }
+    int GetInitNumIterations() const {
+        return iInitNumIterations;
+    }
+
+protected:
+    CViterbiDecoder		ViterbiDecoder[MC_MAX_NUM_LEVELS];
+    CMLCMetric			MLCMetric;
+    /* Two different types of deinterleaver table */
+    CBitDeinterleaver	BitDeinterleaver[2];
+    CBitInterleaver		BitInterleaver[2];
+    CConvEncoder		ConvEncoder[MC_MAX_NUM_LEVELS];
+    CEngergyDispersal	EnergyDisp;
+
+    /* Internal buffers */
+    CVector<CDistance>	vecMetric;
+
+    CVector<_DECISION>	vecDecOutBits[MC_MAX_NUM_LEVELS];
+    CVector<_DECISION>	vecSubsetDef[MC_MAX_NUM_LEVELS];
+    int					iNumOutBits;
+
+    /* Accumulated metric */
+    _REAL				rAccMetric;
+
+    /* Internal buffer for GetVectorSpace function */
+    CVector<_COMPLEX>	vecSigSpacBuf;
+
+    int					iNumIterations;
+    int					iInitNumIterations;
+    int					iIndexLastBranch;
+
+    virtual void InitInternal(CParameter& Parameters);
+    virtual void ProcessDataInternal(CParameter& Parameters);
+};
+
+
+/******************************************************************************\
+* Customized channel (de-)coders											   *
+\******************************************************************************/
+class CMSCMLCEncoder : public CMLCEncoder
+{
+protected:
+    virtual void InitInternal(CParameter& TransmParam)
+    {
+        /* Set corresponding type */
+        eChannelType = CT_MSC;
+
+        /* Call init in encoder */
+        CMLCEncoder::InitInternal(TransmParam);
+    };
+};
+
+class CSDCMLCEncoder : public CMLCEncoder
+{
+protected:
+    virtual void InitInternal(CParameter& TransmParam)
+    {
+        /* Set corresponding type */
+        eChannelType = CT_SDC;
+
+        /* Call init in encoder */
+        CMLCEncoder::InitInternal(TransmParam);
+    };
+};
+
+class CFACMLCEncoder : public CMLCEncoder
+{
+protected:
+    virtual void InitInternal(CParameter& TransmParam)
+    {
+        /* Set corresponding type */
+        eChannelType = CT_FAC;
+
+        /* Call init in encoder */
+        CMLCEncoder::InitInternal(TransmParam);
+    };
+};
+
+class CMSCMLCDecoder : public CMLCDecoder
+{
+protected:
+    virtual void InitInternal(CParameter& Parameters)
+    {
+        /* Set corresponding type */
+        eChannelType = CT_MSC;
+
+        /* Call init in encoder */
+        CMLCDecoder::InitInternal(Parameters);
+    };
+};
+
+class CSDCMLCDecoder : public CMLCDecoder
+{
+protected:
+    virtual void InitInternal(CParameter& Parameters)
+    {
+        /* Set corresponding type */
+        eChannelType = CT_SDC;
+
+        /* Call init in encoder */
+        CMLCDecoder::InitInternal(Parameters);
+    };
+};
+
+class CFACMLCDecoder : public CMLCDecoder
+{
+protected:
+    virtual void InitInternal(CParameter& Parameters)
+    {
+        /* Set corresponding type */
+        eChannelType = CT_FAC;
+
+        /* Call init in encoder */
+        CMLCDecoder::InitInternal(Parameters);
+    };
+};
+
+
+#endif // !defined(MLC_H__3B0BA660_CA63_4344_BB2B_23E7A0D31912__INCLUDED_)
diff --git a/src/mlc/Metric.cpp b/src/mlc/Metric.cpp
new file mode 100644
index 0000000..c7373bc
--- /dev/null
+++ b/src/mlc/Metric.cpp
@@ -0,0 +1,1096 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *
+ * The metric is calculated as follows:
+ * Using ML: M = |r - s * h| = |h| * |r / h - s|
+ * Using MAP: M = |r - s * h|^2 = |h|^2 * |r / h - s|^2
+ *
+ * Subset definition:
+ * [1 2 3]  -> ([vecSubsetDef1 vecSubsetDef2 vecSubsetDef3])
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "Metric.h"
+
+
+/* Definitions ****************************************************************/
+/* Definitions for binary numbers (BI). On the left is most sigificant bit */
+#define BI_00	0 /* Two bits */
+#define BI_01	1
+#define BI_10	2
+#define BI_11	3
+#define BI_000	0 /* Three bits */
+#define BI_001	1
+#define BI_010	2
+#define BI_011	3
+#define BI_100	4
+#define BI_101	5
+#define BI_110	6
+#define BI_111	7
+
+
+/* Implementation *************************************************************/
+void CMLCMetric::CalculateMetric(CVector<CEquSig>* pcInSymb,
+                                 CVector<CDistance>& vecMetric,
+                                 CVector<_DECISION>& vecSubsetDef1,
+                                 CVector<_DECISION>& vecSubsetDef2,
+                                 CVector<_DECISION>& vecSubsetDef3,
+                                 CVector<_DECISION>& vecSubsetDef4,
+                                 CVector<_DECISION>& vecSubsetDef5,
+                                 CVector<_DECISION>& vecSubsetDef6,
+                                 int iLevel, _BOOLEAN bIteration)
+{
+    int i, k;
+    int iTabInd0;
+
+    switch (eMapType)
+    {
+    case CS_1_SM:
+        /**********************************************************************/
+        /* 4QAM	***************************************************************/
+        /**********************************************************************/
+        /* Metric according DRM-standard: (i_0  q_0) = (y_0,0  y_0,1) */
+        for (i = 0, k = 0; i < iInputBlockSize; i++, k += 2)
+        {
+            /* Real part ---------------------------------------------------- */
+            /* Distance to "0" */
+            vecMetric[k].rTow0 = Minimum1((*pcInSymb)[i].cSig.real(),
+                                          rTableQAM4[0][0], (*pcInSymb)[i].rChan);
+
+            /* Distance to "1" */
+            vecMetric[k].rTow1 = Minimum1((*pcInSymb)[i].cSig.real(),
+                                          rTableQAM4[1][0], (*pcInSymb)[i].rChan);
+
+
+            /* Imaginary part ----------------------------------------------- */
+            /* Distance to "0" */
+            vecMetric[k + 1].rTow0 = Minimum1((*pcInSymb)[i].cSig.imag(),
+                                              rTableQAM4[0][1], (*pcInSymb)[i].rChan);
+
+            /* Distance to "1" */
+            vecMetric[k + 1].rTow1 = Minimum1((*pcInSymb)[i].cSig.imag(),
+                                              rTableQAM4[1][1], (*pcInSymb)[i].rChan);
+        }
+
+        break;
+
+    case CS_2_SM:
+        /**********************************************************************/
+        /* 16QAM **************************************************************/
+        /**********************************************************************/
+        /* (i_0  i_1  q_0  q_1) = (y_0,0  y_1,0  y_0,1  y_1,1) */
+        switch (iLevel)
+        {
+        case 0:
+            for (i = 0, k = 0; i < iInputBlockSize; i++, k += 2)
+            {
+                if (bIteration == TRUE)
+                {
+                    /* Real part -------------------------------------------- */
+#ifdef USE_MAX_LOG_MAP
+                    vecMetric[k].rTow0 =
+                        Minimum2((*pcInSymb)[i].cSig.real(),
+                                 rTableQAM16[BI_00 /* [0  0] */][0],
+                                 rTableQAM16[BI_01 /* [0  1] */][0],
+                                 (*pcInSymb)[i].rChan, vecSubsetDef2[k]);
+
+                    vecMetric[k].rTow1 =
+                        Minimum2((*pcInSymb)[i].cSig.real(),
+                                 rTableQAM16[BI_10 /* [1  0] */][0],
+                                 rTableQAM16[BI_11 /* [1  1] */][0],
+                                 (*pcInSymb)[i].rChan, vecSubsetDef2[k]);
+#else
+                    /* Lowest bit defined by "vecSubsetDef2" */
+                    iTabInd0 = ExtractBit(vecSubsetDef2[k]) & 1;
+
+                    /* Distance to "0" */
+                    vecMetric[k].rTow0 =
+                        Minimum1((*pcInSymb)[i].cSig.real(),
+                                 rTableQAM16[iTabInd0][0], (*pcInSymb)[i].rChan);
+
+                    /* Distance to "1" */
+                    vecMetric[k].rTow1 =
+                        Minimum1((*pcInSymb)[i].cSig.real(),
+                                 rTableQAM16[iTabInd0 | (1 << 1)][0],
+                                 (*pcInSymb)[i].rChan);
+#endif
+
+
+                    /* Imaginary part --------------------------------------- */
+#ifdef USE_MAX_LOG_MAP
+                    vecMetric[k + 1].rTow0 = Minimum2((*pcInSymb)[i].cSig.imag(),
+                                                      rTableQAM16[BI_00 /* [0  0] */][1],
+                                                      rTableQAM16[BI_01 /* [0  1] */][1],
+                                                      (*pcInSymb)[i].rChan, vecSubsetDef2[k + 1]);
+
+                    vecMetric[k + 1].rTow1 = Minimum2((*pcInSymb)[i].cSig.imag(),
+                                                      rTableQAM16[BI_10 /* [1  0] */][1],
+                                                      rTableQAM16[BI_11 /* [1  1] */][1],
+                                                      (*pcInSymb)[i].rChan, vecSubsetDef2[k + 1]);
+#else
+                    /* Lowest bit defined by "vecSubsetDef2" */
+                    iTabInd0 = ExtractBit(vecSubsetDef2[k + 1]) & 1;
+
+                    /* Distance to "0" */
+                    vecMetric[k + 1].rTow0 =
+                        Minimum1((*pcInSymb)[i].cSig.imag(),
+                                 rTableQAM16[iTabInd0][1], (*pcInSymb)[i].rChan);
+
+                    /* Distance to "1" */
+                    vecMetric[k + 1].rTow1 =
+                        Minimum1((*pcInSymb)[i].cSig.imag(),
+                                 rTableQAM16[iTabInd0 | (1 << 1)][1],
+                                 (*pcInSymb)[i].rChan);
+#endif
+                }
+                else
+                {
+                    /* There are two possible points for each bit. Both have to
+                       be used. In the first step: {i_1}, {q_1} = 0
+                       In the second step: {i_1}, {q_1} = 1 */
+
+                    /* Calculate distances */
+                    /* Real part */
+                    vecMetric[k].rTow0 =
+                        Minimum2((*pcInSymb)[i].cSig.real(),
+                                 rTableQAM16[BI_00 /* [0  0] */][0],
+                                 rTableQAM16[BI_01 /* [0  1] */][0],
+                                 (*pcInSymb)[i].rChan);
+
+                    vecMetric[k].rTow1 =
+                        Minimum2((*pcInSymb)[i].cSig.real(),
+                                 rTableQAM16[BI_10 /* [1  0] */][0],
+                                 rTableQAM16[BI_11 /* [1  1] */][0],
+                                 (*pcInSymb)[i].rChan);
+
+                    /* Imaginary part */
+                    vecMetric[k + 1].rTow0 =
+                        Minimum2((*pcInSymb)[i].cSig.imag(),
+                                 rTableQAM16[BI_00 /* [0  0] */][1],
+                                 rTableQAM16[BI_01 /* [0  1] */][1],
+                                 (*pcInSymb)[i].rChan);
+
+                    vecMetric[k + 1].rTow1 =
+                        Minimum2((*pcInSymb)[i].cSig.imag(),
+                                 rTableQAM16[BI_10 /* [1  0] */][1],
+                                 rTableQAM16[BI_11 /* [1  1] */][1],
+                                 (*pcInSymb)[i].rChan);
+                }
+            }
+
+            break;
+
+        case 1:
+            for (i = 0, k = 0; i < iInputBlockSize; i++, k += 2)
+            {
+                /* Real part ------------------------------------------------ */
+#ifdef USE_MAX_LOG_MAP
+                vecMetric[k].rTow0 =
+                    Minimum2((*pcInSymb)[i].cSig.real(),
+                             rTableQAM16[BI_00 /* [0  0] */][0],
+                             rTableQAM16[BI_10 /* [1  0] */][0],
+                             (*pcInSymb)[i].rChan, vecSubsetDef1[k]);
+
+                vecMetric[k].rTow1 =
+                    Minimum2((*pcInSymb)[i].cSig.real(),
+                             rTableQAM16[BI_01 /* [0  1] */][0],
+                             rTableQAM16[BI_11 /* [1  1] */][0],
+                             (*pcInSymb)[i].rChan, vecSubsetDef1[k]);
+#else
+                /* Higest bit defined by "vecSubsetDef1" */
+                iTabInd0 = ((ExtractBit(vecSubsetDef1[k]) & 1) << 1);
+
+                /* Distance to "0" */
+                vecMetric[k].rTow0 = Minimum1((*pcInSymb)[i].cSig.real(),
+                                              rTableQAM16[iTabInd0][0], (*pcInSymb)[i].rChan);
+
+                /* Distance to "1" */
+                vecMetric[k].rTow1 = Minimum1((*pcInSymb)[i].cSig.real(),
+                                              rTableQAM16[iTabInd0 | 1][0], (*pcInSymb)[i].rChan);
+#endif
+
+
+                /* Imaginary part ------------------------------------------- */
+#ifdef USE_MAX_LOG_MAP
+                vecMetric[k + 1].rTow0 =
+                    Minimum2((*pcInSymb)[i].cSig.imag(),
+                             rTableQAM16[BI_00 /* [0  0] */][1],
+                             rTableQAM16[BI_10 /* [1  0] */][1],
+                             (*pcInSymb)[i].rChan, vecSubsetDef1[k + 1]);
+
+                vecMetric[k + 1].rTow1 =
+                    Minimum2((*pcInSymb)[i].cSig.imag(),
+                             rTableQAM16[BI_01 /* [0  1] */][1],
+                             rTableQAM16[BI_11 /* [1  1] */][1],
+                             (*pcInSymb)[i].rChan, vecSubsetDef1[k + 1]);
+#else
+                /* Higest bit defined by "vecSubsetDef1" */
+                iTabInd0 = ((ExtractBit(vecSubsetDef1[k + 1]) & 1) << 1);
+
+                /* Distance to "0" */
+                vecMetric[k + 1].rTow0 = Minimum1((*pcInSymb)[i].cSig.imag(),
+                                                  rTableQAM16[iTabInd0][1], (*pcInSymb)[i].rChan);
+
+                /* Distance to "1" */
+                vecMetric[k + 1].rTow1 = Minimum1((*pcInSymb)[i].cSig.imag(),
+                                                  rTableQAM16[iTabInd0 | 1][1], (*pcInSymb)[i].rChan);
+#endif
+            }
+
+            break;
+        }
+
+        break;
+
+    case CS_3_SM:
+        /**********************************************************************/
+        /* 64QAM SM ***********************************************************/
+        /**********************************************************************/
+        /* (i_0  i_1  i_2  q_0  q_1  q_2) =
+           (y_0,0  y_1,0  y_2,0  y_0,1  y_1,1  y_2,1) */
+        switch (iLevel)
+        {
+        case 0:
+            for (i = 0, k = 0; i < iInputBlockSize; i++, k += 2)
+            {
+                if (bIteration == TRUE)
+                {
+                    /* Real part -------------------------------------------- */
+#ifdef USE_MAX_LOG_MAP
+                    vecMetric[k].rTow0 =
+                        Minimum4((*pcInSymb)[i].cSig.real(),
+                                 rTableQAM64SM[BI_000 /* [0 0 0] */][0],
+                                 rTableQAM64SM[BI_010 /* [0 1 0] */][0],
+                                 rTableQAM64SM[BI_001 /* [0 0 1] */][0],
+                                 rTableQAM64SM[BI_011 /* [0 1 1] */][0],
+                                 (*pcInSymb)[i].rChan,
+                                 vecSubsetDef2[k], vecSubsetDef3[k]);
+
+                    vecMetric[k].rTow1 =
+                        Minimum4((*pcInSymb)[i].cSig.real(),
+                                 rTableQAM64SM[BI_100 /* [1 0 0] */][0],
+                                 rTableQAM64SM[BI_110 /* [1 1 0] */][0],
+                                 rTableQAM64SM[BI_101 /* [1 0 1] */][0],
+                                 rTableQAM64SM[BI_111 /* [1 1 1] */][0],
+                                 (*pcInSymb)[i].rChan,
+                                 vecSubsetDef2[k], vecSubsetDef3[k]);
+#else
+                    /* Lowest bit defined by "vecSubsetDef3" next bit defined
+                       by "vecSubsetDef2" */
+                    iTabInd0 =
+                        (ExtractBit(vecSubsetDef3[k]) & 1) |
+                        ((ExtractBit(vecSubsetDef2[k]) & 1) << 1);
+
+                    vecMetric[k].rTow0 =
+                        Minimum1((*pcInSymb)[i].cSig.real(),
+                                 rTableQAM64SM[iTabInd0][0],	(*pcInSymb)[i].rChan);
+
+                    vecMetric[k].rTow1 =
+                        Minimum1((*pcInSymb)[i].cSig.real(),
+                                 rTableQAM64SM[iTabInd0 | (1 << 2)][0],
+                                 (*pcInSymb)[i].rChan);
+#endif
+
+
+                    /* Imaginary part --------------------------------------- */
+#ifdef USE_MAX_LOG_MAP
+                    vecMetric[k + 1].rTow0 =
+                        Minimum4((*pcInSymb)[i].cSig.imag(),
+                                 rTableQAM64SM[BI_000 /* [0 0 0] */][1],
+                                 rTableQAM64SM[BI_010 /* [0 1 0] */][1],
+                                 rTableQAM64SM[BI_001 /* [0 0 1] */][1],
+                                 rTableQAM64SM[BI_011 /* [0 1 1] */][1],
+                                 (*pcInSymb)[i].rChan,
+                                 vecSubsetDef2[k + 1], vecSubsetDef3[k + 1]);
+
+                    vecMetric[k + 1].rTow1 =
+                        Minimum4((*pcInSymb)[i].cSig.imag(),
+                                 rTableQAM64SM[BI_100 /* [1 0 0] */][1],
+                                 rTableQAM64SM[BI_110 /* [1 1 0] */][1],
+                                 rTableQAM64SM[BI_101 /* [1 0 1] */][1],
+                                 rTableQAM64SM[BI_111 /* [1 1 1] */][1],
+                                 (*pcInSymb)[i].rChan,
+                                 vecSubsetDef2[k + 1], vecSubsetDef3[k + 1]);
+#else
+                    /* Lowest bit defined by "vecSubsetDef3" next bit defined
+                       by "vecSubsetDef2" */
+                    iTabInd0 =
+                        (ExtractBit(vecSubsetDef3[k + 1]) & 1) |
+                        ((ExtractBit(vecSubsetDef2[k + 1]) & 1) << 1);
+
+                    /* Calculate distances, imaginary part */
+                    vecMetric[k + 1].rTow0 =
+                        Minimum1((*pcInSymb)[i].cSig.imag(),
+                                 rTableQAM64SM[iTabInd0][1],	(*pcInSymb)[i].rChan);
+
+                    vecMetric[k + 1].rTow1 =
+                        Minimum1((*pcInSymb)[i].cSig.imag(),
+                                 rTableQAM64SM[iTabInd0 | (1 << 2)][1],
+                                 (*pcInSymb)[i].rChan);
+#endif
+                }
+                else
+                {
+                    /* Real part -------------------------------------------- */
+                    vecMetric[k].rTow0 =
+                        Minimum4((*pcInSymb)[i].cSig.real(),
+                                 rTableQAM64SM[BI_000 /* [0 0 0] */][0],
+                                 rTableQAM64SM[BI_001 /* [0 0 1] */][0],
+                                 rTableQAM64SM[BI_010 /* [0 1 0] */][0],
+                                 rTableQAM64SM[BI_011 /* [0 1 1] */][0],
+                                 (*pcInSymb)[i].rChan);
+
+                    vecMetric[k].rTow1 =
+                        Minimum4((*pcInSymb)[i].cSig.real(),
+                                 rTableQAM64SM[BI_100 /* [1 0 0] */][0],
+                                 rTableQAM64SM[BI_101 /* [1 0 1] */][0],
+                                 rTableQAM64SM[BI_110 /* [1 1 0] */][0],
+                                 rTableQAM64SM[BI_111 /* [1 1 1] */][0],
+                                 (*pcInSymb)[i].rChan);
+
+
+                    /* Imaginary part --------------------------------------- */
+                    vecMetric[k + 1].rTow0 =
+                        Minimum4((*pcInSymb)[i].cSig.imag(),
+                                 rTableQAM64SM[BI_000 /* [0 0 0] */][1],
+                                 rTableQAM64SM[BI_001 /* [0 0 1] */][1],
+                                 rTableQAM64SM[BI_010 /* [0 1 0] */][1],
+                                 rTableQAM64SM[BI_011 /* [0 1 1] */][1],
+                                 (*pcInSymb)[i].rChan);
+
+                    vecMetric[k + 1].rTow1 =
+                        Minimum4((*pcInSymb)[i].cSig.imag(),
+                                 rTableQAM64SM[BI_100 /* [1 0 0] */][1],
+                                 rTableQAM64SM[BI_101 /* [1 0 1] */][1],
+                                 rTableQAM64SM[BI_110 /* [1 1 0] */][1],
+                                 rTableQAM64SM[BI_111 /* [1 1 1] */][1],
+                                 (*pcInSymb)[i].rChan);
+                }
+            }
+
+            break;
+
+        case 1:
+            for (i = 0, k = 0; i < iInputBlockSize; i++, k += 2)
+            {
+                if (bIteration == TRUE)
+                {
+                    /* Real part -------------------------------------------- */
+#ifdef USE_MAX_LOG_MAP
+                    vecMetric[k].rTow0 =
+                        Minimum4((*pcInSymb)[i].cSig.real(),
+                                 rTableQAM64SM[BI_000 /* [0 0 0] */][0],
+                                 rTableQAM64SM[BI_100 /* [1 0 0] */][0],
+                                 rTableQAM64SM[BI_001 /* [0 0 1] */][0],
+                                 rTableQAM64SM[BI_101 /* [1 0 1] */][0],
+                                 (*pcInSymb)[i].rChan,
+                                 vecSubsetDef1[k], vecSubsetDef3[k]);
+
+                    vecMetric[k].rTow1 =
+                        Minimum4((*pcInSymb)[i].cSig.real(),
+                                 rTableQAM64SM[BI_010 /* [0 1 0] */][0],
+                                 rTableQAM64SM[BI_110 /* [1 1 0] */][0],
+                                 rTableQAM64SM[BI_011 /* [0 1 1] */][0],
+                                 rTableQAM64SM[BI_111 /* [1 1 1] */][0],
+                                 (*pcInSymb)[i].rChan,
+                                 vecSubsetDef1[k], vecSubsetDef3[k]);
+#else
+                    /* Lowest bit defined by "vecSubsetDef3",highest defined
+                       by "vecSubsetDef1" */
+                    iTabInd0 =
+                        ((ExtractBit(vecSubsetDef1[k]) & 1) << 2) |
+                        (ExtractBit(vecSubsetDef3[k]) & 1);
+
+                    vecMetric[k].rTow0 = Minimum1((*pcInSymb)[i].cSig.real(),
+                                                  rTableQAM64SM[iTabInd0][0],	(*pcInSymb)[i].rChan);
+
+                    vecMetric[k].rTow1 = Minimum1((*pcInSymb)[i].cSig.real(),
+                                                  rTableQAM64SM[iTabInd0 | (1 << 1)][0],
+                                                  (*pcInSymb)[i].rChan);
+#endif
+
+
+                    /* Imaginary part --------------------------------------- */
+#ifdef USE_MAX_LOG_MAP
+                    vecMetric[k + 1].rTow0 =
+                        Minimum4((*pcInSymb)[i].cSig.imag(),
+                                 rTableQAM64SM[BI_000 /* [0 0 0] */][1],
+                                 rTableQAM64SM[BI_100 /* [1 0 0] */][1],
+                                 rTableQAM64SM[BI_001 /* [0 0 1] */][1],
+                                 rTableQAM64SM[BI_101 /* [1 0 1] */][1],
+                                 (*pcInSymb)[i].rChan,
+                                 vecSubsetDef1[k + 1], vecSubsetDef3[k + 1]);
+
+                    vecMetric[k + 1].rTow1 =
+                        Minimum4((*pcInSymb)[i].cSig.imag(),
+                                 rTableQAM64SM[BI_010 /* [0 1 0] */][1],
+                                 rTableQAM64SM[BI_110 /* [1 1 0] */][1],
+                                 rTableQAM64SM[BI_011 /* [0 1 1] */][1],
+                                 rTableQAM64SM[BI_111 /* [1 1 1] */][1],
+                                 (*pcInSymb)[i].rChan,
+                                 vecSubsetDef1[k + 1], vecSubsetDef3[k + 1]);
+#else
+                    /* Lowest bit defined by "vecSubsetDef3",highest defined
+                       by "vecSubsetDef1" */
+                    iTabInd0 =
+                        ((ExtractBit(vecSubsetDef1[k + 1]) & 1) << 2) |
+                        (ExtractBit(vecSubsetDef3[k + 1]) & 1);
+
+                    vecMetric[k + 1].rTow0 =
+                        Minimum1((*pcInSymb)[i].cSig.imag(),
+                                 rTableQAM64SM[iTabInd0][1],
+                                 (*pcInSymb)[i].rChan);
+
+                    vecMetric[k + 1].rTow1 =
+                        Minimum1((*pcInSymb)[i].cSig.imag(),
+                                 rTableQAM64SM[iTabInd0 | (1 << 1)][1],
+                                 (*pcInSymb)[i].rChan);
+#endif
+                }
+                else
+                {
+                    /* There are two possible points for each bit. Both have to
+                       be used. In the first step: {i_2} = 0, Higest bit
+                       defined by "vecSubsetDef1" */
+
+                    /* Real part -------------------------------------------- */
+#ifdef USE_MAX_LOG_MAP
+                    vecMetric[k].rTow0 =
+                        Minimum4((*pcInSymb)[i].cSig.real(),
+                                 rTableQAM64SM[BI_000 /* [0 0 0] */][0],
+                                 rTableQAM64SM[BI_100 /* [1 0 0] */][0],
+                                 rTableQAM64SM[BI_001 /* [0 0 1] */][0],
+                                 rTableQAM64SM[BI_101 /* [1 0 1] */][0],
+                                 (*pcInSymb)[i].rChan,
+                                 vecSubsetDef1[k]);
+
+                    vecMetric[k].rTow1 =
+                        Minimum4((*pcInSymb)[i].cSig.real(),
+                                 rTableQAM64SM[BI_010 /* [0 1 0] */][0],
+                                 rTableQAM64SM[BI_110 /* [1 1 0] */][0],
+                                 rTableQAM64SM[BI_011 /* [0 1 1] */][0],
+                                 rTableQAM64SM[BI_111 /* [1 1 1] */][0],
+                                 (*pcInSymb)[i].rChan,
+                                 vecSubsetDef1[k]);
+#else
+                    iTabInd0 = ((ExtractBit(vecSubsetDef1[k]) & 1) << 2);
+                    vecMetric[k].rTow0 =
+                        Minimum2((*pcInSymb)[i].cSig.real(),
+                                 rTableQAM64SM[iTabInd0][0],
+                                 rTableQAM64SM[iTabInd0 | 1][0], (*pcInSymb)[i].rChan);
+
+                    iTabInd0 = ((ExtractBit(vecSubsetDef1[k]) & 1) << 2) |
+                               (1 << 1);
+                    vecMetric[k].rTow1 =
+                        Minimum2((*pcInSymb)[i].cSig.real(),
+                                 rTableQAM64SM[iTabInd0][0],
+                                 rTableQAM64SM[iTabInd0 | 1][0], (*pcInSymb)[i].rChan);
+#endif
+
+
+                    /* Imaginary part --------------------------------------- */
+#ifdef USE_MAX_LOG_MAP
+                    vecMetric[k + 1].rTow0 =
+                        Minimum4((*pcInSymb)[i].cSig.imag(),
+                                 rTableQAM64SM[BI_000 /* [0 0 0] */][1],
+                                 rTableQAM64SM[BI_100 /* [1 0 0] */][1],
+                                 rTableQAM64SM[BI_001 /* [0 0 1] */][1],
+                                 rTableQAM64SM[BI_101 /* [1 0 1] */][1],
+                                 (*pcInSymb)[i].rChan,
+                                 vecSubsetDef1[k + 1]);
+
+                    vecMetric[k + 1].rTow1 =
+                        Minimum4((*pcInSymb)[i].cSig.imag(),
+                                 rTableQAM64SM[BI_010 /* [0 1 0] */][1],
+                                 rTableQAM64SM[BI_110 /* [1 1 0] */][1],
+                                 rTableQAM64SM[BI_011 /* [0 1 1] */][1],
+                                 rTableQAM64SM[BI_111 /* [1 1 1] */][1],
+                                 (*pcInSymb)[i].rChan,
+                                 vecSubsetDef1[k + 1]);
+#else
+                    iTabInd0 = ((ExtractBit(vecSubsetDef1[k + 1]) & 1) << 2);
+                    vecMetric[k + 1].rTow0 =
+                        Minimum2((*pcInSymb)[i].cSig.imag(),
+                                 rTableQAM64SM[iTabInd0][1],
+                                 rTableQAM64SM[iTabInd0 | 1][1], (*pcInSymb)[i].rChan);
+
+                    iTabInd0 = ((ExtractBit(vecSubsetDef1[k + 1]) & 1) << 2) |
+                               (1 << 1);
+                    vecMetric[k + 1].rTow1 =
+                        Minimum2((*pcInSymb)[i].cSig.imag(),
+                                 rTableQAM64SM[iTabInd0][1],
+                                 rTableQAM64SM[iTabInd0 | 1][1], (*pcInSymb)[i].rChan);
+#endif
+                }
+            }
+
+            break;
+
+        case 2:
+            for (i = 0, k = 0; i < iInputBlockSize; i++, k += 2)
+            {
+                /* Real part ------------------------------------------------ */
+#ifdef USE_MAX_LOG_MAP
+                vecMetric[k].rTow0 =
+                    Minimum4((*pcInSymb)[i].cSig.real(),
+                             rTableQAM64SM[BI_000 /* [0 0 0] */][0],
+                             rTableQAM64SM[BI_100 /* [1 0 0] */][0],
+                             rTableQAM64SM[BI_010 /* [0 1 0] */][0],
+                             rTableQAM64SM[BI_110 /* [1 1 0] */][0],
+                             (*pcInSymb)[i].rChan,
+                             vecSubsetDef1[k], vecSubsetDef2[k]);
+
+                vecMetric[k].rTow1 =
+                    Minimum4((*pcInSymb)[i].cSig.real(),
+                             rTableQAM64SM[BI_001 /* [0 0 1] */][0],
+                             rTableQAM64SM[BI_101 /* [1 0 1] */][0],
+                             rTableQAM64SM[BI_011 /* [0 1 1] */][0],
+                             rTableQAM64SM[BI_111 /* [1 1 1] */][0],
+                             (*pcInSymb)[i].rChan,
+                             vecSubsetDef1[k], vecSubsetDef2[k]);
+#else
+                /* Higest bit defined by "vecSubsetDef1" next bit defined
+                   by "vecSubsetDef2" */
+                iTabInd0 =
+                    ((ExtractBit(vecSubsetDef1[k]) & 1) << 2) |
+                    ((ExtractBit(vecSubsetDef2[k]) & 1) << 1);
+
+                vecMetric[k].rTow0 = Minimum1((*pcInSymb)[i].cSig.real(),
+                                              rTableQAM64SM[iTabInd0][0], (*pcInSymb)[i].rChan);
+
+                vecMetric[k].rTow1 = Minimum1((*pcInSymb)[i].cSig.real(),
+                                              rTableQAM64SM[iTabInd0 | 1][0], (*pcInSymb)[i].rChan);
+#endif
+
+
+                /* Imaginary part ------------------------------------------- */
+#ifdef USE_MAX_LOG_MAP
+                vecMetric[k + 1].rTow0 =
+                    Minimum4((*pcInSymb)[i].cSig.imag(),
+                             rTableQAM64SM[BI_000 /* [0 0 0] */][1],
+                             rTableQAM64SM[BI_100 /* [1 0 0] */][1],
+                             rTableQAM64SM[BI_010 /* [0 1 0] */][1],
+                             rTableQAM64SM[BI_110 /* [1 1 0] */][1],
+                             (*pcInSymb)[i].rChan,
+                             vecSubsetDef1[k + 1], vecSubsetDef2[k + 1]);
+
+                vecMetric[k + 1].rTow1 =
+                    Minimum4((*pcInSymb)[i].cSig.imag(),
+                             rTableQAM64SM[BI_001 /* [0 0 1] */][1],
+                             rTableQAM64SM[BI_101 /* [1 0 1] */][1],
+                             rTableQAM64SM[BI_011 /* [0 1 1] */][1],
+                             rTableQAM64SM[BI_111 /* [1 1 1] */][1],
+                             (*pcInSymb)[i].rChan,
+                             vecSubsetDef1[k + 1], vecSubsetDef2[k + 1]);
+#else
+                /* Higest bit defined by "vecSubsetDef1" next bit defined
+                   by "vecSubsetDef2" */
+                iTabInd0 =
+                    ((ExtractBit(vecSubsetDef1[k + 1]) & 1) << 2) |
+                    ((ExtractBit(vecSubsetDef2[k + 1]) & 1) << 1);
+
+                /* Calculate distances, imaginary part */
+                vecMetric[k + 1].rTow0 = Minimum1((*pcInSymb)[i].cSig.imag(),
+                                                  rTableQAM64SM[iTabInd0][1], (*pcInSymb)[i].rChan);
+
+                vecMetric[k + 1].rTow1 = Minimum1((*pcInSymb)[i].cSig.imag(),
+                                                  rTableQAM64SM[iTabInd0 | 1][1], (*pcInSymb)[i].rChan);
+#endif
+            }
+
+            break;
+        }
+
+        break;
+
+    case CS_3_HMSYM:
+        /**********************************************************************/
+        /* 64QAM HMsym ********************************************************/
+        /**********************************************************************/
+        /* (i_0  i_1  i_2  q_0  q_1  q_2) =
+           (y_0,0  y_1,0  y_2,0  y_0,1  y_1,1  y_2,1) */
+        switch (iLevel)
+        {
+        case 0:
+            for (i = 0, k = 0; i < iInputBlockSize; i++, k += 2)
+            {
+                if (bIteration == TRUE)
+                {
+                    /* Real part -------------------------------------------- */
+                    /* Lowest bit defined by "vecSubsetDef3" next bit defined
+                       by "vecSubsetDef2" */
+                    iTabInd0 =
+                        (ExtractBit(vecSubsetDef3[k]) & 1) |
+                        ((ExtractBit(vecSubsetDef2[k]) & 1) << 1);
+
+                    vecMetric[k].rTow0 = Minimum1((*pcInSymb)[i].cSig.real(),
+                                                  rTableQAM64HMsym[iTabInd0][0], (*pcInSymb)[i].rChan);
+
+                    vecMetric[k].rTow1 = Minimum1((*pcInSymb)[i].cSig.real(),
+                                                  rTableQAM64HMsym[iTabInd0 | (1 << 2)][0],
+                                                  (*pcInSymb)[i].rChan);
+
+
+                    /* Imaginary part --------------------------------------- */
+                    /* Lowest bit defined by "vecSubsetDef3" next bit defined
+                       by "vecSubsetDef2" */
+                    iTabInd0 =
+                        (ExtractBit(vecSubsetDef3[k + 1]) & 1) |
+                        ((ExtractBit(vecSubsetDef2[k + 1]) & 1) << 1);
+
+                    /* Calculate distances, imaginary part */
+                    vecMetric[k + 1].rTow0 =
+                        Minimum1((*pcInSymb)[i].cSig.imag(),
+                                 rTableQAM64HMsym[iTabInd0][1], (*pcInSymb)[i].rChan);
+
+                    vecMetric[k + 1].rTow1 =
+                        Minimum1((*pcInSymb)[i].cSig.imag(),
+                                 rTableQAM64HMsym[iTabInd0 | (1 << 2)][1],
+                                 (*pcInSymb)[i].rChan);
+                }
+                else
+                {
+                    /* Real part -------------------------------------------- */
+                    vecMetric[k].rTow0 =
+                        Minimum4((*pcInSymb)[i].cSig.real(),
+                                 rTableQAM64HMsym[BI_000 /* [0 0 0] */][0],
+                                 rTableQAM64HMsym[BI_001 /* [0 0 1] */][0],
+                                 rTableQAM64HMsym[BI_010 /* [0 1 0] */][0],
+                                 rTableQAM64HMsym[BI_011 /* [0 1 1] */][0],
+                                 (*pcInSymb)[i].rChan);
+
+                    vecMetric[k].rTow1 =
+                        Minimum4((*pcInSymb)[i].cSig.real(),
+                                 rTableQAM64HMsym[BI_100 /* [1 0 0] */][0],
+                                 rTableQAM64HMsym[BI_101 /* [1 0 1] */][0],
+                                 rTableQAM64HMsym[BI_110 /* [1 1 0] */][0],
+                                 rTableQAM64HMsym[BI_111 /* [1 1 1] */][0],
+                                 (*pcInSymb)[i].rChan);
+
+
+                    /* Imaginary part --------------------------------------- */
+                    vecMetric[k + 1].rTow0 =
+                        Minimum4((*pcInSymb)[i].cSig.imag(),
+                                 rTableQAM64HMsym[BI_000 /* [0 0 0] */][1],
+                                 rTableQAM64HMsym[BI_001 /* [0 0 1] */][1],
+                                 rTableQAM64HMsym[BI_010 /* [0 1 0] */][1],
+                                 rTableQAM64HMsym[BI_011 /* [0 1 1] */][1],
+                                 (*pcInSymb)[i].rChan);
+
+                    vecMetric[k + 1].rTow1 =
+                        Minimum4((*pcInSymb)[i].cSig.imag(),
+                                 rTableQAM64HMsym[BI_100 /* [1 0 0] */][1],
+                                 rTableQAM64HMsym[BI_101 /* [1 0 1] */][1],
+                                 rTableQAM64HMsym[BI_110 /* [1 1 0] */][1],
+                                 rTableQAM64HMsym[BI_111 /* [1 1 1] */][1],
+                                 (*pcInSymb)[i].rChan);
+                }
+            }
+
+            break;
+
+        case 1:
+            for (i = 0, k = 0; i < iInputBlockSize; i++, k += 2)
+            {
+                if (bIteration == TRUE)
+                {
+                    /* Real part -------------------------------------------- */
+                    /* Lowest bit defined by "vecSubsetDef3",highest defined
+                       by "vecSubsetDef1" */
+                    iTabInd0 =
+                        ((ExtractBit(vecSubsetDef1[k]) & 1) << 2) |
+                        (ExtractBit(vecSubsetDef3[k]) & 1);
+
+                    vecMetric[k].rTow0 = Minimum1((*pcInSymb)[i].cSig.real(),
+                                                  rTableQAM64HMsym[iTabInd0][0],
+                                                  (*pcInSymb)[i].rChan);
+
+                    vecMetric[k].rTow1 = Minimum1((*pcInSymb)[i].cSig.real(),
+                                                  rTableQAM64HMsym[iTabInd0 | (1 << 1)][0],
+                                                  (*pcInSymb)[i].rChan);
+
+
+                    /* Imaginary part --------------------------------------- */
+                    /* Lowest bit defined by "vecSubsetDef3",highest defined
+                       by "vecSubsetDef1" */
+                    iTabInd0 =
+                        ((ExtractBit(vecSubsetDef1[k + 1]) & 1) << 2) |
+                        (ExtractBit(vecSubsetDef3[k + 1]) & 1);
+
+                    vecMetric[k + 1].rTow0 =
+                        Minimum1((*pcInSymb)[i].cSig.imag(),
+                                 rTableQAM64HMsym[iTabInd0][1], (*pcInSymb)[i].rChan);
+
+                    vecMetric[k + 1].rTow1 =
+                        Minimum1((*pcInSymb)[i].cSig.imag(),
+                                 rTableQAM64HMsym[iTabInd0 | (1 << 1)][1],
+                                 (*pcInSymb)[i].rChan);
+                }
+                else
+                {
+                    /* There are two possible points for each bit. Both have to
+                       be used. In the first step: {i_2} = 0, Higest bit
+                       defined by "vecSubsetDef1" */
+
+                    /* Real part -------------------------------------------- */
+                    iTabInd0 = ((ExtractBit(vecSubsetDef1[k]) & 1) << 2);
+                    vecMetric[k].rTow0 =
+                        Minimum2((*pcInSymb)[i].cSig.real(),
+                                 rTableQAM64HMsym[iTabInd0][0],
+                                 rTableQAM64HMsym[iTabInd0 | 1][0],
+                                 (*pcInSymb)[i].rChan);
+
+                    iTabInd0 = ((ExtractBit(vecSubsetDef1[k]) & 1) << 2) |
+                               (1 << 1);
+                    vecMetric[k].rTow1 =
+                        Minimum2((*pcInSymb)[i].cSig.real(),
+                                 rTableQAM64HMsym[iTabInd0][0],
+                                 rTableQAM64HMsym[iTabInd0 | 1][0],
+                                 (*pcInSymb)[i].rChan);
+
+
+                    /* Imaginary part --------------------------------------- */
+                    iTabInd0 = ((ExtractBit(vecSubsetDef1[k + 1]) & 1) << 2);
+                    vecMetric[k + 1].rTow0 =
+                        Minimum2((*pcInSymb)[i].cSig.imag(),
+                                 rTableQAM64HMsym[iTabInd0][1],
+                                 rTableQAM64HMsym[iTabInd0 | 1][1],
+                                 (*pcInSymb)[i].rChan);
+
+                    iTabInd0 = ((ExtractBit(vecSubsetDef1[k + 1]) & 1) << 2) |
+                               (1 << 1);
+                    vecMetric[k + 1].rTow1 =
+                        Minimum2((*pcInSymb)[i].cSig.imag(),
+                                 rTableQAM64HMsym[iTabInd0][1],
+                                 rTableQAM64HMsym[iTabInd0 | 1][1],
+                                 (*pcInSymb)[i].rChan);
+                }
+            }
+
+            break;
+
+        case 2:
+            for (i = 0, k = 0; i < iInputBlockSize; i++, k += 2)
+            {
+                /* Real part ------------------------------------------------ */
+                /* Higest bit defined by "vecSubsetDef1" next bit defined
+                   by "vecSubsetDef2" */
+                iTabInd0 =
+                    ((ExtractBit(vecSubsetDef1[k]) & 1) << 2) |
+                    ((ExtractBit(vecSubsetDef2[k]) & 1) << 1);
+
+                vecMetric[k].rTow0 = Minimum1((*pcInSymb)[i].cSig.real(),
+                                              rTableQAM64HMsym[iTabInd0][0], (*pcInSymb)[i].rChan);
+
+                vecMetric[k].rTow1 = Minimum1((*pcInSymb)[i].cSig.real(),
+                                              rTableQAM64HMsym[iTabInd0 | 1][0], (*pcInSymb)[i].rChan);
+
+
+                /* Imaginary part ------------------------------------------- */
+                /* Higest bit defined by "vecSubsetDef1" next bit defined
+                   by "vecSubsetDef2" */
+                iTabInd0 =
+                    ((ExtractBit(vecSubsetDef1[k + 1]) & 1) << 2) |
+                    ((ExtractBit(vecSubsetDef2[k + 1]) & 1) << 1);
+
+                /* Calculate distances, imaginary part */
+                vecMetric[k + 1].rTow0 = Minimum1((*pcInSymb)[i].cSig.imag(),
+                                                  rTableQAM64HMsym[iTabInd0][1], (*pcInSymb)[i].rChan);
+
+                vecMetric[k + 1].rTow1 = Minimum1((*pcInSymb)[i].cSig.imag(),
+                                                  rTableQAM64HMsym[iTabInd0 | 1][1], (*pcInSymb)[i].rChan);
+            }
+
+            break;
+        }
+
+        break;
+
+    case CS_3_HMMIX:
+        /**********************************************************************/
+        /* 64QAM HMmix ********************************************************/
+        /**********************************************************************/
+        /* (i_0  i_1  i_2  q_0  q_1  q_2) =
+           (y_0,0Re  y_1,0Re  y_2,0Re  y_0,0Im  y_1,0Im  y_2,0Im) */
+        switch (iLevel)
+        {
+        case 0:
+            for (i = 0; i < iInputBlockSize; i++)
+            {
+                if (bIteration == TRUE)
+                {
+                    /* Real part -------------------------------------------- */
+                    /* Lowest bit defined by "vecSubsetDef5" next bit defined
+                       by "vecSubsetDef3" */
+                    iTabInd0 =
+                        (ExtractBit(vecSubsetDef5[i]) & 1) |
+                        ((ExtractBit(vecSubsetDef3[i]) & 1) << 1);
+
+                    vecMetric[i].rTow0 = Minimum1((*pcInSymb)[i].cSig.real(),
+                                                  rTableQAM64HMmix[iTabInd0][0], (*pcInSymb)[i].rChan);
+
+                    vecMetric[i].rTow1 = Minimum1((*pcInSymb)[i].cSig.real(),
+                                                  rTableQAM64HMmix[iTabInd0 | (1 << 2)][0],
+                                                  (*pcInSymb)[i].rChan);
+                }
+                else
+                {
+                    /* Real part -------------------------------------------- */
+                    vecMetric[i].rTow0 = Minimum4((*pcInSymb)[i].cSig.real(),
+                                                  rTableQAM64HMmix[BI_000 /* [0 0 0] */][0],
+                                                  rTableQAM64HMmix[BI_001 /* [0 0 1] */][0],
+                                                  rTableQAM64HMmix[BI_010 /* [0 1 0] */][0],
+                                                  rTableQAM64HMmix[BI_011 /* [0 1 1] */][0],
+                                                  (*pcInSymb)[i].rChan);
+
+                    vecMetric[i].rTow1 = Minimum4((*pcInSymb)[i].cSig.real(),
+                                                  rTableQAM64HMmix[BI_100 /* [1 0 0] */][0],
+                                                  rTableQAM64HMmix[BI_101 /* [1 0 1] */][0],
+                                                  rTableQAM64HMmix[BI_110 /* [1 1 0] */][0],
+                                                  rTableQAM64HMmix[BI_111 /* [1 1 1] */][0],
+                                                  (*pcInSymb)[i].rChan);
+                }
+            }
+
+            break;
+
+        case 1:
+            for (i = 0; i < iInputBlockSize; i++)
+            {
+                if (bIteration == TRUE)
+                {
+                    /* Imaginary part --------------------------------------- */
+                    /* Lowest bit defined by "vecSubsetDef6" next bit defined
+                       by "vecSubsetDef4" */
+                    iTabInd0 =
+                        (ExtractBit(vecSubsetDef6[i]) & 1) |
+                        ((ExtractBit(vecSubsetDef4[i]) & 1) << 1);
+
+                    /* Calculate distances, imaginary part */
+                    vecMetric[i].rTow0 = Minimum1((*pcInSymb)[i].cSig.imag(),
+                                                  rTableQAM64HMmix[iTabInd0][1], (*pcInSymb)[i].rChan);
+
+                    vecMetric[i].rTow1 = Minimum1((*pcInSymb)[i].cSig.imag(),
+                                                  rTableQAM64HMmix[iTabInd0 | (1 << 2)][1],
+                                                  (*pcInSymb)[i].rChan);
+                }
+                else
+                {
+                    /* Imaginary part --------------------------------------- */
+                    vecMetric[i].rTow0 = Minimum4((*pcInSymb)[i].cSig.imag(),
+                                                  rTableQAM64HMmix[BI_000 /* [0 0 0] */][1],
+                                                  rTableQAM64HMmix[BI_001 /* [0 0 1] */][1],
+                                                  rTableQAM64HMmix[BI_010 /* [0 1 0] */][1],
+                                                  rTableQAM64HMmix[BI_011 /* [0 1 1] */][1],
+                                                  (*pcInSymb)[i].rChan);
+
+                    vecMetric[i].rTow1 = Minimum4((*pcInSymb)[i].cSig.imag(),
+                                                  rTableQAM64HMmix[BI_100 /* [1 0 0] */][1],
+                                                  rTableQAM64HMmix[BI_101 /* [1 0 1] */][1],
+                                                  rTableQAM64HMmix[BI_110 /* [1 1 0] */][1],
+                                                  rTableQAM64HMmix[BI_111 /* [1 1 1] */][1],
+                                                  (*pcInSymb)[i].rChan);
+                }
+            }
+
+            break;
+
+        case 2:
+            for (i = 0; i < iInputBlockSize; i++)
+            {
+                if (bIteration == TRUE)
+                {
+                    /* Real part -------------------------------------------- */
+                    /* Lowest bit defined by "vecSubsetDef5",highest defined
+                       by "vecSubsetDef1" */
+                    iTabInd0 =
+                        ((ExtractBit(vecSubsetDef1[i]) & 1) << 2) |
+                        (ExtractBit(vecSubsetDef5[i]) & 1);
+
+                    vecMetric[i].rTow0 = Minimum1((*pcInSymb)[i].cSig.real(),
+                                                  rTableQAM64HMmix[iTabInd0][0], (*pcInSymb)[i].rChan);
+
+                    vecMetric[i].rTow1 = Minimum1((*pcInSymb)[i].cSig.real(),
+                                                  rTableQAM64HMmix[iTabInd0 | (1 << 1)][0],
+                                                  (*pcInSymb)[i].rChan);
+                }
+                else
+                {
+                    /* There are two possible points for each bit. Both have to
+                       be used. In the first step: {i_2} = 0, Higest bit
+                       defined by "vecSubsetDef1" */
+
+                    /* Real part -------------------------------------------- */
+                    iTabInd0 = ((ExtractBit(vecSubsetDef1[i]) & 1) << 2);
+                    vecMetric[i].rTow0 = Minimum2((*pcInSymb)[i].cSig.real(),
+                                                  rTableQAM64HMmix[iTabInd0][0],
+                                                  rTableQAM64HMmix[iTabInd0 | 1][0],
+                                                  (*pcInSymb)[i].rChan);
+
+                    iTabInd0 =
+                        ((ExtractBit(vecSubsetDef1[i]) & 1) << 2) | (1 << 1);
+                    vecMetric[i].rTow1 = Minimum2((*pcInSymb)[i].cSig.real(),
+                                                  rTableQAM64HMmix[iTabInd0][0],
+                                                  rTableQAM64HMmix[iTabInd0 | 1][0],
+                                                  (*pcInSymb)[i].rChan);
+                }
+            }
+
+            break;
+
+        case 3:
+            for (i = 0; i < iInputBlockSize; i++)
+            {
+                if (bIteration == TRUE)
+                {
+                    /* Imaginary part --------------------------------------- */
+                    /* Lowest bit defined by "vecSubsetDef6",highest defined
+                       by "vecSubsetDef2" */
+                    iTabInd0 =
+                        ((ExtractBit(vecSubsetDef2[i]) & 1) << 2) |
+                        (ExtractBit(vecSubsetDef6[i]) & 1);
+
+                    vecMetric[i].rTow0 = Minimum1((*pcInSymb)[i].cSig.imag(),
+                                                  rTableQAM64HMmix[iTabInd0][1], (*pcInSymb)[i].rChan);
+
+                    vecMetric[i].rTow1 = Minimum1((*pcInSymb)[i].cSig.imag(),
+                                                  rTableQAM64HMmix[iTabInd0 | (1 << 1)][1],
+                                                  (*pcInSymb)[i].rChan);
+                }
+                else
+                {
+                    /* There are two possible points for each bit. Both have to
+                       be used. In the first step: {i_2} = 0, Higest bit
+                       defined by "vecSubsetDef1" */
+
+                    /* Imaginary part ------------------------------------------- */
+                    iTabInd0 = ((ExtractBit(vecSubsetDef2[i]) & 1) << 2);
+                    vecMetric[i].rTow0 = Minimum2((*pcInSymb)[i].cSig.imag(),
+                                                  rTableQAM64HMmix[iTabInd0][1],
+                                                  rTableQAM64HMmix[iTabInd0 | 1][1], (*pcInSymb)[i].rChan);
+
+                    iTabInd0 =
+                        ((ExtractBit(vecSubsetDef2[i]) & 1) << 2) | (1 << 1);
+                    vecMetric[i].rTow1 = Minimum2((*pcInSymb)[i].cSig.imag(),
+                                                  rTableQAM64HMmix[iTabInd0][1],
+                                                  rTableQAM64HMmix[iTabInd0 | 1][1], (*pcInSymb)[i].rChan);
+                }
+            }
+
+            break;
+
+        case 4:
+            for (i = 0; i < iInputBlockSize; i++)
+            {
+                /* Real part ------------------------------------------------ */
+                /* Higest bit defined by "vecSubsetDef1" next bit defined
+                   by "vecSubsetDef2" */
+                iTabInd0 =
+                    ((ExtractBit(vecSubsetDef1[i]) & 1) << 2) |
+                    ((ExtractBit(vecSubsetDef3[i]) & 1) << 1);
+
+                vecMetric[i].rTow0 = Minimum1((*pcInSymb)[i].cSig.real(),
+                                              rTableQAM64HMmix[iTabInd0][0], (*pcInSymb)[i].rChan);
+
+                vecMetric[i].rTow1 = Minimum1((*pcInSymb)[i].cSig.real(),
+                                              rTableQAM64HMmix[iTabInd0 | 1][0], (*pcInSymb)[i].rChan);
+            }
+
+            break;
+
+        case 5:
+            for (i = 0; i < iInputBlockSize; i++)
+            {
+                /* Imaginary part ------------------------------------------- */
+                /* Higest bit defined by "vecSubsetDef1" next bit defined
+                   by "vecSubsetDef2" */
+                iTabInd0 =
+                    ((ExtractBit(vecSubsetDef2[i]) & 1) << 2) |
+                    ((ExtractBit(vecSubsetDef4[i]) & 1) << 1);
+
+                /* Calculate distances, imaginary part */
+                vecMetric[i].rTow0 = Minimum1((*pcInSymb)[i].cSig.imag(),
+                                              rTableQAM64HMmix[iTabInd0][1], (*pcInSymb)[i].rChan);
+
+                vecMetric[i].rTow1 = Minimum1((*pcInSymb)[i].cSig.imag(),
+                                              rTableQAM64HMmix[iTabInd0 | 1][1], (*pcInSymb)[i].rChan);
+            }
+
+            break;
+        }
+
+        break;
+    }
+
+#ifdef USE_ERASURE_FOR_FASTER_ACQ
+    /* Take care of special case with "CS_3_HMMIX" */
+    if (eMapType != CS_3_HMMIX)
+    {
+        for (i = 0; i < iInputBlockSize; i++)
+        {
+            /* If input symbol is erasure, reset metrics to zero */
+            if ((*pcInSymb)[i].rChan == ERASURE_TAG_VALUE)
+            {
+                vecMetric[2 * i].rTow0 = (_REAL) 0.0;
+                vecMetric[2 * i].rTow1 = (_REAL) 0.0;
+                vecMetric[2 * i + 1].rTow0 = (_REAL) 0.0;
+                vecMetric[2 * i + 1].rTow1 = (_REAL) 0.0;
+            }
+        }
+    }
+    else
+    {
+        for (i = 0; i < iInputBlockSize; i++)
+        {
+            /* If input symbol is erasure, reset metrics to zero */
+            if ((*pcInSymb)[i].rChan == ERASURE_TAG_VALUE)
+            {
+                vecMetric[i].rTow0 = (_REAL) 0.0;
+                vecMetric[i].rTow1 = (_REAL) 0.0;
+            }
+        }
+    }
+#endif
+}
+
+void CMLCMetric::Init(int iNewInputBlockSize, ECodScheme eNewCodingScheme)
+{
+    iInputBlockSize = iNewInputBlockSize;
+    eMapType = eNewCodingScheme;
+}
+
+/* Cleanup definitions afterwards */
+#undef BI_00
+#undef BI_01
+#undef BI_10
+#undef BI_11
+#undef BI_000
+#undef BI_001
+#undef BI_010
+#undef BI_011
+#undef BI_100
+#undef BI_101
+#undef BI_110
+#undef BI_111
diff --git a/src/mlc/Metric.h b/src/mlc/Metric.h
new file mode 100644
index 0000000..76e4202
--- /dev/null
+++ b/src/mlc/Metric.h
@@ -0,0 +1,232 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#if !defined(MLC_METRIC_H__3B0BA660_CA63_4344_BB2B_23E7A0D31912__INCLUDED_)
+#define MLC_METRIC_H__3B0BA660_CA63_4344_BB2B_23E7A0D31912__INCLUDED_
+
+#include "../GlobalDefinitions.h"
+#include "../tables/TableQAMMapping.h"
+#include "../util/Vector.h"
+#include "../Parameter.h"
+
+
+/* Classes ********************************************************************/
+inline _REAL Metric(const _REAL rDist, const _REAL rChan)
+{
+    /* The calculation of "rChan" was done in the channel estimation module */
+#ifdef USE_MAX_LOG_MAP
+    /* | r / h - s | ^ 2 * | h | ^ 2 */
+    return rDist * rDist * rChan;
+#else
+    /* | r / h - s | * | h | */
+    return rDist * rChan;
+#endif
+}
+
+class CMLCMetric
+{
+public:
+    CMLCMetric() {}
+    virtual ~CMLCMetric() {}
+
+    /* Return the number of used symbols for calculating one branch-metric */
+    void CalculateMetric(CVector<CEquSig>* pcInSymb,
+                         CVector<CDistance>& vecMetric,
+                         CVector<_DECISION>& vecSubsetDef1,
+                         CVector<_DECISION>& vecSubsetDef2,
+                         CVector<_DECISION>& vecSubsetDef3,
+                         CVector<_DECISION>& vecSubsetDef4,
+                         CVector<_DECISION>& vecSubsetDef5,
+                         CVector<_DECISION>& vecSubsetDef6,
+                         int iLevel, _BOOLEAN bIteration);
+    void Init(int iNewInputBlockSize, ECodScheme eNewCodingScheme);
+
+protected:
+#ifdef USE_MAX_LOG_MAP
+    inline _REAL Minimum2(const _REAL rA, const _REAL rX0, const _REAL rX1,
+                          const _REAL rChan, const _REAL rLVal0) const
+    {
+        /* X0: L0 < 0
+           X1: L0 > 0 */
+
+        /* First, calculate all distances */
+        _REAL rResult1 = Metric(fabs(rA - rX0), rChan);
+        _REAL rResult2 = Metric(fabs(rA - rX1), rChan);
+
+        /* Add L-value to metrics which to not correspond to correct hard decision */
+        if (rLVal0 > 0.0)
+            rResult1 += rLVal0;
+        else
+            rResult2 -= rLVal0;
+
+        /* Return smallest one */
+        if (rResult1 < rResult2)
+            return rResult1;
+        else
+            return rResult2;
+    }
+
+    inline _REAL Minimum4(const _REAL rA, const _REAL rX00, const _REAL rX01,
+                          const _REAL rX10, _REAL rX11, const _REAL rChan,
+                          const _REAL rLVal0) const
+    {
+        /* X00: L0 < 0
+           X01: L0 > 0
+           X10: L0 < 0
+           X11: L0 > 0 */
+
+        /* First, calculate all distances */
+        _REAL rResult1 = Metric(fabs(rA - rX00), rChan);
+        _REAL rResult2 = Metric(fabs(rA - rX01), rChan);
+        _REAL rResult3 = Metric(fabs(rA - rX10), rChan);
+        _REAL rResult4 = Metric(fabs(rA - rX11), rChan);
+
+        /* Add L-value to metrics which to not correspond to correct hard decision */
+        if (rLVal0 > 0.0)
+        {
+            rResult1 += rLVal0;
+            rResult3 += rLVal0;
+        }
+        else
+        {
+            rResult2 -= rLVal0;
+            rResult4 -= rLVal0;
+        }
+
+        /* Search for smallest one */
+        _REAL rReturn = rResult1;
+        if (rResult2 < rReturn)
+            rReturn = rResult2;
+        if (rResult3 < rReturn)
+            rReturn = rResult3;
+        if (rResult4 < rReturn)
+            rReturn = rResult4;
+
+        return rReturn;
+    }
+
+    inline _REAL Minimum4(const _REAL rA, const _REAL rX00, const _REAL rX01,
+                          const _REAL rX10, _REAL rX11, const _REAL rChan,
+                          const _REAL rLVal0, const _REAL rLVal1) const
+    {
+        /* X00: L0 < 0, L1 < 0
+           X01: L0 > 0, L1 < 0
+           X10: L0 < 0, L1 > 0
+           X11: L0 > 0, L1 > 0 */
+
+        /* First, calculate all distances */
+        _REAL rResult1 = Metric(fabs(rA - rX00), rChan);
+        _REAL rResult2 = Metric(fabs(rA - rX01), rChan);
+        _REAL rResult3 = Metric(fabs(rA - rX10), rChan);
+        _REAL rResult4 = Metric(fabs(rA - rX11), rChan);
+
+        /* Add L-value to metrics which to not correspond to correct hard decision */
+        if (rLVal0 > 0.0)
+        {
+            rResult1 += rLVal0;
+            rResult3 += rLVal0;
+        }
+        else
+        {
+            rResult2 -= rLVal0;
+            rResult4 -= rLVal0;
+        }
+
+        if (rLVal1 > 0.0)
+        {
+            rResult1 += rLVal1;
+            rResult2 += rLVal1;
+        }
+        else
+        {
+            rResult3 -= rLVal1;
+            rResult4 -= rLVal1;
+        }
+
+        /* Search for smallest one */
+        _REAL rReturn = rResult1;
+        if (rResult2 < rReturn)
+            rReturn = rResult2;
+        if (rResult3 < rReturn)
+            rReturn = rResult3;
+        if (rResult4 < rReturn)
+            rReturn = rResult4;
+
+        return rReturn;
+    }
+#endif
+
+    inline _REAL Minimum1(const _REAL rA, const _REAL rB,
+                          const _REAL rChan) const
+    {
+        /* The minium in case of only one parameter is trivial */
+        return Metric(fabs(rA - rB), rChan);
+    }
+
+    inline _REAL Minimum2(const _REAL rA, const _REAL rB1, const _REAL rB2,
+                          const _REAL rChan) const
+    {
+        /* First, calculate all distances */
+        const _REAL rResult1 = fabs(rA - rB1);
+        const _REAL rResult2 = fabs(rA - rB2);
+
+        /* Return smallest one */
+        if (rResult1 < rResult2)
+            return Metric(rResult1, rChan);
+        else
+            return Metric(rResult2, rChan);
+    }
+
+    inline _REAL Minimum4(const _REAL rA, const _REAL rB1, const _REAL rB2,
+                          const _REAL rB3, _REAL rB4, const _REAL rChan) const
+    {
+        /* First, calculate all distances */
+        const _REAL rResult1 = fabs(rA - rB1);
+        const _REAL rResult2 = fabs(rA - rB2);
+        const _REAL rResult3 = fabs(rA - rB3);
+        const _REAL rResult4 = fabs(rA - rB4);
+
+        /* Search for smallest one */
+        _REAL rReturn = rResult1;
+        if (rResult2 < rReturn)
+            rReturn = rResult2;
+        if (rResult3 < rReturn)
+            rReturn = rResult3;
+        if (rResult4 < rReturn)
+            rReturn = rResult4;
+
+        return Metric(rReturn, rChan);
+    }
+
+
+    int						iInputBlockSize;
+    ECodScheme	eMapType;
+};
+
+
+#endif // !defined(MLC_METRIC_H__3B0BA660_CA63_4344_BB2B_23E7A0D31912__INCLUDED_)
diff --git a/src/mlc/QAMMapping.cpp b/src/mlc/QAMMapping.cpp
new file mode 100644
index 0000000..b9203fe
--- /dev/null
+++ b/src/mlc/QAMMapping.cpp
@@ -0,0 +1,175 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "QAMMapping.h"
+
+
+/* Implementation *************************************************************/
+void CQAMMapping::Map(CVector<_DECISION>& vecInputData1,
+                      CVector<_DECISION>& vecInputData2,
+                      CVector<_DECISION>& vecInputData3,
+                      CVector<_DECISION>& vecInputData4,
+                      CVector<_DECISION>& vecInputData5,
+                      CVector<_DECISION>& vecInputData6,
+                      CVector<_COMPLEX>* pcOutputData)
+{
+    /*
+    	We always use "& 1" when we combine binary values with logical operators
+    	for safety reasons.
+    */
+    int i;
+    int iIndexReal;
+    int iIndexImag;
+
+    switch (eMapType)
+    {
+    case CS_1_SM:
+        /* 4QAM ------------------------------------------------------------- */
+        /* Mapping according DRM-standard:
+           {i_0  q_0} = (y'_0  y'_1) = (y_0,0  y_0,1) */
+        for (i = 0; i < iOutputBlockSize; i++)
+        {
+            (*pcOutputData)[i] = _COMPLEX(
+                                     /* Odd entries (second column in "rTableQAM4") */
+                                     rTableQAM4[ExtractBit(vecInputData1[2 * i]) & 1][0],
+                                     /* Even entries in input-vector */
+                                     rTableQAM4[ExtractBit(vecInputData1[2 * i + 1]) & 1][1]);
+        }
+        break;
+
+    case CS_2_SM:
+        /* 16QAM ------------------------------------------------------------ */
+        /* Mapping according DRM-standard:
+           {i_0  i_1  q_0  q_1} = (y_0,0  y_1,0  y_0,1  y_1,1) */
+        for (i = 0; i < iOutputBlockSize; i++)
+        {
+            const int i2i = 2 * i;
+            const int i2ip1 = 2 * i + 1;
+
+            /* Filling indices [y_0,0, y_1,0]. Incoming bits are shifted to
+               their desired positions in the integer variables "iIndexImag"
+               and "iIndexReal" and combined */
+            iIndexReal = ((ExtractBit(vecInputData1[i2i]) & 1) << 1) |
+                         (ExtractBit(vecInputData2[i2i]) & 1);
+            iIndexImag = ((ExtractBit(vecInputData1[i2ip1]) & 1) << 1) |
+                         (ExtractBit(vecInputData2[i2ip1]) & 1);
+
+            (*pcOutputData)[i] =
+                /* Odd entries (second column in "rTableQAM16") */
+                _COMPLEX(rTableQAM16[iIndexReal][0],
+                         /* Even entries in input-vector */
+                         rTableQAM16[iIndexImag][1]);
+        }
+        break;
+
+    case CS_3_SM:
+        /* 64QAM SM --------------------------------------------------------- */
+        /* Mapping according DRM-standard: {i_0  i_1  i_2  q_0  q_1  q_2} =
+           (y_0,0  y_1,0  y_2,0  y_0,1  y_1,1  y_2,1) */
+        for (i = 0; i < iOutputBlockSize; i++)
+        {
+            const int i2i = 2 * i;
+            const int i2ip1 = 2 * i + 1;
+
+            /* Filling indices [y_0,0, y_1,0, y_2,0]. Incoming bits
+               are shifted to their desired positions in the integer variables
+               "iIndexImag" and "iIndexReal" and combined */
+            iIndexReal = ((ExtractBit(vecInputData1[i2i]) & 1) << 2) |
+                         ((ExtractBit(vecInputData2[i2i]) & 1) << 1) |
+                         (ExtractBit(vecInputData3[i2i]) & 1);
+            iIndexImag = ((ExtractBit(vecInputData1[i2ip1]) & 1) << 2) |
+                         ((ExtractBit(vecInputData2[i2ip1]) & 1) << 1) |
+                         (ExtractBit(vecInputData3[i2ip1]) & 1);
+
+            (*pcOutputData)[i] =
+                /* Odd entries (second column in "rTableQAM64SM") */
+                _COMPLEX(rTableQAM64SM[iIndexReal][0],
+                         /* Even entries in input-vector */
+                         rTableQAM64SM[iIndexImag][1]);
+        }
+        break;
+
+    case CS_3_HMSYM:
+        /* 64QAM HMsym ------------------------------------------------------ */
+        /* Mapping according DRM-standard: {i_0  i_1  i_2  q_0  q_1  q_2} =
+           (y_0,0  y_1,0  y_2,0  y_0,1  y_1,1  y_2,1) */
+        for (i = 0; i < iOutputBlockSize; i++)
+        {
+            const int i2i = 2 * i;
+            const int i2ip1 = 2 * i + 1;
+
+            /* Filling indices [y_0,0, y_1,0, y_2,0]. Incoming bits
+               are shifted to their desired positions in the integer variables
+               "iIndexImag" and "iIndexReal" and combined */
+            iIndexReal = ((ExtractBit(vecInputData1[i2i]) & 1) << 2) |
+                         ((ExtractBit(vecInputData2[i2i]) & 1) << 1) |
+                         (ExtractBit(vecInputData3[i2i]) & 1);
+            iIndexImag = ((ExtractBit(vecInputData1[i2ip1]) & 1) << 2) |
+                         ((ExtractBit(vecInputData2[i2ip1]) & 1) << 1) |
+                         (ExtractBit(vecInputData3[i2ip1]) & 1);
+
+            (*pcOutputData)[i] =
+                /* Odd entries (second column in "rTableQAM64HMsym") */
+                _COMPLEX(rTableQAM64HMsym[iIndexReal][0],
+                         /* Even entries in input-vector */
+                         rTableQAM64HMsym[iIndexImag][1]);
+        }
+        break;
+
+    case CS_3_HMMIX:
+        /* 64QAM HMmix------------------------------------------------------- */
+        /* Mapping according DRM-standard: {i_0  i_1  i_2  q_0  q_1  q_2} =
+           (y_0,0Re  y_1,0Re  y_2,0Re  y_0,0Im  y_1,0Im  y_2,0Im) */
+        for (i = 0; i < iOutputBlockSize; i++)
+        {
+            /* Filling indices [y_0,0, y_1,0, y_2,0] (Re, Im). Incoming bits
+               are shifted to their desired positions in the integer variables
+               "iIndexImag" and "iIndexReal" and combined */
+            iIndexReal = ((ExtractBit(vecInputData1[i]) & 1) << 2) |
+                         ((ExtractBit(vecInputData3[i]) & 1) << 1) |
+                         (ExtractBit(vecInputData5[i]) & 1);
+            iIndexImag = ((ExtractBit(vecInputData2[i]) & 1) << 2) |
+                         ((ExtractBit(vecInputData4[i]) & 1) << 1) |
+                         (ExtractBit(vecInputData6[i]) & 1);
+
+            (*pcOutputData)[i] =
+                /* Odd entries (second column in "rTableQAM64HMmix") */
+                _COMPLEX(rTableQAM64HMmix[iIndexReal][0],
+                         /* Even entries in input-vector */
+                         rTableQAM64HMmix[iIndexImag][1]);
+        }
+        break;
+    }
+}
+
+void CQAMMapping::Init(int iNewOutputBlockSize, ECodScheme eNewCodingScheme)
+{
+    /* Set the two internal parameters */
+    iOutputBlockSize = iNewOutputBlockSize;
+    eMapType = eNewCodingScheme;
+}
diff --git a/src/mlc/QAMMapping.h b/src/mlc/QAMMapping.h
new file mode 100644
index 0000000..deb2d97
--- /dev/null
+++ b/src/mlc/QAMMapping.h
@@ -0,0 +1,60 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#if !defined(QAM_MAPPING_H__3B0BA660_CA63_4344_BB2B_23E7A0D31912__INCLUDED_)
+#define QAM_MAPPING_H__3B0BA660_CA63_4344_BB2B_23E7A0D31912__INCLUDED_
+
+#include "../GlobalDefinitions.h"
+#include "../tables/TableQAMMapping.h"
+#include "../util/Vector.h"
+#include "../Parameter.h"
+
+
+/* Classes ********************************************************************/
+class CQAMMapping
+{
+public:
+    CQAMMapping() {}
+    virtual ~CQAMMapping() {}
+
+    void Map(CVector<_DECISION>& vecInputData1,
+             CVector<_DECISION>& vecInputData2,
+             CVector<_DECISION>& vecInputData3,
+             CVector<_DECISION>& vecInputData4,
+             CVector<_DECISION>& vecInputData5,
+             CVector<_DECISION>& vecInputData6,
+             CVector<_COMPLEX>* pcOutputData);
+    void Init(int iNewOutputBlockSize, ECodScheme eNewCodingScheme);
+
+protected:
+    int						iOutputBlockSize;
+    ECodScheme	eMapType;
+};
+
+
+#endif // !defined(QAM_MAPPING_H__3B0BA660_CA63_4344_BB2B_23E7A0D31912__INCLUDED_)
diff --git a/src/mlc/TrellisUpdateMMX.cpp b/src/mlc/TrellisUpdateMMX.cpp
new file mode 100644
index 0000000..1062a29
--- /dev/null
+++ b/src/mlc/TrellisUpdateMMX.cpp
@@ -0,0 +1,380 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2003
+ *
+ * Author(s):
+ *	Volker Fischer, Phil Karn, Morgan Lius
+ *
+ * Description:
+ *
+	MMX fixed-point implementation of trellis update
+
+	This code is based on a Viterbi sample code from
+	Phil Karn, KA9Q (Dec 2001)
+	simd-viterbi-2.0.3.zip -> viterbi27.c, mmxbfly27.s, ssebfly27.s
+	homepage: http://www.ka9q.net
+
+	Some comments to this MMX code:
+	- To compare two 8-bit sized unsigned char, we need to apply a
+	  special strategy:
+	  psubusb mm5, mm1 // mm5 - mm1
+	  pcmpeqb mm5, mm3 // mm3 = 0
+	  We subtract unsigned with saturation and afterwards compare for
+	  equal to zero. If value in mm1 is larger than the value in mm5, we
+	  always get 0 as the result
+	- Defining __asm Blocks as C Macros in windows: Put the __asm keyword in
+	  front of each assembly instruction
+	- If we want to use c-pointers to arrays (like "pOldTrelMetric"), we
+	  first have to copy it to a register (like edx), otherwise we get
+	  errors
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "ViterbiDecoder.h"
+
+
+/* Implementation *************************************************************/
+#ifdef USE_MMX
+void CViterbiDecoder::TrellisUpdateMMX(const _DECISIONTYPE* pCurDec,
+                                       const _VITMETRTYPE* pCurTrelMetric, const _VITMETRTYPE* pOldTrelMetric,
+                                       const _VITMETRTYPE* pchMet1, const _VITMETRTYPE* pchMet2)
+{
+#ifdef _WIN32
+    /**************************************************************************\
+    * Windows                                                                  *
+    \**************************************************************************/
+    __asm
+    {
+        /* Each invocation of BFLY() will do 8 butterflies in parallel */
+#		define BFLY(GROUP) \
+		{ \
+			/* Compute branch metrics */ \
+			__asm mov edx, pOldTrelMetric /* Incoming path metric */ \
+			__asm movq mm4, [edx + (8 * GROUP)] /* high bit = 0 */ \
+			__asm movq mm5, [edx + ((8 * GROUP) + 32)] /* high bit = 1 */ \
+			__asm mov edx, pchMet1 \
+			__asm movq mm0, [edx + (8 * GROUP)] \
+			__asm mov edx, pchMet2 \
+			__asm movq mm3, [edx + (8 * GROUP)] \
+			\
+			__asm movq mm1, mm4 /* first set (mm1, mm2) */ \
+			__asm paddusb mm1, mm0 /* first set: decision for bit = 0 (mm1) */ \
+			__asm movq mm2, mm5 \
+			__asm paddusb mm2, mm3 /* first set: decision for bit = 1 (mm2) */ \
+			__asm movq mm6, mm4 /* second set (mm6, mm7) */ \
+			__asm paddusb mm6, mm3 /* second set: decision for bit = 0 (mm6) */ \
+			__asm movq mm7, mm5 \
+			__asm paddusb mm7, mm0 /* second set: decision for bit = 1 (mm7) */ \
+			\
+			/* live registers 1 2 6 7. Compare mm1 and mm2; mm6 and mm7 */ \
+			__asm movq mm5, mm2 \
+			__asm movq mm4, mm7 \
+			__asm psubusb mm5, mm1 /* mm5 = mm2 - mm1 */ \
+			__asm psubusb mm4, mm6 /* mm4 = mm7 - mm6 */ \
+			__asm pxor mm3, mm3 /* zero mm3 register, needed for comparison */ \
+			__asm pcmpeqb mm5, mm3 /* mm5 = first set of decisions */ \
+			__asm pcmpeqb mm4, mm3 /* mm4 = second set of decisions */ \
+			\
+			/* live registers 1 2 4 5 6 7. Select survivors. Avoid jumps
+        -> mask results with AND and ANDN. then OR */ \
+        __asm movq mm3, mm5 \
+        __asm movq mm0, mm4 \
+        __asm pand mm2, mm5 \
+        __asm pand mm7, mm4 \
+        __asm pandn mm3, mm1 \
+        __asm pandn mm0, mm6 \
+        __asm por mm2, mm3 /* mm2: first set survivors (decisions in mm5) */ \
+        __asm por mm7, mm0 /* mm7: second set survivors (decisions in mm4) */ \
+        \
+        /* live registers 2 4 5 7 */ \
+        /* interleave & store decisions in mm4, mm5 */ \
+        /* interleave & store new branch metrics in mm2, mm7 */ \
+        __asm movq mm3, mm5 \
+        __asm movq mm0, mm2 \
+        __asm punpcklbw mm3, mm4 /* interleave first 8 decisions */ \
+        __asm punpckhbw mm5, mm4 /* interleave second 8 decisions */ \
+        __asm punpcklbw mm0, mm7 /* interleave first 8 new metrics */ \
+        __asm punpckhbw mm2, mm7 /* interleave second 8 new metrics */ \
+        __asm mov edx, pCurDec \
+        __asm movq [edx + (16 * GROUP)], mm3 \
+        __asm movq [edx + (16 * GROUP + 8)], mm5 \
+        __asm mov edx, pCurTrelMetric \
+        __asm movq [edx + (16 * GROUP)], mm0 /* new metrics */ \
+        __asm movq [edx + (16 * GROUP + 8)], mm2 \
+    }
+
+    /* Invoke macro 4 times for a total of 32 butterflies */
+    BFLY(0)
+    BFLY(1)
+    BFLY(2)
+    BFLY(3)
+
+
+    /* -----------------------------------------------------------------
+       Normalize by finding smallest metric and subtracting it
+       from all metrics */
+
+#if 1 // if 0, always normalize
+    /* See if we have to normalize */
+    mov eax, [edx] /* Extract first output metric */
+    and eax, 255
+    cmp eax, 150 /* Is it greater than 150? */
+    mov eax, 0
+    jle done /* No, no need to normalize */
+#endif
+
+    /* Search for the minimum metric. Result ist stored in mm0 */
+#		define PMINUB_MM0_MM1 \
+		{ \
+			__asm movq mm2, mm0 \
+			__asm psubusb mm2, mm1 /* mm2 = mm0 - mm1 */ \
+			__asm pxor mm3, mm3 /* zero mm3 register, needed for comparison */ \
+			__asm pcmpeqb mm2, mm3 /* decisions */ \
+			\
+			__asm pand mm0, mm2 \
+			__asm pandn mm2, mm1 \
+			__asm por mm0, mm2 \
+		}
+
+    /* Search for minimum, byte-wise for whole register */
+    movq mm0, [edx]
+    movq mm1, [edx + 8]
+    PMINUB_MM0_MM1
+    movq mm1, [edx + 16]
+    PMINUB_MM0_MM1
+    movq mm1, [edx + 24]
+    PMINUB_MM0_MM1
+    movq mm1, [edx + 32]
+    PMINUB_MM0_MM1
+    movq mm1, [edx + 40]
+    PMINUB_MM0_MM1
+    movq mm1, [edx + 48]
+    PMINUB_MM0_MM1
+    movq mm1, [edx + 56]
+    PMINUB_MM0_MM1
+
+    /* mm0 contains 8 smallest metrics
+       crunch down to single lowest metric */
+    movq mm1, mm0
+    psrlq mm0, 32 /* Compare lowest 4 bytes with highest 4 bytes */
+    PMINUB_MM0_MM1 /* -> results are in lowest 4 bytes */
+    movq mm1, mm0
+    psrlq mm0, 16 /* Compare lowest 2 bytes with mext 2 bytes */
+    PMINUB_MM0_MM1 /* -> results are in lowest 2 bytes */
+    movq mm1, mm0
+    psrlq mm0, 8 /* Compare lowest byte with second lowest byte */
+    PMINUB_MM0_MM1 /* -> resulting minium metric is in lowest byte */
+
+    /* Expand value in lowest byte to all 8 bytes */
+    punpcklbw mm0,mm0 /* First 2 bytes have same value */
+    punpcklbw mm0,mm0 /* First 4 bytes have same value */
+    punpcklbw mm0,mm0 /* All bytes are the same */
+
+
+    /* mm0 now contains lowest metric in all 8 bytes
+       subtract it from every output metric. Trashes mm7 */
+#		define PSUBUSBM(MEM, REG) \
+		{ \
+			__asm movq mm7, MEM \
+			__asm psubusb mm7, REG \
+			__asm movq MEM, mm7 \
+		}
+
+    PSUBUSBM([edx], mm0)
+    PSUBUSBM([edx + 8], mm0)
+    PSUBUSBM([edx + 16], mm0)
+    PSUBUSBM([edx + 24], mm0)
+    PSUBUSBM([edx + 32], mm0)
+    PSUBUSBM([edx + 40], mm0)
+    PSUBUSBM([edx + 48], mm0)
+    PSUBUSBM([edx + 56], mm0)
+
+
+done:
+    /* Needed, when we have used mmx registers and want to use floating
+       point operations afterwards */
+    emms
+
+#undef BFLY
+#undef MINIMUM
+#undef PSUBUSBM
+}
+#else
+    /**************************************************************************\
+    * Linux                                                                    *
+    \**************************************************************************/
+    /* Each invocation of BFLY() will do 8 butterflies in parallel */
+#	define BFLY(GROUP) \
+		/* Compute branch metrics */ \
+		"mov %1,%%edx; " /* Incoming path metric (input) */ \
+		"movq (8 * "GROUP")(%%edx),%%mm4; " /* high bit = 0 */ \
+		"movq ((8 * "GROUP")+32)(%%edx),%%mm5; "	/* high bit = 1  */ \
+		"mov %2,%%eax; "  \
+		"mov %3,%%ebx ;"   \
+		"movq (8 * "GROUP")(%%eax),%%mm0; "  \
+		"movq (8 * "GROUP")(%%ebx),%%mm3; "  \
+		\
+		"movq %%mm4,%%mm1; " /* first set (mm1, mm2) */ \
+		"paddusb %%mm0,%%mm1; " /* first set: decision for bit = 0 (mm1) */ \
+		"movq %%mm5,%%mm2; " \
+		"paddusb %%mm3,%%mm2; " /* first set: decision for bit = 1 (mm2) */ \
+		"movq %%mm4,%%mm6;" /* second set (mm6, mm7) */ \
+		"paddusb %%mm3,%%mm6; " /* second set: decision for bit = 0 (mm6) */ \
+		"movq %%mm5,%%mm7; " \
+		"paddusb %%mm0,%%mm7; " /* second set: decision for bit = 1 (mm7) */ \
+		\
+		/* live registers 1 2 6 7. Compare mm1 and mm2; mm6 and mm7 */ \
+		"movq %%mm2,%%mm5; " \
+		"movq %%mm7,%%mm4; " \
+		"psubusb %%mm1,%%mm5; " /* mm5 = mm2 - mm1 */ \
+		"psubusb %%mm6,%%mm4; " /* mm4 = mm7 - mm6 */ \
+		"pxor %%mm3,%%mm3; " /* zero mm3 register, needed for comparison */ \
+		"pcmpeqb %%mm3,%%mm5; " /* mm5 = first set of decisions */ \
+		"pcmpeqb %%mm3,%%mm4; " /* mm4 = second set of decisions */ \
+		\
+		/* live registers 1 2 4 5 6 7. Select survivors. Avoid jumps */ \
+		/*   -> mask results with AND and ANDN. then OR */ \
+		"movq %%mm5,%%mm3; " \
+		"movq %%mm4,%%mm0; " \
+		"pand %%mm5,%%mm2; " \
+		"pand %%mm4,%%mm7; " \
+		"pandn %%mm1,%%mm3; " \
+		"pandn %%mm6,%%mm0; " \
+		"por %%mm3,%%mm2; " /* mm2: first set survivors (decisions in mm5) */ \
+		"por %%mm0,%%mm7; " /* mm7: second set survivors (decisions in mm4) */ \
+		\
+		/* live registers 2 4 5 7 */ \
+		/* interleave & store decisions in mm4, mm5 */ \
+		/* interleave & store new branch metrics in mm2, mm7 */ \
+		"movq %%mm5,%%mm3; " \
+		"movq %%mm2,%%mm0; " \
+		"punpcklbw %%mm4,%%mm3; " /* interleave first 8 decisions */ \
+		"punpckhbw %%mm4,%%mm5; " /* interleave second 8 decisions */ \
+		"punpcklbw %%mm7,%%mm0; " /* interleave first 8 new metrics */ \
+		"punpckhbw %%mm7,%%mm2; " /* interleave second 8 new metrics */ \
+		"mov %4,%%edx; " \
+		"movq %%mm3,(16 * "GROUP")(%%edx); "  \
+		"movq %%mm5,((16 * "GROUP") + 8)(%%edx); "   \
+		"mov %0,%%edx; " \
+		"movq %%mm0,(16 * "GROUP")(%%edx); " /* new metrics */ \
+		"movq %%mm2,((16 * "GROUP") + 8)(%%edx); " \
+ 
+
+    asm
+    (
+        /* Invoke macro 4 times for a total of 32 butterflies */
+        BFLY("0")
+        BFLY("1")
+        BFLY("2")
+        BFLY("3")
+
+
+        /* -----------------------------------------------------------------
+           Normalize by finding smallest metric and subtracting it
+           from all metrics */
+
+#if 1 // if 0, always normalize
+        /* See if we have to normalize */
+
+        "mov (%%edx),%%eax; " /* Extract first output metric */
+        "and $255,%%eax; "
+        "cmp $150,%%eax; " /* Is it greater than 150? */
+        "mov $0,%%eax ;"
+        "jle done; " /* No, no need to normalize.  */
+
+#endif
+
+        /* Search for the minimum metric. Result ist stored in mm0 */
+#		define PMINUBMM0MM1 \
+			"movq %%mm0,%%mm2; " \
+			"psubusb %%mm1,%%mm2; " /* mm2 = mm0 - mm1 */ \
+			"pxor %%mm3,%%mm3; " /* zero mm3 register, needed for comparison */ \
+			"pcmpeqb %%mm3,%%mm2; " /* decisions */ \
+			"pand %%mm2,%%mm0; " \
+			"pandn %%mm1,%%mm2; " \
+			"por %%mm2,%%mm0; "
+
+
+        /* Search for minimum, byte-wise for whole register */
+        "movq (%%edx),%%mm0; "
+        "movq 8(%%edx),%%mm1; "
+        PMINUBMM0MM1
+        "movq 16(%%edx),%%mm1; "
+        PMINUBMM0MM1
+        "movq 24(%%edx),%%mm1;"
+        PMINUBMM0MM1
+        "movq 32(%%edx),%%mm1; "
+        PMINUBMM0MM1
+        "movq 40(%%edx),%%mm1; "
+        PMINUBMM0MM1
+        "movq 48(%%edx),%%mm1; "
+        PMINUBMM0MM1
+        "movq 56(%%edx),%%mm1; "
+        PMINUBMM0MM1
+
+        /* mm0 contains 8 smallest metrics
+           crunch down to single lowest metric */
+
+        "movq %%mm0,%%mm1; "
+        "psrlq $32,%%mm0; " /* Compare lowest 4 bytes with highest 4 bytes */
+        PMINUBMM0MM1 /* -> results are in lowest 4 bytes */
+        "movq %%mm0,%%mm1; "
+        "psrlq $16,%%mm0; " /* Compare lowest 2 bytes with mext 2 bytes */
+        PMINUBMM0MM1 /* -> results are in lowest 2 bytes */
+        "movq %%mm0,%%mm1; "
+        "psrlq $8,%%mm0; " /* Compare lowest byte with second lowest byte */
+        PMINUBMM0MM1 /* -> resulting minium metric is in lowest byte */
+
+        /* Expand value in lowest byte to all 8 bytes */
+        "punpcklbw %%mm0,%%mm0; " /* First 2 bytes have same value */
+        "punpcklbw %%mm0,%%mm0; " /* First 4 bytes have same value */
+        "punpcklbw %%mm0,%%mm0; " /* All bytes are the same */
+
+
+        /* mm0 now contains lowest metric in all 8 bytes
+           subtract it from every output metric. Trashes mm7 */
+#		define PSUBUSBM(REG, MEM) \
+			"movq "MEM",%%mm7; " \
+			"psubusb "REG",%%mm7; " \
+			"movq %%mm7,"MEM"; " \
+ 
+
+        PSUBUSBM("%%mm0","(%%edx)")
+        PSUBUSBM("%%mm0","8(%%edx)")
+        PSUBUSBM("%%mm0","16(%%edx)")
+        PSUBUSBM("%%mm0","24(%%edx)")
+        PSUBUSBM("%%mm0","32(%%edx)")
+        PSUBUSBM("%%mm0","40(%%edx)")
+        PSUBUSBM("%%mm0","48(%%edx)")
+        PSUBUSBM("%%mm0","56(%%edx)")
+
+
+        "done: emms; "	/* Needed, when we have used mmx registers and want to use floating
+			 point operations afterwards */
+
+                :
+                :"m"(pCurTrelMetric),"m"(pOldTrelMetric),"m"(pchMet1),"m"(pchMet2),"m"(pCurDec)
+            );
+
+#undef BFLY
+#undef MINIMUM
+#undef PSUBUSBM
+#endif
+}
+#endif
diff --git a/src/mlc/TrellisUpdateSSE2.cpp b/src/mlc/TrellisUpdateSSE2.cpp
new file mode 100644
index 0000000..99fa647
--- /dev/null
+++ b/src/mlc/TrellisUpdateSSE2.cpp
@@ -0,0 +1,329 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2003
+ *
+ * Author(s):
+ *	Volker Fischer, Phil Karn, Morgan Lius
+ *
+ * Description:
+ *
+	SSE2 fixed-point implementation of trellis update
+
+	This code is based on a Viterbi sample code from
+	Phil Karn, KA9Q (Dec 2001)
+	simd-viterbi-2.0.3.zip -> viterbi27.c, mmxbfly27.s, ssebfly27.s
+	homepage: http://www.ka9q.net
+
+	Some comments to this MMX code:
+	- To compare two 8-bit sized unsigned char, we need to apply a
+	  special strategy:
+	  psubusb mm5, mm1 // mm5 - mm1
+	  pcmpeqb mm5, mm3 // mm3 = 0
+	  We subtract unsigned with saturation and afterwards compare for
+	  equal to zero. If value in mm1 is larger than the value in mm5, we
+	  always get 0 as the result
+	- Defining __asm Blocks as C Macros in windows: Put the __asm keyword in
+	  front of each assembly instruction
+	- If we want to use c-pointers to arrays (like "pOldTrelMetric"), we
+	  first have to copy it to a register (like edx), otherwise we get
+	  errors
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "ViterbiDecoder.h"
+
+
+/* Implementation *************************************************************/
+#ifdef USE_SSE2
+void CViterbiDecoder::TrellisUpdateSSE2(const _DECISIONTYPE* pCurDec,
+                                        const _VITMETRTYPE* pCurTrelMetric, const _VITMETRTYPE* pOldTrelMetric,
+                                        const _VITMETRTYPE* pchMet1, const _VITMETRTYPE* pchMet2)
+{
+#ifdef _WIN32
+    /**************************************************************************\
+    * Windows                                                                  *
+    \**************************************************************************/
+    __asm
+    {
+        /* Each invocation of BFLY() will do 8 butterflies in parallel */
+#		define BFLY(GROUP) \
+		{ \
+			/* Compute branch metrics */ \
+			__asm mov edx, pOldTrelMetric /* Incoming path metric */ \
+			__asm movdqu xmm4, [edx + (16 * GROUP)] /* high bit = 0 */ \
+			__asm movdqu xmm5, [edx + ((16 * GROUP) + 32)] /* high bit = 1 */ \
+			__asm mov edx, pchMet1 \
+			__asm movdqu xmm0, [edx + (16 * GROUP)] \
+			__asm mov edx, pchMet2 \
+			__asm movdqu xmm3, [edx + (16 * GROUP)] \
+			\
+			__asm movdqu xmm1, xmm4 /* first set (mm1, mm2) */ \
+			__asm paddusb xmm1, xmm0 /* first set: decision for bit = 0 (mm1) */ \
+			__asm movdqu xmm2, xmm5 \
+			__asm paddusb xmm2, xmm3 /* first set: decision for bit = 1 (mm2) */ \
+			__asm movdqu xmm6, xmm4 /* second set (mm6, mm7) */ \
+			__asm paddusb xmm6, xmm3 /* second set: decision for bit = 0 (mm6) */ \
+			__asm movdqu xmm7, xmm5 \
+			__asm paddusb xmm7, xmm0 /* second set: decision for bit = 1 (mm7) */ \
+			\
+			/* live registers 1 2 6 7. Compare mm1 and mm2; mm6 and mm7 */ \
+			__asm movdqu xmm5, xmm2 \
+			__asm movdqu xmm4, xmm7 \
+			__asm psubusb xmm5, xmm1 /* mm5 = mm2 - mm1 */ \
+			__asm psubusb xmm4, xmm6 /* mm4 = mm7 - mm6 */ \
+			__asm pxor xmm3, xmm3 /* zero mm3 register, needed for comparison */ \
+			__asm pcmpeqb xmm5, xmm3 /* mm5 = first set of decisions */ \
+			__asm pcmpeqb xmm4, xmm3 /* mm4 = second set of decisions */ \
+			\
+			/* live registers 1 2 4 5 6 7. Select survivors. Avoid jumps
+        -> mask results with AND and ANDN. then OR */ \
+        __asm movdqu xmm3, xmm5 \
+        __asm movdqu xmm0, xmm4 \
+        __asm pand xmm2, xmm5 \
+        __asm pand xmm7, xmm4 \
+        __asm pandn xmm3, xmm1 \
+        __asm pandn xmm0, xmm6 \
+        __asm por xmm2, xmm3 /* mm2: first set survivors (decisions in mm5) */ \
+        __asm por xmm7, xmm0 /* mm7: second set survivors (decisions in mm4) */ \
+        \
+        /* live registers 2 4 5 7 */ \
+        /* interleave & store decisions in mm4, mm5 */ \
+        /* interleave & store new branch metrics in mm2, mm7 */ \
+        __asm movdqu xmm3, xmm5 \
+        __asm movdqu xmm0, xmm2 \
+        __asm punpcklbw xmm3, xmm4 /* interleave first 8 decisions */ \
+        __asm punpckhbw xmm5, xmm4 /* interleave second 8 decisions */ \
+        __asm punpcklbw xmm0, xmm7 /* interleave first 8 new metrics */ \
+        __asm punpckhbw xmm2, xmm7 /* interleave second 8 new metrics */ \
+        __asm mov edx, pCurDec \
+        __asm movdqu [edx + (32 * GROUP)], xmm3 \
+        __asm movdqu [edx + (32 * GROUP + 16)], xmm5 \
+        __asm mov edx, pCurTrelMetric \
+        __asm movdqu [edx + (32 * GROUP)], xmm0 /* new metrics */ \
+        __asm movdqu [edx + (32 * GROUP + 16)], xmm2 \
+    }
+
+    BFLY(0)
+    BFLY(1)
+
+
+    /* -----------------------------------------------------------------
+       Normalize by finding smallest metric and subtracting it
+       from all metrics */
+
+#if 1 // if 0, always normalize
+    /* See if we have to normalize */
+    mov eax, [edx] /* Extract first output metric */
+    and eax, 255
+    cmp eax, 150 /* Is it greater than 150? */
+    mov eax, 0
+    jle done /* No, no need to normalize */
+#endif
+
+    /* Search for minimum, byte-wise for whole register */
+    movdqu xmm0, [edx]
+    movdqu xmm1, [edx + 16]
+    pminub xmm0, xmm1
+    movdqu xmm1, [edx + 32]
+    pminub xmm0, xmm1
+    movdqu xmm1, [edx + 48]
+    pminub xmm0, xmm1
+
+    /* mm0 contains 8 smallest metrics
+       crunch down to single lowest metric */
+    movdqu xmm1, xmm0
+    psrldq xmm0, 8 /* The count to psrldq is in bytes not bits! */
+    pminub xmm0, xmm1
+    movdqu xmm1, xmm0
+    psrlq xmm0, 32 /* Compare lowest 4 bytes with highest 4 bytes */
+    pminub xmm0, xmm1 /* -> results are in lowest 4 bytes */
+    movdqu xmm1, xmm0
+    psrlq xmm0, 16 /* Compare lowest 2 bytes with mext 2 bytes */
+    pminub xmm0, xmm1 /* -> results are in lowest 2 bytes */
+    movdqu xmm1, xmm0
+    psrlq xmm0, 8 /* Compare lowest byte with second lowest byte */
+    pminub xmm0, xmm1 /* -> resulting minium metric is in lowest byte */
+
+    /* Expand value in lowest byte to all 16 bytes (watch this part better) */
+    punpcklbw xmm0,xmm0 /* lowest 2 bytes have same value */
+    pshuflw xmm0, xmm0, 0 /*  lowest 8 bytes have same value */
+    punpcklqdq xmm0,xmm0 /* all 16 bytes have same value */
+
+
+    /* mm0 now contains lowest metric in all 8 bytes
+       subtract it from every output metric. Trashes mm7 */
+#		define PSUBUSBM(MEM, REG) \
+		{ \
+			__asm movdqu xmm7, MEM \
+			__asm psubusb xmm7, REG \
+			__asm movdqu MEM, xmm7 \
+		}
+
+    PSUBUSBM([edx], mm0)
+    PSUBUSBM([edx + 16], mm0)
+    PSUBUSBM([edx + 32], mm0)
+    PSUBUSBM([edx + 48], mm0)
+
+
+done:
+    /* Needed, when we have used mmx registers and want to use floating
+       point operations afterwards */
+    emms
+
+#undef BFLY
+#undef MINIMUM
+#undef PSUBUSBM
+}
+#else
+    /**************************************************************************\
+    * Linux                                                                    *
+    \**************************************************************************/
+    /* Each invocation of BFLY() will do 16 butterflies in parallel */
+#	define BFLY(GROUP) \
+		/* Compute branch metrics */ \
+		"mov %1,%%edx; " /* Incoming path metric (input) */ \
+		"movdqu (16 * "GROUP")(%%edx),%%xmm4; " /* high bit = 0 */ \
+		"movdqu ((16 * "GROUP") + 32)(%%edx),%%xmm5; "	/* high bit = 1  */ \
+		"mov %2,%%eax; "  \
+		"mov %3,%%ebx ;"   \
+		"movdqu (16 * "GROUP")(%%eax),%%xmm0; "  \
+		"movdqu (16 * "GROUP")(%%ebx),%%xmm3; "  \
+		\
+		"movdqu %%xmm4,%%xmm1; " /* first set (mm1, mm2) */ \
+		"paddusb %%xmm0,%%xmm1; " /* first set: decision for bit = 0 (mm1) */ \
+		"movdqu %%xmm5,%%xmm2; " \
+		"paddusb %%xmm3,%%xmm2; " /* first set: decision for bit = 1 (mm2) */ \
+		"movdqu %%xmm4,%%xmm6;" /* second set (mm6, mm7) */ \
+		"paddusb %%xmm3,%%xmm6; " /* second set: decision for bit = 0 (mm6) */ \
+		"movdqu %%xmm5,%%xmm7; " \
+		"paddusb %%xmm0,%%xmm7; " /* second set: decision for bit = 1 (mm7) */ \
+		\
+		/* live registers 1 2 6 7. Compare mm1 and mm2; mm6 and mm7 */ \
+		"movdqu %%xmm2,%%xmm5; " \
+		"movdqu %%xmm7,%%xmm4; " \
+		"psubusb %%xmm1,%%xmm5; " /* mm5 = mm2 - mm1 */ \
+		"psubusb %%xmm6,%%xmm4; " /* mm4 = mm7 - mm6 */ \
+		"pxor %%xmm3,%%xmm3; " /* zero mm3 register, needed for comparison */ \
+		"pcmpeqb %%xmm3,%%xmm5; " /* mm5 = first set of decisions */ \
+		"pcmpeqb %%xmm3,%%xmm4; " /* mm4 = second set of decisions */ \
+		\
+		/* live registers 1 2 4 5 6 7. Select survivors. Avoid jumps */ \
+		/*   -> mask results with AND and ANDN. then OR */ \
+		"movdqu %%xmm5,%%xmm3; " \
+		"movdqu %%xmm4,%%xmm0; " \
+		"pand %%xmm5,%%xmm2; " \
+		"pand %%xmm4,%%xmm7; " \
+		"pandn %%xmm1,%%xmm3; " \
+		"pandn %%xmm6,%%xmm0; " \
+		"por %%xmm3,%%xmm2; " /* mm2: first set survivors (decisions in mm5) */ \
+		"por %%xmm0,%%xmm7; " /* mm7: second set survivors (decisions in mm4) */ \
+		\
+		/* live registers 2 4 5 7 */ \
+		/* interleave & store decisions in mm4, mm5 */ \
+		/* interleave & store new branch metrics in mm2, mm7 */ \
+		"movdqu %%xmm5,%%xmm3; " \
+		"movdqu %%xmm2,%%xmm0; " \
+		"punpcklbw %%xmm4,%%xmm3; " /* interleave first 8 decisions */ \
+		"punpckhbw %%xmm4,%%xmm5; " /* interleave second 8 decisions */ \
+		"punpcklbw %%xmm7,%%xmm0; " /* interleave first 8 new metrics */ \
+		"punpckhbw %%xmm7,%%xmm2; " /* interleave second 8 new metrics */ \
+		"mov %4,%%edx; " \
+		"movdqu %%xmm3,(32 * "GROUP")(%%edx); "  \
+		"movdqu %%xmm5,((32 * "GROUP") + 16)(%%edx); "   \
+		"mov %0,%%edx; " \
+		"movdqu %%xmm0,(32 * "GROUP")(%%edx); " /* new metrics */ \
+		"movdqu %%xmm2,((32 * "GROUP") + 16)(%%edx); " \
+ 
+
+    asm
+    (
+        BFLY("0")
+        BFLY("1")
+
+
+        /* -----------------------------------------------------------------
+           Normalize by finding smallest metric and subtracting it
+           from all metrics */
+#if 1 // if 0, always normalize
+        /* See if we have to normalize */
+
+        "mov (%%edx),%%eax ;" /* Extract first output metric */
+        "and $255,%%eax ;"
+        "cmp $150,%%eax ;" /* Is it greater than 150? */
+        "mov $0,%%eax ;"
+        "jle done ;" /* No, no need to normalize. Where is the label done? */
+#endif
+
+
+        /* Search for minimum, byte-wise for whole register */
+        "movdqu (%%edx),%%xmm0 ;"
+        "movdqu 16(%%edx),%%xmm1 ;"
+        "pminub %%xmm1,%%xmm0 ;"
+        "movdqu 32(%%edx),%%xmm1 ;"
+        "pminub %%xmm1,%%xmm0 ;"
+        "movdqu 48(%%edx),%%xmm1 ;" /* Offset is in bytes  */
+        "pminub %%xmm1,%%xmm0 ;"
+
+        /* xmm0 contains 16 smallest metrics
+           crunch down to single lowest metric */
+        "movdqu %%xmm0,%%xmm1 ;"
+        "psrldq $8,%%xmm0 ;" /* The count to psrldq is in bytes not bits! */
+        "pminub %%xmm1,%%xmm0 ;"
+        "movdqu %%xmm0,%%xmm1 ;"
+        "psrlq $32,%%xmm0 ;" /* Compare lowest 4 bytes with highest 4 bytes */
+        "pminub %%xmm1,%%xmm0 ;" /* -> results are in lowest 4 bytes */
+        "movdqu %%xmm0,%%xmm1 ;"
+        "psrlq $16,%%xmm0 ;" /* Compare lowest 2 bytes with mext 2 bytes */
+        "pminub %%xmm1,%%xmm0 ;" /* -> results are in lowest 2 bytes */
+        "movdqu %%xmm0,%%xmm1 ;"
+        "psrlq $8,%%xmm0 ;" /* Compare lowest byte with second lowest byte */
+        "pminub %%xmm1,%%xmm0 ;" /* -> resulting minium metric is in lowest byte */
+
+        /* Expand value in lowest byte to all 16 bytes (watch this part better) */
+        "punpcklbw %%xmm0,%%xmm0 ;"	/* lowest 2 bytes have same value */
+        "pshuflw $0,%%xmm0,%%xmm0 ;" /* lowest 8 bytes have same value */
+        "punpcklqdq %%xmm0,%%xmm0 ;" /* all 16 bytes have same value */
+
+
+        /* xmm0 now contains lowest metric in all 16 bytes
+           subtract it from every output metric. Trashes mm7 */
+#		define PSUBUSBM(REG, MEM) \
+			"movdqu "MEM",%%xmm7 ;" \
+			"psubusb "REG",%%xmm7 ;" \
+			"movdqu %%xmm7,"MEM" ;" \
+ 
+
+        PSUBUSBM("%%xmm0","(%%edx)")
+        PSUBUSBM("%%xmm0","16(%%edx)")
+        PSUBUSBM("%%xmm0","32(%%edx)")
+        PSUBUSBM("%%xmm0","48(%%edx)")
+
+
+        "done: emms ;"	/* Needed, when we have used mmx registers and want to use floating
+			 point operations afterwards */
+
+                :
+                :"m"(pCurTrelMetric),"m"(pOldTrelMetric),"m"(pchMet1),"m"(pchMet2),"m"(pCurDec)
+            );
+
+#undef BFLY
+#undef PSUBUSBM
+#endif
+}
+#endif
diff --git a/src/mlc/ViterbiDecoder.cpp b/src/mlc/ViterbiDecoder.cpp
new file mode 100644
index 0000000..6b61913
--- /dev/null
+++ b/src/mlc/ViterbiDecoder.cpp
@@ -0,0 +1,658 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer, Alexander Kurpiers
+ *
+ * Description:
+ *
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "ViterbiDecoder.h"
+
+
+/* Implementation *************************************************************/
+_REAL CViterbiDecoder::Decode(CVector<CDistance>& vecNewDistance,
+                              CVector<_DECISION>& vecOutputBits)
+{
+    int				i;
+    int				iDistCnt;
+    int				iCurDecState;
+    _VITMETRTYPE*	pCurTrelMetric;
+    _VITMETRTYPE*	pOldTrelMetric;
+
+#ifdef USE_SIMD
+    /* -------------------------------------------------------------------------
+       Since the metric is 8-bit fixed-point type, we need to scale the input
+       metrics to avoid overflows */
+    /* Calculate average value of input metrics */
+    _REAL rAverage = (_REAL) 0.0;
+    for (i = 0; i < iNumOutBitsWithMemory; i++)
+    {
+        rAverage += vecNewDistance[i].rTow0;
+        rAverage += vecNewDistance[i].rTow1;
+    }
+
+    /* Scale input metrics */
+    const _REAL rAmp = rAverage / (2 * iNumOutBitsWithMemory) / 10;
+    for (i = 0; i < iNumOutBitsWithMemory; i++)
+    {
+        vecNewDistance[i].rTow0 /= rAmp;
+        vecNewDistance[i].rTow1 /= rAmp;
+    }
+#endif
+
+    /* Init pointers for old and new trellis state */
+    pCurTrelMetric = vecTrelMetric1;
+    pOldTrelMetric = vecTrelMetric2;
+
+    /* Reset all metrics in the trellis. We initialize all states exept of
+       the zero state with a high metric, because we KNOW that the state "0"
+       is the transmitted state */
+    pOldTrelMetric[0] = (_VITMETRTYPE) 0;
+    for (i = 1; i < MC_NUM_STATES; i++)
+        pOldTrelMetric[i] = MC_METRIC_INIT_VALUE;
+
+    /* Reset counter for puncturing and distance (from metric) */
+    iDistCnt = 0;
+
+
+    /* Main loop over all bits ---------------------------------------------- */
+    for (i = 0; i < iNumOutBitsWithMemory; i++)
+    {
+        /* Calculate all possible metrics ----------------------------------- */
+        /* There are only a small set of possible puncturing patterns used for
+           DRM: 0001, 0101, 0011, 0111, 1111. These need different numbers of
+           input bits (increment of "iDistCnt" is dependent on pattern!). To
+           optimize the calculation of the metrics, a "subset" of bits are first
+           calculated which are used to get the final result. In this case,
+           redundancy can be avoided.
+           Note, that not all possible bit-combinations are used in the coder,
+           only a subset of numbers: 0, 2, 4, 6, 9, 11, 13, 15 (compare numbers
+           in the BUTTERFLY() calls) */
+
+        /* Get first position in input vector (is needed for all cases) */
+        const int iPos0 = iDistCnt;
+        iDistCnt++;
+
+        if (veciTablePuncPat[i] == PP_TYPE_0001)
+        {
+            /* Pattern 0001 */
+            METRICSET(i)[ 0] = vecNewDistance[iPos0].rTow0;
+            METRICSET(i)[ 2] = vecNewDistance[iPos0].rTow0;
+            METRICSET(i)[ 4] = vecNewDistance[iPos0].rTow0;
+            METRICSET(i)[ 6] = vecNewDistance[iPos0].rTow0;
+            METRICSET(i)[ 9] = vecNewDistance[iPos0].rTow1;
+            METRICSET(i)[11] = vecNewDistance[iPos0].rTow1;
+            METRICSET(i)[13] = vecNewDistance[iPos0].rTow1;
+            METRICSET(i)[15] = vecNewDistance[iPos0].rTow1;
+        }
+        else
+        {
+            /* The following patterns need one more bit */
+            const int iPos1 = iDistCnt;
+            iDistCnt++;
+
+            /* Calculate "subsets" of bit-combinations. "rIRxx00" means that
+               the fist two bits are used, others are x-ed. "IR" stands for
+               "intermediate result" */
+            const _REAL rIRxx00 =
+                vecNewDistance[iPos1].rTow0 + vecNewDistance[iPos0].rTow0;
+            const _REAL rIRxx10 =
+                vecNewDistance[iPos1].rTow1 + vecNewDistance[iPos0].rTow0;
+            const _REAL rIRxx01 =
+                vecNewDistance[iPos1].rTow0 + vecNewDistance[iPos0].rTow1;
+            const _REAL rIRxx11 =
+                vecNewDistance[iPos1].rTow1 + vecNewDistance[iPos0].rTow1;
+
+            if (veciTablePuncPat[i] == PP_TYPE_0101)
+            {
+                /* Pattern 0101 */
+                METRICSET(i)[ 0] = rIRxx00;
+                METRICSET(i)[ 2] = rIRxx00;
+                METRICSET(i)[ 4] = rIRxx10;
+                METRICSET(i)[ 6] = rIRxx10;
+                METRICSET(i)[ 9] = rIRxx01;
+                METRICSET(i)[11] = rIRxx01;
+                METRICSET(i)[13] = rIRxx11;
+                METRICSET(i)[15] = rIRxx11;
+            }
+            else if (veciTablePuncPat[i] == PP_TYPE_0011)
+            {
+                /* Pattern 0011 */
+                METRICSET(i)[ 0] = rIRxx00;
+                METRICSET(i)[ 2] = rIRxx10;
+                METRICSET(i)[ 4] = rIRxx00;
+                METRICSET(i)[ 6] = rIRxx10;
+                METRICSET(i)[ 9] = rIRxx01;
+                METRICSET(i)[11] = rIRxx11;
+                METRICSET(i)[13] = rIRxx01;
+                METRICSET(i)[15] = rIRxx11;
+            }
+            else
+            {
+                /* The following patterns need one more bit */
+                const int iPos2 = iDistCnt;
+                iDistCnt++;
+
+                if (veciTablePuncPat[i] == PP_TYPE_0111)
+                {
+                    /* Pattern 0111 */
+                    METRICSET(i)[ 0] = vecNewDistance[iPos2].rTow0 + rIRxx00;
+                    METRICSET(i)[ 2] = vecNewDistance[iPos2].rTow0 + rIRxx10;
+                    METRICSET(i)[ 4] = vecNewDistance[iPos2].rTow1 + rIRxx00;
+                    METRICSET(i)[ 6] = vecNewDistance[iPos2].rTow1 + rIRxx10;
+                    METRICSET(i)[ 9] = vecNewDistance[iPos2].rTow0 + rIRxx01;
+                    METRICSET(i)[11] = vecNewDistance[iPos2].rTow0 + rIRxx11;
+                    METRICSET(i)[13] = vecNewDistance[iPos2].rTow1 + rIRxx01;
+                    METRICSET(i)[15] = vecNewDistance[iPos2].rTow1 + rIRxx11;
+                }
+                else
+                {
+                    /* Pattern 1111 */
+                    /* This pattern needs all four bits */
+                    const int iPos3 = iDistCnt;
+                    iDistCnt++;
+
+                    /* Calculate "subsets" of bit-combinations. "rIRxx00" means
+                       that the last two bits are used, others are x-ed.
+                       "IR" stands for "intermediate result" */
+                    const _REAL rIR00xx = vecNewDistance[iPos3].rTow0 +
+                                          vecNewDistance[iPos2].rTow0;
+                    const _REAL rIR10xx = vecNewDistance[iPos3].rTow1 +
+                                          vecNewDistance[iPos2].rTow0;
+                    const _REAL rIR01xx = vecNewDistance[iPos3].rTow0 +
+                                          vecNewDistance[iPos2].rTow1;
+                    const _REAL rIR11xx = vecNewDistance[iPos3].rTow1 +
+                                          vecNewDistance[iPos2].rTow1;
+
+                    METRICSET(i)[ 0] = rIR00xx + rIRxx00; /* 0 */
+                    METRICSET(i)[ 2] = rIR00xx + rIRxx10; /* 2 */
+                    METRICSET(i)[ 4] = rIR01xx + rIRxx00; /* 4 */
+                    METRICSET(i)[ 6] = rIR01xx + rIRxx10; /* 6 */
+                    METRICSET(i)[ 9] = rIR10xx + rIRxx01; /* 9 */
+                    METRICSET(i)[11] = rIR10xx + rIRxx11; /* 11 */
+                    METRICSET(i)[13] = rIR11xx + rIRxx01; /* 13 */
+                    METRICSET(i)[15] = rIR11xx + rIRxx11; /* 15 */
+                }
+            }
+        }
+
+
+        /* Update trellis --------------------------------------------------- */
+#ifdef USE_SIMD
+        /* Use the butterfly unroll for reordering the metrics for SIMD
+           trellis */
+#define BUTTERFLY(cur, next, prev0, prev1, met0, met1) \
+		{ \
+			/* At this point we convert from float to char! No overflow-check
+        is done here */ \
+        chMet1[prev0] = (_VITMETRTYPE) METRICSET(i)[met0]; \
+        chMet2[prev0] = (_VITMETRTYPE) METRICSET(i)[met1]; \
+    }
+#else
+        /* c++ version of trellis update */
+#define BUTTERFLY(cur, next, prev0, prev1, met0, met1) \
+		{ \
+			/* First state in this set ------------------------------------ */ \
+			/* Calculate metrics from the two previous states, use the old
+        metric from the previous states plus the "transition-metric" */ \
+        const _VITMETRTYPE rFiStAccMetricPrev0 = \
+                pOldTrelMetric[prev0] + METRICSET(i)[met0]; \
+        const _VITMETRTYPE  rFiStAccMetricPrev1 = \
+                pOldTrelMetric[prev1] + METRICSET(i)[met1]; \
+        \
+        /* Take path with smallest metric */ \
+        if (rFiStAccMetricPrev0 < rFiStAccMetricPrev1) \
+            { \
+              /* Save minimum metric for this state and store decision */ \
+              pCurTrelMetric[cur] = rFiStAccMetricPrev0; \
+              matdecDecisions[i][cur] = 0; \
+            } \
+            else \
+                { \
+                    /* Save minimum metric for this state and store decision */ \
+                    pCurTrelMetric[cur] = rFiStAccMetricPrev1; \
+                    matdecDecisions[i][cur] = 1; \
+                } \
+                \
+                /* Second state in this set ----------------------------------- */ \
+                /* The only difference is that we swapped the matric sets */ \
+                const _VITMETRTYPE rSecStAccMetricPrev0 = \
+                        pOldTrelMetric[prev0] + METRICSET(i)[met1]; \
+        const _VITMETRTYPE  rSecStAccMetricPrev1 = \
+                pOldTrelMetric[prev1] + METRICSET(i)[met0]; \
+        \
+        /* Take path with smallest metric */ \
+        if (rSecStAccMetricPrev0 < rSecStAccMetricPrev1) \
+            { \
+              /* Save minimum metric for this state and store decision */ \
+              pCurTrelMetric[next] = rSecStAccMetricPrev0; \
+              matdecDecisions[i][next] = 0; \
+            } \
+            else \
+                { \
+                    /* Save minimum metric for this state and store decision */ \
+                    pCurTrelMetric[next] = rSecStAccMetricPrev1; \
+                    matdecDecisions[i][next] = 1; \
+                } \
+            }
+#endif
+
+    /* Unroll butterflys to avoid loop overhead. For c++ version, the
+       actual calculation of the trellis update is done here, for MMX
+       version, only the reordering of the new metrics is done here */
+    BUTTERFLY( 0,  1,  0, 32,  0, 15)
+    BUTTERFLY( 2,  3,  1, 33,  6,  9)
+    BUTTERFLY( 4,  5,  2, 34, 11,  4)
+    BUTTERFLY( 6,  7,  3, 35, 13,  2)
+    BUTTERFLY( 8,  9,  4, 36, 11,  4)
+    BUTTERFLY(10, 11,  5, 37, 13,  2)
+    BUTTERFLY(12, 13,  6, 38,  0, 15)
+    BUTTERFLY(14, 15,  7, 39,  6,  9)
+    BUTTERFLY(16, 17,  8, 40,  4, 11)
+    BUTTERFLY(18, 19,  9, 41,  2, 13)
+    BUTTERFLY(20, 21, 10, 42, 15,  0)
+    BUTTERFLY(22, 23, 11, 43,  9,  6)
+    BUTTERFLY(24, 25, 12, 44, 15,  0)
+    BUTTERFLY(26, 27, 13, 45,  9,  6)
+    BUTTERFLY(28, 29, 14, 46,  4, 11)
+    BUTTERFLY(30, 31, 15, 47,  2, 13)
+    BUTTERFLY(32, 33, 16, 48,  9,  6)
+    BUTTERFLY(34, 35, 17, 49, 15,  0)
+    BUTTERFLY(36, 37, 18, 50,  2, 13)
+    BUTTERFLY(38, 39, 19, 51,  4, 11)
+    BUTTERFLY(40, 41, 20, 52,  2, 13)
+    BUTTERFLY(42, 43, 21, 53,  4, 11)
+    BUTTERFLY(44, 45, 22, 54,  9,  6)
+    BUTTERFLY(46, 47, 23, 55, 15,  0)
+    BUTTERFLY(48, 49, 24, 56, 13,  2)
+    BUTTERFLY(50, 51, 25, 57, 11,  4)
+    BUTTERFLY(52, 53, 26, 58,  6,  9)
+    BUTTERFLY(54, 55, 27, 59,  0, 15)
+    BUTTERFLY(56, 57, 28, 60,  6,  9)
+    BUTTERFLY(58, 59, 29, 61,  0, 15)
+    BUTTERFLY(60, 61, 30, 62, 13,  2)
+    BUTTERFLY(62, 63, 31, 63, 11,  4)
+
+
+#undef BUTTERFLY
+
+#ifdef USE_SIMD
+    /* Do actual trellis update in separate file (assembler implementation) */
+#ifdef USE_MMX
+    TrellisUpdateMMX(
+#endif
+#ifdef USE_SSE2
+        TrellisUpdateSSE2(
+#endif
+            &matdecDecisions[i][0], pCurTrelMetric, pOldTrelMetric,
+            chMet1, chMet2);
+#endif
+
+#ifdef USE_MAX_LOG_MAP
+        /* Store accumulated metrics for backward Viterbi */
+        for (int j = 0; j < MC_NUM_STATES; j++)
+        matrAlpha[i][j] = pOldTrelMetric[j];
+#endif
+
+        /* Swap trellis data pointers (old -> new, new -> old) */
+        _VITMETRTYPE* pTMPTrelMetric = pCurTrelMetric;
+        pCurTrelMetric = pOldTrelMetric;
+        pOldTrelMetric = pTMPTrelMetric;
+    }
+
+
+#ifdef USE_MAX_LOG_MAP
+    /* MAX-LOG MAP implementation ------------------------------------------- */
+    /* Reset all metrics in the trellis. We initialize all states exept of
+       the zero state with a high metric, because we KNOW that the state "0"
+       is the transmitted state */
+    pOldTrelMetric[0] = (_VITMETRTYPE) 0;
+for (i = 1; i < MC_NUM_STATES; i++)
+    pOldTrelMetric[i] = MC_METRIC_INIT_VALUE;
+
+/* Backward direction */
+for (i = iNumOutBitsWithMemory - 1; i >= 0; i--)
+{
+    /* Variables storing the likelihood of 0 and 1 bit */
+    _VITMETRTYPE rL0 = MC_METRIC_INIT_VALUE;
+    _VITMETRTYPE rL1 = MC_METRIC_INIT_VALUE;
+
+
+    /* Update trellis --------------------------------------------------- */
+#define BUTTERFLY(cur, prev0, prev1, met0, met1) \
+		{ \
+			/* Calculate metrics from the two previous states, use the old
+    metric from the previous states plus the "transition-metric" */
+    \
+    const _VITMETRTYPE rFiStAccMetricPrev0 = \
+            pOldTrelMetric[prev0] + METRICSET(i)[met0];
+    \
+    const _VITMETRTYPE  rFiStAccMetricPrev1 = \
+            pOldTrelMetric[prev1] + METRICSET(i)[met1];
+    \
+    \
+    /* Take path with smallest metric */ \
+    if (rFiStAccMetricPrev0 < rFiStAccMetricPrev1) \
+        { \
+          /* Save minimum metric for this state */ \
+          pCurTrelMetric[cur] = rFiStAccMetricPrev0;
+          \
+          \
+          /* Likelihood for 0 bit: max(alpha + beta) */ \
+          const _VITMETRTYPE rL0tmp = \
+                                      rFiStAccMetricPrev0 + matrAlpha[i][cur];
+          \
+          if (rL0tmp < rL0) \
+          rL0 = rL0tmp;
+          \
+        } \
+        else \
+            {
+                \
+                /* Save minimum metric for this state */ \
+                pCurTrelMetric[cur] = rFiStAccMetricPrev1;
+                \
+                \
+                /* Likelihood for 1 bit: max(alpha + beta) */ \
+                const _VITMETRTYPE rL1tmp = \
+                                            rFiStAccMetricPrev1 + matrAlpha[i][cur];
+                \
+                if (rL1tmp < rL1) \
+                    rL1 = rL1tmp;
+                    \
+                } \
+            }
+
+/* Unroll butterflys with backwards direction parameters */
+BUTTERFLY( 0,  0,  1,  0, 15)
+BUTTERFLY( 1,  2,  3,  6,  9)
+BUTTERFLY( 2,  4,  5, 11,  4)
+BUTTERFLY( 3,  6,  7, 13,  2)
+BUTTERFLY( 4,  8,  9, 11,  4)
+BUTTERFLY( 5, 10, 11, 13,  2)
+BUTTERFLY( 6, 12, 13,  0, 15)
+BUTTERFLY( 7, 14, 15,  6,  9)
+BUTTERFLY( 8, 16, 17,  4, 11)
+BUTTERFLY( 9, 18, 19,  2, 13)
+BUTTERFLY(10, 20, 21, 15,  0)
+BUTTERFLY(11, 22, 23,  9,  6)
+BUTTERFLY(12, 24, 25, 15,  0)
+BUTTERFLY(13, 26, 27,  9,  6)
+BUTTERFLY(14, 28, 29,  4, 11)
+BUTTERFLY(15, 30, 31,  2, 13)
+BUTTERFLY(16, 32, 33,  9,  6)
+BUTTERFLY(17, 34, 35, 15,  0)
+BUTTERFLY(18, 36, 37,  2, 13)
+BUTTERFLY(19, 38, 39,  4, 11)
+BUTTERFLY(20, 40, 41,  2, 13)
+BUTTERFLY(21, 42, 43,  4, 11)
+BUTTERFLY(22, 44, 45,  9,  6)
+BUTTERFLY(23, 46, 47, 15,  0)
+BUTTERFLY(24, 48, 49, 13,  2)
+BUTTERFLY(25, 50, 51, 11,  4)
+BUTTERFLY(26, 52, 53,  6,  9)
+BUTTERFLY(27, 54, 55,  0, 15)
+BUTTERFLY(28, 56, 57,  6,  9)
+BUTTERFLY(29, 58, 59,  0, 15)
+BUTTERFLY(30, 60, 61, 13,  2)
+BUTTERFLY(31, 62, 63, 11,  4)
+BUTTERFLY(32,  0,  1, 15,  0)
+BUTTERFLY(33,  2,  3,  9,  6)
+BUTTERFLY(34,  4,  5,  4, 11)
+BUTTERFLY(35,  6,  7,  2, 13)
+BUTTERFLY(36,  8,  9,  4, 11)
+BUTTERFLY(37, 10, 11,  2, 13)
+BUTTERFLY(38, 12, 13, 15,  0)
+BUTTERFLY(39, 14, 15,  9,  6)
+BUTTERFLY(40, 16, 17, 11,  4)
+BUTTERFLY(41, 18, 19, 13,  2)
+BUTTERFLY(42, 20, 21,  0, 15)
+BUTTERFLY(43, 22, 23,  6,  9)
+BUTTERFLY(44, 24, 25,  0, 15)
+BUTTERFLY(45, 26, 27,  6,  9)
+BUTTERFLY(46, 28, 29, 11,  4)
+BUTTERFLY(47, 30, 31, 13,  2)
+BUTTERFLY(48, 32, 33,  6,  9)
+BUTTERFLY(49, 34, 35,  0, 15)
+BUTTERFLY(50, 36, 37, 13,  2)
+BUTTERFLY(51, 38, 39, 11,  4)
+BUTTERFLY(52, 40, 41, 13,  2)
+BUTTERFLY(53, 42, 43, 11,  4)
+BUTTERFLY(54, 44, 45,  6,  9)
+BUTTERFLY(55, 46, 47,  0, 15)
+BUTTERFLY(56, 48, 49,  2, 13)
+BUTTERFLY(57, 50, 51,  4, 11)
+BUTTERFLY(58, 52, 53,  9,  6)
+BUTTERFLY(59, 54, 55, 15,  0)
+BUTTERFLY(60, 56, 57,  9,  6)
+BUTTERFLY(61, 58, 59, 15,  0)
+BUTTERFLY(62, 60, 61,  2, 13)
+BUTTERFLY(63, 62, 63,  4, 11)
+
+#undef BUTTERFLY
+
+
+/* Calculate final soft out value */
+if (i < iNumOutBits)
+    vecOutputBits[i] = rL0 - rL1;
+
+/* Swap trellis data pointers (old -> new, new -> old) */
+_VITMETRTYPE* pTMPTrelMetric = pCurTrelMetric;
+pCurTrelMetric = pOldTrelMetric;
+pOldTrelMetric = pTMPTrelMetric;
+}
+#endif
+
+
+#ifndef USE_MAX_LOG_MAP
+/* Chainback the decoded bits from trellis (only for MLSE) -------------- */
+/* The end-state is defined by the DRM standard as all-zeros (shift register
+   in the encoder is padded with zeros at the end */
+iCurDecState = 0;
+
+for (i = 0; i < iNumOutBits; i++)
+{
+    /* Read out decisions "backwards". Mask only first bit, because in MMX
+       implementation, all 8 bits of a "char" are set to the decision */
+    const _DECISIONTYPE decCurBit =
+        matdecDecisions[iNumOutBitsWithMemory - i - 1][iCurDecState] & 1;
+
+    /* Calculate next state from previous decoded bit -> shift old data
+       and add new bit */
+    iCurDecState = (iCurDecState >> 1) | (decCurBit << 5);
+
+    /* Set decisions "backwards" in actual result vector */
+    vecOutputBits[iNumOutBits - i - 1] = (_BINARY) decCurBit;
+}
+#endif
+
+#ifdef USE_SIMD
+/* No accumulated metric available because of normalizing the metric because
+   of fixed-point implementation */
+return (_REAL) 1.0;
+#else
+/* Return normalized accumulated minimum metric */
+return pOldTrelMetric[0] / iDistCnt;
+#endif
+}
+
+void CViterbiDecoder::Init(ECodScheme eNewCodingScheme,
+                           EChanType eNewChannelType, int iN1,
+                           int iN2, int iNewNumOutBitsPartA,
+                           int iNewNumOutBitsPartB, int iPunctPatPartA,
+                           int iPunctPatPartB, int iLevel)
+{
+    /* Number of bits out is the sum of all protection levels */
+    iNumOutBits = iNewNumOutBitsPartA + iNewNumOutBitsPartB;
+
+    /* Number of out bits including the state memory */
+    iNumOutBitsWithMemory = iNumOutBits + MC_CONSTRAINT_LENGTH - 1;
+
+    /* Init vector, storing table for puncturing pattern and generate pattern */
+    veciTablePuncPat.Init(iNumOutBitsWithMemory);
+
+    veciTablePuncPat = GenPuncPatTable(eNewCodingScheme, eNewChannelType, iN1,
+                                       iN2, iNewNumOutBitsPartA, iNewNumOutBitsPartB, iPunctPatPartA,
+                                       iPunctPatPartB, iLevel);
+
+    /* Init vector for storing the decided bits */
+    matdecDecisions.Init(iNumOutBitsWithMemory, MC_NUM_STATES);
+
+#ifdef USE_MAX_LOG_MAP
+    /* Matrix is needed for storing the metrics since we use forward and
+       backward Viterbi algorithm */
+    matrMetricSet.Init(iNumOutBitsWithMemory, MC_NUM_OUTPUT_COMBINATIONS);
+
+    /* Init matrix for storing the accumulated metrics of forward Viterbi */
+    matrAlpha.Init(iNumOutBitsWithMemory, MC_NUM_STATES);
+#endif
+}
+
+CViterbiDecoder::CViterbiDecoder()
+{
+#if 0
+    /* Create trellis *********************************************************/
+    /* Activate this code to generate the table needed for the butterfly calls
+       in the processing routine */
+
+    /* We need to analyze 2^(MC_CONSTRAINT_LENGTH - 1) states in the trellis */
+    int	i;
+    int	iPrev0IndexForw[MC_NUM_STATES];
+    int	iPrev1IndexForw[MC_NUM_STATES];
+    int	iMetricPrev0Forw[MC_NUM_STATES];
+    int	iMetricPrev1Forw[MC_NUM_STATES];
+    int	iPrev0IndexBackw[MC_NUM_STATES];
+    int	iPrev1IndexBackw[MC_NUM_STATES];
+    int	iMetricPrev0Backw[MC_NUM_STATES];
+    int	iMetricPrev1Backw[MC_NUM_STATES];
+
+    for (i = 0; i < MC_NUM_STATES; i++)
+    {
+        /* Define previous states ------------------------------------------- */
+        /* We define in this trellis that we shift the bits from right to
+           the left. We use the transition-bits which "fall" out of the
+           shift-register (forward case) */
+        iPrev0IndexForw[i] = (i >> 1);			/* Old state, Leading "0"
+												   (automatically inserted by
+												   shifting */
+        iPrev1IndexForw[i] = (i >> 1)			 /* Old state */
+                             | (1 << (MC_CONSTRAINT_LENGTH - 2)); /* New "1", must be on position
+													MC_CONSTRAINT_LENGTH - 1 */
+
+        /* We define in this trellis that we shift the bits from left to
+           the right. We use the transition-bits which get in the
+           shift-register (backward case) */
+        /* Mask operator for length of state register of this code
+           [... 0, 0, 1, 1, 1, 1, 1, 1] */
+        const int iStRegMask = /* "MC_CONSTRAINT_LENGTH - 1" number of ones */
+            1 | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4) | (1 << 5);
+
+        iPrev0IndexBackw[i] = (i << 1) & iStRegMask; /* Old state, Beginning "0"
+												        (automatically inserted
+														by shifting. Mask result
+														to have length of state
+														register */
+        iPrev1IndexBackw[i] = ((i << 1) & iStRegMask) | 1;	/* New "1", must on
+															   first position */
+
+
+        /* Assign metrics to the transitions from both paths ---------------- */
+        /* We define with the metrics the order: [b_3, b_2, b_1, b_0] */
+        iMetricPrev0Forw[i] = 0;
+        iMetricPrev1Forw[i] = 0;
+        iMetricPrev0Backw[i] = 0;
+        iMetricPrev1Backw[i] = 0;
+        for (int j = 0; j < MC_NUM_OUTPUT_BITS_PER_STEP; j++)
+        {
+            /* Calculate respective metrics from convolution of state and
+               transition bit */
+            /* forwards */
+            /* "0" */
+            iMetricPrev0Forw[i] |= Convolution(
+                                       /* Set all states in the shift-register for encoder. Use
+                                          current state with a leading "0" (which is automatically
+                                          there) */
+                                       i
+                                       /* Use generator-polynomial j */
+                                       , j)
+                                   /* Shift generated bit to the correct position */
+                                   << j;
+
+            /* "1" */
+            iMetricPrev1Forw[i] |= Convolution(
+                                       /* Set all states in the shift-register for encoder. Use
+                                          current state with a leading "1". The position of this
+                                          bit is "MC_CONSTRAINT_LENGTH" (shifting from position 1:
+                                          "MC_CONSTRAINT_LENGTH - 1") */
+                                       i | (1 << (MC_CONSTRAINT_LENGTH - 1))
+                                       /* Use generator-polynomial j */
+                                       , j)
+                                   /* Shift generated bit to the correct position */
+                                   << j;
+
+            /* backwards */
+            /* "0" */
+            iMetricPrev0Backw[i] |= Convolution(
+                                        /* Set all states in the shift-register for encoder. Use
+                                           current state with a "0" at beginning (which is automatically
+                                           there) */
+                                        (i << 1),
+                                        /* Use generator-polynomial j */
+                                        j)
+                                    /* Shift generated bit to the correct position */
+                                    << j;
+
+            /* "1" */
+            iMetricPrev1Backw[i] |= Convolution(
+                                        /* Set all states in the shift-register for encoder. Use
+                                           current state with a "1" at beginning */
+                                        (i << 1) | 1,
+                                        /* Use generator-polynomial j */
+                                        j)
+                                    /* Shift generated bit to the correct position */
+                                    << j;
+        }
+    }
+
+    /* Save trellis in file (for substituting in the code) */
+    static FILE* pFile = fopen("test/trellis.dat", "w");
+
+    /* forwards */
+    fprintf(pFile, "/* forwards */\n");
+    for (i = 0; i < MC_NUM_STATES; i += 2)
+        fprintf(pFile, "BUTTERFLY(%2d, %2d, %2d, %2d, %2d, %2d)\n", i, i + 1,
+                iPrev0IndexForw[i], iPrev1IndexForw[i],
+                iMetricPrev0Forw[i], iMetricPrev1Forw[i]);
+
+    /* backwards */
+    fprintf(pFile, "\n\n\n/* backwards */\n");
+    for (i = 0; i < MC_NUM_STATES; i++)
+        fprintf(pFile, "BUTTERFLY(%2d, %2d, %2d, %2d, %2d)\n", i,
+                iPrev0IndexBackw[i], iPrev1IndexBackw[i],
+                iMetricPrev0Backw[i], iMetricPrev1Backw[i]);
+
+    fprintf(pFile, "\n");
+    fflush(pFile);
+    exit(1);
+#endif
+}
diff --git a/src/mlc/ViterbiDecoder.h b/src/mlc/ViterbiDecoder.h
new file mode 100644
index 0000000..942f9cb
--- /dev/null
+++ b/src/mlc/ViterbiDecoder.h
@@ -0,0 +1,143 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#if !defined(VITERBI_DECODER_H__3B0BA660_CA63_4344_BB2B_23E7A0D31912__INCLUDED_)
+#define VITERBI_DECODER_H__3B0BA660_CA63_4344_BB2B_23E7A0D31912__INCLUDED_
+
+#include "../GlobalDefinitions.h"
+#include "../tables/TableMLC.h"
+#include "ConvEncoder.h"
+#include "ChannelCode.h"
+
+
+/* Definitions ****************************************************************/
+/* SIMD implementation is always fixed-point (is disabled if MAP decoder is
+   activated!) */
+#define USE_SIMD
+#undef USE_SIMD
+
+/* Use MMX or SSE2 */
+#define USE_MMX
+#undef USE_MMX
+
+
+/* No MAP implementation for SIMD! */
+#ifdef USE_MAX_LOG_MAP
+# undef USE_SIMD
+#endif
+
+#ifdef USE_SIMD
+# ifndef USE_MMX
+#  define USE_SSE2
+# endif
+#endif
+
+/* Data type for Viterbi metric */
+#ifdef USE_SIMD
+# define _VITMETRTYPE				unsigned char
+# define _DECISIONTYPE				unsigned char
+#else
+# define _VITMETRTYPE				float
+# define _DECISIONTYPE				_BINARY
+#endif
+
+/* We initialize each new block of data all branches-metrics with the following
+   value exept of the zero-state. This can be done since we actually KNOW that
+   the zero state MUST be the transmitted one. The initialization vaule should
+   be fairly high. But we have to be careful choosing this parameter. We
+   should not take the largest value possible of the data type of the metric
+   variable since in the Viterbi-routine we add something to this value and
+   in that case we would force an overrun! */
+#ifdef USE_SIMD
+# define MC_METRIC_INIT_VALUE		((_VITMETRTYPE) 60)
+#else
+# define MC_METRIC_INIT_VALUE		((_VITMETRTYPE) 1e10)
+#endif
+
+
+/* In case of MAP decoder, all metrics must be stored for the entire input
+   vector since we need them for the forward and backward direction */
+#ifdef USE_MAX_LOG_MAP
+# define METRICSET(a)		matrMetricSet[a]
+#else
+# define METRICSET(a)		vecrMetricSet
+#endif
+
+
+/* Classes ********************************************************************/
+class CViterbiDecoder : public CChannelCode
+{
+public:
+    CViterbiDecoder();
+    virtual ~CViterbiDecoder() {}
+
+    _REAL	Decode(CVector<CDistance>& vecNewDistance,
+                 CVector<_DECISION>& vecOutputBits);
+    void	Init(ECodScheme eNewCodingScheme,
+              EChanType eNewChannelType, int iN1, int iN2,
+              int iNewNumOutBitsPartA, int iNewNumOutBitsPartB,
+              int iPunctPatPartA, int iPunctPatPartB, int iLevel);
+
+protected:
+    /* Two trellis data vectors are needed for current and old state */
+    _VITMETRTYPE			vecTrelMetric1[MC_NUM_STATES];
+    _VITMETRTYPE			vecTrelMetric2[MC_NUM_STATES];
+
+#ifdef USE_MAX_LOG_MAP
+    CMatrix<_REAL>			matrAlpha;
+    CMatrix<_REAL>			matrMetricSet;
+#else
+    _REAL					vecrMetricSet[MC_NUM_OUTPUT_COMBINATIONS];
+#endif
+
+    CVector<int>			veciTablePuncPat;
+
+    int						iNumOutBits;
+    int						iNumOutBitsWithMemory;
+
+    CMatrix<_DECISIONTYPE>	matdecDecisions;
+
+#ifdef USE_SIMD
+    /* Fields for storing the reodered metrics for MMX trellis */
+    _VITMETRTYPE			chMet1[MC_NUM_STATES / 2];
+    _VITMETRTYPE			chMet2[MC_NUM_STATES / 2];
+
+#ifdef USE_MMX
+    void TrellisUpdateMMX(
+#endif
+#ifdef USE_SSE2
+        void TrellisUpdateSSE2(
+#endif
+            const _DECISIONTYPE* pCurDec,
+            const _VITMETRTYPE* pCurTrelMetric, const _VITMETRTYPE* pOldTrelMetric,
+            const _VITMETRTYPE* pchMet1, const _VITMETRTYPE* pchMet2);
+#endif
+    };
+
+
+#endif // !defined(VITERBI_DECODER_H__3B0BA660_CA63_4344_BB2B_23E7A0D31912__INCLUDED_)
diff --git a/src/ofdmcellmapping/CellMappingTable.cpp b/src/ofdmcellmapping/CellMappingTable.cpp
new file mode 100644
index 0000000..330a860
--- /dev/null
+++ b/src/ofdmcellmapping/CellMappingTable.cpp
@@ -0,0 +1,727 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *	Table of the mapping of OFDM cells.
+ *	We build a table of one super-frame where we set flags for each cell to
+ *	identify the symbol for this place. E.g. if the flag "CM_MSC" is set for
+ *	one table entry this is the cell for a MSC-symbol. The name of the table
+ *	is matiMapTab.
+ *	We use the table "matcPilotCells" for storing the complex values for the
+ *	pilots. For simplicity we allocate memory for all blocks but only the
+ *	pilot positions are used.
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "../GlobalDefinitions.h"
+#include "CellMappingTable.h"
+
+
+/* Implementation *************************************************************/
+void CCellMappingTable::MakeTable(
+  ERobMode eNewRobustnessMode, ESpecOcc eNewSpectOccup, int iSampleRate)
+{
+	int			iNoMSCDummyCells; /* Number of MSC dummy cells */
+	int			iNumTimePilots=0; /* Number of time pilots per frame */
+	CScatPilots		ScatPilots;
+	int			iSym;
+	int			iFrameSym;
+	int			iCar;
+	int			iTimePilotsCounter;
+	int			iFreqPilotsCounter;
+	int			iScatPilotsCounter;
+	int			iFACCounter;
+	int			iScatPilPhase;
+	int			iCarArrInd;
+	int			iSpecOccArrayIndex=0;
+	/* Tables */
+	const int*		piTableFAC=NULL;
+	const int*		piTableTimePilots=NULL;
+	const int*		piTableFreqPilots=NULL;
+
+
+	/* Set Parameters and pointers to the tables ******************************/
+	switch (eNewSpectOccup)
+	{
+	case SO_0:
+		iSpecOccArrayIndex = 0;
+		break;
+
+	case SO_1:
+		iSpecOccArrayIndex = 1;
+		break;
+
+	case SO_2:
+		iSpecOccArrayIndex = 2;
+		break;
+
+	case SO_3:
+		iSpecOccArrayIndex = 3;
+		break;
+
+	case SO_4:
+		iSpecOccArrayIndex = 4;
+		break;
+
+	case SO_5:
+		iSpecOccArrayIndex = 5;
+		break;
+	case SO_6:
+		iSpecOccArrayIndex = 6;
+		break;
+	}
+
+	/* The robust mode defines all other parameters */
+	switch (eNewRobustnessMode)
+	{
+	case RM_ROBUSTNESS_MODE_A:
+		iCarrierKmin = iTableCarrierKmin[iSpecOccArrayIndex][0];
+		iCarrierKmax = iTableCarrierKmax[iSpecOccArrayIndex][0];
+		
+		iFFTSizeN = RMA_FFT_SIZE_N;
+		RatioTgTu.iEnum = RMA_ENUM_TG_TU;
+		RatioTgTu.iDenom = RMA_DENOM_TG_TU;
+
+		iNumSymPerFrame = RMA_NUM_SYM_PER_FRAME;
+		iNumSymbolsPerSuperframe = iNumSymPerFrame * NUM_FRAMES_IN_SUPERFRAME;
+		piTableFAC = &iTableFACRobModA[0][0];
+		iNumTimePilots = RMA_NUM_TIME_PIL;
+		piTableTimePilots = &iTableTimePilRobModA[0][0];
+		piTableFreqPilots = &iTableFreqPilRobModA[0][0];
+		iScatPilTimeInt = RMA_SCAT_PIL_TIME_INT;
+		iScatPilFreqInt = RMA_SCAT_PIL_FREQ_INT;
+
+		/* Scattered pilots phase definition */
+		ScatPilots.piConst = iTableScatPilConstRobModA;
+		ScatPilots.iColSizeWZ = SIZE_COL_WZ_ROB_MOD_A;
+		ScatPilots.piW = &iScatPilWRobModA[0][0];
+		ScatPilots.piZ = &iScatPilZRobModA[0][0];
+		ScatPilots.iQ = iScatPilQRobModA;
+
+		ScatPilots.piGainTable = &iScatPilGainRobModA[iSpecOccArrayIndex][0];
+		break;
+
+	case RM_ROBUSTNESS_MODE_B:
+		iCarrierKmin = iTableCarrierKmin[iSpecOccArrayIndex][1];
+		iCarrierKmax = iTableCarrierKmax[iSpecOccArrayIndex][1];
+
+		iFFTSizeN = RMB_FFT_SIZE_N;
+		RatioTgTu.iEnum = RMB_ENUM_TG_TU;
+		RatioTgTu.iDenom = RMB_DENOM_TG_TU;
+
+		iNumSymPerFrame = RMB_NUM_SYM_PER_FRAME;
+		iNumSymbolsPerSuperframe = iNumSymPerFrame * NUM_FRAMES_IN_SUPERFRAME;
+		piTableFAC = &iTableFACRobModB[0][0];
+		iNumTimePilots = RMB_NUM_TIME_PIL;
+		piTableTimePilots = &iTableTimePilRobModB[0][0];
+		piTableFreqPilots = &iTableFreqPilRobModB[0][0];
+		iScatPilTimeInt = RMB_SCAT_PIL_TIME_INT;
+		iScatPilFreqInt = RMB_SCAT_PIL_FREQ_INT;
+
+		/* Scattered pilots phase definition */
+		ScatPilots.piConst = iTableScatPilConstRobModB;
+		ScatPilots.iColSizeWZ = SIZE_COL_WZ_ROB_MOD_B;
+		ScatPilots.piW = &iScatPilWRobModB[0][0];
+		ScatPilots.piZ = &iScatPilZRobModB[0][0];
+		ScatPilots.iQ = iScatPilQRobModB;
+
+		ScatPilots.piGainTable = &iScatPilGainRobModB[iSpecOccArrayIndex][0];
+		break;
+
+	case RM_ROBUSTNESS_MODE_C:
+		iCarrierKmin = iTableCarrierKmin[iSpecOccArrayIndex][2];
+		iCarrierKmax = iTableCarrierKmax[iSpecOccArrayIndex][2];
+
+		iFFTSizeN = RMC_FFT_SIZE_N;
+		RatioTgTu.iEnum = RMC_ENUM_TG_TU;
+		RatioTgTu.iDenom = RMC_DENOM_TG_TU;
+
+		iNumSymPerFrame = RMC_NUM_SYM_PER_FRAME;
+		iNumSymbolsPerSuperframe = iNumSymPerFrame * NUM_FRAMES_IN_SUPERFRAME;
+		piTableFAC = &iTableFACRobModC[0][0];
+		iNumTimePilots = RMC_NUM_TIME_PIL;
+		piTableTimePilots = &iTableTimePilRobModC[0][0];
+		piTableFreqPilots = &iTableFreqPilRobModC[0][0];
+		iScatPilTimeInt = RMC_SCAT_PIL_TIME_INT;
+		iScatPilFreqInt = RMC_SCAT_PIL_FREQ_INT;
+
+		/* Scattered pilots phase definition */
+		ScatPilots.piConst = iTableScatPilConstRobModC;
+		ScatPilots.iColSizeWZ = SIZE_COL_WZ_ROB_MOD_C;
+		ScatPilots.piW = &iScatPilWRobModC[0][0];
+		ScatPilots.piZ = &iScatPilZRobModC[0][0];
+		ScatPilots.iQ = iScatPilQRobModC;
+
+		ScatPilots.piGainTable = &iScatPilGainRobModC[iSpecOccArrayIndex][0];
+		break;
+
+	case RM_ROBUSTNESS_MODE_D:
+		iCarrierKmin = iTableCarrierKmin[iSpecOccArrayIndex][3];
+		iCarrierKmax = iTableCarrierKmax[iSpecOccArrayIndex][3];
+
+		iFFTSizeN = RMD_FFT_SIZE_N;
+		RatioTgTu.iEnum = RMD_ENUM_TG_TU;
+		RatioTgTu.iDenom = RMD_DENOM_TG_TU;
+
+		iNumSymPerFrame = RMD_NUM_SYM_PER_FRAME;
+		iNumSymbolsPerSuperframe = iNumSymPerFrame * NUM_FRAMES_IN_SUPERFRAME;
+		piTableFAC = &iTableFACRobModD[0][0];
+		iNumTimePilots = RMD_NUM_TIME_PIL;
+		piTableTimePilots = &iTableTimePilRobModD[0][0];
+		piTableFreqPilots = &iTableFreqPilRobModD[0][0];
+		iScatPilTimeInt = RMD_SCAT_PIL_TIME_INT;
+		iScatPilFreqInt = RMD_SCAT_PIL_FREQ_INT;
+
+		/* Scattered pilots phase definition */
+		ScatPilots.piConst = iTableScatPilConstRobModD;
+		ScatPilots.iColSizeWZ = SIZE_COL_WZ_ROB_MOD_D;
+		ScatPilots.piW = &iScatPilWRobModD[0][0];
+		ScatPilots.piZ = &iScatPilZRobModD[0][0];
+		ScatPilots.iQ = iScatPilQRobModD;
+
+		ScatPilots.piGainTable = &iScatPilGainRobModD[iSpecOccArrayIndex][0];
+		break;
+
+	default:
+		break;
+	}
+
+	/* Adjusting fft size to sample rate */
+	iFFTSizeN = ADJ_FOR_SRATE(iFFTSizeN, iSampleRate);
+
+	/* Get number of carriers with DC */
+	iNumCarrier = iCarrierKmax - iCarrierKmin + 1;
+
+	/* Length of guard-interval measured in "time-bins". We do the calculation
+	   with integer variables -> "/ RatioTgTu.iDenom" MUST be the last
+	   operation! */
+	iGuardSize = iFFTSizeN * RatioTgTu.iEnum / RatioTgTu.iDenom;
+
+	/* Symbol block size is the guard-interval plus the useful part */
+	iSymbolBlockSize = iFFTSizeN + iGuardSize;
+
+	/* Calculate the index of the DC carrier in the shifted spectrum */
+	iIndexDCFreq = (int) ((_REAL) VIRTUAL_INTERMED_FREQ *
+		iFFTSizeN / iSampleRate);
+
+	/* Index of minimum useful carrier (shifted) */
+	iShiftedKmin = iIndexDCFreq + iCarrierKmin;
+
+	/* Index. of maximum useful carrier (shifted) */
+	iShiftedKmax = iIndexDCFreq + iCarrierKmax;
+
+	/* Calculate number of time-interploated frequency pilots. Special case
+	   with robustness mode D: pilots in all carriers! BUT: DC carrier is
+	   counted as a pilot in that case!!! Be aware of that! */
+	if (iScatPilFreqInt > 1)
+		iNumIntpFreqPil = (int) ((_REAL) iNumCarrier / iScatPilFreqInt + 1);
+	else
+		iNumIntpFreqPil = iNumCarrier;
+
+
+	/* Allocate memory for vectors and matrices ----------------------------- */
+	/* Allocate memory for mapping table (Matrix) */
+	matiMapTab.Init(iNumSymbolsPerSuperframe, iNumCarrier);
+
+	/* Allocate memory for pilot cells definition and set it to zero */
+	matcPilotCells.Init(iNumSymbolsPerSuperframe, iNumCarrier,
+		_COMPLEX((_REAL) 0.0, (_REAL) 0.0));
+
+	/* Allocate memory for vectors with number of certain cells */
+	veciNumMSCSym.Init(iNumSymbolsPerSuperframe);
+	veciNumFACSym.Init(iNumSymbolsPerSuperframe);
+	veciNumSDCSym.Init(iNumSymbolsPerSuperframe);
+
+
+	/* Build table ************************************************************/
+	/* Some of the definitions at the beginning are overwritten by successive
+	   definitions! E.g., first define all carriers as MSC cells */
+	iFreqPilotsCounter = 0;
+	iTimePilotsCounter = 0;
+	iFACCounter = 0;
+	for (iSym = 0; iSym < iNumSymbolsPerSuperframe; iSym++)
+	{
+		/* Frame symbol: Counts symbols in one frame, not super frame! */
+		iFrameSym = iSym % iNumSymPerFrame;
+
+		/* Reset FAC counter at the beginning of each new frame */
+		if (iFrameSym == 0)
+			iFACCounter = 0;
+
+		/* Calculate the start value of "p" in equation for gain reference
+		   cells in Table 90 (8.4.4.1) */
+		iScatPilotsCounter = (int) ((_REAL) (iCarrierKmin -
+			(int) ((_REAL) iScatPilFreqInt / 2 + .5) -
+			iScatPilFreqInt * mod(iFrameSym, iScatPilTimeInt)
+			) / (iScatPilFreqInt * iScatPilTimeInt));
+
+		for (iCar = iCarrierKmin; iCar < iCarrierKmax + 1; iCar++)
+		{
+			/* Set carrier array index (since we do not have negative indices
+			   in c++) */
+			iCarArrInd = iCar - iCarrierKmin;
+
+
+			/* MSC ---------------------------------------------------------- */
+			/* First set all cells to MSC-cells */
+			matiMapTab[iSym][iCarArrInd] = CM_MSC;
+
+
+			/* SDC ---------------------------------------------------------- */
+			/* No MSC-cells in the first two (or three) symbols -> SDC */
+			switch (eNewRobustnessMode)
+			{
+			case RM_ROBUSTNESS_MODE_A:
+			case RM_ROBUSTNESS_MODE_B:
+				if ((iSym == 0) || (iSym == 1))
+					matiMapTab[iSym][iCarArrInd] = CM_SDC;
+				break;
+
+			case RM_ROBUSTNESS_MODE_C:
+			case RM_ROBUSTNESS_MODE_D:
+				if ((iSym == 0) || (iSym == 1) || (iSym == 2))
+					matiMapTab[iSym][iCarArrInd] = CM_SDC;
+				break;
+
+			default:
+				break;
+			}
+
+
+			/* FAC ---------------------------------------------------------- */
+			/* FAC positions are defined in a table */
+			if (iFACCounter < NUM_FAC_CELLS)
+			{
+				/* piTableFAC[x * 2]: first column; piTableFAC[x * 2 + 1]:
+				   second column */
+				if (piTableFAC[iFACCounter * 2] * iNumCarrier +
+					piTableFAC[iFACCounter * 2 + 1] == iFrameSym *
+					iNumCarrier + iCar)
+				{
+					iFACCounter++;
+					matiMapTab[iSym][iCarArrInd] = CM_FAC;
+				}
+			}
+
+
+			/* Scattered pilots --------------------------------------------- */
+			/* Standard: 8.4.4.3:
+			   "In some cases gain references fall in locations which coincide
+			   with those already defined for either frequency or time
+			   references. In these cases, the phase definitions given in
+			   clauses 8.4.2 and 8.4.3 take precedence."
+			   Therefore, Scattered pilots must be definded FIRST here! */
+
+			/* The rule for calculating the scattered pilots is defined in the
+			   specification in the following form:
+			   e.g.: k = 2 + 4 * (s mod 5) + 20 * p
+			   We define a "frequency-" (FreqInt) and "time-interpolation"
+			   (TimeInt). In this example, "4" is the FreqInt and "5" is the
+			   TimeInt. The first term "2" is the half of the FreqInt, rounded
+			   towards infinity. The parameter "20" is FreqInt * TimeInt */
+			if (iCar == (int) ((_REAL) iScatPilFreqInt / 2 + .5) +
+				iScatPilFreqInt * mod(iFrameSym, iScatPilTimeInt) +
+				iScatPilFreqInt * iScatPilTimeInt * iScatPilotsCounter)
+			{
+				iScatPilotsCounter++;
+
+				/* Set flag in mapping table */
+				matiMapTab[iSym][iCarArrInd] = CM_SCAT_PI;
+
+				/* Set complex value for this pilot */
+				/* Phase calculation ---------------------------------------- */
+				int in, im, ip, i;
+
+				/* Calculations as in drm-standard (8.4.4.3.1) */
+				/* "in" is ROW index and "im" is COLUMN index! */
+				in = mod(iFrameSym, ScatPilots.piConst[1] /* "y" */);
+				im = (int)
+					((_REAL) iFrameSym / ScatPilots.piConst[1] /* "y" */);
+				ip = (int) ((_REAL) (iCar - ScatPilots.piConst[2] /* "k_0" */ -
+					in * ScatPilots.piConst[0] /* "x" */) / (
+					ScatPilots.piConst[0] /* "x" */ *
+					ScatPilots.piConst[1] /* "y" */));
+
+				/* Phase_1024[s,k] =
+				   (4Z_256[n,m]pW_1024[n,m] + p^2(1 + s)Q_1024) mod 1024 */
+				iScatPilPhase = mod(4 * ScatPilots.piZ[in *
+					ScatPilots.iColSizeWZ + im] + ip *
+					ScatPilots.piW[in *
+					ScatPilots.iColSizeWZ + im] +
+					ip * ip * (1 + iFrameSym) * ScatPilots.iQ, 1024);
+
+
+				/* Gain calculation and applying of complex value ----------- */
+				/* Test, if current carrier-index is one of the "boosted pilots"
+				   position */
+				_BOOLEAN bIsBoostedPilot = FALSE;
+				for (i = 0; i < NUM_BOOSTED_SCAT_PILOTS; i++)
+				{
+					/* In case of match set flag */
+					if (ScatPilots.piGainTable[i] == iCar)
+						bIsBoostedPilot = TRUE;
+				}
+
+				/* Boosted pilot: Gain = 2, Regular pilot: Gain = sqrt(2) */
+				if (bIsBoostedPilot)
+				{
+					matcPilotCells[iSym][iCarArrInd] =
+						Polar2Cart(sqrt(AV_BOOSTED_PIL_POWER), iScatPilPhase);
+
+					/* Add flag for boosted pilot */
+					matiMapTab[iSym][iCarArrInd] |= CM_BOOSTED_PI;
+				}
+				else
+				{
+					matcPilotCells[iSym][iCarArrInd] =
+						Polar2Cart(sqrt(AV_PILOT_POWER), iScatPilPhase);
+				}
+			}
+
+
+			/* Time-reference pilots ---------------------------------------- */
+			/* Time refs at the beginning of each frame, we use a table */
+			if (iFrameSym == 0)
+			{
+				/* Use only the first column in piTableTimePilots */
+				if (piTableTimePilots[iTimePilotsCounter * 2] == iCar)
+				{
+					/* Set flag in mapping table, consider case of both,
+					   scattered pilot and time pilot at same position */
+					if (_IsScatPil(matiMapTab[iSym][iCarArrInd]))
+						matiMapTab[iSym][iCarArrInd] |= CM_TI_PI;
+					else
+						matiMapTab[iSym][iCarArrInd] = CM_TI_PI;
+
+					/* Set complex value for this pilot */
+					matcPilotCells[iSym][iCarArrInd] =
+						Polar2Cart(sqrt(AV_PILOT_POWER),
+						piTableTimePilots[iTimePilotsCounter * 2 + 1]);
+
+					if (iTimePilotsCounter == iNumTimePilots - 1)
+						iTimePilotsCounter = 0;
+					else
+						iTimePilotsCounter++;
+				}
+			}
+
+
+			/* Frequency-reference pilots ----------------------------------- */
+			/* These pilots are in all symbols, the positions are stored in
+			   a table */
+			/* piTableFreqPilots[x * 2]: first column;
+			   piTableFreqPilots[x * 2 + 1]: second column */
+			if (piTableFreqPilots[iFreqPilotsCounter * 2] == iCar)
+			{
+				/* Set flag in mapping table, consider case of multiple
+				   definitions of pilot-mapping */
+				if (_IsTiPil(matiMapTab[iSym][iCarArrInd]) ||
+					_IsScatPil(matiMapTab[iSym][iCarArrInd]))
+				{
+					matiMapTab[iSym][iCarArrInd] |= CM_FRE_PI;
+				}
+				else
+					matiMapTab[iSym][iCarArrInd] = CM_FRE_PI;
+
+				/* Set complex value for this pilot */
+				/* Test for "special case" defined in drm-standard */
+				_BOOLEAN bIsFreqPilSpeciCase = FALSE;
+				if (eNewRobustnessMode == RM_ROBUSTNESS_MODE_D)
+				{
+					/* For robustness mode D, carriers 7 and 21 (Means: first
+					   and second pilot, not No. 28 (NUM_FREQ_PILOTS - 1) */
+					if (iFreqPilotsCounter != NUM_FREQ_PILOTS - 1)
+					{
+						/* Test for odd values of "s" (iSym) */
+						if ((iFrameSym % 2) == 1)
+							bIsFreqPilSpeciCase = TRUE;
+					}
+				}
+
+				/* Apply complex value */
+				if (bIsFreqPilSpeciCase)
+				{
+					matcPilotCells[iSym][iCarArrInd] =
+						Polar2Cart(sqrt(AV_PILOT_POWER), mod(
+						piTableFreqPilots[iFreqPilotsCounter * 2 + 1] +
+						512, 1024));
+				}
+				else
+				{
+					matcPilotCells[iSym][iCarArrInd] =
+						Polar2Cart(sqrt(AV_PILOT_POWER),
+						piTableFreqPilots[iFreqPilotsCounter * 2 + 1]);
+				}
+
+				/* Increase counter and wrap if needed */
+				if (iFreqPilotsCounter == NUM_FREQ_PILOTS - 1)
+					iFreqPilotsCounter = 0;
+				else
+					iFreqPilotsCounter++;
+			}
+
+
+			/* DC-carrier (not used by DRM) --------------------------------- */
+			/* Mark DC-carrier. Must be marked after scattered pilots, because
+			   in one case (Robustness Mode D) some pilots must be overwritten!
+			   */
+			if (iCar == 0)
+				matiMapTab[iSym][iCarArrInd] = CM_DC;
+
+			/* In Robustness Mode A there are three "not used carriers" */
+			if (eNewRobustnessMode == RM_ROBUSTNESS_MODE_A)
+			{
+				if ((iCar == -1) || (iCar == 1))
+					matiMapTab[iSym][iCarArrInd] = CM_DC;
+			} 
+		}
+	}
+
+
+	/* Count individual cells *************************************************/
+	/* We need to count the cells in a symbol for defining how many values from
+	   each source is needed to generate one symbol in carrier-mapping */
+	/* Init all counters */
+	iMaxNumMSCSym = 0;
+	iNumSDCCellsPerSFrame = 0;
+	int iMSCCounter = 0;
+	int iScatPilotCellCnt = 0;
+
+	rAvPowPerSymbol = (_REAL) 0.0;
+	rAvScatPilPow = (_REAL) 0.0;
+
+	for (iSym = 0; iSym < iNumSymbolsPerSuperframe; iSym++)
+	{
+		/* Init all counters */
+		veciNumMSCSym[iSym] = 0;
+		veciNumFACSym[iSym] = 0;
+		veciNumSDCSym[iSym] = 0;
+
+		for (iCar = 0; iCar < iNumCarrier; iCar++)
+		{
+			/* MSC */
+			if (_IsMSC(matiMapTab[iSym][iCar]))
+			{
+				veciNumMSCSym[iSym]++;
+
+				/* Count ALL MSC cells per super-frame */
+				iMSCCounter++;
+			}
+
+			/* FAC */
+			if (_IsFAC(matiMapTab[iSym][iCar]))
+				veciNumFACSym[iSym]++;
+
+			/* SDC */
+			if (_IsSDC(matiMapTab[iSym][iCar]))
+			{
+				veciNumSDCSym[iSym]++;
+
+				/* Count ALL SDC cells per super-frame */
+				iNumSDCCellsPerSFrame++;
+			}
+
+			/* Calculations for average power per symbol (needed for SNR
+			   estimation and simulation). DC carrier is zero (contributes not
+			   to the average power) */
+			if (!_IsDC(matiMapTab[iSym][iCar]))
+			{
+				if (_IsData(matiMapTab[iSym][iCar]))
+				{
+					/* Data cells have average power of 1 */
+					rAvPowPerSymbol += AV_DATA_CELLS_POWER;
+				}
+				else
+				{
+					/* All pilots have power of 2 except of the boosted pilots
+					   at the edges of the spectrum (they have power of 4) */
+					if (_IsBoosPil(matiMapTab[iSym][iCar]))
+					{
+						rAvPowPerSymbol += AV_BOOSTED_PIL_POWER;
+
+						if (_IsScatPil(matiMapTab[iSym][iCar]))
+						{
+							/* Boosted scattered pilots power */
+							rAvScatPilPow += AV_BOOSTED_PIL_POWER;
+							iScatPilotCellCnt++;
+						}
+					}
+					else
+					{
+						/* Regular pilot has power of 2 */
+						rAvPowPerSymbol += AV_PILOT_POWER;
+
+						if (_IsScatPil(matiMapTab[iSym][iCar]))
+						{
+							/* Scattered pilots power */
+							rAvScatPilPow += AV_PILOT_POWER;
+							iScatPilotCellCnt++;
+						}
+					}
+				}
+			}
+		}
+
+		/* Set maximum for symbol */
+		/* MSC */
+		if (iMaxNumMSCSym < veciNumMSCSym[iSym])
+			iMaxNumMSCSym = veciNumMSCSym[iSym];
+	}
+
+	/* Set number of useful MSC cells */
+	iNumUsefMSCCellsPerFrame =
+		(int) (iMSCCounter / NUM_FRAMES_IN_SUPERFRAME);
+
+	/* Calculate dummy cells for MSC */
+	iNoMSCDummyCells = iMSCCounter - iNumUsefMSCCellsPerFrame *
+		NUM_FRAMES_IN_SUPERFRAME;
+
+	/* Correct last MSC count (because of dummy cells) */
+	veciNumMSCSym[iNumSymbolsPerSuperframe - 1] -= iNoMSCDummyCells;
+
+	/* Normalize the average powers */
+	rAvPowPerSymbol /= iNumSymbolsPerSuperframe;
+	rAvScatPilPow /= iScatPilotCellCnt;
+
+
+/* ########################################################################## */
+#ifdef _DEBUG_
+/* Save table in file */
+FILE* pFile = fopen("test/CarMapTable.dat", "w");
+
+/* Title */
+fprintf(pFile, "Robustness mode ");
+switch (eNewRobustnessMode)
+{
+case RM_ROBUSTNESS_MODE_A:
+	fprintf(pFile, "A");
+	break;
+case RM_ROBUSTNESS_MODE_B:
+	fprintf(pFile, "B");
+	break;
+case RM_ROBUSTNESS_MODE_C:
+	fprintf(pFile, "C");
+	break;
+case RM_ROBUSTNESS_MODE_D:
+	fprintf(pFile, "D");
+	break;
+}
+fprintf(pFile, " / Spectrum occupancy %d\n\n", iSpecOccArrayIndex);
+
+/* Actual table */
+for (int i = 0; i < iNumSymbolsPerSuperframe; i++)
+{
+	for (int j = 0; j < iNumCarrier; j++)
+	{
+		if (_IsDC(matiMapTab[i][j]))
+		{
+			fprintf(pFile, ":");
+			continue;
+		}
+		if (_IsMSC(matiMapTab[i][j]))
+		{
+			fprintf(pFile, ".");
+			continue;
+		}
+		if (_IsSDC(matiMapTab[i][j]))
+		{
+			fprintf(pFile, "S");
+			continue;
+		}
+		if (_IsFAC(matiMapTab[i][j]))
+		{
+			fprintf(pFile, "X");
+			continue;
+		}
+		if (_IsTiPil(matiMapTab[i][j]))
+		{
+			fprintf(pFile, "T");
+			continue;
+		}
+		if (_IsFreqPil(matiMapTab[i][j]))
+		{
+			fprintf(pFile, "f");
+			continue;
+		}
+		if (_IsScatPil(matiMapTab[i][j]))
+		{
+			/* Special mark for boosted pilots */
+			if (_IsBoosPil(matiMapTab[i][j]))
+				fprintf(pFile, "*");
+			else
+				fprintf(pFile, "0");
+			continue;
+		}
+	}
+	fprintf(pFile, "\n");
+}
+
+/* Legend */
+fprintf(pFile, "\n------------------>\n subcarrier index");
+fprintf(pFile, "\n\n\nLegend:\n\t: DC-carrier\n\t. MCS cells\n\tS SDC cells");
+fprintf(pFile, "\n\tX FAC cells\n\tT time pilots\n\tf frequency pilots");
+fprintf(pFile, "\n\t0 scattered pilots\n\t* boosted scattered pilots\n");
+
+fclose(pFile);
+
+/* Save pilot values in file */
+/* Use following command to plot pilot complex values in Matlab:
+
+	clear all;close all;load PilotCells.dat;subplot(211),mesh(abs(complex(PilotCells(:,1:2:end), PilotCells(:,2:2:end))));subplot(212),mesh(angle(complex(PilotCells(:,1:2:end), PilotCells(:,2:2:end))))
+
+(It plots the absolute of the pilots in the upper plot and angle in 
+the lower plot.)
+*/
+pFile = fopen("test/PilotCells.dat", "w");
+for (int z = 0; z < iNumSymbolsPerSuperframe; z++)
+{
+	for (int v = 0; v < iNumCarrier; v++)
+		fprintf(pFile, "%e %e ", matcPilotCells[z][v].real(),
+			matcPilotCells[z][v].imag());
+
+	fprintf(pFile, "\n");
+}
+fclose(pFile);
+#endif
+/* ########################################################################## */
+}
+
+_COMPLEX CCellMappingTable::Polar2Cart(const _REAL rAbsolute,
+									   const int iPhase) const
+{
+/*
+	This function takes phases normalized to 1024 as defined in the drm-
+	standard.
+*/
+	return _COMPLEX(rAbsolute * cos((_REAL) 2 * crPi * iPhase / 1024),
+		rAbsolute * sin((_REAL) 2 * crPi * iPhase / 1024));
+}
+
+int CCellMappingTable::mod(const int ix, const int iy) const
+{
+	/* Modulus definition for integer numbers */
+	if (ix < 0)
+		return ix % iy + iy;
+	else
+		return ix % iy;
+}
diff --git a/src/ofdmcellmapping/CellMappingTable.h b/src/ofdmcellmapping/CellMappingTable.h
new file mode 100644
index 0000000..e76573e
--- /dev/null
+++ b/src/ofdmcellmapping/CellMappingTable.h
@@ -0,0 +1,148 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *	
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later 
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT 
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#if !defined(CELLMAPPINGTABLE_H__3B0BA660_CA63_4347A0D31912__INCLUDED_)
+#define CELLMAPPINGTABLE_H__3B0BA660_CA63_4347A0D31912__INCLUDED_
+
+#include "../GlobalDefinitions.h"
+#include "../tables/TableCarMap.h"
+#include "../tables/TableFAC.h"
+#include "../util/Vector.h"
+
+
+/* Definitions ****************************************************************/
+/* Power definitions for pilots, boosted pilots and data cells (average) */
+#define AV_DATA_CELLS_POWER		((_REAL) 1.0)
+#define AV_PILOT_POWER			((_REAL) 2.0)
+#define AV_BOOSTED_PIL_POWER	((_REAL) 4.0)
+
+
+/* We define a bit for each flag to allow multiple assignments */
+#define	CM_DC					1	/* Bit 0 */ // CM: Carrier Mapping
+#define	CM_MSC					2	/* Bit 1 */
+#define	CM_SDC					4	/* Bit 2 */
+#define	CM_FAC					8	/* Bit 3 */
+#define	CM_TI_PI				16	/* Bit 4 */
+#define	CM_FRE_PI				32	/* Bit 5 */
+#define	CM_SCAT_PI				64	/* Bit 6 */
+#define	CM_BOOSTED_PI			128	/* Bit 7 */
+
+/* Definitions for checking the cells */
+#define _IsDC(a)				((a) & CM_DC)
+
+#define _IsMSC(a)				((a) & CM_MSC)
+#define _IsSDC(a)				((a) & CM_SDC)
+#define _IsFAC(a)				((a) & CM_FAC)
+
+#define _IsData(a)				(((a) & CM_MSC) || ((a) & CM_SDC) || ((a) & CM_FAC))
+
+
+#define _IsTiPil(a)				((a) & CM_TI_PI)
+#define _IsFreqPil(a)			((a) & CM_FRE_PI)
+#define _IsScatPil(a)			((a) & CM_SCAT_PI)
+
+#define _IsPilot(a)				(((a) & CM_TI_PI) || ((a) & CM_FRE_PI) || ((a) & CM_SCAT_PI))
+#define _IsBoosPil(a)			((a) & CM_BOOSTED_PI)
+
+
+/* Classes ********************************************************************/
+class CCellMappingTable
+{
+public:
+	CCellMappingTable() : iNumSymbolsPerSuperframe(0) {}
+	virtual ~CCellMappingTable() {}
+
+	void MakeTable(ERobMode eNewRobustnessMode, ESpecOcc eNewSpectOccup, int iSampleRate);
+
+	struct CRatio {int iEnum; int iDenom;};
+
+	/* Mapping table and pilot cell matrix */
+	CMatrix<int>		matiMapTab; 
+	CMatrix<_COMPLEX>	matcPilotCells;
+
+	int					iNumSymbolsPerSuperframe;
+	int					iNumSymPerFrame; /* Number of symbols per frame */
+	int					iNumCarrier;
+	int					iScatPilTimeInt; /* Time interpolation */
+	int					iScatPilFreqInt; /* Frequency interpolation */
+
+	int					iMaxNumMSCSym; /* Max number of MSC cells in a symbol */
+
+	/* Number of MSC cells in a symbol */
+	CVector<int>		veciNumMSCSym; 
+
+	/* Number of FAC cells in a symbol */
+	CVector<int>		veciNumFACSym; 
+
+	/* Number of SDC cells in a symbol */
+	CVector<int>		veciNumSDCSym;
+
+	int					iFFTSizeN; /* FFT size of the OFDM modulation */
+	int					iCarrierKmin; /* Carrier index of carrier with lowest frequency */
+	int					iCarrierKmax; /* Carrier index of carrier with highest frequency */
+	int					iIndexDCFreq; /* Index of DC carrier */
+	int					iShiftedKmin; /* Shifted carrier min ("sound card pass-band") */
+	int					iShiftedKmax; /* Shifted carrier max ("sound card pass-band") */
+	CRatio				RatioTgTu; /* Ratio between guard-interval and useful part */
+	int					iGuardSize; /* Length of guard-interval measured in "time-bins" */
+	int					iSymbolBlockSize; /* Useful part plus guard-interval in "time-bins" */
+	int					iNumIntpFreqPil; /* Number of time-interploated frequency pilots */
+
+	int					iNumUsefMSCCellsPerFrame; /* Number of MSC cells per multiplex frame N_{MUX} */
+	int					iNumSDCCellsPerSFrame; /* Number of SDC cells per super-frame */
+
+	/* Needed for SNR estimation and simulation */
+	_REAL				rAvPowPerSymbol; /* Total average power per symbol */
+	_REAL				rAvScatPilPow; /* Average power of scattered pilots per cell */
+
+protected:
+	/* Internal parameters for MakeTable function --------------------------- */
+	struct CScatPilots
+	{	
+		CScatPilots(): piConst(NULL), iColSizeWZ(0), piW(NULL), piZ(NULL),
+		iQ(0),piGainTable(NULL) {}
+
+		/* For the pase */
+		const int*  piConst;
+		int			iColSizeWZ;
+		const int*	piW;
+		const int*	piZ;
+		int			iQ;
+
+		/* For the gain */
+		const int*	piGainTable;
+	};
+
+
+private:
+	_COMPLEX	Polar2Cart(const _REAL rAbsolute, const int iPhase) const;
+	int			mod(const int ix, const int iy) const;
+};
+
+
+#endif // !defined(CELLMAPPINGTABLE_H__3B0BA660_CA63_4347A0D31912__INCLUDED_)
diff --git a/src/ofdmcellmapping/OFDMCellMapping.cpp b/src/ofdmcellmapping/OFDMCellMapping.cpp
new file mode 100644
index 0000000..5bdf5c4
--- /dev/null
+++ b/src/ofdmcellmapping/OFDMCellMapping.cpp
@@ -0,0 +1,329 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *	Mapping of the symbols on the carriers
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "OFDMCellMapping.h"
+
+
+/* Implementation *************************************************************/
+/******************************************************************************\
+* OFDM cells mapping														   *
+\******************************************************************************/
+void COFDMCellMapping::ProcessDataInternal(CParameter& TransmParam)
+{
+	const CCellMappingTable& Param = TransmParam.CellMappingTable;
+
+	/* Mapping of the data and pilot cells on the OFDM symbol --------------- */
+	/* Set absolute symbol position */
+	int iSymbolCounterAbs =
+		TransmParam.iFrameIDTransm * iNumSymPerFrame + iSymbolCounter;
+
+	/* Init temporary counter */
+	int iDummyCellCounter = 0;
+	int iMSCCounter = 0;
+	int iFACCounter = 0;
+	int iSDCCounter = 0;
+	for (int iCar = 0; iCar < iNumCarrier; iCar++)
+	{
+		/* MSC */
+		if (_IsMSC(Param.matiMapTab[iSymbolCounterAbs][iCar]))
+		{
+			if (iMSCCounter >= Param.veciNumMSCSym[iSymbolCounterAbs])
+			{
+				/* Insert dummy cells */
+				(*pvecOutputData)[iCar] = pcDummyCells[iDummyCellCounter];
+
+				iDummyCellCounter++;
+			}
+			else
+				(*pvecOutputData)[iCar] = (*pvecInputData)[iMSCCounter];
+				
+			iMSCCounter++;
+		}
+
+		/* FAC */
+		if (_IsFAC(Param.matiMapTab[iSymbolCounterAbs][iCar]))
+		{
+			(*pvecOutputData)[iCar] = (*pvecInputData2)[iFACCounter];
+				
+			iFACCounter++;
+		}
+
+		/* SDC */
+		if (_IsSDC(Param.matiMapTab[iSymbolCounterAbs][iCar]))
+		{
+			(*pvecOutputData)[iCar] = (*pvecInputData3)[iSDCCounter];
+				
+			iSDCCounter++;
+		}
+
+		/* Pilots */
+		if (_IsPilot(Param.matiMapTab[iSymbolCounterAbs][iCar]))
+			(*pvecOutputData)[iCar] = Param.matcPilotCells[iSymbolCounterAbs][iCar];
+
+		/* DC carrier */
+		if (_IsDC(Param.matiMapTab[iSymbolCounterAbs][iCar]))
+			(*pvecOutputData)[iCar] = _COMPLEX((_REAL) 0.0, (_REAL) 0.0);
+	}
+
+	/* Increase symbol-counter and wrap if needed */
+	iSymbolCounter++;
+	if (iSymbolCounter == iNumSymPerFrame)
+	{
+		iSymbolCounter = 0;
+
+		/* Increase frame-counter (ID) (Used also in FAC.cpp) */
+		TransmParam.iFrameIDTransm++;
+		if (TransmParam.iFrameIDTransm == NUM_FRAMES_IN_SUPERFRAME)
+			TransmParam.iFrameIDTransm = 0;
+	}
+
+	/* Set absolute symbol position (for updated relative positions) */
+	iSymbolCounterAbs =
+		TransmParam.iFrameIDTransm * iNumSymPerFrame + iSymbolCounter;
+
+	/* Set input block-sizes for next symbol */
+	iInputBlockSize = Param.veciNumMSCSym[iSymbolCounterAbs];
+	iInputBlockSize2 = Param.veciNumFACSym[iSymbolCounterAbs];
+	iInputBlockSize3 = Param.veciNumSDCSym[iSymbolCounterAbs];
+}
+
+void COFDMCellMapping::InitInternal(CParameter& TransmParam)
+{
+	const CCellMappingTable& Param = TransmParam.CellMappingTable;
+
+	iNumSymPerFrame = Param.iNumSymPerFrame;
+	iNumCarrier = Param.iNumCarrier;
+
+	/* Init symbol-counter */
+	iSymbolCounter = 0;
+
+	/* Init frame ID */
+	TransmParam.iFrameIDTransm = 0;
+
+	/* Choose right dummy cells for MSC QAM scheme */
+	switch (TransmParam.eMSCCodingScheme)
+	{
+	case CS_1_SM: /* no 4QAM in MSC */
+		break;
+
+	case CS_2_SM:
+		pcDummyCells = (_COMPLEX*) &cDummyCells16QAM[0];
+		break;
+
+	case CS_3_SM:
+	case CS_3_HMSYM:
+	case CS_3_HMMIX:
+		pcDummyCells = (_COMPLEX*) &cDummyCells64QAM[0];
+		break;
+	}
+
+	/* Define block-sizes for input and output of the module ---------------- */
+	iInputBlockSize = Param.veciNumMSCSym[0]; /* MSC */
+	iInputBlockSize2 = Param.veciNumFACSym[0]; /* FAC */
+	iInputBlockSize3 = Param.veciNumSDCSym[0]; /* SDC */
+	iOutputBlockSize = Param.iNumCarrier; /* Output */
+}
+
+
+/******************************************************************************\
+* OFDM cells demapping														   *
+\******************************************************************************/
+void COFDMCellDemapping::ProcessDataInternal(CParameter& Parameters)
+{
+	const CCellMappingTable& Param = Parameters.CellMappingTable;
+
+	/* Set absolute symbol position */
+	const int iSymbolCounterAbs =
+		iCurrentFrameID * iNumSymPerFrame + iSymbolCounter;
+
+	/* Set output block-sizes for this symbol */
+	iOutputBlockSize = Param.veciNumMSCSym[iSymbolCounterAbs];
+	iOutputBlockSize2 = Param.veciNumFACSym[iSymbolCounterAbs];
+	iOutputBlockSize3 = Param.veciNumSDCSym[iSymbolCounterAbs];
+
+	/* Demap data from the cells */
+	int iMSCCounter = 0;
+	int iFACCounter = 0;
+	int iSDCCounter = 0;
+	for (int iCar = 0; iCar < iNumCarrier; iCar++)
+	{
+		/* MSC */
+		if (_IsMSC(Param.matiMapTab[iSymbolCounterAbs][iCar]))
+		{
+			/* Ignore dummy cells */
+			if (iMSCCounter < Param.veciNumMSCSym[iSymbolCounterAbs])
+			{
+				(*pvecOutputData)[iMSCCounter] = (*pvecInputData)[iCar];
+
+				iMSCCounter++; /* Local counter */
+				iMSCCellCounter++; /* Super-frame counter */
+			}
+		}
+
+		/* FAC */
+		if (_IsFAC(Param.matiMapTab[iSymbolCounterAbs][iCar]))
+		{
+			(*pvecOutputData2)[iFACCounter] = (*pvecInputData)[iCar];
+
+			iFACCounter++; /* Local counter */
+			iFACCellCounter++; /* Super-frame counter */
+		}
+
+		/* SDC */
+		if (_IsSDC(Param.matiMapTab[iSymbolCounterAbs][iCar]))
+		{
+			(*pvecOutputData3)[iSDCCounter] = (*pvecInputData)[iCar];
+
+			iSDCCounter++; /* Local counter */
+			iSDCCellCounter++; /* Super-frame counter */
+		}
+	}
+
+	/* Get symbol-counter for next symbol and adjust frame-ID. Use the extended
+	   data, shipped with the input vector */
+	int iNewSymbolCounter = (*pvecInputData).GetExData().iSymbolID + 1;
+
+	/* Check range (iSymbolCounter must be in {0, ... , iNumSymPerFrame - 1} */
+	while (iNewSymbolCounter >= iNumSymPerFrame)
+		iNewSymbolCounter -= iNumSymPerFrame;
+	while (iNewSymbolCounter < 0)
+		iNewSymbolCounter += iNumSymPerFrame;
+
+	/* Increment internal symbol counter and take care of wrap around */
+	iSymbolCounter++;
+	if (iSymbolCounter == iNumSymPerFrame)
+		iSymbolCounter = 0;
+
+	/* Check if symbol counter has changed (e.g. due to frame synchronization
+	   unit). Reset all buffers in that case to avoid buffer overflow */
+	if (iSymbolCounter != iNewSymbolCounter)
+	{
+		/* Init symbol counter with new value and reset all output buffers */
+		iSymbolCounter = iNewSymbolCounter;
+
+		SetBufReset1();
+		SetBufReset2();
+		SetBufReset3();
+		iMSCCellCounter = 0;
+		iFACCellCounter = 0;
+		iSDCCellCounter = 0;
+	}
+
+	/* If frame bound is reached, update frame ID from FAC stream */
+	if (iSymbolCounter == 0)
+	{
+		/* Check, if number of FAC cells is correct. If not, reset
+		   output cyclic-buffer. An incorrect number of FAC cells can be if
+		   the "iSymbolCounterAbs" was changed, e.g. by the synchronization
+		   units */
+		if (iFACCellCounter != NUM_FAC_CELLS)
+			SetBufReset2(); /* FAC: buffer number 2 */
+
+		/* Reset FAC cell counter */
+		iFACCellCounter = 0;
+
+		/* Frame ID of this FAC block stands for the "current" block. We need
+		   the ID of the next block, therefore we have to add "1" */
+		int iNewFrameID = Parameters.iFrameIDReceiv + 1;
+		if (iNewFrameID == NUM_FRAMES_IN_SUPERFRAME)
+			iNewFrameID = 0;
+
+		/* Increment internal frame ID and take care of wrap around */
+		iCurrentFrameID++;
+		if (iCurrentFrameID == NUM_FRAMES_IN_SUPERFRAME)
+			iCurrentFrameID = 0;
+
+		/* Check if frame ID has changed, if yes, reset output buffers to avoid
+		   buffer overflows */
+		if (iCurrentFrameID != iNewFrameID)
+		{
+			iCurrentFrameID = iNewFrameID;
+
+			/* Only SDC and MSC depend on frame ID */
+			SetBufReset1(); /* MSC: buffer number 1 */
+			SetBufReset3(); /* SDC: buffer number 3 */
+			iMSCCellCounter = 0;
+			iSDCCellCounter = 0;
+		}
+
+		if (iCurrentFrameID == 0)
+		{
+			/* Super-frame bound reached, test cell-counters (same as with the
+			   FAC cells, see above) */
+			if (iMSCCellCounter != iNumUsefMSCCellsPerFrame *
+				NUM_FRAMES_IN_SUPERFRAME)
+			{
+				SetBufReset1(); /* MSC: buffer number 1 */
+			}
+			if (iSDCCellCounter != iNumSDCCellsPerSFrame)
+				SetBufReset3(); /* SDC: buffer number 3 */
+
+			/* Reset counters */
+			iMSCCellCounter = 0;
+			iSDCCellCounter = 0;
+		}
+	}
+}
+
+void COFDMCellDemapping::InitInternal(CParameter& Parameters)
+{
+	const CCellMappingTable& Param = Parameters.CellMappingTable;
+
+	iNumSymPerFrame = Param.iNumSymPerFrame;
+	iNumCarrier = Param.iNumCarrier;
+	iNumUsefMSCCellsPerFrame = Param.iNumUsefMSCCellsPerFrame;
+	iNumSDCCellsPerSFrame = Param.iNumSDCCellsPerSFrame;
+
+	/* Init symbol-counter and internal frame counter */
+	iSymbolCounter = 0;
+	iCurrentFrameID = 0;
+
+	/* Init cell-counter */
+	iSDCCellCounter = 0;
+	iMSCCellCounter = 0;
+	iFACCellCounter = 0;
+
+	/* Define block-sizes for input and output of the module ---------------- */
+	/* Input */
+	iInputBlockSize = iNumCarrier;
+
+	/* Define space for output cyclic buffers. We must consider enough headroom
+	   otherwise the buffers could overrun */
+	/* FAC, one block is exactly finished when last symbol with FAC cells is
+	   processed */
+    iMaxOutputBlockSize2 = Parameters.iNumFACBitsPerBlock;
+	/* SDC, one block is exactly finished when last symbol with SDC cells is
+	   processed */
+	iMaxOutputBlockSize3 = Param.iNumSDCCellsPerSFrame;
+	/* MSC, since the MSC logical frames must not end at the end of one symbol
+	   (could be somewhere in the middle of the symbol), the output buffer must
+	   accept more cells than one logical MSC frame is long. The worst case is
+	   that the block ends right at the beginning of one symbol; in this case we
+	   have an overhang of approximately one symbol of MSC cells */
+	iMaxOutputBlockSize = Param.iNumUsefMSCCellsPerFrame + Param.iMaxNumMSCSym;
+}
diff --git a/src/ofdmcellmapping/OFDMCellMapping.h b/src/ofdmcellmapping/OFDMCellMapping.h
new file mode 100644
index 0000000..e326164
--- /dev/null
+++ b/src/ofdmcellmapping/OFDMCellMapping.h
@@ -0,0 +1,80 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *	
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later 
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT 
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#if !defined(OFDMCELLMAPPING_H__3B0BA660_CA63_4344_BB2BE7A0D31912__INCLUDED_)
+#define OFDMCELLMAPPING_H__3B0BA660_CA63_4344_BB2BE7A0D31912__INCLUDED_
+
+#include "../GlobalDefinitions.h"
+#include "../Parameter.h"
+#include "../util/Modul.h"
+#include "../tables/TableCarMap.h"
+#include "../tables/TableFAC.h"
+
+
+/* Classes ********************************************************************/
+class COFDMCellMapping : public CTransmitterModul<_COMPLEX, _COMPLEX>
+{
+public:
+	COFDMCellMapping() {}
+	virtual ~COFDMCellMapping() {}
+
+protected:
+	int			iNumSymPerFrame;
+	int			iNumCarrier;
+	int			iSymbolCounter;
+	_COMPLEX*	pcDummyCells;
+
+	virtual void InitInternal(CParameter& TransmParam);
+	virtual void ProcessDataInternal(CParameter& TransmParam);
+};
+
+class COFDMCellDemapping : public CReceiverModul<CEquSig, CEquSig>
+{
+public:
+	COFDMCellDemapping() {}
+	virtual ~COFDMCellDemapping() {}
+
+protected:
+	int		iNumSymPerFrame;
+	int		iNumCarrier;
+	int		iNumUsefMSCCellsPerFrame;
+	int		iNumSDCCellsPerSFrame;
+
+	int		iSymbolCounter;
+	int		iCurrentFrameID;
+
+	int		iSDCCellCounter;
+	int		iMSCCellCounter;
+	int		iFACCellCounter;
+
+	virtual void InitInternal(CParameter& Parameters);
+	virtual void ProcessDataInternal(CParameter& Parameters);
+};
+
+
+#endif // !defined(OFDMCELLMAPPING_H__3B0BA660_CA63_4344_BB2BE7A0D31912__INCLUDED_)
diff --git a/src/resample/Resample.cpp b/src/resample/Resample.cpp
new file mode 100644
index 0000000..f57c49a
--- /dev/null
+++ b/src/resample/Resample.cpp
@@ -0,0 +1,384 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2002, 2001-2014, 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer, David Flamand (added CSpectrumResample, speex resampler)
+ *
+ * Description:
+ * Resample routine for arbitrary sample-rate conversions in a low range (for
+ * frequency offset correction).
+ * The algorithm is based on a polyphase structure. We upsample the input
+ * signal with a factor INTERP_DECIM_I_D and calculate two successive samples
+ * whereby we perform a linear interpolation between these two samples to get
+ * an arbitraty sample grid.
+ * The polyphase filter is calculated with Matlab(TM), the associated file
+ * is ResampleFilter.m.
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "Resample.h"
+#include "ResampleFilter.h"
+#ifdef HAVE_SPEEX
+# include <string.h>
+# define RESAMPLING_QUALITY 6 /* 0-10 : 0=fast/bad 10=slow/good */
+#endif
+
+
+/* Implementation *************************************************************/
+int CResample::Resample(CVector<_REAL>* prInput, CVector<_REAL>* prOutput,
+						_REAL rRation)
+{
+	/* Move old data from the end to the history part of the buffer and
+	   add new data (shift register) */
+	vecrIntBuff.AddEnd((*prInput), iInputBlockSize);
+
+	/* Sample-interval of new sample frequency in relation to interpolated
+	   sample-interval */
+	rTStep = (_REAL) INTERP_DECIM_I_D / rRation;
+
+	/* Init output counter */
+	int im = 0;
+
+	/* Main loop */
+	do
+	{
+		/* Quantize output-time to interpolated time-index */
+		const int ik = (int) rtOut;
+
+
+		/* Calculate convolutions for the two interpolation-taps ------------ */
+		/* Phase for the linear interpolation-taps */
+		const int ip1 = ik % INTERP_DECIM_I_D;
+		const int ip2 = (ik + 1) % INTERP_DECIM_I_D;
+
+		/* Sample positions in input vector */
+		const int in1 = (int) (ik / INTERP_DECIM_I_D);
+		const int in2 = (int) ((ik + 1) / INTERP_DECIM_I_D);
+
+		/* Convolution */
+		_REAL ry1 = (_REAL) 0.0;
+		_REAL ry2 = (_REAL) 0.0;
+		for (int i = 0; i < RES_FILT_NUM_TAPS_PER_PHASE; i++)
+		{
+			ry1 += fResTaps1To1[ip1][i] * vecrIntBuff[in1 - i];
+			ry2 += fResTaps1To1[ip2][i] * vecrIntBuff[in2 - i];
+		}
+
+
+		/* Linear interpolation --------------------------------------------- */
+		/* Get numbers after the comma */
+		const _REAL rxInt = rtOut - (int) rtOut;
+		(*prOutput)[im] = (ry2 - ry1) * rxInt + ry1;
+
+
+		/* Increase output counter */
+		im++;
+
+		/* Increase output-time and index one step */
+		rtOut = rtOut + rTStep;
+	} 
+	while (rtOut < rBlockDuration);
+
+	/* Set rtOut back */
+	rtOut -= iInputBlockSize * INTERP_DECIM_I_D;
+
+	return im;
+}
+
+void CResample::Init(const int iNewInputBlockSize)
+{
+	iInputBlockSize = iNewInputBlockSize;
+
+	/* History size must be one sample larger, because we use always TWO
+	   convolutions */
+	iHistorySize = RES_FILT_NUM_TAPS_PER_PHASE + 1;
+
+	/* Calculate block duration */
+	rBlockDuration =
+		(iInputBlockSize + RES_FILT_NUM_TAPS_PER_PHASE) * INTERP_DECIM_I_D;
+
+	/* Allocate memory for internal buffer, clear sample history */
+	vecrIntBuff.Init(iInputBlockSize + iHistorySize, (_REAL) 0.0);
+
+	/* Init absolute time for output stream (at the end of the history part) */
+	rtOut = (_REAL) RES_FILT_NUM_TAPS_PER_PHASE * INTERP_DECIM_I_D;
+}
+
+#ifdef HAVE_SPEEX
+CAudioResample::CAudioResample() :
+	rRation(1.0), iInputBlockSize(0), iOutputBlockSize(0),
+	resampler(NULL), iInputBuffered(0), iMaxInputSize(0)
+{
+}
+CAudioResample::~CAudioResample()
+{
+	Free();
+}
+void CAudioResample::Free()
+{
+	if (resampler != NULL)
+	{
+		speex_resampler_destroy(resampler);
+		resampler = NULL;
+	}
+	vecfInput.Init(0);
+	vecfOutput.Init(0);
+	rRation = 1.0;
+}
+void CAudioResample::Resample(CVector<_REAL>& rInput, CVector<_REAL>& rOutput)
+{
+	if (rRation == 1.0)
+	{
+		memcpy(&rOutput[0], &rInput[0], sizeof(_REAL) * iOutputBlockSize);
+	}
+	else
+	{
+		int i;
+		if (rOutput.Size() != iOutputBlockSize)
+			qDebug("CAudioResample::Resample(): rOutput.Size(%i) != iOutputBlockSize(%i)", (int)rOutput.Size(), iOutputBlockSize);
+
+		int iInputSize = GetFreeInputSize();
+		for (i = 0; i < iInputSize; i++)
+			vecfInput[i+iInputBuffered] = rInput[i];
+
+		int input_frames_used = 0;
+		int output_frames_gen = 0;
+		int input_frames = iInputBuffered + iInputSize;
+
+		if (resampler != NULL)
+		{
+			spx_uint32_t in_len = input_frames;
+			spx_uint32_t out_len = iOutputBlockSize;
+			int err = speex_resampler_process_float(
+				resampler,
+				0,
+				&vecfInput[0],
+				&in_len,
+				&vecfOutput[0],
+				&out_len);
+			if (err != RESAMPLER_ERR_SUCCESS)
+				qDebug("CAudioResample::Init(): libspeexdsp error: %s", speex_resampler_strerror(err));
+			input_frames_used = err != RESAMPLER_ERR_SUCCESS ? 0 : in_len;
+			output_frames_gen = err != RESAMPLER_ERR_SUCCESS ? 0 : out_len;
+		}
+
+		if (output_frames_gen != iOutputBlockSize)
+			qDebug("CAudioResample::Resample(): output_frames_gen(%i) != iOutputBlockSize(%i)", output_frames_gen, iOutputBlockSize);
+
+		for (i = 0; i < iOutputBlockSize; i++)
+			rOutput[i] = vecfOutput[i];
+		
+		iInputBuffered = input_frames - input_frames_used;
+		for (i = 0; i < iInputBuffered; i++)
+			vecfInput[i] = vecfInput[i+input_frames_used];
+	}
+}
+int CAudioResample::GetMaxInputSize() const
+{
+	return iMaxInputSize != 0 ? iMaxInputSize : iInputBlockSize;
+}
+int CAudioResample::GetFreeInputSize() const
+{
+	return GetMaxInputSize() - iInputBuffered;
+}
+void CAudioResample::Reset()
+{
+	iInputBuffered = 0;
+	if (resampler != NULL)
+	{
+		int err = speex_resampler_reset_mem(resampler);
+		if (err != RESAMPLER_ERR_SUCCESS)
+			qDebug("CAudioResample::Init(): libspeexdsp error: %s", speex_resampler_strerror(err));
+	}
+}
+void CAudioResample::Init(const int iNewInputBlockSize, const _REAL rNewRation)
+{
+	Free();
+	if (!iNewInputBlockSize)
+		return;
+	iInputBlockSize = iNewInputBlockSize;
+	iOutputBlockSize = int(iNewInputBlockSize * rNewRation);
+	rRation = _REAL(iOutputBlockSize) / iInputBlockSize;
+	iInputBuffered = 0;
+	iMaxInputSize = 0;
+	if (rRation != 1.0)
+	{
+		int err;
+		resampler = speex_resampler_init(1, spx_uint32_t(iInputBlockSize), spx_uint32_t(iOutputBlockSize), RESAMPLING_QUALITY, &err);
+		if (!resampler)
+			qDebug("CAudioResample::Init(): libspeexdsp error: %s", speex_resampler_strerror(err));
+		vecfInput.Init(iInputBlockSize);
+		vecfOutput.Init(iOutputBlockSize);
+	}
+}
+void CAudioResample::Init(const int iNewOutputBlockSize, const int iInputSamplerate, const int iOutputSamplerate)
+{
+	rRation = _REAL(iOutputSamplerate) / iInputSamplerate;
+	iInputBlockSize = int(iNewOutputBlockSize / rRation);
+	iOutputBlockSize = iNewOutputBlockSize;
+	if (rRation != 1.0)
+	{
+		const int iNewMaxInputSize = iInputBlockSize * 2;
+		const int iInputSize = vecfInput.Size();
+		if (iInputSize < iNewMaxInputSize)
+		{
+			vecfInput.Enlarge(iNewMaxInputSize - iInputSize);
+			iMaxInputSize = iNewMaxInputSize;
+		}
+		vecfOutput.Init(iOutputBlockSize);
+		int err = RESAMPLER_ERR_SUCCESS;
+		if (resampler == NULL)
+		{
+			resampler = speex_resampler_init(1, spx_uint32_t(iInputSamplerate), spx_uint32_t(iOutputSamplerate), RESAMPLING_QUALITY, &err);
+			iInputBuffered = 0;
+		}
+		else
+		{
+			err = speex_resampler_set_rate(resampler, spx_uint32_t(iInputSamplerate), spx_uint32_t(iOutputSamplerate));
+		}
+		if (err != RESAMPLER_ERR_SUCCESS)
+			qDebug("CAudioResample::Init(): libspeexdsp error: %s", speex_resampler_strerror(err));
+	}
+	else
+	{
+		Free();
+	}
+}
+
+#else // HAVE_SPEEX
+CAudioResample::CAudioResample() {}
+CAudioResample::~CAudioResample() {}
+void CAudioResample::Resample(CVector<_REAL>& rInput, CVector<_REAL>& rOutput)
+{
+	int j;
+
+	if (rRation == (_REAL) 1.0)
+	{
+		/* If ratio is 1, no resampling is needed, just copy vector */
+		for (j = 0; j < iOutputBlockSize; j++)
+			rOutput[j] = rInput[j];
+	}
+	else
+	{
+		/* Move old data from the end to the history part of the buffer and
+		   add new data (shift register) */
+		vecrIntBuff.AddEnd(rInput, iInputBlockSize);
+
+		/* Main loop */
+		for (j = 0; j < iOutputBlockSize; j++)
+		{
+			/* Phase for the linear interpolation-taps */
+			const int ip =
+				(int) (j * INTERP_DECIM_I_D / rRation) % INTERP_DECIM_I_D;
+
+			/* Sample position in input vector */
+			const int in = (int) (j / rRation) + RES_FILT_NUM_TAPS_PER_PHASE;
+
+			/* Convolution */
+			_REAL ry = (_REAL) 0.0;
+			for (int i = 0; i < RES_FILT_NUM_TAPS_PER_PHASE; i++)
+				ry += fResTaps1To1[ip][i] * vecrIntBuff[in - i];
+
+			rOutput[j] = ry;
+		}
+	}
+}
+void CAudioResample::Init(int iNewInputBlockSize, _REAL rNewRation)
+{
+	rRation = rNewRation;
+	iInputBlockSize = iNewInputBlockSize;
+	iOutputBlockSize = (int) (iInputBlockSize * rRation);
+	Reset();
+}
+void CAudioResample::Init(const int iNewOutputBlockSize, const int iInputSamplerate, const int iOutputSamplerate)
+{
+	rRation = _REAL(iOutputSamplerate) / iInputSamplerate;
+	iInputBlockSize = (int) (iNewOutputBlockSize / rRation);
+	iOutputBlockSize = iNewOutputBlockSize;
+	Reset();
+}
+int CAudioResample::GetMaxInputSize() const
+{
+	return iInputBlockSize;
+}
+int CAudioResample::GetFreeInputSize() const
+{
+	return iInputBlockSize;
+}
+void CAudioResample::Reset()
+{
+	/* Allocate memory for internal buffer, clear sample history */
+	vecrIntBuff.Init(iInputBlockSize + RES_FILT_NUM_TAPS_PER_PHASE,
+		(_REAL) 0.0);
+}
+#endif // HAVE_SPEEX
+
+void CSpectrumResample::Resample(CVector<_REAL>* prInput, CVector<_REAL>** pprOutput,
+	int iNewOutputBlockSize, _BOOLEAN bResample)
+{
+	if (!bResample)
+		iNewOutputBlockSize = 0;
+
+	if (iNewOutputBlockSize != iOutputBlockSize)
+	{
+		iOutputBlockSize = iNewOutputBlockSize;
+
+		/* Allocate memory for internal buffer */
+		vecrIntBuff.Init(iNewOutputBlockSize);
+	}
+
+	int iInputBlockSize = prInput->Size();
+	_REAL rRation = _REAL(iInputBlockSize) / _REAL(iOutputBlockSize);
+
+	if (!bResample || rRation <= (_REAL) 1.0)
+	{
+		/* If ratio is 1 or less, no resampling is needed */
+		*pprOutput = prInput;
+	}
+	else
+	{
+		int j, i;
+		CVector<_REAL>* prOutput;
+		prOutput = &vecrIntBuff;
+		_REAL rBorder = rRation;
+		_REAL rMax = -1.0e10;
+		_REAL rValue;
+
+		/* Main loop */
+		for (j = 0, i = 0; j < iInputBlockSize && i < iOutputBlockSize; j++)
+		{
+			rValue = (*prInput)[j];
+			/* We only take the maximum value within the interval,
+			   because what is important it's the signal
+			   and not the lack of signal */
+			if (rValue > rMax) rMax = rValue;
+			if (j > (int)floor(rBorder))
+			{
+				(*prOutput)[i++] = rMax - 6.0;
+				rMax = -1.0e10;
+				rBorder = rRation * i;
+			}
+		}
+		if (i < iOutputBlockSize)
+			(*prOutput)[i] = rMax - 6.0;
+		*pprOutput = prOutput;
+	}
+}
+
diff --git a/src/resample/Resample.h b/src/resample/Resample.h
new file mode 100644
index 0000000..d2de4a5
--- /dev/null
+++ b/src/resample/Resample.h
@@ -0,0 +1,104 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2002, 2001-2014, 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer, David Flamand (added CSpectrumResample, speex resampler)
+ *
+ * Description:
+ *	See Resampling.cpp
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later 
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT 
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#if !defined(RESAMPLE_H__3B0FEUFE7876F_FE8FE_CA63_4344_1912__INCLUDED_)
+#define RESAMPLE_H__3B0FEUFE7876F_FE8FE_CA63_4344_1912__INCLUDED_
+
+#include "../GlobalDefinitions.h"
+#include "../util/Vector.h"
+#ifdef HAVE_SPEEX
+# include <speex/speex_resampler.h>
+#endif
+
+
+/* Classes ********************************************************************/
+class CResample
+{
+public:
+	CResample() {}
+	virtual ~CResample() {}
+
+	void Init(const int iNewInputBlockSize);
+	int Resample(CVector<_REAL>* prInput, CVector<_REAL>* prOutput,
+				 _REAL rRation);
+
+protected:
+	_REAL					rTStep;
+	_REAL					rtOut;
+	_REAL					rBlockDuration;
+
+	CShiftRegister<_REAL>	vecrIntBuff;
+	int						iHistorySize;
+
+	int						iInputBlockSize;
+};
+
+class CAudioResample
+{
+public:
+	CAudioResample();
+	virtual ~CAudioResample();
+
+	void Init(int iNewInputBlockSize, _REAL rNewRation);
+	void Init(int iNewOutputBlockSize, int iInputSamplerate, int iOutputSamplerate);
+	void Resample(CVector<_REAL>& rInput, CVector<_REAL>& rOutput);
+	int GetFreeInputSize() const;
+	int GetMaxInputSize() const;
+	void Reset();
+
+protected:
+	_REAL					rRation;
+	int						iInputBlockSize;
+	int						iOutputBlockSize;
+#ifdef HAVE_SPEEX
+	SpeexResamplerState*	resampler; 
+	CVector<float>			vecfInput;
+	CVector<float>			vecfOutput;
+	int						iInputBuffered;
+	int						iMaxInputSize;
+	void Free();
+#else
+	CShiftRegister<_REAL>	vecrIntBuff;
+	int						iHistorySize;
+#endif
+};
+
+class CSpectrumResample
+{
+public:
+	CSpectrumResample() : iOutputBlockSize(0) {}
+	virtual ~CSpectrumResample() {}
+
+	void Resample(CVector<_REAL>* prInput, CVector<_REAL>** pprOutput, int iNewOutputBlockSize, _BOOLEAN bResample);
+
+protected:
+	CVector<_REAL>			vecrIntBuff;
+	int						iOutputBlockSize;
+};
+
+#endif // !defined(RESAMPLE_H__3B0FEUFE7876F_FE8FE_CA63_4344_1912__INCLUDED_)
diff --git a/src/resample/ResampleFilter.cpp b/src/resample/ResampleFilter.cpp
new file mode 100644
index 0000000..ee6ad9b
--- /dev/null
+++ b/src/resample/ResampleFilter.cpp
@@ -0,0 +1,149 @@
+/* Automatically generated file with MATLAB */
+/* File name: "ResampleFilter.m" */
+/* Filter taps in time-domain */
+
+#include "ResampleFilter.h"
+
+/* Filter for ratios close to 1 */
+float fResTaps1To1[INTERP_DECIM_I_D][RES_FILT_NUM_TAPS_PER_PHASE] = {
+{
+	-0.00129181992672801360f,
+	0.00561586829442904840f,
+	-0.01349857823816511800f,
+	0.02541150940858524100f,
+	-0.04267869501534898200f,
+	0.07724474282951483700f,
+	0.96609875058711103000f,
+	-0.01641812005088002400f,
+	-0.00427135103965109450f,
+	0.00726225824406205160f,
+	-0.00544188094946287510f,
+	0.00266742068076876060f
+},
+{
+	-0.00207886551285772290f,
+	0.00866090598717600930f,
+	-0.02161960909069559500f,
+	0.04383507935997314800f,
+	-0.08302470868585065700f,
+	0.18738870090358245000f,
+	0.93524350914423104000f,
+	-0.09031872116141286000f,
+	0.02909509423931267600f,
+	-0.00897188476756275060f,
+	0.00178311012364952820f,
+	0.00010586149691723067f
+},
+{
+	-0.00287519800425638110f,
+	0.01143197533872717000f,
+	-0.02889142869399521600f,
+	0.06060641890050100900f,
+	-0.12152802242786863000f,
+	0.30933747340895279000f,
+	0.87539536840978205000f,
+	-0.14271415809850990000f,
+	0.05516985095031713000f,
+	-0.02205265100214613000f,
+	0.00761119378345958850f,
+	-0.00187713739944610450f
+},
+{
+	-0.00354120720771153910f,
+	0.01351098086300389300f,
+	-0.03433664370844288100f,
+	0.07367662235517660800f,
+	-0.15398027155782226000f,
+	0.43728178746780866000f,
+	0.79013921003423337000f,
+	-0.17341770937821352000f,
+	0.07263788052016696700f,
+	-0.03120859084480779800f,
+	0.01170664402374247200f,
+	-0.00319259334815649940f
+},
+{
+	-0.00391755659664638590f,
+	0.01447751287549226700f,
+	-0.03701682481313090000f,
+	0.08107302414568577600f,
+	-0.17606165300033697000f,
+	0.56464344237183917000f,
+	0.68451472884717957000f,
+	-0.18369620562420094000f,
+	0.08111657494320076400f,
+	-0.03614676421513295800f,
+	0.01396276906259418800f,
+	-0.00384568128202934270f
+},
+{
+	-0.00384568128202934270f,
+	0.01396276906259418800f,
+	-0.03614676421513295800f,
+	0.08111657494320076400f,
+	-0.18369620562420094000f,
+	0.68451472884717957000f,
+	0.56464344237183917000f,
+	-0.17606165300033697000f,
+	0.08107302414568577600f,
+	-0.03701682481313090000f,
+	0.01447751287549226700f,
+	-0.00391755659664638590f
+},
+{
+	-0.00319259334815649940f,
+	0.01170664402374247200f,
+	-0.03120859084480779800f,
+	0.07263788052016696700f,
+	-0.17341770937821352000f,
+	0.79013921003423337000f,
+	0.43728178746780866000f,
+	-0.15398027155782226000f,
+	0.07367662235517660800f,
+	-0.03433664370844288100f,
+	0.01351098086300389300f,
+	-0.00354120720771153910f
+},
+{
+	-0.00187713739944610450f,
+	0.00761119378345958850f,
+	-0.02205265100214613000f,
+	0.05516985095031713000f,
+	-0.14271415809850990000f,
+	0.87539536840978205000f,
+	0.30933747340895279000f,
+	-0.12152802242786863000f,
+	0.06060641890050100900f,
+	-0.02889142869399521600f,
+	0.01143197533872717000f,
+	-0.00287519800425638110f
+},
+{
+	0.00010586149691723067f,
+	0.00178311012364952820f,
+	-0.00897188476756275060f,
+	0.02909509423931267600f,
+	-0.09031872116141286000f,
+	0.93524350914423104000f,
+	0.18738870090358245000f,
+	-0.08302470868585065700f,
+	0.04383507935997314800f,
+	-0.02161960909069559500f,
+	0.00866090598717600930f,
+	-0.00207886551285772290f
+},
+{
+	0.00266742068076876060f,
+	-0.00544188094946287510f,
+	0.00726225824406205160f,
+	-0.00427135103965109450f,
+	-0.01641812005088002400f,
+	0.96609875058711103000f,
+	0.07724474282951483700f,
+	-0.04267869501534898200f,
+	0.02541150940858524100f,
+	-0.01349857823816511800f,
+	0.00561586829442904840f,
+	-0.00129181992672801360f
+}
+};
diff --git a/src/resample/ResampleFilter.h b/src/resample/ResampleFilter.h
new file mode 100644
index 0000000..b3d2b7b
--- /dev/null
+++ b/src/resample/ResampleFilter.h
@@ -0,0 +1,14 @@
+/* Automatically generated file with MATLAB */
+/* File name: "ResampleFilter.m" */
+/* Filter taps in time-domain */
+
+#ifndef _RESAMPLEFILTER_H_
+#define _RESAMPLEFILTER_H_
+
+#define RES_FILT_NUM_TAPS_PER_PHASE  12
+#define INTERP_DECIM_I_D             10
+
+/* Filter for ratios close to 1 */
+extern float fResTaps1To1[INTERP_DECIM_I_D][RES_FILT_NUM_TAPS_PER_PHASE];
+
+#endif	/* _RESAMPLEFILTER_H_ */
diff --git a/src/resample/ResampleFilter.m b/src/resample/ResampleFilter.m
new file mode 100644
index 0000000..cf5042d
--- /dev/null
+++ b/src/resample/ResampleFilter.m
@@ -0,0 +1,77 @@
+%******************************************************************************\
+%* Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+%* Copyright (c) 2002
+%*
+%* Author:
+%*	Volker Fischer
+%*
+%* Description:
+%* 	Generating resample filter taps
+%*
+%******************************************************************************
+%*
+%* This program is free software; you can redistribute it and/or modify it under
+%* the terms of the GNU General Public License as published by the Free Software
+%* Foundation; either version 2 of the License, or (at your option) any later 
+%* version.
+%*
+%* This program is distributed in the hope that it will be useful, but WITHOUT 
+%* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+%* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 
+%* details.
+%*
+%* You should have received a copy of the GNU General Public License along with
+%* this program; if not, write to the Free Software Foundation, Inc., 
+%* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+%*
+%******************************************************************************/
+
+% Filter for ratios close to 1 -------------------------------------------------
+% Fixed for sample-rate conversiones of R ~ 1
+I = 10; % D = I
+
+% Number of taps per poly-phase
+NumTapsP = 12;
+
+% Cut-off frequency
+fc = 0.97 / I;
+
+% MMSE filter-design and windowing
+h = I * firls(I * NumTapsP - 1, [0 fc fc 1], [1 1 0 0]) .* kaiser(I * NumTapsP, 5)';
+
+
+% Export coefficiants to file ****************************************
+fid = fopen('ResampleFilter.h', 'w');
+
+fprintf(fid, '/* Automatically generated file with MATLAB */\n');
+fprintf(fid, '/* File name: "ResampleFilter.m" */\n');
+fprintf(fid, '/* Filter taps in time-domain */\n\n');
+
+fprintf(fid, '#ifndef _RESAMPLEFILTER_H_\n');
+fprintf(fid, '#define _RESAMPLEFILTER_H_\n\n');
+
+fprintf(fid, '#define RES_FILT_NUM_TAPS_PER_PHASE  ');
+fprintf(fid, int2str(NumTapsP));
+fprintf(fid, '\n');
+fprintf(fid, '#define INTERP_DECIM_I_D             ');
+fprintf(fid, int2str(I));
+fprintf(fid, '\n\n\n');
+
+% Write filter taps
+fprintf(fid, '/* Filter for ratios close to 1 */\n');
+fprintf(fid, 'static float fResTaps1To1[INTERP_DECIM_I_D][RES_FILT_NUM_TAPS_PER_PHASE] = {\n');
+for i = 1:I
+	hTemp = h(i:I:end) ;
+	fprintf(fid, '{\n');
+	fprintf(fid, '	%.20ff,\n', hTemp(1:end - 1));
+	fprintf(fid, '	%.20ff\n', hTemp(end));
+    if (i < I)
+        fprintf(fid, '},\n');
+    else
+        fprintf(fid, '}\n');        
+    end    
+end
+fprintf(fid, '};\n\n\n');
+
+fprintf(fid, '#endif	/* _RESAMPLEFILTER_H_ */\n');
+fclose(fid);
diff --git a/src/resample/ResampleFilter.octave b/src/resample/ResampleFilter.octave
new file mode 100644
index 0000000..0dce61e
--- /dev/null
+++ b/src/resample/ResampleFilter.octave
@@ -0,0 +1,86 @@
+%******************************************************************************\
+%* Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+%* Copyright (c) 2002
+%*
+%* Author:
+%*	Volker Fischer
+%*
+%* Description:
+%* 	Generating resample filter taps
+%*
+%******************************************************************************
+%*
+%* This program is free software; you can redistribute it and/or modify it under
+%* the terms of the GNU General Public License as published by the Free Software
+%* Foundation; either version 2 of the License, or (at your option) any later 
+%* version.
+%*
+%* This program is distributed in the hope that it will be useful, but WITHOUT 
+%* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+%* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 
+%* details.
+%*
+%* You should have received a copy of the GNU General Public License along with
+%* this program; if not, write to the Free Software Foundation, Inc., 
+%* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+%*
+%******************************************************************************/
+
+% Filter for ratios close to 1 -------------------------------------------------
+% Fixed for sample-rate conversiones of R ~ 1
+I = 10; % D = I
+
+% Number of taps per poly-phase
+NumTapsP = 12;
+
+% Cut-off frequency
+fc = 0.97 / I;
+
+% MMSE filter-design and windowing
+h = I * firls(I * NumTapsP - 1, [0 fc fc 1], [1 1 0 0]) .* kaiser(I * NumTapsP, 5)';
+
+
+% Export coefficiants to file ****************************************
+fid = fopen('ResampleFilter.h', 'w');
+
+fprintf(fid, '/* Automatically generated file with GNU Octave */\n');
+fprintf(fid, '/* File name: "ResampleFilter.m" */\n');
+fprintf(fid, '/* Filter taps in time-domain */\n\n');
+
+fprintf(fid, '#ifndef _RESAMPLEFILTER_H_\n');
+fprintf(fid, '#define _RESAMPLEFILTER_H_\n\n');
+
+fprintf(fid, '#define RES_FILT_NUM_TAPS_PER_PHASE  ');
+fprintf(fid, int2str(NumTapsP));
+fprintf(fid, '\n');
+fprintf(fid, '#define INTERP_DECIM_I_D             ');
+fprintf(fid, int2str(I));
+fprintf(fid, '\n\n\n');
+fprintf(fid, 'extern float fResTaps1To1[INTERP_DECIM_I_D][RES_FILT_NUM_TAPS_PER_PHASE];\n');
+
+fprintf(fid, '#endif	/* _RESAMPLEFILTER_H_ */\n');
+fclose(fid);
+
+fid = fopen('ResampleFilter.cpp', 'w');
+
+fprintf(fid, '/* Automatically generated file with GNU Octave */\n');
+fprintf(fid, '/* File name: "ResampleFilter.m" */\n');
+fprintf(fid, '/* Filter taps in time-domain */\n\n');
+fprintf(fid, '#include "ResampleFilter.h"\n\n');
+
+% Write filter taps
+fprintf(fid, '/* Filter for ratios close to 1 */\n');
+fprintf(fid, 'float fResTaps1To1[INTERP_DECIM_I_D][RES_FILT_NUM_TAPS_PER_PHASE] = {\n');
+for i = 1:I
+	hTemp = h(i:I:end) ;
+	fprintf(fid, '{\n');
+	fprintf(fid, '	%.20ff,\n', hTemp(1:end - 1));
+	fprintf(fid, '	%.20ff\n', hTemp(end));
+    if (i < I)
+        fprintf(fid, '},\n');
+    else
+        fprintf(fid, '}\n');        
+    end    
+end
+fprintf(fid, '};\n\n\n');
+fclose(fid);
diff --git a/src/sound/LatencyFilter.h b/src/sound/LatencyFilter.h
new file mode 100644
index 0000000..d52077f
--- /dev/null
+++ b/src/sound/LatencyFilter.h
@@ -0,0 +1,46 @@
+/* Automatically generated file with GNU Octave */
+
+/* File name: "LatencyFilter.octave" */
+/* Filter taps in time-domain */
+
+#ifndef _LATENCYFILTER_H_
+#define _LATENCYFILTER_H_
+
+#define NUM_TAPS_LATENCY_FILT 31
+
+static const double dLatFilt[NUM_TAPS_LATENCY_FILT] =
+{
+	3.101587164852689493e-04,
+	8.885262220146099808e-04,
+	2.033957519086429088e-03,
+	3.972274650614384013e-03,
+	6.945793774105016652e-03,
+	1.115650859902323974e-02,
+	1.671930039987959415e-02,
+	2.361805292339210979e-02,
+	3.167387746460251924e-02,
+	4.053382929389261896e-02,
+	4.968570622697088268e-02,
+	5.850017390895686370e-02,
+	6.629633398893952645e-02,
+	7.242202385517454433e-02,
+	7.633665638551227761e-02,
+	7.768313160458335809e-02,
+	7.633665638551227761e-02,
+	7.242202385517454433e-02,
+	6.629633398893952645e-02,
+	5.850017390895686370e-02,
+	4.968570622697088268e-02,
+	4.053382929389261896e-02,
+	3.167387746460251924e-02,
+	2.361805292339210979e-02,
+	1.671930039987959415e-02,
+	1.115650859902323974e-02,
+	6.945793774105016652e-03,
+	3.972274650614384013e-03,
+	2.033957519086429088e-03,
+	8.885262220146099808e-04,
+	3.101587164852689493e-04
+};
+
+#endif /* _LATENCYFILTER_H_ */
diff --git a/src/sound/LatencyFilter.octave b/src/sound/LatencyFilter.octave
new file mode 100644
index 0000000..2912115
--- /dev/null
+++ b/src/sound/LatencyFilter.octave
@@ -0,0 +1,64 @@
+%******************************************************************************\
+%*
+%* Copyright (c) 2001-2014
+%*
+%* Author:
+%*	David Flamand
+%*
+%* Description:
+%* 	Lowpass Filter for Filtering Latency
+%*
+%******************************************************************************
+%*
+%* This program is free software; you can redistribute it and/or modify it under
+%* the terms of the GNU General Public License as published by the Free Software
+%* Foundation; either version 2 of the License, or (at your option) any later 
+%* version.
+%*
+%* This program is distributed in the hope that it will be useful, but WITHOUT 
+%* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+%* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 
+%* details.
+%*
+%* You should have received a copy of the GNU General Public License along with
+%* this program; if not, write to the Free Software Foundation, Inc., 
+%* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+%*
+%******************************************************************************/
+
+n = 31;
+f = [0  1/4096  1/5  1];
+m = [1 1 0 0];
+b = remez(n - 1, f, m, 'bandpass', 512);
+
+PLOT = 1;
+if (PLOT == 1)
+    close all;
+    freqz(b);
+    plot(b);
+    figure;
+end
+
+fid = fopen('LatencyFilter.h', 'w');
+fprintf(fid, '/* Automatically generated file with GNU Octave */\n');
+fprintf(fid, '\n');
+fprintf(fid, '/* File name: "LatencyFilter.octave" */\n');
+fprintf(fid, '/* Filter taps in time-domain */\n');
+fprintf(fid, '\n');
+fprintf(fid, '#ifndef _LATENCYFILTER_H_\n');
+fprintf(fid, '#define _LATENCYFILTER_H_\n');
+fprintf(fid, '\n');
+fprintf(fid, '#define NUM_TAPS_LATENCY_FILT %i\n', n);
+fprintf(fid, '\n');
+fprintf(fid, 'static const double dLatFilt[NUM_TAPS_LATENCY_FILT] =\n');
+fprintf(fid, '{\n');
+fprintf(fid, '	%.18e,\n', b(1:end - 1));
+fprintf(fid, '	%.18e\n', b(end));
+fprintf(fid, '};\n');
+fprintf(fid, '\n');
+fprintf(fid, '#endif /* _LATENCYFILTER_H_ */\n');
+fclose(fid);
+
+if (PLOT == 1)
+    input("press enter to exit ");
+end
diff --git a/src/sound/audiofilein.cpp b/src/sound/audiofilein.cpp
new file mode 100644
index 0000000..85da491
--- /dev/null
+++ b/src/sound/audiofilein.cpp
@@ -0,0 +1,388 @@
+/******************************************************************************\
+ * British Broadcasting Corporation
+ * Copyright (c) 2001-2014, 2001-2014, 2001-2014
+ *
+ * Author(s):
+ *	Julian Cable, David Flamand
+ *
+ * Decription:
+ *  Read a file at the correct rate
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "audiofilein.h"
+#ifdef _WIN32
+# include <windows.h>
+#endif
+#include <iostream>
+#ifdef HAVE_LIBSNDFILE
+# include <sndfile.h>
+#endif
+#include <cstdlib>
+#include <cstring>
+#include <string.h>
+
+
+CAudioFileIn::CAudioFileIn(): CSoundInInterface(), eFmt(fmt_other),
+    pFileReceiver(NULL), iSampleRate(0), iRequestedSampleRate(0), iBufferSize(0),
+    iFileSampleRate(0), iFileChannels(0), pacer(NULL),
+    ResampleObjL(NULL), ResampleObjR(NULL), buffer(NULL)
+{
+}
+
+CAudioFileIn::~CAudioFileIn()
+{
+    Close();
+}
+
+void
+CAudioFileIn::SetFileName(const string& strFileName)
+{
+    strInFileName = strFileName;
+    string ext;
+    size_t p = strInFileName.rfind('.');
+    if (p != string::npos)
+        ext = strInFileName.substr(p+1);
+	eFmt = fmt_other;
+    if (ext == "txt") eFmt = fmt_txt;
+    if (ext == "TXT") eFmt = fmt_txt;
+    if (ext.substr(0,2) == "iq") eFmt = fmt_raw_stereo;
+    if (ext.substr(0,2) == "IQ") eFmt = fmt_raw_stereo;
+    if (ext.substr(0,2) == "if") eFmt = fmt_raw_stereo;
+    if (ext.substr(0,2) == "IF") eFmt = fmt_raw_stereo;
+    if (ext == "pcm") eFmt = fmt_raw_mono;
+    if (ext == "PCM") eFmt = fmt_raw_mono;
+    switch (eFmt)
+    {
+    case fmt_raw_stereo:
+        iFileChannels = 2;
+        if (ext.length() == 4 || ext.length() == 5) /* e.g.: iq48, IF192 */
+            iFileSampleRate = 1000 * atoi(ext.substr(2).c_str());
+        else
+            iFileSampleRate = DEFAULT_SOUNDCRD_SAMPLE_RATE;
+        break;
+    default:
+        iFileChannels = 1;
+        if (ext.length() == 5 || ext.length() == 6) /* e.g.: TXT48, pcm192 */
+            iFileSampleRate = 1000 * atoi(ext.substr(3).c_str());
+        else
+            iFileSampleRate = DEFAULT_SOUNDCRD_SAMPLE_RATE;
+        break;
+    }
+
+#ifdef HAVE_LIBSNDFILE
+    SF_INFO sfinfo;
+    memset(&sfinfo, 0, sizeof(SF_INFO));
+    switch (eFmt)
+    {
+    case fmt_txt:
+        pFileReceiver = fopen(strInFileName.c_str(), "r");
+        break;
+    case fmt_raw_mono:
+    case fmt_raw_stereo:
+        sfinfo.samplerate = iFileSampleRate;
+        sfinfo.channels = iFileChannels;
+        sfinfo.format = SF_FORMAT_RAW|SF_FORMAT_PCM_16|SF_ENDIAN_LITTLE;
+        pFileReceiver = (FILE*)sf_open(strInFileName.c_str(), SFM_READ, &sfinfo);
+        if (pFileReceiver == NULL)
+            throw CGenErr(string("")+sf_strerror(0)+" raised on "+strInFileName);
+        break;
+    case fmt_other:
+        pFileReceiver = (FILE*)sf_open(strInFileName.c_str(), SFM_READ, &sfinfo);
+        if (pFileReceiver != NULL)
+        {
+            iFileChannels = sfinfo.channels;
+            iFileSampleRate = sfinfo.samplerate;
+		} else {
+            string errs = string("")+sf_strerror(0)+" for "+strInFileName;
+            throw CGenErr(errs);
+		}
+        break;
+    default:
+        pFileReceiver = NULL;
+        break;
+    }
+#else
+    if (eFmt == fmt_txt)
+        pFileReceiver = fopen(strInFileName.c_str(), "r");
+    else
+        pFileReceiver = fopen(strInFileName.c_str(), "rb");
+#endif
+
+    /* Check for errors */
+#ifdef HAVE_LIBSNDFILE
+    if (pFileReceiver != NULL)
+    {
+        sf_count_t count;
+        switch (eFmt)
+        {
+        case fmt_txt:
+            // TODO
+            break;
+        case fmt_raw_mono:
+        case fmt_raw_stereo:
+        case fmt_other:
+            count = sf_seek((SNDFILE*)pFileReceiver, 1, SEEK_SET);
+            /* Must contain at least one sample, mono or stereo */
+            if (sf_error((SNDFILE*)pFileReceiver) || count != 1 || iFileChannels < 1 || iFileChannels > 2)
+            {
+                sf_close((SNDFILE*)pFileReceiver);
+                pFileReceiver = NULL;
+            }
+            else
+            {
+                /* Reset position */
+                sf_seek((SNDFILE*)pFileReceiver, 0, SEEK_SET);
+            }
+            break;
+        }
+    }
+#else
+    // TODO
+#endif
+
+// The error is reported when reading (red light in system eval on interface IO led)
+//    if (pFileReceiver == NULL)
+//        throw CGenErr("The file " + strInFileName + " could not be openned");
+
+    iRequestedSampleRate = iFileSampleRate;
+    if      (iRequestedSampleRate <= 24000) iRequestedSampleRate = 24000;
+    else if (iRequestedSampleRate <= 48000) iRequestedSampleRate = 48000;
+    else if (iRequestedSampleRate <= 96000) iRequestedSampleRate = 96000;
+    else                                    iRequestedSampleRate = 192000;
+}
+
+_BOOLEAN
+CAudioFileIn::Init(int iNewSampleRate, int iNewBufferSize, _BOOLEAN bNewBlocking)
+{
+	//qDebug("CAudioFileIn::Init() iNewSampleRate=%i iNewBufferSize=%i bNewBlocking=%i", iNewSampleRate, iNewBufferSize, bNewBlocking);
+
+    if (pacer)
+    {
+        delete pacer;
+        pacer = NULL;
+    }
+    if (bNewBlocking)
+    {
+        double interval = double(iNewBufferSize/2) / double(iNewSampleRate);
+        pacer = new CPacer(uint64_t(1e9*interval));
+    }
+
+    if (pFileReceiver == NULL)
+        return TRUE;
+
+    _BOOLEAN bChanged = FALSE;
+
+	if (iSampleRate != iNewSampleRate)
+    {
+        iSampleRate = iNewSampleRate;
+        bChanged = TRUE;
+    }
+
+    if (iBufferSize != iNewBufferSize || bChanged)
+    {
+        iBufferSize = iNewBufferSize;
+        if (buffer)
+            delete[] buffer;
+        /* Create a resampler object if the file's sample rate isn't supported */
+        if (iNewSampleRate != iFileSampleRate)
+        {
+            iOutBlockSize = iNewBufferSize / 2; /* Mono */
+            if (ResampleObjL == NULL)
+                ResampleObjL = new CAudioResample();
+            ResampleObjL->Init(iOutBlockSize, iFileSampleRate, iNewSampleRate);
+            if (iFileChannels == 2)
+            {
+                if (ResampleObjR == NULL)
+                    ResampleObjR = new CAudioResample();
+                ResampleObjR->Init(iOutBlockSize, iFileSampleRate, iNewSampleRate);
+            }
+            const int iMaxInputSize = ResampleObjL->GetMaxInputSize();
+            vecTempResBufIn.Init(iMaxInputSize, (_REAL) 0.0);
+            vecTempResBufOut.Init(iOutBlockSize, (_REAL) 0.0);
+            buffer = new short[iMaxInputSize * 2];
+            if (bChanged)
+            {
+                if (ResampleObjL != NULL)
+                    ResampleObjL->Reset();
+                if (ResampleObjR != NULL)
+                    ResampleObjR->Reset();
+            }
+        }
+        else
+        {
+            buffer = new short[iNewBufferSize * 2];
+        }
+    }
+
+    return bChanged;
+}
+
+_BOOLEAN
+CAudioFileIn::Read(CVector<short>& psData)
+{
+    if (pacer)
+        pacer->wait();
+
+    if (pFileReceiver == NULL || psData.Size() < iBufferSize)
+        return TRUE;
+
+    const int iFrames = ResampleObjL ? ResampleObjL->GetFreeInputSize() : iBufferSize/2;
+    int i;
+
+    if (eFmt == fmt_txt)
+    {
+        for (i = 0; i < iFrames; i++)
+        {
+            float tIn;
+            if (fscanf(pFileReceiver, "%e\n", &tIn) == EOF)
+            {
+                /* If end-of-file is reached, stop simulation */
+                return FALSE;
+            }
+            psData[2*i] = (short)tIn;
+            psData[2*i+1] = (short)tIn;
+        }
+        return FALSE;
+    }
+
+    _BOOLEAN bError = FALSE;
+    int iRemainingFrame = iFrames;
+    int iReadFrame = 0;
+#ifdef HAVE_LIBSNDFILE
+    while (iRemainingFrame > 0)
+    {
+	    sf_count_t c = sf_readf_short((SNDFILE*)pFileReceiver, &buffer[iReadFrame * iFileChannels], iRemainingFrame);
+	    if (c != sf_count_t(iRemainingFrame))
+	    {
+            /* rewind */
+            if (sf_error((SNDFILE*)pFileReceiver) || sf_seek((SNDFILE*)pFileReceiver, 0, SEEK_SET) == -1)
+            {
+                memset(&buffer[iReadFrame * iFileChannels], 0, iRemainingFrame * iFileChannels);
+                bError = TRUE;
+                break;
+            }
+	    }
+        iRemainingFrame -= c;
+        iReadFrame += c;
+    }
+#else
+    while (iRemainingFrame > 0)
+    {
+        size_t c = fread(&buffer[iReadFrame * iFileChannels], sizeof(short), size_t(iRemainingFrame), pFileReceiver);
+        if (c != size_t(iRemainingFrame))
+        {
+            /* rewind */
+            if (ferror(pFileReceiver) || fseek(pFileReceiver, 0, SEEK_SET) == -1)
+            {
+                memset(&buffer[iReadFrame * iFileChannels], 0, iRemainingFrame * iFileChannels);
+                bError = TRUE;
+                break;
+            }
+        }
+        iRemainingFrame -= c;
+        iReadFrame += c;
+    }
+#endif
+
+    if (ResampleObjL)
+    {   /* Resampling is needed */
+        if (iFileChannels == 2)
+        {   /* Stereo */
+            /* Left channel*/
+            for (i = 0; i < iFrames; i++)
+                vecTempResBufIn[i] = buffer[2*i];
+            ResampleObjL->Resample(vecTempResBufIn, vecTempResBufOut);
+            for (i = 0; i < iOutBlockSize; i++)
+                psData[i*2] = Real2Sample(vecTempResBufOut[i]);
+            /* Right channel*/
+            for (i = 0; i < iFrames; i++)
+                vecTempResBufIn[i] = buffer[2*i+1];
+            ResampleObjR->Resample(vecTempResBufIn, vecTempResBufOut);
+            for (i = 0; i < iOutBlockSize; i++)
+                psData[i*2+1] = Real2Sample(vecTempResBufOut[i]);
+        }
+        else
+        {   /* Mono */
+            for (i = 0; i < iFrames; i++)
+                vecTempResBufIn[i] = buffer[i];
+            ResampleObjL->Resample(vecTempResBufIn, vecTempResBufOut);
+            for (i = 0; i < iOutBlockSize; i++)
+                psData[i*2] = psData[i*2+1] = Real2Sample(vecTempResBufOut[i]);
+        }
+    }
+    else
+    {   /* Resampling is not needed, only copy data */
+        if (iFileChannels == 2)
+        {   /* Stereo */
+            for (i = 0; i < iFrames; i++)
+            {
+                psData[2*i] = buffer[2*i];
+                psData[2*i+1] = buffer[2*i+1];
+            }
+        }
+        else
+        {   /* Mono */
+            for (i = 0; i < iFrames; i++)
+                psData[2*i] = psData[2*i+1] = buffer[i];
+        }
+    }
+
+    return bError;
+}
+
+void
+CAudioFileIn::Close()
+{
+    /* Close file (if opened) */
+    if (pFileReceiver != NULL)
+    {
+#ifdef HAVE_LIBSNDFILE
+        if (eFmt == fmt_txt)
+            fclose(pFileReceiver);
+        else
+            sf_close((SNDFILE*)pFileReceiver);
+#else
+        fclose(pFileReceiver);
+#endif
+        pFileReceiver = NULL;
+    }
+
+	if (buffer != NULL)
+		delete[] buffer;
+    buffer = NULL;
+
+    if (pacer != NULL)
+        delete pacer;
+    pacer = NULL;
+
+    if (ResampleObjL != NULL)
+        delete ResampleObjL;
+    ResampleObjL = NULL;
+
+    if (ResampleObjR != NULL)
+        delete ResampleObjR;
+    ResampleObjR = NULL;
+
+    vecTempResBufIn.Init(0, (_REAL) 0.0);
+    vecTempResBufOut.Init(0, (_REAL) 0.0);
+
+    iSampleRate = 0;
+    iBufferSize = 0;
+}
diff --git a/src/sound/audiofilein.h b/src/sound/audiofilein.h
new file mode 100644
index 0000000..7671b51
--- /dev/null
+++ b/src/sound/audiofilein.h
@@ -0,0 +1,72 @@
+/******************************************************************************\
+ * British Broadcasting Corporation
+ * Copyright (c) 2001-2014, 2001-2014, 2001-2014
+ *
+ * Author(s):
+ *	Julian Cable, David Flamand
+ *
+ * Decription:
+ *  Read a file at the correct rate
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#ifndef _AUDIOFILEIN
+#define _AUDIOFILEIN
+
+#include "soundinterface.h"
+#include "../util/Pacer.h"
+#include "../resample/Resample.h"
+
+/* Classes ********************************************************************/
+class CAudioFileIn : public CSoundInInterface
+{
+public:
+    CAudioFileIn();
+    virtual ~CAudioFileIn();
+
+    virtual void		Enumerate(vector<string>&, vector<string>&) {}
+    virtual void		SetDev(string sNewDevice) {sCurrentDevice = sNewDevice;}
+    virtual string		GetDev() {return sCurrentDevice;}
+    virtual void		SetFileName(const string& strFileName);
+    virtual int			GetSampleRate() {return iRequestedSampleRate;};
+
+    virtual _BOOLEAN	Init(int iNewSampleRate, int iNewBufferSize, _BOOLEAN bNewBlocking);
+    virtual _BOOLEAN 	Read(CVector<short>& psData);
+    virtual void 		Close();
+
+protected:
+    string				strInFileName;
+    CVector<_REAL>		vecTempResBufIn;
+    CVector<_REAL>		vecTempResBufOut;
+    enum { fmt_txt, fmt_raw_mono, fmt_raw_stereo, fmt_other } eFmt;
+    FILE*				pFileReceiver;
+    int					iSampleRate;
+    int					iRequestedSampleRate;
+    int					iBufferSize;
+    int					iFileSampleRate;
+    int					iFileChannels;
+    CPacer*				pacer;
+    CAudioResample*		ResampleObjL;
+    CAudioResample*		ResampleObjR;
+    short*				buffer;
+    int					iOutBlockSize;
+    string				sCurrentDevice;
+};
+
+#endif
diff --git a/src/sound/drm_portaudio.cpp b/src/sound/drm_portaudio.cpp
new file mode 100644
index 0000000..7ac2f52
--- /dev/null
+++ b/src/sound/drm_portaudio.cpp
@@ -0,0 +1,426 @@
+/******************************************************************************\
+ * British Broadcasting Corporation
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Julian Cable
+ *
+ * Decription:
+ * PortAudio sound interface
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "drm_portaudio.h"
+#include <iostream>
+#include <cstring>
+
+/* 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
+captureCallback(const void *inputBuffer, void *outputBuffer,
+                unsigned long framesPerBuffer,
+                const PaStreamCallbackTimeInfo *,
+                PaStreamCallbackFlags statusFlags, void *userData)
+{
+    /* Cast data passed through stream to our structure. */
+    CPaCommon *This = (CPaCommon *) userData;
+    (void) outputBuffer;		/* Prevent unused variable warning. */
+    long bytes = framesPerBuffer*2*sizeof(short);
+    long avail = PaUtil_GetRingBufferWriteAvailable(&This->ringBuffer);
+    PaUtil_WriteRingBuffer(&This->ringBuffer, inputBuffer, (avail<bytes)?avail:bytes);
+    if (statusFlags&paInputOverflow)
+        This->xruns++;
+    return 0;
+}
+
+static int
+playbackCallback(const void *inputBuffer, void *outputBuffer,
+                 unsigned long framesPerBuffer,
+                 const PaStreamCallbackTimeInfo *,
+                 PaStreamCallbackFlags statusFlags, void *userData)
+{
+    CPaCommon *This = (CPaCommon *) userData;
+    (void) inputBuffer;			/* Prevent unused variable warning. */
+    long bytes = framesPerBuffer*2*sizeof(short);
+    long avail = PaUtil_GetRingBufferReadAvailable(&This->ringBuffer);
+    PaUtil_ReadRingBuffer(&This->ringBuffer, outputBuffer, (avail<bytes)?avail:bytes);
+    if (statusFlags&paOutputUnderflow)
+        This->xruns++;
+    return 0;
+}
+
+int CPaCommon::pa_count = 0;
+
+CPaCommon::CPaCommon(bool cap):ringBuffer(),xruns(0),stream(NULL),
+        names(), devices(),
+        is_capture(cap), blocking(true), device_changed(true), xrun(false),
+        framesPerBuffer(0), ringBufferData(NULL)
+{
+    if (pa_count == 0)
+    {
+        int
+        err = Pa_Initialize();
+        if (err != paNoError)
+            throw string("PortAudio error: ") + Pa_GetErrorText(err);
+    }
+    pa_count++;
+    vector < string > choices;
+    vector < string > descriptions;
+    Enumerate(choices, descriptions);
+}
+
+CPaCommon::~CPaCommon()
+{
+    Close();
+    if (ringBufferData)
+        delete[] ringBufferData;
+
+    pa_count--;
+    if (pa_count == 0)
+    {
+        int err = Pa_Terminate();
+        if (err != paNoError)
+            throw string("PortAudio error: ") + Pa_GetErrorText(err);
+    }
+}
+
+void
+CPaCommon::Enumerate(vector < string > &choices, vector < string > &descriptions)
+{
+    vector < string > tmp;
+
+    names.clear();
+    descriptions.clear();
+	names.push_back(""); /* default device */
+	descriptions.push_back("");
+
+    int numDevices = Pa_GetDeviceCount();
+    if (numDevices < 0)
+        throw string("PortAudio error: ") + Pa_GetErrorText(numDevices);
+    PaHostApiIndex nApis = Pa_GetHostApiCount();
+
+    for (int i = 0; i < numDevices; i++)
+    {
+        const PaDeviceInfo *deviceInfo = Pa_GetDeviceInfo(i);
+        if (( is_capture && deviceInfo->maxInputChannels > 1)
+                || ( (!is_capture) && deviceInfo->maxOutputChannels > 1))
+        {
+            string api="";
+            if (nApis>1)
+            {
+                const PaHostApiInfo* info = Pa_GetHostApiInfo(deviceInfo->hostApi);
+                if (info)
+                    api = string(info->name)+":";
+            }
+            names.push_back(api+deviceInfo->name);
+            devices.push_back(i);
+        }
+    }
+    choices = names;
+}
+
+void
+CPaCommon::SetDev(string sNewDevice)
+{
+    if (dev != sNewDevice)
+    {
+        dev = sNewDevice;
+        device_changed = true;
+    }
+}
+
+string
+CPaCommon::GetDev()
+{
+    return dev;
+}
+
+/* buffer_size is in samples - frames would be better */
+_BOOLEAN
+CPaCommon::Init(int iSampleRate, int iNewBufferSize, _BOOLEAN bNewBlocking)
+{
+    if (device_changed == false && double(iSampleRate) == samplerate)
+        return FALSE;
+
+    unsigned long channels=2;
+
+    samplerate = double(iSampleRate);
+
+    if (is_capture)
+        framesPerBuffer = iNewBufferSize / channels;
+    else
+        framesPerBuffer = 256;
+
+    blocking = bNewBlocking; /* TODO honour this */
+    iBufferSize = iNewBufferSize;
+
+    ReInit();
+
+    if (stream)
+    {
+        const PaStreamInfo* info = Pa_GetStreamInfo( stream );
+        if (is_capture)
+            cout << "init capture ";
+        else
+            cout << "init play ";
+        cout << iNewBufferSize;
+        if (info)
+            cout << " latency " << info->outputLatency;
+        else
+            cout << " can't read latency";
+        cout << endl;
+    }
+    else
+    {
+        cerr << "portaudio can't open stream" << endl;
+        //throw "portaudio open error";
+    }
+
+    return TRUE;
+}
+
+void
+CPaCommon::ReInit()
+{
+    Close();
+
+    PaStreamParameters pParameters;
+
+    memset(&pParameters, 0, sizeof(pParameters));
+    pParameters.channelCount = 2;
+    pParameters.hostApiSpecificStreamInfo = NULL;
+    pParameters.sampleFormat = paInt16;
+
+    int idev = -1;
+    for (int i = 0; i < int(names.size()); i++)
+    {
+        if (names[i] == dev)
+        {
+            idev = i;
+            break;
+        }
+    }
+
+    if (idev < 0 || idev >= int(devices.size()))
+    {
+        if (is_capture)
+            pParameters.device = Pa_GetDefaultInputDevice();
+        else
+            pParameters.device = Pa_GetDefaultOutputDevice();
+    }
+    else
+    {
+        cout << "opening " << names[idev] << endl;
+        pParameters.device = devices[idev];
+    }
+
+    if (pParameters.device == paNoDevice)
+        return;
+
+    unsigned long minRingBufferSize;
+    int err;
+
+    if (is_capture)
+    {
+        pParameters.suggestedLatency = Pa_GetDeviceInfo(pParameters.device)->defaultLowInputLatency;
+        minRingBufferSize = 2*iBufferSize*sizeof(short);
+    }
+    else
+    {
+        pParameters.suggestedLatency = 0.8;
+        minRingBufferSize = 4*iBufferSize*sizeof(short);
+    }
+
+    /* See the specific host's API docs for info on using this field */
+    pParameters.hostApiSpecificStreamInfo = NULL;
+
+    /* flags that can be used to define dither, clip settings and more */
+    if (is_capture)
+    {
+        err = Pa_OpenStream(&stream, &pParameters, NULL, samplerate,
+                            framesPerBuffer, paNoFlag, captureCallback,
+                            (void *) this);
+
+        if (err != paNoError) {
+            //throw string("PortAudio error: ") + Pa_GetErrorText(err);
+		}
+        err = Pa_StartStream(stream);
+        if (err != paNoError) {
+            //throw string("PortAudio error: ") + Pa_GetErrorText(err);
+		}
+    }
+    else
+    {
+        err = Pa_OpenStream(&stream, NULL, &pParameters, samplerate,
+                            framesPerBuffer, paNoFlag, playbackCallback,
+                            (void *) this);
+        if (err != paNoError) {
+            //throw string("PortAudio error: ") + Pa_GetErrorText(err);
+		}
+    }
+
+    unsigned long n = 2;
+    while (n < minRingBufferSize)
+        n <<= 2;				/* smallest power of 2 >= requested */
+
+    if (ringBufferData)
+        delete[] ringBufferData;
+    ringBufferData = new char[n];
+    PaUtil_InitializeRingBuffer(&ringBuffer, n, ringBufferData);
+
+    device_changed = false;
+    xrun = false;
+}
+
+void
+CPaCommon::Close()
+{
+    if (stream)
+    {
+        int err = Pa_AbortStream(stream);
+        if (err != paNoError)
+        {
+            cout << "PortAudio error: " << Pa_GetErrorText(err) << endl;
+        }
+
+        err = Pa_CloseStream(stream);
+        if (err != paNoError)
+        {
+            cout << "PortAudio error: " << Pa_GetErrorText(err) << endl;
+        }
+
+        stream = NULL;
+        device_changed = true;
+    }
+}
+
+_BOOLEAN
+CPaCommon::Read(CVector < short >&psData)
+{
+    if (device_changed)
+        ReInit();
+
+    if (stream==NULL)
+        return TRUE;
+
+    size_t bytes = psData.Size() * sizeof(short);
+
+    while (PaUtil_GetRingBufferReadAvailable(&ringBuffer)<int(bytes))
+    {
+        //cout << "Read: want " << bytes << " avail " << PaUtil_GetRingBufferReadAvailable(&ringBuffer) << endl;
+        Pa_Sleep(10);
+    }
+
+    PaUtil_ReadRingBuffer(&ringBuffer, &psData[0], bytes);
+    if (xruns==0)
+        return FALSE;
+    else
+        cout << "overrun" << endl;
+    xruns = 0;
+    return TRUE;
+}
+
+_BOOLEAN
+CPaCommon::Write(CVector < short >&psData)
+{
+    if (device_changed)
+        ReInit();
+
+    if (stream==NULL)
+        return TRUE;
+
+    size_t bytes = psData.Size() * sizeof(short);
+
+    //cout << "Write: got " << bytes << " can put " << PaUtil_GetRingBufferWriteAvailable(&ringBuffer) << endl;
+    if (PaUtil_GetRingBufferWriteAvailable(&ringBuffer) < int(bytes))
+        return FALSE;			/* TODO use newer data in preference to draining old */
+
+    PaUtil_WriteRingBuffer(&ringBuffer, &psData[0], bytes);
+    if (Pa_IsStreamStopped( stream ))
+    {
+        int err = Pa_StartStream(stream);
+        if (err != paNoError) {
+            //throw string("PortAudio error: ") + Pa_GetErrorText(err);
+		}
+    }
+    if (xruns==0)
+        return FALSE;
+    else
+        cout << "underrun" << endl;
+    xruns = 0;
+    return TRUE;
+}
+
+CPaIn::CPaIn():hw(true)
+{
+}
+
+CPaIn::~CPaIn()
+{
+    Close();
+}
+
+_BOOLEAN
+CPaIn::Init(int iSampleRate, int iNewBufferSize, _BOOLEAN bNewBlocking)
+{
+    return hw.Init(iSampleRate, iNewBufferSize, bNewBlocking);
+}
+
+_BOOLEAN
+CPaIn::Read(CVector<short>& psData)
+{
+    return hw.Read(psData);
+}
+
+void
+CPaIn::Close()
+{
+    hw.Close();
+    cout << "capture close" << endl;
+}
+
+CPaOut::CPaOut():hw(false)
+{
+}
+
+CPaOut::~CPaOut()
+{
+    Close();
+}
+
+_BOOLEAN
+CPaOut::Init(int iSampleRate, int iNewBufferSize, _BOOLEAN bNewBlocking)
+{
+    return hw.Init(iSampleRate, iNewBufferSize, bNewBlocking);
+}
+
+_BOOLEAN
+CPaOut::Write(CVector<short>& psData)
+{
+    return hw.Write(psData);
+}
+
+void
+CPaOut::Close()
+{
+    hw.Close();
+    cout << "play close" << endl;
+}
diff --git a/src/sound/drm_portaudio.h b/src/sound/drm_portaudio.h
new file mode 100644
index 0000000..1fe9155
--- /dev/null
+++ b/src/sound/drm_portaudio.h
@@ -0,0 +1,118 @@
+/******************************************************************************\
+ * British Broadcasting Corporation
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Julian Cable
+ *
+ * Decription:
+ * PortAudio sound interface
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#ifndef _DRM_PORTAUDIO_H
+#define _DRM_PORTAUDIO_H
+
+#include "../sound/soundinterface.h"
+#include <portaudio.h>
+#include "pa_ringbuffer.h"
+
+class CPaCommon: public CSelectionInterface
+{
+public:
+    CPaCommon(bool);
+    virtual 		~CPaCommon();
+
+    virtual void	Enumerate(vector<string>& choices, vector<string>& descriptions);
+    virtual void	SetDev(string sNewDevice);
+    virtual string	GetDev();
+
+    _BOOLEAN		Init(int iSampleRate, int iNewBufferSize, _BOOLEAN bNewBlocking);
+    void			ReInit();
+    _BOOLEAN		Read(CVector<short>& psData);
+    _BOOLEAN		Write(CVector<short>& psData);
+    void			Close();
+
+    PaUtilRingBuffer ringBuffer;
+    int xruns;
+
+protected:
+
+    PaStream *stream;
+    vector<string> names;
+    vector<PaDeviceIndex> devices;
+    string dev;
+    bool is_capture,blocking,device_changed,xrun;
+    int framesPerBuffer;
+    int iBufferSize;
+    char *ringBufferData;
+    double samplerate;
+
+    static int pa_count;
+};
+
+class CPaIn: public CSoundInInterface
+{
+public:
+    CPaIn();
+    virtual 			~CPaIn();
+    virtual void		Enumerate(vector<string>& choices, vector<string>& descriptions) {
+        hw.Enumerate(choices, descriptions);
+    }
+    virtual void		SetDev(string sNewDevice) {
+        hw.SetDev(sNewDevice);
+    }
+    virtual string		GetDev() {
+        return hw.GetDev();
+    }
+
+    virtual _BOOLEAN	Init(int iSampleRate, int iNewBufferSize, _BOOLEAN bNewBlocking);
+    virtual void		Close();
+    virtual _BOOLEAN	Read(CVector<short>& psData);
+
+protected:
+
+    CPaCommon hw;
+};
+
+class CPaOut: public CSoundOutInterface
+{
+public:
+    CPaOut();
+    virtual 			~CPaOut();
+    virtual void		Enumerate(vector<string>& choices, vector<string>& descriptions) {
+        hw.Enumerate(choices, descriptions);
+    }
+    virtual void		SetDev(string sNewDevice) {
+        hw.SetDev(sNewDevice);
+    }
+    virtual string		GetDev() {
+        return hw.GetDev();
+    }
+
+    virtual _BOOLEAN	Init(int iSampleRate, int iNewBufferSize, _BOOLEAN bNewBlocking);
+    virtual void		Close();
+    virtual _BOOLEAN	Write(CVector<short>& psData);
+
+protected:
+
+    CPaCommon hw;
+};
+
+#endif
diff --git a/src/sound/drm_pulseaudio.cpp b/src/sound/drm_pulseaudio.cpp
new file mode 100644
index 0000000..c51a08a
--- /dev/null
+++ b/src/sound/drm_pulseaudio.cpp
@@ -0,0 +1,1014 @@
+/******************************************************************************\
+ *
+ * Copyright (c) 2001-2014-2001-2014
+ *
+ * Author(s):
+ *	David Flamand
+ *
+ * Decription:
+ *  PulseAudio sound interface with clock drift adjustment (optional)
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT 
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include <unistd.h>
+#include <time.h>
+#include <string.h>
+#include <stdlib.h>
+#include <vector>
+#include "drm_pulseaudio.h"
+
+#ifndef PA_STREAM_ADJUST_LATENCY
+# define PA_STREAM_ADJUST_LATENCY 0
+#endif
+#ifndef PA_STREAM_DONT_MOVE
+# define PA_STREAM_DONT_MOVE 0
+#endif
+
+#define RECORD_BUFFER_US    2000000 // us
+#define PLAYBACK_BUFFER_US  2000000 // us
+#define PLAYBACK_LATENCY_US 1000000 // us (50% of PLAYBACK_BUFFER_US)
+#define WAIT_PREBUFFER ((int)(PLAYBACK_LATENCY_US + 399999) / 400000) // 400000us = .4s (frame duration)
+#define NUM_CHANNELS 2 // Stereo
+#define BYTES_PER_SAMPLE ((int)sizeof(_SAMPLE))
+#define PA_RECORD_MAXLENGTH ((int)((double)(NUM_CHANNELS * BYTES_PER_SAMPLE * iSampleRate) * ((double)RECORD_BUFFER_US)    / (double)1000000))
+#define PA_PLAYBACK_TLENGTH ((int)((double)(NUM_CHANNELS * BYTES_PER_SAMPLE * iSampleRate) * ((double)PLAYBACK_BUFFER_US)  / (double)1000000))
+#define PA_PLAYBACK_PREBUF  ((int)((double)(NUM_CHANNELS * BYTES_PER_SAMPLE * iSampleRate) * ((double)PLAYBACK_LATENCY_US) / (double)1000000))
+#define STREAM_FLAGS (PA_STREAM_ADJUST_LATENCY | PA_STREAM_DONT_MOVE)
+#define STREAM_NAME(io, blocking) (blocking ? "Signal " io : "Audio " io)
+#define APP_NAME(io, blocking) ((!io != !blocking) ? "Dream Transmitter" : "Dream Receiver")
+
+#define DEBUG_MSG(...) fprintf(stderr, __VA_ARGS__)
+
+
+#ifdef CLOCK_DRIFT_ADJ_ENABLED
+/* TODO more optimized algorithm and/or parameters */
+# define ALGO_ERROR_MULTIPLIER 256.0
+# define ALGO_ERROR_EXPONENT 2.0
+# include "LatencyFilter.h"
+#endif
+
+
+/* stdin/stdout ***************************************************************/
+
+#ifdef ENABLE_STDIN_STDOUT
+# define STDIN_STDOUT_DEVICE_NAME        "-" /* assumed to be stereo (for backward compatibility) */
+# define STDIN_STDOUT_DEVICE_NAME_MONO   "-1"
+# define STDIN_STDOUT_DEVICE_NAME_STEREO "-2"
+static int StdoutWrite(const char *buf, ssize_t count)
+{
+	ssize_t chunk;
+	while (count > 0) {
+		chunk = write(STDOUT_FILENO, buf, count);
+		if (chunk <= 0)
+			return 1;
+		buf += chunk;
+		count -= chunk;
+	};
+	return 0;
+}
+static int StdinRead(char *buf, ssize_t count)
+{
+	ssize_t chunk;
+	while (count > 0) {
+		chunk = read(STDIN_FILENO, buf, count);
+		if (chunk <= 0) {
+			memset(buf, 0, count);
+			return 1;
+		}
+		buf += chunk;
+		count -= chunk;
+	};
+	return 0;
+}
+#endif
+
+
+/* PulseAudio low level functions *********************************************/
+
+
+static pa_object pa_obj =
+{
+	/*.pa_m =*/			NULL,
+	/*.pa_c =*/			NULL,
+	/*.ref_count =*/	1
+};
+
+static int pa_c_sync(pa_object *pa_obj, int error)
+{
+	int retval;
+	pa_mainloop *pa_m = pa_obj->pa_m;
+	pa_context *pa_c = pa_obj->pa_c;
+	pa_context_state_t pa_c_s;
+	if (error==PA_OK) {
+		do {
+			pa_mainloop_iterate(pa_m, 1, &retval);
+			pa_c_s = pa_context_get_state(pa_c);
+		} while (pa_c_s!=PA_CONTEXT_READY && pa_c_s!=PA_CONTEXT_FAILED);
+		return pa_c_s==PA_CONTEXT_READY ? PA_OK : PA_ERR_MAX;
+	}
+	DEBUG_MSG("pa_c_sync failed, error %i\n", error);
+	return error;
+}
+static int pa_o_sync(pa_object *pa_obj, pa_operation *pa_o)
+{
+	int retval, error;
+	pa_mainloop *pa_m = pa_obj->pa_m;
+	pa_context *pa_c = pa_obj->pa_c;
+	pa_operation_state pa_o_s;
+	if (pa_o) {
+		do {
+			pa_mainloop_iterate(pa_m, 1, &retval);
+			pa_o_s = pa_operation_get_state(pa_o);
+		} while (pa_o_s==PA_OPERATION_RUNNING);
+		pa_operation_unref(pa_o);
+		return pa_o_s==PA_OPERATION_DONE ? PA_OK : PA_ERR_MAX;
+	}
+	error = pa_context_errno(pa_c);
+	DEBUG_MSG("pa_o_sync failed, error %i\n", error);
+	return error;
+}
+static int pa_s_sync(pa_object *pa_obj, pa_stream *pa_s, int error)
+{
+	int retval;
+	pa_mainloop *pa_m = pa_obj->pa_m;
+	pa_stream_state pa_s_s;
+	if (error==PA_OK) {
+		do {
+			pa_mainloop_iterate(pa_m, 1, &retval);
+			pa_s_s = pa_stream_get_state(pa_s);
+		} while (pa_s_s==PA_STREAM_CREATING);
+		return pa_s_s==PA_STREAM_READY ? PA_OK : PA_ERR_MAX;
+	}
+	DEBUG_MSG("pa_s_sync failed, error %i\n", error);
+	return error;
+}
+
+static int pa_init(pa_object *pa_obj, const char *app_name)
+{
+	int ret;
+	pa_mainloop *pa_m_tmp;
+	pa_context *pa_c_tmp;
+//	DEBUG_MSG("pa_init ref_count=%i\n", pa_obj->ref_count);
+	if (pa_obj->pa_m == NULL) {
+		pa_m_tmp = pa_mainloop_new();
+		if (!pa_m_tmp) {
+			DEBUG_MSG("pa_init pa_mainloop_new failed\n");
+			return PA_ERR_MAX;
+		}
+		pa_c_tmp = pa_context_new(pa_mainloop_get_api(pa_m_tmp), app_name);
+		if (!pa_c_tmp) {
+			DEBUG_MSG("pa_init pa_context_new failed\n");
+			pa_mainloop_free(pa_m_tmp);
+			return PA_ERR_MAX;
+		}
+		pa_object pa_obj_tmp = { /*.pa_m=*/pa_m_tmp, /*.pa_c=*/pa_c_tmp, /*.ref_count=*/1 };
+		ret = pa_context_connect(pa_c_tmp, NULL, PA_CONTEXT_NOFLAGS, NULL);
+		if (pa_c_sync(&pa_obj_tmp, ret)!=PA_OK) {
+			DEBUG_MSG("pa_init pa_context_connect failed\n");
+			pa_context_unref(pa_c_tmp);
+			pa_mainloop_free(pa_m_tmp);
+			return PA_ERR_MAX;
+		}
+		pa_obj->pa_m = pa_m_tmp;
+		pa_obj->pa_c = pa_c_tmp;
+	}
+	pa_obj->ref_count++;
+	return PA_OK;
+}
+
+static void pa_free(pa_object *pa_obj)
+{
+	pa_mainloop **pa_m = &pa_obj->pa_m;
+	pa_context **pa_c = &pa_obj->pa_c;
+//	DEBUG_MSG("pa_free ref_count=%i\n", pa_obj->ref_count);
+	if (pa_obj->ref_count > 0)
+	{
+		pa_obj->ref_count--;
+		if (pa_obj->ref_count == 0)
+		{
+//			DEBUG_MSG("pa_free freeing\n");
+			if (*pa_c) {
+				pa_context_disconnect(*pa_c);
+				pa_context_unref(*pa_c);
+				*pa_c = NULL;
+			}
+			if (*pa_m) {
+				pa_mainloop_free(*pa_m);
+				*pa_m = NULL;
+			}
+		}
+	}
+}
+
+static void pa_s_free(pa_stream **pa_s)
+{
+	if (*pa_s) {
+		pa_stream_disconnect(*pa_s);
+		pa_stream_unref(*pa_s);
+		*pa_s = NULL;
+	}
+}
+
+static void pa_stream_notify_cb(pa_stream *, void *userdata)
+{
+	pa_stream_notify_cb_userdata_t* ud = (pa_stream_notify_cb_userdata_t*)userdata;
+	CSoundOutPulse& SoundOutPulse = *ud->SoundOutPulse;
+	if (!SoundOutPulse.bMuteError)
+	{
+		if (!SoundOutPulse.bPrebuffer)
+		{
+			DEBUG_MSG("*** playback %sFLOW\n", ud->bOverflow ? "OVER" : "UNDER");
+			SoundOutPulse.bBufferingError = TRUE;
+		}
+	}
+	if (ud->bOverflow)
+		SoundOutPulse.bSeek = TRUE;
+	else
+		SoundOutPulse.bPrebuffer = TRUE;
+}
+
+static void pa_stream_success_cb(pa_stream *, int /*success*/, void */*userdata*/)
+{
+//	if (userdata)
+//		DEBUG_MSG("pa_stream_success_cb(%s) = %i\n", (char*)userdata, success);
+}
+
+static int pa_stream_get_latency(pa_object *pa_obj, pa_stream *pa_s, int sample_rate, uint64_t *usec)
+{
+	if (pa_o_sync(pa_obj, pa_stream_update_timing_info(pa_s, pa_stream_success_cb, NULL)) == PA_OK) {
+		const pa_timing_info *ti;
+		ti = pa_stream_get_timing_info(pa_s);
+		if (ti && !ti->write_index_corrupt && !ti->read_index_corrupt) {
+			uint64_t samples = llabs(ti->write_index - ti->read_index) / (NUM_CHANNELS*BYTES_PER_SAMPLE);
+			*usec = samples * (uint32_t)1000000 / (uint32_t)sample_rate;
+			return 1;
+		}
+	}
+	return 0;
+}
+
+#ifdef CLOCK_DRIFT_ADJ_ENABLED
+static void pa_set_sample_rate(pa_object *pa_obj, pa_stream *pa_s, int sample_rate)
+{
+	if (pa_o_sync(pa_obj, pa_stream_update_sample_rate(pa_s, sample_rate, pa_stream_success_cb, NULL)) != PA_OK)
+		DEBUG_MSG("pa_set_sample_rate(%i): pa_stream_update_sample_rate failed\n", sample_rate);
+}
+#endif
+
+
+/****************/
+/* devices list */
+
+typedef struct USERDATA {
+	vector<string> *names;
+	vector<string> *descriptions;
+} USERDATA;
+
+static void pa_source_info_cb(pa_context *, const pa_source_info *i, int eol, void *userdata)
+{
+	if (!eol)
+	{
+		((USERDATA*)userdata)->names->push_back(string(i->name));
+		((USERDATA*)userdata)->descriptions->push_back(string(i->description));
+	}
+}
+static void pa_sink_info_cb(pa_context *, const pa_sink_info *i, int eol, void *userdata)
+{
+	if (!eol)
+	{
+		((USERDATA*)userdata)->names->push_back(string(i->name));
+		((USERDATA*)userdata)->descriptions->push_back(string(i->description));
+	}
+}
+
+
+/* Classes ********************************************************************/
+
+/* Implementation *************************************************************/
+
+
+void CSoundInPulse::Init_HW()
+{
+	int ret;
+	pa_sample_spec ss;
+	pa_buffer_attr pa_attr;
+	const char *recdevice=NULL;
+
+	DEBUG_MSG("CSoundInPulse::Init_HW()\n");
+
+	ss.format = PA_SAMPLE_S16NE;
+	ss.channels = NUM_CHANNELS;
+	ss.rate = iSampleRate;
+
+	/* record device */
+	if (!IsDefaultDevice())
+		recdevice = sCurrentDevice.c_str();
+
+	if (pa_init(&pa_obj, APP_NAME(1, bBlockingRec)) != PA_OK)
+	{
+		DEBUG_MSG("CSoundInPulse::Init_HW pa_init failed\n");
+		return;
+	}
+
+	pa_s = pa_stream_new(pa_obj.pa_c,		// The context to create this stream in
+		STREAM_NAME("input", bBlockingRec),	// A name for this stream
+		&ss,								// Our sample format.
+		NULL								// Use default channel map
+		);
+	if (!pa_s)
+	{
+		DEBUG_MSG("CSoundInPulse::Init_HW pa_stream_new failed\n");
+		return;
+	}
+
+	pa_attr.maxlength = PA_RECORD_MAXLENGTH;			// Maximum length of the buffer.
+	pa_attr.tlength   = -1;								// Playback only: target length of the buffer.
+	pa_attr.prebuf    = -1; 							// Playback only: pre-buffering.
+	pa_attr.minreq    = -1;								// Playback only: minimum request.
+	pa_attr.fragsize  = iBufferSize*BYTES_PER_SAMPLE;	// Recording only: fragment size.
+
+	ret = pa_stream_connect_record(pa_s,	// The stream to connect to a source 
+		recdevice,							// Name of the source to connect to, or NULL for default
+		&pa_attr,							// Buffer attributes, or NULL for default
+#ifdef CLOCK_DRIFT_ADJ_ENABLED
+		(pa_stream_flags_t)(STREAM_FLAGS | (!bBlockingRec ? PA_STREAM_VARIABLE_RATE : 0)) // Additional flags, or 0 for default
+#else
+		(pa_stream_flags_t)STREAM_FLAGS		// Additional flags, or 0 for default
+#endif
+		);
+	if (pa_s_sync(&pa_obj, pa_s, ret) != PA_OK)
+		DEBUG_MSG("CSoundInPulse::Init_HW pa_stream_connect_record failed\n");
+
+	remaining_nbytes = 0;
+	remaining_data   = NULL;
+
+	DEBUG_MSG("pulseaudio input device '%s', init done\n", sCurrentDevice.c_str());
+}
+
+int CSoundInPulse::Read_HW(void *recbuf, int size)
+{
+	int ret, retval, filled, chunk;
+	const void *data;
+	size_t nbytes;
+
+	filled = 0;
+	size *= BYTES_PER_SAMPLE;
+
+	if (pa_s)
+	{
+		/* Buffering error when latency >= 75% of RECORD_BUFFER_US */
+		_BOOLEAN bError = TRUE;
+		uint64_t recording_usec;
+		if (pa_stream_get_latency(&pa_obj, pa_s, iSampleRate, &recording_usec))
+			bError = recording_usec >= (uint64_t)(RECORD_BUFFER_US * 75 / 100) ? TRUE : FALSE;
+		bBufferingError |= bError;
+
+#ifdef CLOCK_DRIFT_ADJ_ENABLED
+		if (!bBlockingRec && cp) {
+			if (bClockDriftComp != cp->bClockDriftComp) {
+				bClockDriftComp = cp->bClockDriftComp;
+				DEBUG_MSG("CSoundInPulse::Read_HW(): bClockDriftComp=%i\n", bClockDriftComp);
+				if (!bClockDriftComp)
+					pa_set_sample_rate(&pa_obj, pa_s, iSampleRate);
+			}
+			int sample_rate = iSampleRate - cp->sample_rate_offset;
+			if (record_sample_rate != sample_rate) {
+				record_sample_rate = sample_rate;
+				pa_set_sample_rate(&pa_obj, pa_s, sample_rate);
+			}
+		}
+#endif
+
+		while (size) {
+			if (!remaining_nbytes) {
+				nbytes = 0;
+				data   = NULL;
+				ret = pa_stream_peek(pa_s, &data, &nbytes);
+				if (ret != PA_OK) break;
+				if (!data) {
+					ret = pa_mainloop_iterate(pa_obj.pa_m, 1, &retval);
+					if (ret < 0) break;
+				}
+			}
+			else {
+				nbytes = remaining_nbytes;
+				data   = remaining_data;
+			}
+			if (data) {
+				if (nbytes > (size_t)size) {
+					chunk = size;
+					remaining_nbytes = nbytes - chunk;
+					remaining_data   = (char*)data   + chunk;
+//					DEBUG_MSG("pa_stream_peek frag %6i %6i\n", (int)nbytes, chunk);
+					memcpy(recbuf, data, chunk);
+				}
+				else {
+					chunk = (int)nbytes;
+					remaining_nbytes = 0;
+					remaining_data   = NULL;
+//					DEBUG_MSG("pa_stream_peek full %6i %6i\n", (int)nbytes, chunk);
+					memcpy(recbuf, data, chunk);
+					pa_stream_drop(pa_s); // <- after memcpy
+				}
+				filled += chunk;
+				size -= chunk;
+				recbuf = ((char*)recbuf)+chunk;
+			}
+		}
+	}
+
+	if (size > 0) {
+		memset(recbuf, 0, size);
+		if (bBlockingRec)
+			usleep(lTimeToWait);
+	}
+
+//	DEBUG_MSG("CSoundInPulse::read_HW filled %6i\n", filled);
+	return filled / BYTES_PER_SAMPLE;
+}
+
+void CSoundInPulse::Close_HW()
+{
+	if (pa_s)
+	{
+		DEBUG_MSG("CSoundInPulse::close_HW()\n");
+		remaining_nbytes = 0;
+		remaining_data   = NULL;
+		pa_s_free(&pa_s);
+		pa_free(&pa_obj);
+	}
+}
+
+void CSoundInPulse::SetBufferSize_HW()
+{
+#ifdef PA_STREAM_FIX_RATE /* used to check for at least version 0.9.8 */
+	pa_buffer_attr pa_attr;
+	pa_attr.maxlength = PA_RECORD_MAXLENGTH;			// Maximum length of the buffer.
+	pa_attr.tlength   = -1;								// Playback only: target length of the buffer.
+	pa_attr.prebuf    = -1; 							// Playback only: pre-buffering.
+	pa_attr.minreq    = -1;								// Playback only: minimum request.
+	pa_attr.fragsize  = iBufferSize*BYTES_PER_SAMPLE;	// Recording only: fragment size.
+	if (pa_o_sync(&pa_obj, pa_stream_set_buffer_attr(pa_s, &pa_attr, pa_stream_success_cb, NULL)) != PA_OK)
+		DEBUG_MSG("CSoundInPulse::SetBufferSize_HW() error\n");
+#endif
+}
+
+void CSoundOutPulse::Init_HW()
+{
+	int ret;
+	pa_sample_spec ss;
+	pa_buffer_attr pa_attr;
+	const char *playdevice=NULL;
+
+	DEBUG_MSG("CSoundOutPulse::Init_HW()\n");
+
+	ss.format = PA_SAMPLE_S16NE;
+	ss.channels = NUM_CHANNELS;
+	ss.rate = iSampleRate;
+
+	/* playback device */
+	if (!IsDefaultDevice())
+		playdevice = sCurrentDevice.c_str();
+
+	if (pa_init(&pa_obj, APP_NAME(0, bBlockingPlay)) != PA_OK)
+	{
+		DEBUG_MSG("CSoundOutPulse::Init_HW pa_init failed\n");
+		return;
+	}
+
+	pa_s = pa_stream_new(pa_obj.pa_c,			// The context to create this stream in
+		STREAM_NAME("output", bBlockingPlay),	// A name for this stream
+		&ss,									// Our sample format.
+		NULL									// Use default channel map
+		);
+	if (!pa_s)
+	{
+		DEBUG_MSG("CSoundOutPulse::Init_HW pa_stream_new failed\n");
+		return;
+	}
+
+	pa_attr.maxlength = PA_PLAYBACK_TLENGTH;	// Maximum length of the buffer.
+	pa_attr.tlength   = PA_PLAYBACK_TLENGTH;	// Playback only: target length of the buffer.
+	pa_attr.prebuf    = PA_PLAYBACK_PREBUF;		// Playback only: pre-buffering.
+	pa_attr.minreq    = -1;						// Playback only: minimum request.
+	pa_attr.fragsize  = -1;						// Recording only: fragment size.
+
+	ret = pa_stream_connect_playback(pa_s,	// The stream to connect to a sink
+		playdevice,							// Name of the source to connect to, or NULL for default
+		&pa_attr,							// Buffer attributes, or NULL for default
+#ifdef CLOCK_DRIFT_ADJ_ENABLED
+		(pa_stream_flags_t)(STREAM_FLAGS | (!bBlockingPlay ? PA_STREAM_VARIABLE_RATE : 0)), // Additional flags, or 0 for default
+#else
+		(pa_stream_flags_t)STREAM_FLAGS,	// Additional flags, or 0 for default
+#endif
+		NULL,								// Initial volume, or NULL for default
+		NULL								// Synchronize this stream with the specified one, or NULL for a standalone stream
+		);
+	if (pa_s_sync(&pa_obj, pa_s, ret) != PA_OK)
+		DEBUG_MSG("CSoundOutPulse::Init_HW pa_stream_connect_playback failed\n");
+
+	pa_stream_notify_cb_userdata_underflow.SoundOutPulse = this;
+	pa_stream_notify_cb_userdata_underflow.bOverflow = FALSE;
+	pa_stream_set_underflow_callback(pa_s, &pa_stream_notify_cb, (void*)&pa_stream_notify_cb_userdata_underflow);
+	pa_stream_notify_cb_userdata_overflow.SoundOutPulse = this;
+	pa_stream_notify_cb_userdata_overflow.bOverflow = TRUE;
+	pa_stream_set_overflow_callback(pa_s, &pa_stream_notify_cb, (void*)&pa_stream_notify_cb_userdata_overflow);
+
+#ifdef CLOCK_DRIFT_ADJ_ENABLED
+	X.Init(1);
+	A.Init(1, 1.0);
+	B.Init(NUM_TAPS_LATENCY_FILT);
+	for (int i = 0; i < NUM_TAPS_LATENCY_FILT; i++)
+		B[i] = dLatFilt[i];
+#endif
+
+	/* Clear mute error flag */
+	bMuteError = FALSE;
+
+	DEBUG_MSG("pulseaudio output device '%s', init done\n", sCurrentDevice.c_str());
+}
+
+int CSoundOutPulse::Write_HW(void *playbuf, int size)
+{
+	int ret;
+	int retval;
+
+	if (pa_s)
+	{
+#ifdef CLOCK_DRIFT_ADJ_ENABLED
+		_BOOLEAN bInitClockDriftComp = FALSE;
+		if (cp.bClockDriftComp != bNewClockDriftComp) {
+			cp.bClockDriftComp = bNewClockDriftComp;
+			DEBUG_MSG("CSoundOutPulse::write_HW(): bClockDriftComp=%i\n", cp.bClockDriftComp);
+			if (cp.bClockDriftComp)
+				bInitClockDriftComp = TRUE;
+			else
+				if (!bBlockingPlay)
+					pa_set_sample_rate(&pa_obj, pa_s, iSampleRate);
+		}
+#endif
+
+		if (bPrebuffer) {
+	//		pa_o_sync(&pa_obj, pa_stream_prebuf(pa_s, pa_stream_success_cb, NULL);
+	//		DEBUG_MSG("CSoundOutPulse::write_HW(): prebuffering ...\n");
+			if (pa_o_sync(&pa_obj, pa_stream_prebuf(pa_s, pa_stream_success_cb, NULL)) != PA_OK)
+				DEBUG_MSG("CSoundOutPulse::write_HW(): prebuffering failed\n");
+			bPrebuffer = FALSE;
+			bSeek = FALSE;
+#ifdef CLOCK_DRIFT_ADJ_ENABLED
+			bInitClockDriftComp = TRUE;
+#endif
+		}
+
+#ifdef CLOCK_DRIFT_ADJ_ENABLED
+		if (cp.bClockDriftComp) {
+			if (bInitClockDriftComp) {
+				iMaxSampleRateOffset = iSampleRate * 2 / 100; /* = 2% */
+				playback_usec_smoothed = PLAYBACK_LATENCY_US;
+				target_latency = PLAYBACK_LATENCY_US;
+				wait_prebuffer = WAIT_PREBUFFER;
+				cp.sample_rate_offset = 0;
+				filter_stabilized = NUM_TAPS_LATENCY_FILT;
+				Z.Init(NUM_TAPS_LATENCY_FILT, CReal(PLAYBACK_LATENCY_US));
+				clock = playback_usec = 0; // DEBUG
+			}
+
+			if (!bBlockingPlay)
+	/*Receiver*/	DEBUG_MSG("playback latency: %07i us, smoothed %07i us, %i, %02i, %02i, %i\n", playback_usec, (int)playback_usec_smoothed, iSampleRate + cp.sample_rate_offset, wait_prebuffer, filter_stabilized, ++clock);
+			else
+	/*Transmitter*/	DEBUG_MSG("playback latency: %07i us, smoothed %07i us, %i, %02i, %02i, %i\n", playback_usec, (int)playback_usec_smoothed, iSampleRate - cp.sample_rate_offset, wait_prebuffer, filter_stabilized, ++clock);
+
+			if (wait_prebuffer > 0) {
+				wait_prebuffer--;
+			}
+			else {
+				if (!filter_stabilized) {
+					/****************************************************************************************************************/
+					/* The Clock Drift Adjustment Algorithm                                                                         */
+					int offset;
+					double error = (playback_usec_smoothed - (double)target_latency) / (double)target_latency * ALGO_ERROR_MULTIPLIER;
+	//				error = error * error * (error >= 0.0 ? 1.0 : -1.0);
+					error = pow(fabs(error), ALGO_ERROR_EXPONENT) * (error >= 0.0 ? 1.0 : -1.0);
+					if (error >= 0.0) offset = (int)floor(error + 0.5);
+					else              offset = (int) ceil(error - 0.5);
+					if      (offset>iMaxSampleRateOffset)  offset=iMaxSampleRateOffset;
+					else if (offset<-iMaxSampleRateOffset) offset=-iMaxSampleRateOffset;
+					/****************************************************************************************************************/
+					if (!bBlockingPlay && cp.sample_rate_offset != offset) {
+						pa_set_sample_rate(&pa_obj, pa_s, iSampleRate + offset);
+					}
+					cp.sample_rate_offset = offset;
+				}
+			}
+		}
+#endif
+
+		ret = pa_stream_write(pa_s,		// The stream to use
+			playbuf,					// The data to write
+			size * BYTES_PER_SAMPLE,	// The length of the data to write in bytes
+			NULL,						// A cleanup routine for the data or NULL to request an internal copy
+			bSeek ? -(PA_PLAYBACK_PREBUF/2) : 0,	// Offset for seeking, must be 0 for upload streams
+			PA_SEEK_RELATIVE			// Seek mode, must be PA_SEEK_RELATIVE for upload streams
+			);
+
+#ifdef CLOCK_DRIFT_ADJ_ENABLED
+		if (cp.bClockDriftComp) {
+			if (!wait_prebuffer) {
+				uint64_t playback_usec;
+				if (pa_stream_get_latency(&pa_obj, pa_s, iSampleRate, &playback_usec)) {
+					this->playback_usec = (int)playback_usec; // DEBUG
+					X[0] = CReal(playback_usec);
+					playback_usec_smoothed = Filter(B, A, X, Z)[0];
+					if (filter_stabilized > 0) {
+						filter_stabilized--;
+						if(!filter_stabilized) {
+							target_latency = playback_usec_smoothed;
+						}
+					}
+				}
+			}
+		}
+#endif
+
+		bSeek = FALSE;
+
+		if (ret == PA_OK) {
+			do {
+				ret = pa_mainloop_iterate(pa_obj.pa_m, 0, &retval);
+			} while (ret>0);
+			return size;
+		}
+	}
+
+	if (size > 0) {
+		if (bBlockingPlay)
+			usleep(lTimeToWait);
+	}
+
+	return -1;
+}
+
+void CSoundOutPulse::Close_HW()
+{
+	if (pa_s)
+	{
+		DEBUG_MSG("CSoundOutPulse::close_HW()\n");
+		bMuteError = TRUE;
+		if (bBlockingPlay && pa_obj.pa_m!=NULL && pa_obj.pa_c!=NULL && pa_s!=NULL)
+		{
+			if (pa_o_sync(&pa_obj, pa_stream_drain(pa_s, pa_stream_success_cb, NULL)) != PA_OK)
+			{
+				DEBUG_MSG("CSoundOutPulse::close_HW() pa_stream_drain failed\n");
+			}		
+		}
+		pa_s_free(&pa_s);
+		pa_free(&pa_obj);
+	}
+}
+
+
+/*********************************************************************************************************************/
+
+
+/* Common ********************************************************************/
+
+CSoundPulse::CSoundPulse(_BOOLEAN bPlayback)
+	: bPlayback(bPlayback), bChangDev(TRUE)
+#ifdef ENABLE_STDIN_STDOUT
+	, bStdinStdout(FALSE)
+	, bMono(FALSE)
+#endif
+{
+}
+
+void CSoundPulse::Enumerate(vector<string>& names, vector<string>& descriptions)
+{
+	pa_object pa_obj = { /*.pa_m=*/NULL, /*.pa_c=*/NULL, /*.ref_count=*/0 };
+	pa_operation *pa_o;
+	USERDATA userdata;
+
+	names.clear();
+	descriptions.clear();
+	names.push_back(""); /* default device */
+	descriptions.push_back("");
+
+	if (pa_init(&pa_obj, "") != PA_OK)
+	{
+		DEBUG_MSG("CSoundPulse::Enumerate(): pa_init failed\n");
+		return;
+	}
+
+	userdata.names = &names;
+	userdata.descriptions = &descriptions;
+
+	if (bPlayback)
+		pa_o = pa_context_get_sink_info_list(pa_obj.pa_c, pa_sink_info_cb, &userdata);
+	else
+		pa_o = pa_context_get_source_info_list(pa_obj.pa_c, pa_source_info_cb, &userdata);
+
+	if (pa_o_sync(&pa_obj, pa_o) != PA_OK)
+		DEBUG_MSG("CSoundPulse::Enumerate(): pa_context_get_(sink/source)_info_list failed\n");
+
+	pa_free(&pa_obj);
+}
+
+void CSoundPulse::SetDev(string sNewDevice)
+{
+	if (sNewDevice != sCurrentDevice)
+	{
+		sCurrentDevice = sNewDevice;
+		bChangDev = TRUE;
+	}
+}
+
+string CSoundPulse::GetDev()
+{
+	return sCurrentDevice;
+}
+
+_BOOLEAN CSoundPulse::IsDefaultDevice()
+{
+	const char *str = sCurrentDevice.c_str();
+	return *str == 0;
+}
+
+#ifdef ENABLE_STDIN_STDOUT
+_BOOLEAN CSoundPulse::IsStdinStdout()
+{
+	bMono =
+		sCurrentDevice == STDIN_STDOUT_DEVICE_NAME_MONO;
+	bStdinStdout =
+		sCurrentDevice == STDIN_STDOUT_DEVICE_NAME ||
+		sCurrentDevice == STDIN_STDOUT_DEVICE_NAME_MONO ||
+		sCurrentDevice == STDIN_STDOUT_DEVICE_NAME_STEREO;
+	return bStdinStdout;
+}
+#endif
+
+
+/* Wave in ********************************************************************/
+
+CSoundInPulse::CSoundInPulse(): CSoundPulse(FALSE),
+	iSampleRate(0), iBufferSize(0), lTimeToWait(0),
+	bBlockingRec(FALSE), bBufferingError(FALSE), pa_s(NULL),
+	remaining_nbytes(0), remaining_data(NULL)
+#ifdef CLOCK_DRIFT_ADJ_ENABLED
+	, record_sample_rate(0), bClockDriftComp(FALSE), cp(NULL)
+#endif
+{
+}
+
+_BOOLEAN CSoundInPulse::Init(int iNewSampleRate, int iNewBufferSize, _BOOLEAN bNewBlocking)
+{
+	DEBUG_MSG("initrec %i %i %i\n", iNewSampleRate, iNewBufferSize, bNewBlocking);
+	_BOOLEAN bChanged = FALSE;
+
+#ifdef ENABLE_STDIN_STDOUT
+	/* Check if it's stdin */
+	if (IsStdinStdout())
+	{
+		iBufferSize = iNewBufferSize * BYTES_PER_SAMPLE;
+		return FALSE;
+	}
+#endif
+
+	/* Save blocking mode */
+	bBlockingRec = bNewBlocking;
+
+	/* Check if device must be opened or reinitialized */
+	if (bChangDev == TRUE || iSampleRate != iNewSampleRate)
+	{
+		/* Save samplerate buffer size */
+		iSampleRate = iNewSampleRate;
+		iBufferSize = iNewBufferSize;
+
+		/* Time to wait in case of read error (ns) */
+		lTimeToWait = (iNewBufferSize / NUM_CHANNELS) * 1000l / (iNewSampleRate / 1000l) + 1000;
+
+		/* Close the previous input */
+		Close_HW();
+
+		/* Open the new input */
+		Init_HW();
+
+		/* Reset flag */
+		bChangDev = FALSE;
+
+		/* Set changed flag */
+		bChanged = TRUE;
+	}
+	else {
+		if (iBufferSize != iNewBufferSize)
+		{
+			/* Save buffer size */
+			iBufferSize = iNewBufferSize;
+
+			/* Set buffer size */
+			SetBufferSize_HW();
+		}
+	}
+
+	/* Clear buffering error flag */
+	bBufferingError = FALSE;
+
+	return bChanged;
+}
+
+_BOOLEAN CSoundInPulse::Read(CVector<_SAMPLE>& psData)
+{
+#ifdef ENABLE_STDIN_STDOUT
+	/* Stdin support */
+	if (bStdinStdout)
+	{
+		if (!bMono)
+			return StdinRead((char*)&psData[0], iBufferSize);
+		else
+		{
+			int sample = iBufferSize / BYTES_PER_SAMPLE;
+			_BOOLEAN ret = StdinRead((char*)&psData[0], iBufferSize/2);
+			for (int i=sample-2, j=i/2; i>=0; i-=2, j--)
+				psData[i] = psData[i+1] = psData[j];
+			return ret;
+		}
+	}
+#endif
+
+	/* Check if device must be opened or reinitialized */
+	if (bChangDev == TRUE)
+	{
+		/* Reinit sound interface */
+		Init(iSampleRate, iBufferSize, bBlockingRec);
+
+		/* Reset flag */
+		bChangDev = FALSE;
+	}
+
+	/* Read from 'hardware' */
+	_BOOLEAN bError = Read_HW(&psData[0], iBufferSize) != iBufferSize;
+	if (bError)
+	    DEBUG_MSG("CSoundInPulse::Read(): read_HW error\n");
+
+	bError |= bBufferingError;
+	bBufferingError = FALSE;
+
+	return bError;
+}
+
+void CSoundInPulse::Close()
+{
+	DEBUG_MSG("stoprec\n");
+
+#ifdef ENABLE_STDIN_STDOUT
+	/* Stdout support */
+	if (bStdinStdout)
+		return;
+#endif
+
+	/* Close the input */
+	Close_HW();
+
+	/* Set flag to open devices the next time it is initialized */
+	bChangDev = TRUE;
+}
+
+
+/* Wave out *******************************************************************/
+
+CSoundOutPulse::CSoundOutPulse(): CSoundPulse(TRUE),
+	bPrebuffer(FALSE), bSeek(FALSE),
+	bBufferingError(FALSE), bMuteError(FALSE),
+	iSampleRate(0), iBufferSize(0), lTimeToWait(0),
+	bBlockingPlay(FALSE), pa_s(NULL)
+#ifdef CLOCK_DRIFT_ADJ_ENABLED
+	, iMaxSampleRateOffset(0)
+//	, bNewClockDriftComp(TRUE), cp()
+	, bNewClockDriftComp(FALSE), cp()
+#endif
+{
+}
+
+_BOOLEAN CSoundOutPulse::Init(int iNewSampleRate, int iNewBufferSize, _BOOLEAN bNewBlocking)
+{
+	DEBUG_MSG("initplay %i %i %i\n", iNewSampleRate, iNewBufferSize, bNewBlocking);
+	_BOOLEAN bChanged = FALSE;
+
+#ifdef ENABLE_STDIN_STDOUT
+	/* Check if it's stdin */
+	if (IsStdinStdout())
+	{
+		iBufferSize = iNewBufferSize * BYTES_PER_SAMPLE;
+		return FALSE;
+	}
+#endif
+
+	/* Save blocking mode and buffer size */
+	bBlockingPlay = bNewBlocking;
+	iBufferSize = iNewBufferSize;
+
+	/* Check if device must be opened or reinitialized */
+	if (bChangDev == TRUE || iSampleRate != iNewSampleRate)
+	{
+		/* Save samplerate */
+		iSampleRate = iNewSampleRate;
+
+		/* Time to wait in case of write error (ns) */
+		lTimeToWait = (iNewBufferSize / NUM_CHANNELS) * 1000l / (iNewSampleRate / 1000l) + 1000;
+
+		/* Close the previous input */
+		Close_HW();
+
+		/* Open the new input */
+		Init_HW();
+
+		/* Reset flag */
+		bChangDev = FALSE;
+
+		/* Set changed flag */
+		bChanged = TRUE;
+	}
+
+	/* Set prebuffer flag */
+	bPrebuffer = TRUE;
+	/* Clear seek flag */
+	bSeek = FALSE;
+	/* Clear buffering error flag */
+	bBufferingError = FALSE;
+
+	return bChanged;
+}
+
+_BOOLEAN CSoundOutPulse::Write(CVector<_SAMPLE>& psData)
+{
+#ifdef ENABLE_STDIN_STDOUT
+	/* Stdout support */
+	if (bStdinStdout)
+	{
+		if (!bMono)
+			return StdoutWrite((char*)&psData[0], iBufferSize);
+		else
+		{
+			for (int i=0, j=0; i<iBufferSize; i+=2, j++)
+			{
+				int value = ((int)psData[i] + (int)psData[i+1]) / 2;
+				psData[j] = (_SAMPLE)value;
+			}
+			_BOOLEAN ret = StdoutWrite((char*)&psData[0], iBufferSize/2);
+			return ret;
+		}
+	}
+#endif
+
+	/* Check if device must be opened or reinitialized */
+	if (bChangDev == TRUE)
+	{
+		/* Reinit sound interface */
+		Init(iSampleRate, iBufferSize, bBlockingPlay);
+
+		/* Reset flag */
+		bChangDev = FALSE;
+	}
+
+	/* Write to 'hardware' */
+	_BOOLEAN bError = Write_HW(&psData[0], iBufferSize) != iBufferSize;
+	if (bError)
+		DEBUG_MSG("CSoundOutPulse::Write(): write_HW error\n");
+
+	bError |= bBufferingError;
+	bBufferingError = FALSE;
+
+	return bError;
+}
+
+void CSoundOutPulse::Close()
+{
+	DEBUG_MSG("stopplay\n");
+
+#ifdef ENABLE_STDIN_STDOUT
+	/* Stdout support */
+	if (bStdinStdout)
+		return;
+#endif
+
+	/* Close the output */
+	Close_HW();
+
+	/* Set flag to open devices the next time it is initialized */
+	bChangDev = TRUE;
+}
+
diff --git a/src/sound/drm_pulseaudio.h b/src/sound/drm_pulseaudio.h
new file mode 100644
index 0000000..4e22749
--- /dev/null
+++ b/src/sound/drm_pulseaudio.h
@@ -0,0 +1,186 @@
+/******************************************************************************\
+ *
+ * Copyright (c) 2001-2014-2001-2014
+ *
+ * Author(s):
+ *	David Flamand
+ *
+ * Decription:
+ *  PulseAudio sound interface with clock drift adjustment (optional)
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#ifndef DRM_PULSEAUDIO_H_INCLUDED
+#define DRM_PULSEAUDIO_H_INCLUDED
+
+
+/* Master switch */
+//#define ENABLE_CLOCK_DRIFT_ADJ
+
+
+#include <pulse/pulseaudio.h>
+#include "../sound/soundinterface.h"
+#if defined(PA_STREAM_VARIABLE_RATE) && defined(ENABLE_CLOCK_DRIFT_ADJ)
+# define CLOCK_DRIFT_ADJ_ENABLED
+#endif
+
+#ifdef CLOCK_DRIFT_ADJ_ENABLED
+# include "../matlib/MatlibSigProToolbox.h"
+#endif
+
+#ifndef _WIN32
+# define ENABLE_STDIN_STDOUT
+#endif
+
+
+class CSoundOutPulse;
+typedef struct pa_stream_notify_cb_userdata_t
+{
+	CSoundOutPulse*		SoundOutPulse;
+	_BOOLEAN			bOverflow;
+} pa_stream_notify_cb_userdata_t;
+
+typedef struct pa_common
+{
+	_BOOLEAN		bClockDriftComp;
+	int				sample_rate_offset;
+} pa_common;
+
+typedef struct pa_object
+{
+	pa_mainloop		*pa_m;
+	pa_context		*pa_c;
+	int				ref_count;
+} pa_object;
+
+
+/* Classes ********************************************************************/
+
+class CSoundPulse
+{
+public:
+	CSoundPulse(_BOOLEAN bPlayback);
+	virtual ~CSoundPulse() {}
+	void			Enumerate(vector<string>& names, vector<string>& descriptions);
+	void			SetDev(string sNewDevice);
+	string			GetDev();
+protected:
+	_BOOLEAN		IsDefaultDevice();
+	_BOOLEAN		bPlayback;
+	_BOOLEAN		bChangDev;
+	string			sCurrentDevice;
+#ifdef ENABLE_STDIN_STDOUT
+	_BOOLEAN		IsStdinStdout();
+	_BOOLEAN		bStdinStdout;
+	_BOOLEAN		bMono;
+#endif
+};
+
+class CSoundInPulse : public CSoundPulse, public CSoundInInterface
+{
+public:
+	CSoundInPulse();
+	virtual ~CSoundInPulse() {}
+	void			Enumerate(vector<string>& names, vector<string>& descriptions) {CSoundPulse::Enumerate(names, descriptions);};
+	string			GetDev() {return CSoundPulse::GetDev();};
+	void			SetDev(string sNewDevice) {CSoundPulse::SetDev(sNewDevice);};
+
+	_BOOLEAN		Init(int iNewSampleRate, int iNewBufferSize, _BOOLEAN bNewBlocking);
+	_BOOLEAN		Read(CVector<_SAMPLE>& psData);
+	void			Close();
+#ifdef CLOCK_DRIFT_ADJ_ENABLED
+	void			SetCommonParamPtr(pa_common *cp_ptr) { cp = cp_ptr; }
+#endif
+
+protected:
+	void			Init_HW();
+	int				Read_HW(void *recbuf, int size);
+	void			Close_HW();
+	void			SetBufferSize_HW();
+
+	int				iSampleRate;
+	int				iBufferSize;
+	long			lTimeToWait;
+	_BOOLEAN		bBlockingRec;
+
+	_BOOLEAN		bBufferingError;
+
+	pa_stream		*pa_s;
+	size_t			remaining_nbytes;
+	const char		*remaining_data;
+
+#ifdef CLOCK_DRIFT_ADJ_ENABLED
+	int				record_sample_rate;
+	_BOOLEAN		bClockDriftComp;
+	pa_common		*cp;
+#endif
+};
+
+class CSoundOutPulse : public CSoundPulse, public CSoundOutInterface
+{
+public:
+	CSoundOutPulse();
+	virtual ~CSoundOutPulse() {}
+	void			Enumerate(vector<string>& names, vector<string>& descriptions) {CSoundPulse::Enumerate(names, descriptions);};
+	string			GetDev() {return CSoundPulse::GetDev();};
+	void			SetDev(string sNewDevice) {CSoundPulse::SetDev(sNewDevice);};
+
+	_BOOLEAN		Init(int iNewSampleRate, int iNewBufferSize, _BOOLEAN bNewBlocking);
+	_BOOLEAN		Write(CVector<_SAMPLE>& psData);
+	void			Close();
+#ifdef CLOCK_DRIFT_ADJ_ENABLED
+	pa_common *		GetCommonParamPtr() { return &cp; }
+	void			EnableClockDriftAdj(_BOOLEAN bEnable) { bNewClockDriftComp = bEnable; }
+	_BOOLEAN		IsClockDriftAdjEnabled() { return bNewClockDriftComp; }
+#endif
+
+	_BOOLEAN		bPrebuffer;
+	_BOOLEAN		bSeek;
+	_BOOLEAN		bBufferingError;
+	_BOOLEAN		bMuteError;
+
+protected:
+	void			Init_HW();
+	int				Write_HW(void *playbuf, int size);
+	void			Close_HW();
+
+	int				iSampleRate;
+	int				iBufferSize;
+	long			lTimeToWait;
+	_BOOLEAN		bBlockingPlay;
+
+	pa_stream		*pa_s;
+	pa_stream_notify_cb_userdata_t pa_stream_notify_cb_userdata_underflow;
+	pa_stream_notify_cb_userdata_t pa_stream_notify_cb_userdata_overflow;
+
+#ifdef CLOCK_DRIFT_ADJ_ENABLED
+	int				iMaxSampleRateOffset;
+	CReal			playback_usec_smoothed;
+	int				target_latency;
+	int				filter_stabilized;
+	int				wait_prebuffer;
+	CMatlibVector<CReal> B, A, X, Z;
+	_BOOLEAN		bNewClockDriftComp;
+	pa_common		cp;
+	int				playback_usec; // DEBUG
+	int				clock; // DEBUG
+#endif
+};
+
+#endif
diff --git a/src/sound/pa_ringbuffer.c b/src/sound/pa_ringbuffer.c
new file mode 100644
index 0000000..9074af3
--- /dev/null
+++ b/src/sound/pa_ringbuffer.c
@@ -0,0 +1,284 @@
+/*
+ * $Id: pa_ringbuffer.c,v 1.8 2001-2014/04/22 13:17:56 jcable Exp $
+ * Portable Audio I/O Library
+ * Ring Buffer utility.
+ *
+ * Author: Phil Burk, http://www.softsynth.com
+ * modified for SMP safety on Mac OS X by Bjorn Roche
+ * modified for SMP safety on Linux by Leland Lucius
+ * also, allowed for const where possible
+ * Note that this is safe only for a single-thread reader and a
+ * single-thread writer.
+ *
+ * This program uses the PortAudio Portable Audio Library.
+ * For more information see: http://www.portaudio.com
+ * Copyright (c) 1999-2000 Ross Bencina and Phil Burk
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * The text above constitutes the entire PortAudio license; however,
+ * the PortAudio community also makes the following non-binding requests:
+ *
+ * Any person wishing to distribute modifications to the Software is
+ * requested to send the modifications to the original developer so that
+ * they can be incorporated into the canonical version. It is also
+ * requested that these non-binding requests be included along with the
+ * license above.
+ */
+
+/**
+ @file
+ @ingroup common_src
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include "pa_ringbuffer.h"
+#include <string.h>
+
+/****************
+ * First, we'll define some memory barrier primitives based on the system.
+ * right now only OS X, FreeBSD, and Linux are supported. In addition to providing
+ * memory barriers, these functions should ensure that data cached in registers
+ * is written out to cache where it can be snooped by other CPUs. (ie, the volatile
+ * keyword should not be required)
+ *
+ * the primitives that must be defined are:
+ *
+ * PaUtil_FullMemoryBarrier()
+ * PaUtil_ReadMemoryBarrier()
+ * PaUtil_WriteMemoryBarrier()
+ *
+ ****************/
+
+#if defined(__APPLE__) || defined(__FreeBSD__)
+#   include <libkern/OSAtomic.h>
+/* Here are the memory barrier functions. Mac OS X and FreeBSD only provide
+   full memory barriers, so the three types of barriers are the same. */
+#   define PaUtil_FullMemoryBarrier()  OSMemoryBarrier()
+#   define PaUtil_ReadMemoryBarrier()  OSMemoryBarrier()
+#   define PaUtil_WriteMemoryBarrier() OSMemoryBarrier()
+#elif defined(__GNUC__)
+/* GCC understands volatile asm and "memory" to mean it
+ * should not reorder memory read/writes */
+#   if defined( __PPC__ )
+#      define PaUtil_FullMemoryBarrier()  asm volatile("sync":::"memory")
+#      define PaUtil_ReadMemoryBarrier()  asm volatile("sync":::"memory")
+#      define PaUtil_WriteMemoryBarrier() asm volatile("sync":::"memory")
+#   elif defined( __i386__ ) || defined( __i486__ ) || defined( __i586__ ) || defined( __i686__ ) || defined( __x86_64 )
+#      define PaUtil_FullMemoryBarrier()  asm volatile("mfence":::"memory")
+#      define PaUtil_ReadMemoryBarrier()  asm volatile("lfence":::"memory")
+#      define PaUtil_WriteMemoryBarrier() asm volatile("sfence":::"memory")
+#   else
+#      ifdef ALLOW_SMP_DANGERS
+#         warning Memory barriers not defined on this system or system unknown
+#         warning For SMP safety, you should fix this.
+#         define PaUtil_FullMemoryBarrier()
+#         define PaUtil_ReadMemoryBarrier()
+#         define PaUtil_WriteMemoryBarrier()
+#      else
+#         error Memory barriers are not defined on this system. You can still compile by defining ALLOW_SMP_DANGERS, but SMP safety will not be guaranteed.
+#      endif
+#   endif
+#elif defined(_MSC_VER)
+//#  pragma comment(compiler, "hoping alignment renders barriers unnecessary")
+#  define PaUtil_FullMemoryBarrier()
+#  define PaUtil_ReadMemoryBarrier()
+#  define PaUtil_WriteMemoryBarrier()
+#else
+#   ifdef ALLOW_SMP_DANGERS
+#      warning Memory barriers not defined on this system or system unknown
+#      warning For SMP safety, you should fix this.
+#      define PaUtil_FullMemoryBarrier()
+#      define PaUtil_ReadMemoryBarrier()
+#      define PaUtil_WriteMemoryBarrier()
+#   else
+#      error Memory barriers are not defined on this system. You can still compile by defining ALLOW_SMP_DANGERS, but SMP safety will not be guaranteed.
+#   endif
+#endif
+
+/***************************************************************************
+ * Initialize FIFO.
+ * numBytes must be power of 2, returns -1 if not.
+ */
+long PaUtil_InitializeRingBuffer( PaUtilRingBuffer *rbuf, long numBytes, void *dataPtr )
+{
+    if ( ((numBytes-1) & numBytes) != 0) return -1; /* Not Power of two. */
+    rbuf->bufferSize = numBytes;
+    rbuf->buffer = (char *)dataPtr;
+    PaUtil_FlushRingBuffer( rbuf );
+    rbuf->bigMask = (numBytes*2)-1;
+    rbuf->smallMask = (numBytes)-1;
+    return 0;
+}
+
+/***************************************************************************
+** Return number of bytes available for reading. */
+long PaUtil_GetRingBufferReadAvailable( PaUtilRingBuffer *rbuf )
+{
+    PaUtil_ReadMemoryBarrier();
+    return ( (rbuf->writeIndex - rbuf->readIndex) & rbuf->bigMask );
+}
+/***************************************************************************
+** Return number of bytes available for writing. */
+long PaUtil_GetRingBufferWriteAvailable( PaUtilRingBuffer *rbuf )
+{
+    /* Since we are calling PaUtil_GetRingBufferReadAvailable, we don't need an aditional MB */
+    return ( rbuf->bufferSize - PaUtil_GetRingBufferReadAvailable(rbuf));
+}
+
+/***************************************************************************
+** Clear buffer. Should only be called when buffer is NOT being read. */
+void PaUtil_FlushRingBuffer( PaUtilRingBuffer *rbuf )
+{
+    rbuf->writeIndex = rbuf->readIndex = 0;
+}
+
+/***************************************************************************
+** Get address of region(s) to which we can write data.
+** If the region is contiguous, size2 will be zero.
+** If non-contiguous, size2 will be the size of second region.
+** Returns room available to be written or numBytes, whichever is smaller.
+*/
+long PaUtil_GetRingBufferWriteRegions( PaUtilRingBuffer *rbuf, long numBytes,
+                                       void **dataPtr1, long *sizePtr1,
+                                       void **dataPtr2, long *sizePtr2 )
+{
+    long   index;
+    long   available = PaUtil_GetRingBufferWriteAvailable( rbuf );
+    if ( numBytes > available ) numBytes = available;
+    /* Check to see if write is not contiguous. */
+    index = rbuf->writeIndex & rbuf->smallMask;
+    if ( (index + numBytes) > rbuf->bufferSize )
+    {
+        /* Write data in two blocks that wrap the buffer. */
+        long   firstHalf = rbuf->bufferSize - index;
+        *dataPtr1 = &rbuf->buffer[index];
+        *sizePtr1 = firstHalf;
+        *dataPtr2 = &rbuf->buffer[0];
+        *sizePtr2 = numBytes - firstHalf;
+    }
+    else
+    {
+        *dataPtr1 = &rbuf->buffer[index];
+        *sizePtr1 = numBytes;
+        *dataPtr2 = NULL;
+        *sizePtr2 = 0;
+    }
+    return numBytes;
+}
+
+
+/***************************************************************************
+*/
+long PaUtil_AdvanceRingBufferWriteIndex( PaUtilRingBuffer *rbuf, long numBytes )
+{
+    /* we need to ensure that previous writes are seen before we update the write index */
+    PaUtil_WriteMemoryBarrier();
+    return rbuf->writeIndex = (rbuf->writeIndex + numBytes) & rbuf->bigMask;
+}
+
+/***************************************************************************
+** Get address of region(s) from which we can read data.
+** If the region is contiguous, size2 will be zero.
+** If non-contiguous, size2 will be the size of second region.
+** Returns room available to be written or numBytes, whichever is smaller.
+*/
+long PaUtil_GetRingBufferReadRegions( PaUtilRingBuffer *rbuf, long numBytes,
+                                      void **dataPtr1, long *sizePtr1,
+                                      void **dataPtr2, long *sizePtr2 )
+{
+    long   index;
+    long   available = PaUtil_GetRingBufferReadAvailable( rbuf );
+    if ( numBytes > available ) numBytes = available;
+    /* Check to see if read is not contiguous. */
+    index = rbuf->readIndex & rbuf->smallMask;
+    if ( (index + numBytes) > rbuf->bufferSize )
+    {
+        /* Write data in two blocks that wrap the buffer. */
+        long firstHalf = rbuf->bufferSize - index;
+        *dataPtr1 = &rbuf->buffer[index];
+        *sizePtr1 = firstHalf;
+        *dataPtr2 = &rbuf->buffer[0];
+        *sizePtr2 = numBytes - firstHalf;
+    }
+    else
+    {
+        *dataPtr1 = &rbuf->buffer[index];
+        *sizePtr1 = numBytes;
+        *dataPtr2 = NULL;
+        *sizePtr2 = 0;
+    }
+    return numBytes;
+}
+/***************************************************************************
+*/
+long PaUtil_AdvanceRingBufferReadIndex( PaUtilRingBuffer *rbuf, long numBytes )
+{
+    /* we need to ensure that previous writes are always seen before updating the index. */
+    PaUtil_WriteMemoryBarrier();
+    return rbuf->readIndex = (rbuf->readIndex + numBytes) & rbuf->bigMask;
+}
+
+/***************************************************************************
+** Return bytes written. */
+long PaUtil_WriteRingBuffer( PaUtilRingBuffer *rbuf, const void *data, long numBytes )
+{
+    long size1, size2, numWritten;
+    void *data1, *data2;
+    numWritten = PaUtil_GetRingBufferWriteRegions( rbuf, numBytes, &data1, &size1, &data2, &size2 );
+    if ( size2 > 0 )
+    {
+
+        memcpy( data1, data, size1 );
+        data = ((char *)data) + size1;
+        memcpy( data2, data, size2 );
+    }
+    else
+    {
+        memcpy( data1, data, size1 );
+    }
+    PaUtil_AdvanceRingBufferWriteIndex( rbuf, numWritten );
+    return numWritten;
+}
+
+/***************************************************************************
+** Return bytes read. */
+long PaUtil_ReadRingBuffer( PaUtilRingBuffer *rbuf, void *data, long numBytes )
+{
+    long size1, size2, numRead;
+    void *data1, *data2;
+    numRead = PaUtil_GetRingBufferReadRegions( rbuf, numBytes, &data1, &size1, &data2, &size2 );
+    if ( size2 > 0 )
+    {
+        memcpy( data, data1, size1 );
+        data = ((char *)data) + size1;
+        memcpy( data, data2, size2 );
+    }
+    else
+    {
+        memcpy( data, data1, size1 );
+    }
+    PaUtil_AdvanceRingBufferReadIndex( rbuf, numRead );
+    return numRead;
+}
diff --git a/src/sound/pa_ringbuffer.h b/src/sound/pa_ringbuffer.h
new file mode 100644
index 0000000..42b99be
--- /dev/null
+++ b/src/sound/pa_ringbuffer.h
@@ -0,0 +1,205 @@
+#ifndef PA_RINGBUFFER_H
+#define PA_RINGBUFFER_H
+/*
+ * $Id: pa_ringbuffer.h,v 1.7 2001-2014/04/22 13:17:56 jcable Exp $
+ * Portable Audio I/O Library
+ * Ring Buffer utility.
+ *
+ * Author: Phil Burk, http://www.softsynth.com
+ * modified for SMP safety on OS X by Bjorn Roche.
+ * also allowed for const where possible.
+ * Note that this is safe only for a single-thread reader
+ * and a single-thread writer.
+ *
+ * This program is distributed with the PortAudio Portable Audio Library.
+ * For more information see: http://www.portaudio.com
+ * Copyright (c) 1999-2000 Ross Bencina and Phil Burk
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * The text above constitutes the entire PortAudio license; however,
+ * the PortAudio community also makes the following non-binding requests:
+ *
+ * Any person wishing to distribute modifications to the Software is
+ * requested to send the modifications to the original developer so that
+ * they can be incorporated into the canonical version. It is also
+ * requested that these non-binding requests be included along with the
+ * license above.
+ */
+
+/** @file
+ @ingroup common_src
+*/
+
+#ifdef _MSC_VER
+#  define align64  __declspec(align(8)) 
+#  define ALLOW_SMP_DANGERS
+#else
+#  define align64
+#endif
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+    typedef struct PaUtilRingBuffer
+    {
+        align64 long   bufferSize; /* Number of bytes in FIFO. Power of 2. Set by PaUtil_InitRingBuffer. */
+        align64 long   writeIndex; /* Index of next writable byte. Set by PaUtil_AdvanceRingBufferWriteIndex. */
+        align64 long   readIndex;  /* Index of next readable byte. Set by PaUtil_AdvanceRingBufferReadIndex. */
+        align64 long   bigMask;    /* Used for wrapping indices with extra bit to distinguish full/empty. */
+        align64 long   smallMask;  /* Used for fitting indices to buffer. */
+        align64 char  *buffer;
+    } PaUtilRingBuffer;
+
+    /** Initialize Ring Buffer.
+
+     @param rbuf The ring buffer.
+
+     @param numBytes The number of bytes in the buffer and must be power of 2.
+
+     @param dataPtr A pointer to a previously allocated area where the data
+     will be maintained.  It must be numBytes long.
+
+     @return -1 if numBytes is not a power of 2, otherwise 0.
+    */
+    long PaUtil_InitializeRingBuffer( PaUtilRingBuffer *rbuf, long numBytes, void *dataPtr );
+
+    /** Clear buffer. Should only be called when buffer is NOT being read.
+
+     @param rbuf The ring buffer.
+    */
+    void PaUtil_FlushRingBuffer( PaUtilRingBuffer *rbuf );
+
+    /** Retrieve the number of bytes available in the ring buffer for writing.
+
+     @param rbuf The ring buffer.
+
+     @return The number of bytes available for writing.
+    */
+    long PaUtil_GetRingBufferWriteAvailable( PaUtilRingBuffer *rbuf );
+
+    /** Retrieve the number of bytes available in the ring buffer for reading.
+
+     @param rbuf The ring buffer.
+
+     @return The number of bytes available for reading.
+    */
+    long PaUtil_GetRingBufferReadAvailable( PaUtilRingBuffer *rbuf );
+
+    /** Write data to the ring buffer.
+
+     @param rbuf The ring buffer.
+
+     @param data The address of new data to write to the buffer.
+
+     @param numBytes The number of bytes to be written.
+
+     @return The number of bytes written.
+    */
+    long PaUtil_WriteRingBuffer( PaUtilRingBuffer *rbuf, const void *data, long numBytes );
+
+    /** Read data from the ring buffer.
+
+     @param rbuf The ring buffer.
+
+     @param data The address where the data should be stored.
+
+     @param numBytes The number of bytes to be read.
+
+     @return The number of bytes read.
+    */
+    long PaUtil_ReadRingBuffer( PaUtilRingBuffer *rbuf, void *data, long numBytes );
+
+    /** Get address of region(s) to which we can write data.
+
+     @param rbuf The ring buffer.
+
+     @param numBytes The number of bytes desired.
+
+     @param dataPtr1 The address where the first (or only) region pointer will be
+     stored.
+
+     @param sizePtr1 The address where the first (or only) region length will be
+     stored.
+
+     @param dataPtr2 The address where the second region pointer will be stored if
+     the first region is too small to satisfy numBytes.
+
+     @param sizePtr2 The address where the second region length will be stored if
+     the first region is too small to satisfy numBytes.
+
+     @return The room available to be written or numBytes, whichever is smaller.
+    */
+    long PaUtil_GetRingBufferWriteRegions( PaUtilRingBuffer *rbuf, long numBytes,
+                                           void **dataPtr1, long *sizePtr1,
+                                           void **dataPtr2, long *sizePtr2 );
+
+    /** Advance the write index to the next location to be written.
+
+     @param rbuf The ring buffer.
+
+     @param numBytes The number of bytes to advance.
+
+     @return The new position.
+    */
+    long PaUtil_AdvanceRingBufferWriteIndex( PaUtilRingBuffer *rbuf, long numBytes );
+
+    /** Get address of region(s) from which we can write data.
+
+     @param rbuf The ring buffer.
+
+     @param numBytes The number of bytes desired.
+
+     @param dataPtr1 The address where the first (or only) region pointer will be
+     stored.
+
+     @param sizePtr1 The address where the first (or only) region length will be
+     stored.
+
+     @param dataPtr2 The address where the second region pointer will be stored if
+     the first region is too small to satisfy numBytes.
+
+     @param sizePtr2 The address where the second region length will be stored if
+     the first region is too small to satisfy numBytes.
+
+     @return The number of bytes available for reading.
+    */
+    long PaUtil_GetRingBufferReadRegions( PaUtilRingBuffer *rbuf, long numBytes,
+                                          void **dataPtr1, long *sizePtr1,
+                                          void **dataPtr2, long *sizePtr2 );
+
+    /** Advance the read index to the next location to be read.
+
+     @param rbuf The ring buffer.
+
+     @param numBytes The number of bytes to advance.
+
+     @return The new position.
+    */
+    long PaUtil_AdvanceRingBufferReadIndex( PaUtilRingBuffer *rbuf, long numBytes );
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* PA_RINGBUFFER_H */
diff --git a/src/sound/qtaudio.cpp b/src/sound/qtaudio.cpp
new file mode 100644
index 0000000..cca9628
--- /dev/null
+++ b/src/sound/qtaudio.cpp
@@ -0,0 +1,452 @@
+/******************************************************************************\
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *  Julian Cable, David Flamand
+ *
+ * Description:
+ *  QT Sound Interface
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "qtaudio.h"
+#include <QThread>
+#include <QAudioInput>
+#include <QAudioOutput>
+#include <QAudioDeviceInfo>
+#include <QAudioFormat>
+
+/* some system might need this for proper sample rate listing */
+#if defined(__linux__) && !defined(__ANDROID__)
+# define QTAUDIO_SAMPLERATE_HACK
+#endif
+
+#define INPUT_BUFFER_LEN_IN_SEC 2
+#define OUTPUT_BUFFER_LEN_IN_SEC 2
+
+
+// TODO do the conversion if the device support mono only
+
+// On linux with pulseaudio, sample rate can range from 1Hz to 192kHz,
+//  but supportedSampleRates() return only standard sample rate (8000 11025 22050 44100 48000).
+// TODO isSampleRateSupported() hack is very ugly
+
+
+/**********************************/
+/* QT Audio Common Implementation */
+
+CSoundCommonQT::CSoundCommonQT(bool bInput) :
+    bInput(bInput), bDevChanged(false),
+    iSampleRate(0), iBufferSize(0), bBlocking(FALSE),
+    iFrameSize(0), pIODevice(NULL)
+{
+}
+
+CSoundCommonQT::~CSoundCommonQT()
+{
+}
+
+void CSoundCommonQT::sleep(int len) const
+{
+    /* 1000000 = number of usec. in sec., 2 = channels */
+    qint64 timeToSleep = (qint64)len * (1000000 / iFrameSize) / iSampleRate;
+    /* timeToSleep is the worst case time, zero is the best case time,
+       so let divide this time by 2 to have a mean between worst and best case time,
+       pros: latency and jitter on input is improved, and output will have less chance to underflow
+       cons: function call increased, increased overhead */
+    timeToSleep /= 2;
+    if (timeToSleep)
+        QThread::usleep((unsigned long)timeToSleep);
+}
+
+bool CSoundCommonQT::isSampleRateSupported(const QAudioDeviceInfo &di, int samplerate) const
+{
+    samplerate = abs(samplerate);
+#ifdef QTAUDIO_SAMPLERATE_HACK
+    (void)di;
+    return samplerate >= 1 && samplerate <= 192000;
+#else
+    return di.supportedSampleRates().contains(samplerate);
+#endif
+}
+
+bool CSoundCommonQT::isDeviceGood(const QAudioDeviceInfo &di, const int *desiredsamplerates) const
+{
+    bool bSampleRateOk = false;
+    for (const int* dsr=desiredsamplerates; *dsr; dsr++)
+    {
+        int samplerate = abs(*dsr);
+        if (isSampleRateSupported(di, samplerate))
+        {
+            bSampleRateOk = true;
+            break;
+        }
+    }
+    return
+        bSampleRateOk &&
+        di.supportedChannelCounts().contains(2) && // TODO
+        di.supportedSampleSizes().contains(16) &&
+        di.supportedSampleTypes().contains(QAudioFormat::SignedInt) &&
+        di.supportedByteOrders().contains(QAudioFormat::LittleEndian) &&
+        di.supportedCodecs().contains("audio/pcm");
+}
+
+void CSoundCommonQT::setSamplerate(deviceprop& dp, const QAudioDeviceInfo &di, const int *desiredsamplerates) const
+{
+    dp.samplerates.clear();
+    for (const int* dsr=desiredsamplerates; *dsr; dsr++)
+    {
+        int samplerate = abs(*dsr);
+        dp.samplerates[samplerate] = isSampleRateSupported(di, samplerate);
+    }
+}
+
+QAudioDeviceInfo CSoundCommonQT::getDevice()
+{
+    QAudioDeviceInfo di;
+    if (sDev == DEFAULT_DEVICE_NAME)
+        di = bInput ? QAudioDeviceInfo::defaultInputDevice() : QAudioDeviceInfo::defaultOutputDevice();
+    else
+    {
+        QAudio::Mode mode = bInput ? QAudio::AudioInput : QAudio::AudioOutput;
+        foreach(const QAudioDeviceInfo& tdi, QAudioDeviceInfo::availableDevices(mode))
+        {
+            string name(tdi.deviceName().toLocal8Bit().constData());
+//            qDebug("CSoundCommonQT::getDevice() %i name=%s", bInput, name.c_str());
+            if (name == sDev)
+            {
+                di = tdi;
+                break;
+            }
+        }
+    }
+    dumpAudioDeviceInfo(di, "CSoundCommonQT::getDevice(): di");
+    dumpAudioFormat(di.preferredFormat(), "CSoundCommonQT::getDevice(): di.preferredFormat()");
+    return di;
+}
+
+QAudioFormat CSoundCommonQT::getFormat()
+{
+    QAudioFormat format;
+    format.setSampleRate(iSampleRate);
+    format.setSampleSize(16);
+    format.setSampleType(QAudioFormat::SignedInt);
+    format.setChannelCount(2); // TODO
+    format.setByteOrder(QAudioFormat::LittleEndian);
+    format.setCodec("audio/pcm");
+    return format;
+}
+
+void CSoundCommonQT::dumpAudioDeviceInfo(QAudioDeviceInfo di, const char* text)
+{
+    string codec;
+    for (int i=0; i<di.supportedCodecs().size(); ++i)
+        codec += string(di.supportedCodecs().at(i).toLocal8Bit().constData()) + " ";
+    string channel; QList<int> channellist = di.supportedChannelCounts();
+    for (QList<int>::iterator i= channellist.begin(); i != channellist.end(); ++i)
+        channel += string(QString::number(*i).toLocal8Bit().constData()) + " ";
+    string samplesize; QList<int> sizelist = di.supportedSampleSizes();
+    for (QList<int>::iterator i= sizelist.begin(); i != sizelist.end(); ++i)
+        samplesize += string(QString::number(*i).toLocal8Bit().constData()) + " ";
+    string samplerate; QList<int> ratelist = di.supportedSampleRates();
+    for (QList<int>::iterator i= ratelist.begin(); i != ratelist.end(); ++i)
+        samplerate += string(QString::number(*i).toLocal8Bit().constData()) + " ";
+    string byteorder; QList<QAudioFormat::Endian> orderlist = di.supportedByteOrders();
+    for (QList<QAudioFormat::Endian>::iterator i= orderlist.begin(); i != orderlist.end(); ++i)
+        switch (*i) {
+        case QAudioFormat::BigEndian:    byteorder += "BigEndian ";    break;
+        case QAudioFormat::LittleEndian: byteorder += "LittleEndian "; break; }
+    string sampletype; QList<QAudioFormat::SampleType> typelist = di.supportedSampleTypes();
+    for (QList<QAudioFormat::SampleType>::iterator i= typelist.begin(); i != typelist.end(); ++i)
+        switch (*i) {
+        case QAudioFormat::Unknown:     sampletype += "Unknown ";     break;
+        case QAudioFormat::SignedInt:   sampletype += "SignedInt ";   break;
+        case QAudioFormat::UnSignedInt: sampletype += "UnSignedInt "; break;
+        case QAudioFormat::Float:       sampletype += "Float ";       break; }
+    qDebug(
+        "%s\n"
+        "  CSoundCommonQT::dumpAudioDeviceInfo():\n"
+        "    input/output = %s\n"
+        "    name = %s\n"
+        "    codec = %s\n"
+        "    channel = %s\n"
+        "    sample size = %s\n"
+        "    sample rate = %s\n"
+        "    byte order = %s\n"
+        "    sample type = %s"
+        , text
+        , bInput ? "input" : "output"
+        , string(di.deviceName().toLocal8Bit().constData()).c_str()
+        , codec.c_str()
+        , channel.c_str()
+        , samplesize.c_str()
+        , samplerate.c_str()
+        , byteorder.c_str()
+        , sampletype.c_str()
+    );
+}
+
+void CSoundCommonQT::dumpAudioFormat(QAudioFormat format, const char* text)
+{
+    string byteorder;
+    switch (format.byteOrder()) {
+    case QAudioFormat::BigEndian:    byteorder += "BigEndian ";    break;
+    case QAudioFormat::LittleEndian: byteorder += "LittleEndian "; break; }
+    string sampletype;
+    switch (format.sampleType()) {
+    case QAudioFormat::Unknown:     sampletype += "Unknown ";     break;
+    case QAudioFormat::SignedInt:   sampletype += "SignedInt ";   break;
+    case QAudioFormat::UnSignedInt: sampletype += "UnSignedInt "; break;
+    case QAudioFormat::Float:       sampletype += "Float ";       break; }
+    qDebug(
+        "%s\n"
+        "  CSoundCommonQT::dumpAudioFormat():\n"
+        "    codec = %s\n"
+        "    channel = %i\n"
+        "    sample size = %i\n"
+        "    sample rate = %i\n"
+        "    byte order = %s\n"
+        "    sample type = %s"
+        , text
+        , string(format.codec().toLocal8Bit().constData()).c_str()
+        , format.channelCount()
+        , format.sampleSize()
+        , format.sampleRate()
+        , byteorder.c_str()
+        , sampletype.c_str()
+    );
+}
+
+void CSoundCommonQT::Enumerate(vector<deviceprop>& devs, const int *desiredsamplerates)
+{
+    devs.clear();
+    deviceprop dp;
+
+    /* Default device */
+    const QAudioDeviceInfo& di(bInput ? QAudioDeviceInfo::defaultInputDevice() : QAudioDeviceInfo::defaultOutputDevice());
+    if (isDeviceGood(di, desiredsamplerates))
+    {
+        dp.name = DEFAULT_DEVICE_NAME;
+        setSamplerate(dp, di, desiredsamplerates);
+        devs.push_back(dp);
+    }
+
+    foreach(const QAudioDeviceInfo& di, QAudioDeviceInfo::availableDevices(bInput ? QAudio::AudioInput : QAudio::AudioOutput))
+    {
+        if (isDeviceGood(di, desiredsamplerates))
+        {
+            string name(di.deviceName().toLocal8Bit().constData());
+//            qDebug("CSoundCommonQT::Enumerate() %i name=%s", bInput, name.c_str());
+            dp.name = name;
+            setSamplerate(dp, di, desiredsamplerates);
+            devs.push_back(dp);
+        }
+    }
+}
+
+string CSoundCommonQT::GetDev()
+{
+    return sDev;
+}
+
+void CSoundCommonQT::SetDev(string sNewDev)
+{
+//    qDebug("CSoundCommonQT::SetDev() name=%s", sNewDev.c_str());
+    if (sDev != sNewDev)
+    {
+        sDev = sNewDev;
+        bDevChanged = true;
+    }
+}
+
+
+/******************************/
+/* QT Audio In Implementation */
+
+CSoundInQT::CSoundInQT() :
+    CSoundCommonQT(true), pAudioInput(NULL)
+{
+}
+
+CSoundInQT::~CSoundInQT()
+{
+    Close();
+}
+
+_BOOLEAN CSoundInQT::Init(int iNewSampleRate, int iNewBufferSize, _BOOLEAN bNewBlocking)
+{
+//    qDebug("CSoundInQT::Init() %i %i %i", iNewSampleRate, iNewBufferSize, bNewBlocking);
+    _BOOLEAN bChanged = FALSE;
+    iBufferSize = iNewBufferSize;
+    bBlocking = bNewBlocking;
+
+    if (iSampleRate != iNewSampleRate)
+    {
+        iSampleRate = iNewSampleRate;
+        Close();
+        bChanged = TRUE;
+    }
+
+    if (bDevChanged || !pAudioInput)
+    {
+        bDevChanged = false;
+        pIODevice = NULL;
+        QAudioDeviceInfo di = getDevice();
+        QAudioFormat format = getFormat();
+        pAudioInput = new QAudioInput(di, format);
+        /* make sure we have the requested format */
+        if (pAudioInput->format() == format)
+        {
+            iFrameSize = pAudioInput->format().channelCount() * pAudioInput->format().sampleSize() / 8;
+            pAudioInput->setBufferSize(iSampleRate * iFrameSize * INPUT_BUFFER_LEN_IN_SEC);
+            QIODevice* pIODevice = pAudioInput->start();
+            if (pAudioInput->error() == QAudio::NoError)
+                this->pIODevice = pIODevice;
+            else
+                qDebug("CSoundInQT::Init() Can't open audio input (error = %i)", (int)pAudioInput->error());
+        }
+        else
+            qDebug("CSoundInQT::Init() Can't open audio input (bad format)");
+    }
+    return bChanged;
+}
+
+_BOOLEAN CSoundInQT::Read(CVector<short>& vecsSoundBuffer)
+{
+    _BOOLEAN bError = TRUE;
+    if (bDevChanged)
+        Init(iSampleRate, iBufferSize, bBlocking);
+    if (pIODevice)
+    {
+        int len = (int)(sizeof(short) * vecsSoundBuffer.Size());
+        for (int pos=0;;) {
+            int ret = (int)pIODevice->read((char*)&vecsSoundBuffer[pos], len);
+            if (ret < 0)
+                break;
+            pos += ret/sizeof(short);
+            len -= ret;
+            if (len <= 0)
+                break;
+            sleep(len);
+        }
+        bError = len != 0;
+    }
+    return bError;
+}
+
+void CSoundInQT::Close()
+{
+//    qDebug("CSoundInQT::Close()");
+    if (pAudioInput)
+    {
+        pAudioInput->stop();
+        delete pAudioInput;
+        pAudioInput = NULL;
+        pIODevice = NULL;
+    }
+
+}
+
+
+/*******************************/
+/* QT Audio Out Implementation */
+
+CSoundOutQT::CSoundOutQT() :
+    CSoundCommonQT(false), pAudioOutput(NULL)
+{
+}
+
+CSoundOutQT::~CSoundOutQT()
+{
+    Close();
+}
+
+_BOOLEAN CSoundOutQT::Init(int iNewSampleRate, int iNewBufferSize, _BOOLEAN bNewBlocking)
+{
+//    qDebug("CSoundOutQT::Init() %i %i %i", iNewSampleRate, iNewBufferSize, bNewBlocking);
+    _BOOLEAN bChanged = FALSE;
+    iBufferSize = iNewBufferSize;
+    bBlocking = bNewBlocking;
+
+    if (iSampleRate != iNewSampleRate)
+    {
+        iSampleRate = iNewSampleRate;
+        Close();
+        bChanged = TRUE;
+    }
+
+    if (bDevChanged || !pAudioOutput)
+    {
+        bDevChanged = false;
+        pIODevice = NULL;
+        QAudioDeviceInfo di = getDevice();
+        QAudioFormat format = getFormat();
+        pAudioOutput = new QAudioOutput(di, format);
+        /* make sure we have the requested format */
+        if (pAudioOutput->format() == format)
+        {
+            iFrameSize = pAudioOutput->format().channelCount() * pAudioOutput->format().sampleSize() / 8;
+            pAudioOutput->setBufferSize(iSampleRate * iFrameSize * OUTPUT_BUFFER_LEN_IN_SEC);
+            QIODevice* pIODevice = pAudioOutput->start();
+            if (pAudioOutput->error() == QAudio::NoError)
+                this->pIODevice = pIODevice;
+            else
+                qDebug("CSoundInQT::Init() Can't open audio output (error = %i)", (int)pAudioOutput->error());
+        }
+        else
+            qDebug("CSoundInQT::Init() Can't open audio output (bad format)");
+    }
+    return bChanged;
+}
+
+_BOOLEAN CSoundOutQT::Write(CVector<short>& vecsSoundBuffer)
+{
+    _BOOLEAN bError = TRUE;
+    if (bDevChanged)
+        Init(iSampleRate, iBufferSize, bBlocking);
+    if (pIODevice)
+    {
+        int len = (int)(sizeof(short) * vecsSoundBuffer.Size());
+        for (int pos=0;;) {
+            int ret = (int)pIODevice->write((char*)&vecsSoundBuffer[pos], len);
+            if (ret < 0)
+                break;
+            pos += ret/sizeof(short);
+            len -= ret;
+            if (len <= 0)
+                break;
+            sleep(len);
+        }
+        bError = len != 0;
+    }
+    return bError;
+}
+
+void CSoundOutQT::Close()
+{
+//    qDebug("CSoundOutQT::Close()");
+    if (pAudioOutput)
+    {
+        pAudioOutput->stop();
+        delete pAudioOutput;
+        pAudioOutput = NULL;
+        pIODevice = NULL;
+    }
+}
+
diff --git a/src/sound/qtaudio.h b/src/sound/qtaudio.h
new file mode 100644
index 0000000..b1e4d21
--- /dev/null
+++ b/src/sound/qtaudio.h
@@ -0,0 +1,98 @@
+/******************************************************************************\
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *  Julian Cable, David Flamand
+ *
+ * Description:
+ *  QT Sound Interface
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#ifndef _QTAUDIO_H
+#define _QTAUDIO_H
+
+#include "soundinterface.h"
+
+class QIODevice;
+class QAudioInput;
+class QAudioOutput;
+class QAudioFormat;
+class QAudioDeviceInfo;
+
+/* Classes ********************************************************************/
+
+class CSoundCommonQT : public CSelectionInterface
+{
+public:
+    CSoundCommonQT(bool bInput);
+    virtual ~CSoundCommonQT();
+    virtual void        Enumerate(vector<deviceprop>&, const int*);
+    virtual string      GetDev();
+    virtual void        SetDev(string);
+protected:
+    void                sleep(int len) const;
+    bool                isSampleRateSupported(const QAudioDeviceInfo &di, int samplerate) const;
+    bool                isDeviceGood(const QAudioDeviceInfo &di, const int *desiredsamplerates) const;
+    void                setSamplerate(deviceprop& dp, const QAudioDeviceInfo &di, const int *desiredsamplerates) const;
+    QAudioDeviceInfo    getDevice();
+    QAudioFormat        getFormat();
+    void                dumpAudioDeviceInfo(QAudioDeviceInfo di, const char* text);
+    void                dumpAudioFormat(QAudioFormat format, const char* text);
+    bool                bInput;
+    string              sDev;
+    bool                bDevChanged;
+    int                 iSampleRate;
+    int                 iBufferSize;
+    _BOOLEAN            bBlocking;
+    int                 iFrameSize;
+    QIODevice*          pIODevice;
+};
+
+class CSoundInQT : public CSoundCommonQT, public CSoundInInterface
+{
+public:
+    CSoundInQT();
+    virtual ~CSoundInQT();
+    virtual void        Enumerate(vector<deviceprop>& dp, const int* dsr) { CSoundCommonQT::Enumerate(dp, dsr); }
+    virtual string      GetDev() { return CSoundCommonQT::GetDev(); }
+    virtual void        SetDev(string s) { CSoundCommonQT::SetDev(s); }
+    virtual _BOOLEAN    Init(int, int, _BOOLEAN);
+    virtual _BOOLEAN    Read(CVector<short>&);
+    virtual void        Close();
+private:
+    QAudioInput*        pAudioInput;
+};
+
+class CSoundOutQT : public CSoundCommonQT, public CSoundOutInterface
+{
+public:
+    CSoundOutQT();
+    virtual ~CSoundOutQT();
+    virtual void        Enumerate(vector<deviceprop>& dp, const int* dsr) { CSoundCommonQT::Enumerate(dp, dsr); }
+    virtual string      GetDev() { return CSoundCommonQT::GetDev(); }
+    virtual void        SetDev(string s) { CSoundCommonQT::SetDev(s); }
+    virtual _BOOLEAN    Init(int, int, _BOOLEAN);
+    virtual _BOOLEAN    Write(CVector<short>&);
+    virtual void        Close();
+private:
+    QAudioOutput*       pAudioOutput;
+};
+
+#endif // _QTAUDIO_H
diff --git a/src/sound/selectioninterface.h b/src/sound/selectioninterface.h
new file mode 100644
index 0000000..80c81fd
--- /dev/null
+++ b/src/sound/selectioninterface.h
@@ -0,0 +1,79 @@
+/******************************************************************************\
+ * British Broadcasting Corporation
+ * Copyright (c) 2001-2014, 2001-2014
+ *
+ * Author(s):
+ *  Julian Cable, David Flamand
+ *
+ * Decription:
+ *  sound interfaces
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#ifndef _SELECTIONINTERFACE_H
+#define _SELECTIONINTERFACE_H
+
+#include "../GlobalDefinitions.h"
+#include <vector>
+#include <map>
+#include <string>
+
+#define DEFAULT_DEVICE_NAME ""
+
+typedef struct {
+    string          name; /* unique name that identify the device */
+    string          desc; /* optional device description, set to empty string when not used */
+    map<int,bool>   samplerates; /* supported sample rates by the device */
+} deviceprop;
+
+// TODO update sound interface backend that use old api, remove old Enumerate(names, descs) and make this class pure virtual
+
+class CSelectionInterface
+{
+public:
+    virtual             ~CSelectionInterface() {}
+    /* new/updated interface should reimplement that one */
+    virtual void        Enumerate(vector<deviceprop>& devs, const int* desiredsamplerates)
+    {
+        vector<string> names;
+        vector<string> descriptions;
+        Enumerate(names, descriptions);
+        deviceprop dp;
+        for (const int* dsr=desiredsamplerates; *dsr; dsr++)
+            dp.samplerates[abs(*dsr)] = true;
+        devs.clear();
+        for (size_t i=0; i<names.size(); i++)
+        {
+            dp.name = names.at(i);
+            dp.desc = i<descriptions.size() ? descriptions.at(i) : "";
+            devs.push_back(dp);
+        }
+    };
+    virtual string      GetDev()=0;
+    virtual void        SetDev(string sNewDev)=0;
+protected:
+    /* for backward compatibility */
+    virtual void        Enumerate(vector<string>& names, vector<string>& descriptions)
+    {
+        (void)names;
+        (void)descriptions;
+    }
+};
+
+#endif
diff --git a/src/sound/sound.h b/src/sound/sound.h
new file mode 100644
index 0000000..eabd729
--- /dev/null
+++ b/src/sound/sound.h
@@ -0,0 +1,86 @@
+/******************************************************************************\
+ * British Broadcasting Corporation
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Julian Cable
+ *
+ * Decription:
+ * sound interface selection
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#ifndef _SOUND_H
+#define _SOUND_H
+
+#if defined(WIN32) && !defined(USE_PORTAUDIO) && !defined(USE_JACK) && !defined(USE_QTAUDIO)
+/* mmsystem sound interface */
+# include "../windows/Sound.h"
+#else
+
+# ifdef USE_OSS
+#  include "../linux/soundin.h"
+#  include "../linux/soundout.h"
+# endif
+
+# ifdef USE_ALSA
+#  include "../linux/soundin.h"
+#  include "../linux/soundout.h"
+# endif
+
+# ifdef USE_JACK
+#  include "../linux/jack.h"
+typedef CSoundInJack CSoundIn;
+typedef CSoundOutJack CSoundOut;
+# endif
+
+# ifdef USE_PULSEAUDIO
+#  include "drm_pulseaudio.h"
+typedef CSoundInPulse CSoundIn;
+typedef CSoundOutPulse CSoundOut;
+# endif
+
+# ifdef USE_PORTAUDIO
+#  include "drm_portaudio.h"
+typedef CPaIn CSoundIn;
+typedef CPaOut CSoundOut;
+# endif
+
+# ifdef USE_OPENSL
+#  include "../android/soundin.h"
+#  include "../android/soundout.h"
+typedef COpenSLESIn CSoundIn;
+typedef COpenSLESOut CSoundOut;
+# endif
+
+# ifdef USE_QTAUDIO
+#  include "qtaudio.h"
+typedef CSoundInQT CSoundIn;
+typedef CSoundOutQT CSoundOut;
+# endif
+
+# if !defined(USE_OSS) && !defined(USE_ALSA) && !defined(USE_JACK) && !defined(USE_PULSEAUDIO) && !defined(USE_PORTAUDIO) && !defined(USE_OPENSL) && !defined(USE_QTAUDIO)
+#  include "soundnull.h"
+typedef CSoundInNull CSoundIn;
+typedef CSoundOutNull CSoundOut;
+# endif
+
+#endif
+
+#endif
diff --git a/src/sound/soundinterface.h b/src/sound/soundinterface.h
new file mode 100644
index 0000000..66ae63a
--- /dev/null
+++ b/src/sound/soundinterface.h
@@ -0,0 +1,58 @@
+/******************************************************************************\
+ * British Broadcasting Corporation
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Julian Cable
+ *
+ * Decription:
+ * sound interfaces
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#ifndef _SOUNDINTERFACE_H
+#define _SOUNDINTERFACE_H
+
+#include "selectioninterface.h"
+#include "../util/Vector.h"
+
+class CSoundInInterface : public CSelectionInterface
+{
+public:
+    virtual 		~CSoundInInterface() {}
+
+    /* sound card interface - used by ReadData */
+    virtual _BOOLEAN Init(int iSampleRate, int iNewBufferSize, _BOOLEAN bNewBlocking)=0;
+    virtual _BOOLEAN Read(CVector<short>& psData)=0;
+    virtual void     Close()=0;
+
+};
+
+class CSoundOutInterface : public CSelectionInterface
+{
+public:
+    virtual 		~CSoundOutInterface() {}
+
+    /* sound card interface - used by WriteData */
+    virtual _BOOLEAN Init(int iSampleRate, int iNewBufferSize, _BOOLEAN bNewBlocking)=0;
+    virtual _BOOLEAN Write(CVector<short>& psData)=0;
+    virtual void     Close()=0;
+};
+
+#endif
diff --git a/src/sound/soundnull.h b/src/sound/soundnull.h
new file mode 100644
index 0000000..d4742e6
--- /dev/null
+++ b/src/sound/soundnull.h
@@ -0,0 +1,85 @@
+/******************************************************************************\
+ * British Broadcasting Corporation
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Julian Cable
+ *
+ * Description:
+ *	dummy sound classes
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#ifndef _SOUNDNULL_H
+#define _SOUNDNULL_H
+
+#include "soundinterface.h"
+
+/* Classes ********************************************************************/
+class CSoundInNull : public CSoundInInterface
+{
+public:
+    CSoundInNull() {}
+    virtual ~CSoundInNull() {}
+    virtual _BOOLEAN	Init(int, int, _BOOLEAN) {
+        return TRUE;
+    }
+    virtual _BOOLEAN	Read(CVector<short>&) {
+        return FALSE;
+    }
+    virtual void		Enumerate(vector<string>&choices, vector<string>&) {
+        choices.push_back("(File or Network)");
+    }
+    virtual string		GetDev() {
+        return sDev;
+    }
+    virtual void		SetDev(string sNewDev) {
+        sDev = sNewDev;
+    }
+    virtual void		Close() {}
+private:
+    string sDev;
+};
+
+class CSoundOutNull : public CSoundOutInterface
+{
+public:
+    CSoundOutNull() {}
+    virtual ~CSoundOutNull() {}
+    virtual _BOOLEAN	Init(int, int, _BOOLEAN) {
+        return TRUE;
+    }
+    virtual _BOOLEAN	Write(CVector<short>&) {
+        return FALSE;
+    }
+    virtual void		Enumerate(vector<string>& choices, vector<string>&) {
+        choices.push_back("(None)");
+    }
+    virtual string		GetDev() {
+        return sDev;
+    }
+    virtual void		SetDev(string sNewDev) {
+        sDev = sNewDev;
+    }
+    virtual void		Close() {}
+private:
+    string sDev;
+};
+
+#endif
diff --git a/src/sourcedecoders/AudioCodec.cpp b/src/sourcedecoders/AudioCodec.cpp
new file mode 100644
index 0000000..dccdef4
--- /dev/null
+++ b/src/sourcedecoders/AudioCodec.cpp
@@ -0,0 +1,91 @@
+/******************************************************************************\
+ *
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *  David Flamand
+ *
+ * Description:
+ *  Audio codec base class
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "AudioCodec.h"
+#include "null_codec.h"
+#include "aac_codec.h"
+#include "opus_codec.h"
+
+vector<CAudioCodec*>
+CAudioCodec::CodecList;
+
+int
+CAudioCodec::RefCount = 0;
+
+void
+CAudioCodec::InitCodecList()
+{
+	if (CodecList.size() == 0)
+	{
+		/* Null codec, MUST be the first */
+		CodecList.push_back(new NullCodec);
+
+		/* AAC */
+		CodecList.push_back(new AacCodec);
+
+		/* Opus */
+		CodecList.push_back(new OpusCodec);
+	}
+	RefCount ++;
+}
+
+void
+CAudioCodec::UnrefCodecList()
+{
+	RefCount --;
+	if (!RefCount)
+	{
+		while (CodecList.size() != 0)
+		{
+			delete CodecList.back();
+			CodecList.pop_back();
+		}
+	}
+}
+
+CAudioCodec*
+CAudioCodec::GetDecoder(CAudioParam::EAudCod eAudioCoding, bool bCanReturnNullPtr)
+{
+	const int size = CodecList.size();
+	for (int i = 1; i < size; i++)
+		if (CodecList[i]->CanDecode(eAudioCoding))
+			return CodecList[i];
+	/* Fallback to null codec */
+    return bCanReturnNullPtr ? NULL : CodecList[0]; // ie the null codec
+}
+
+CAudioCodec*
+CAudioCodec::GetEncoder(CAudioParam::EAudCod eAudioCoding, bool bCanReturnNullPtr)
+{
+	const int size = CodecList.size();
+	for (int i = 1; i < size; i++)
+		if (CodecList[i]->CanEncode(eAudioCoding))
+			return CodecList[i];
+	/* Fallback to null codec */
+    return bCanReturnNullPtr ? NULL : CodecList[0]; // ie the null codec
+}
diff --git a/src/sourcedecoders/AudioCodec.h b/src/sourcedecoders/AudioCodec.h
new file mode 100644
index 0000000..a5b9269
--- /dev/null
+++ b/src/sourcedecoders/AudioCodec.h
@@ -0,0 +1,69 @@
+/******************************************************************************\
+ *
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *  David Flamand
+ *
+ * Description:
+ *  See AudioCodec.cpp
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#ifndef _AUDIOCODEC_H_
+#define _AUDIOCODEC_H_
+
+#include "../GlobalDefinitions.h"
+#include "../Parameter.h"
+#include <string>
+#include <vector>
+
+#define AC_NULL ((CAudioParam::EAudCod)-1)
+
+class CAudioCodec
+{
+public:
+	virtual ~CAudioCodec() {}
+	/* Decoder */
+	enum EDecError { DECODER_ERROR_OK, DECODER_ERROR_CRC, DECODER_ERROR_CORRUPTED, DECODER_ERROR_UNKNOWN };
+	virtual string DecGetVersion() = 0;
+	virtual bool CanDecode(CAudioParam::EAudCod eAudioCoding) = 0;
+	virtual bool DecOpen(CAudioParam& AudioParam, int *iAudioSampleRate, int *iLenDecOutPerChan) = 0;
+	virtual _SAMPLE* Decode(CVector<uint8_t>& vecbyPrepAudioFrame, int *iChannels, EDecError *eDecError) = 0;
+	virtual void DecClose() = 0;
+	virtual void DecUpdate(CAudioParam& AudioParam) = 0;
+	/* Encoder */
+	virtual string EncGetVersion() = 0;
+	virtual bool CanEncode(CAudioParam::EAudCod eAudioCoding) = 0;
+	virtual bool EncOpen(int iSampleRate, int iChannels, unsigned long *lNumSampEncIn, unsigned long *lMaxBytesEncOut) = 0;
+	virtual int Encode(CVector<_SAMPLE>& vecsEncInData, unsigned long lNumSampEncIn, CVector<uint8_t>& vecsEncOutData, unsigned long lMaxBytesEncOut) = 0;
+	virtual void EncClose() = 0;
+	virtual void EncSetBitrate(int iBitRate) = 0;
+	virtual void EncUpdate(CAudioParam& AudioParam) = 0;
+	/* Common */
+	static void InitCodecList();
+	static void UnrefCodecList();
+	static CAudioCodec* GetDecoder(CAudioParam::EAudCod eAudioCoding, bool bCanReturnNullPtr=false);
+	static CAudioCodec* GetEncoder(CAudioParam::EAudCod eAudioCoding, bool bCanReturnNullPtr=false);
+private:
+	static vector<CAudioCodec*> CodecList;
+	static int RefCount;
+};
+
+#endif // _AUDIOCODEC_H_
diff --git a/src/sourcedecoders/AudioSourceDecoder.cpp b/src/sourcedecoders/AudioSourceDecoder.cpp
new file mode 100644
index 0000000..d0d69a0
--- /dev/null
+++ b/src/sourcedecoders/AudioSourceDecoder.cpp
@@ -0,0 +1,1164 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *	Audio source encoder/decoder
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "AudioSourceDecoder.h"
+#include <iostream>
+#include <sstream>
+#include <string>
+#include <algorithm>
+#ifdef _WIN32
+# include <direct.h>
+#else
+# include <sys/stat.h>
+# include <sys/types.h>
+#endif
+
+
+/* Implementation *************************************************************/
+
+CAudioSourceDecoder::CAudioSourceDecoder()
+    :	bWriteToFile(FALSE), TextMessage(FALSE),
+        bUseReverbEffect(TRUE), codec(NULL), pFile(NULL)
+{
+    /* Initialize Audio Codec List */
+    CAudioCodec::InitCodecList();
+
+    /* Needed by fdrmdialog.cpp to report missing codec */
+    bCanDecodeAAC  = CAudioCodec::GetDecoder(CAudioParam::AC_AAC,  true) != NULL;
+    bCanDecodeCELP = CAudioCodec::GetDecoder(CAudioParam::AC_CELP, true) != NULL;
+    bCanDecodeHVXC = CAudioCodec::GetDecoder(CAudioParam::AC_HVXC, true) != NULL;
+    bCanDecodeOPUS = CAudioCodec::GetDecoder(CAudioParam::AC_OPUS, true) != NULL;
+}
+
+CAudioSourceDecoder::~CAudioSourceDecoder()
+{
+    /* Unreference Audio Codec List */
+    CAudioCodec::UnrefCodecList();
+}
+
+string
+CAudioSourceDecoder::AACFileName(CParameter & Parameters)
+{
+    // Store AAC-data in file
+    stringstream ss;
+    ss << "test/aac_";
+
+//    Parameters.Lock(); // TODO CAudioSourceDecoder::InitInternal() already have the lock
+    if (Parameters.
+            Service[Parameters.GetCurSelAudioService()].AudioParam.
+            eAudioSamplRate == CAudioParam::AS_12KHZ)
+    {
+        ss << "12kHz_";
+    }
+    else
+        ss << "24kHz_";
+
+    switch (Parameters.
+            Service[Parameters.GetCurSelAudioService()].
+            AudioParam.eAudioMode)
+    {
+    case CAudioParam::AM_MONO:
+        ss << "mono";
+        break;
+
+    case CAudioParam::AM_P_STEREO:
+        ss << "pstereo";
+        break;
+
+    case CAudioParam::AM_STEREO:
+        ss << "stereo";
+        break;
+    }
+
+    if (Parameters.
+            Service[Parameters.GetCurSelAudioService()].AudioParam.
+            eSBRFlag == CAudioParam::SB_USED)
+    {
+        ss << "_sbr";
+    }
+//    Parameters.Unlock(); // TODO CAudioSourceDecoder::InitInternal() already have the lock
+    ss << ".dat";
+
+    return ss.str();
+}
+
+string
+CAudioSourceDecoder::CELPFileName(CParameter & Parameters)
+{
+    stringstream ss;
+    ss << "test/celp_";
+//    Parameters.Lock(); // TODO CAudioSourceDecoder::InitInternal() already have the lock
+    if (Parameters.Service[Parameters.GetCurSelAudioService()].
+            AudioParam.eAudioSamplRate == CAudioParam::AS_8_KHZ)
+    {
+        ss << "8kHz_" << 
+            iTableCELP8kHzUEPParams
+                 [Parameters.
+                  Service[Parameters.GetCurSelAudioService()].
+                  AudioParam.iCELPIndex][0];
+    }
+    else
+    {
+        ss << "16kHz_" <<
+            iTableCELP16kHzUEPParams
+                 [Parameters.
+                  Service[Parameters.GetCurSelAudioService()].
+                  AudioParam.iCELPIndex][0];
+    }
+    ss << "bps";
+
+    if (Parameters.Service[Parameters.GetCurSelAudioService()].
+            AudioParam.eSBRFlag == CAudioParam::SB_USED)
+    {
+        ss << "_sbr";
+    }
+//    Parameters.Unlock(); // TODO CAudioSourceDecoder::InitInternal() already have the lock
+    ss << ".dat";
+
+    return ss.str();
+}
+
+string
+CAudioSourceDecoder::HVXCFileName(CParameter & Parameters)
+{
+    stringstream ss;
+    ss << "test/hvxc_";
+//    Parameters.Lock(); // TODO CAudioSourceDecoder::InitInternal() already have the lock
+    if (Parameters.Service[Parameters.GetCurSelAudioService()].
+            AudioParam.eAudioSamplRate == CAudioParam::AS_8_KHZ)
+    {
+        ss << "8kHz";
+    }
+    else
+    {
+        ss << "unknown";
+    }
+
+    if (Parameters.Service[Parameters.GetCurSelAudioService()].
+            AudioParam.eHVXCRate == CAudioParam::HR_2_KBIT)
+    {
+        ss << "_2kbps";
+    }
+    else if (Parameters.Service[Parameters.GetCurSelAudioService()].
+             AudioParam.eHVXCRate == CAudioParam::HR_4_KBIT)
+    {
+        ss << "_4kbps";
+    }
+    else
+    {
+        ss << "_unknown";
+    }
+
+    if (Parameters.Service[Parameters.GetCurSelAudioService()].
+            AudioParam.bHVXCCRC)
+    {
+        ss << "_crc";
+    }
+
+    if (Parameters.Service[Parameters.GetCurSelAudioService()].
+            AudioParam.eSBRFlag == CAudioParam::SB_USED)
+    {
+        ss << "_sbr";
+    }
+//    Parameters.Unlock(); // TODO CAudioSourceDecoder::InitInternal() already have the lock
+    ss << ".dat";
+
+    return ss.str();
+}
+
+void
+CAudioSourceDecoder::ProcessDataInternal(CParameter & Parameters)
+{
+    int i, j;
+    _BOOLEAN bCurBlockOK;
+    _BOOLEAN bCurBlockFaulty;
+    _BOOLEAN bGoodValues;
+
+    int iDecChannels;
+    CAudioCodec::EDecError eDecError;
+    short *psDecOutSampleBuf;
+
+    bGoodValues = FALSE;
+
+    Parameters.Lock();
+    Parameters.vecbiAudioFrameStatus.Init(0);
+    Parameters.vecbiAudioFrameStatus.ResetBitAccess();
+    Parameters.Unlock();
+
+    /* Check if something went wrong in the initialization routine */
+    if (DoNotProcessData == TRUE)
+    {
+        return;
+    }
+
+    /* Text Message ********************************************************** */
+    /* Total frame size depends on whether text message is used or not */
+    if (bTextMessageUsed == TRUE)
+    {
+        /* Decode last for bytes of input block for text message */
+        for (i = 0; i < SIZEOF__BYTE * NUM_BYTES_TEXT_MESS_IN_AUD_STR; i++)
+            vecbiTextMessBuf[i] = (*pvecInputData)[iTotalFrameSize + i];
+
+        TextMessage.Decode(vecbiTextMessBuf);
+    }
+
+    /* Audio data header parsing ********************************************* */
+    /* Check if audio shall not be decoded */
+    if (DoNotProcessAudDecoder == TRUE)
+    {
+        return;
+    }
+
+    /* Reset bit extraction access */
+    (*pvecInputData).ResetBitAccess();
+
+    vector< vector<uint8_t> > audio_frame(iNumAudioFrames);
+    vector<uint8_t> aac_crc_bits(iNumAudioFrames);
+
+    /* Check which audio coding type is used */
+    if (eAudioCoding == CAudioParam::AC_AAC || eAudioCoding == CAudioParam::AC_OPUS)
+    {
+        /* AAC super-frame-header ------------------------------------------- */
+        bGoodValues = TRUE;
+        size_t iPrevBorder = 0;
+
+        for (i = 0; i < iNumBorders; i++)
+        {
+            /* Frame border in bytes (12 bits) */
+            size_t iFrameBorder = (*pvecInputData).Separate(12);
+
+            /* The length is difference between borders */
+            if(iFrameBorder>=iPrevBorder)
+            {
+                int size = iFrameBorder - iPrevBorder;
+                if (size < iNumHigherProtectedBytes)
+                    size = iNumHigherProtectedBytes;
+                else if (size > iMaxLenOneAudFrame)
+                    size = iMaxLenOneAudFrame;
+                audio_frame[i].resize(size);
+            }
+            else
+                bGoodValues = FALSE;
+            iPrevBorder = iFrameBorder;
+        }
+
+        /* Byte-alignment (4 bits) in case of odd number of borders */
+        if (iNumBorders & 1)
+            (*pvecInputData).Separate(4);
+
+        /* Frame length of last frame */
+        if (iNumBorders != iNumAudioFrames)
+        {
+            if(iAudioPayloadLen>=int(iPrevBorder))
+            {
+                int size = iAudioPayloadLen - iPrevBorder;
+                if (size < iNumHigherProtectedBytes)
+                    size = iNumHigherProtectedBytes;
+                else if (size > iMaxLenOneAudFrame)
+                    size = iMaxLenOneAudFrame;
+                audio_frame[iNumBorders].resize(size);
+            }
+            else
+                bGoodValues = FALSE;
+        }
+
+        /* Check if frame length entries represent possible values */
+/*      // check not needed anymore, the size is checked above     //
+        for (i = 0; i < iNumAudioFrames; i++)
+        {
+            if(int(audio_frame[i].size()) > iMaxLenOneAudFrame)
+            {
+                bGoodValues = FALSE;
+            }
+        }
+*/
+        if (bGoodValues == TRUE)
+        {
+            /* Higher-protected part */
+            for (i = 0; i < iNumAudioFrames; i++)
+            {
+                /* Extract higher protected part bytes (8 bits per byte) */
+                for (j = 0; j < iNumHigherProtectedBytes; j++)
+                    audio_frame[i][j] = _BINARY((*pvecInputData).Separate(8));
+
+                /* Extract CRC bits (8 bits) */
+                aac_crc_bits[i] = _BINARY((*pvecInputData).Separate(8));
+            }
+
+            /* Lower-protected part */
+            for (i = 0; i < iNumAudioFrames; i++)
+            {
+                /* First calculate frame length, derived from higher protected
+                   part frame length and total size */
+                const int iNumLowerProtectedBytes =
+                    audio_frame[i].size() - iNumHigherProtectedBytes;
+
+                /* Extract lower protected part bytes (8 bits per byte) */
+                for (j = 0; j < iNumLowerProtectedBytes; j++)
+                {
+                    audio_frame[i][iNumHigherProtectedBytes + j] =
+                        _BINARY((*pvecInputData).Separate(8));
+                }
+            }
+        }
+    }
+    else if (eAudioCoding == CAudioParam::AC_CELP)
+    {
+        /* celp_super_frame(celp_table_ind) --------------------------------- */
+        /* Higher-protected part */
+        for (i = 0; i < iNumAudioFrames; i++)
+        {
+            celp_frame[i].ResetBitAccess();
+
+            /* Extract higher protected part bits */
+            for (j = 0; j < iNumHigherProtectedBits; j++)
+                celp_frame[i].Enqueue((*pvecInputData).Separate(1), 1);
+
+            /* Extract CRC bits (8 bits) if used */
+            if (bCELPCRC == TRUE)
+                celp_crc_bits[i] = _BINARY((*pvecInputData).Separate(8));
+        }
+
+        /* Lower-protected part */
+        for (i = 0; i < iNumAudioFrames; i++)
+        {
+            for (j = 0; j < iNumLowerProtectedBits; j++)
+                celp_frame[i].Enqueue((*pvecInputData).Separate(1), 1);
+        }
+    }
+    else if (eAudioCoding == CAudioParam::AC_HVXC)
+    {
+        for (i = 0; i < iNumAudioFrames; i++)
+        {
+            hvxc_frame[i].ResetBitAccess();
+
+            for (j = 0; j < iNumHvxcBits; j++)
+                hvxc_frame[i].Enqueue((*pvecInputData).Separate(1), 1);
+        }
+    }
+
+
+    /* Audio decoding ******************************************************** */
+    /* Init output block size to zero, this variable is also used for
+       determining the position for writing the output vector */
+    iOutputBlockSize = 0;
+    _BOOLEAN bCodecUpdated = FALSE;
+
+    for (j = 0; j < iNumAudioFrames; j++)
+    {
+        bCurBlockFaulty = FALSE;
+        if (eAudioCoding == CAudioParam::AC_AAC || eAudioCoding == CAudioParam::AC_OPUS)
+        {
+            if (bGoodValues == TRUE)
+            {
+                /* Prepare data vector with CRC at the beginning (the definition
+                   with faad2 DRM interface) */
+                CVector<uint8_t> vecbyPrepAudioFrame(audio_frame[j].size()+1);
+                vecbyPrepAudioFrame[0] = aac_crc_bits[j];
+
+                for (i = 0; i < int(audio_frame[j].size()); i++)
+                    vecbyPrepAudioFrame[i + 1] = audio_frame[j][i];
+
+                if (bWriteToFile && pFile!=NULL)
+                {
+                    int iNewFrL = audio_frame[j].size() + 1;
+                    fwrite((void *) &iNewFrL, size_t(4), size_t(1), pFile);	// frame length
+                    fwrite((void *) &vecbyPrepAudioFrame[0], size_t(1), size_t(iNewFrL), pFile);	// data
+                    fflush(pFile);
+                }
+
+                /* The actual decoding */
+                psDecOutSampleBuf = codec->Decode(vecbyPrepAudioFrame, &iDecChannels, &eDecError);
+
+                /* Call decoder update */
+                if (!bCodecUpdated)
+                {
+                    bCodecUpdated = TRUE;
+                    Parameters.Lock();
+                    int iCurSelAudioServ = Parameters.GetCurSelAudioService();
+                    codec->DecUpdate(Parameters.Service[iCurSelAudioServ].AudioParam);
+                    Parameters.Unlock();
+                }
+
+                /* OPH: add frame status to vector for RSCI */
+                Parameters.Lock();
+                Parameters.vecbiAudioFrameStatus.Add(eDecError == CAudioCodec::DECODER_ERROR_OK ? 0 : 1);
+                Parameters.Unlock();
+                if (!(eAudioCoding == CAudioParam::AC_OPUS && eDecError == CAudioCodec::DECODER_ERROR_CRC && bUseReverbEffect == FALSE) && eDecError != CAudioCodec::DECODER_ERROR_OK)
+                {
+                    //cerr << "AAC decode error" << endl;
+                    bCurBlockOK = FALSE;	/* Set error flag */
+                }
+                else
+                {
+                    bCurBlockOK = TRUE;
+                    /* Opus can have FEC embeded, thus the audio frame is always OK */
+                    if (eAudioCoding == CAudioParam::AC_OPUS && eDecError != CAudioCodec::DECODER_ERROR_OK)
+                        bCurBlockFaulty = TRUE;
+
+                    if(psDecOutSampleBuf) // might be dummy decoder
+                    {
+                        /* Conversion from _SAMPLE vector to _REAL vector for
+                           resampling. ATTENTION: We use a vector which was
+                           allocated inside the decoder! */
+                        if (iDecChannels == 1)
+                        {
+                            /* Change type of data (short -> real) */
+                            for (i = 0; i < iLenDecOutPerChan; i++)
+                                vecTempResBufInLeft[i] = psDecOutSampleBuf[i];
+
+                            /* Resample data */
+                            ResampleObjL.Resample(vecTempResBufInLeft,
+                                                  vecTempResBufOutCurLeft);
+
+                            /* Mono (write the same audio material in both
+                               channels) */
+                            for (i = 0; i < iResOutBlockSize; i++)
+                            {
+                                vecTempResBufOutCurRight[i] =
+                                    vecTempResBufOutCurLeft[i];
+                            }
+                        }
+                        else
+                        {
+                            /* Stereo */
+                            for (i = 0; i < iLenDecOutPerChan; i++)
+                            {
+                                vecTempResBufInLeft[i] = psDecOutSampleBuf[i * 2];
+                                vecTempResBufInRight[i] =
+                                    psDecOutSampleBuf[i * 2 + 1];
+                            }
+
+                            /* Resample data */
+                            ResampleObjL.Resample(vecTempResBufInLeft,
+                                                  vecTempResBufOutCurLeft);
+                            ResampleObjR.Resample(vecTempResBufInRight,
+                                                  vecTempResBufOutCurRight);
+                        }
+                    }
+                }
+            }
+            else
+            {
+                /* DRM AAC header was wrong, set flag to "bad block" */
+                bCurBlockOK = FALSE;
+                /* OPH: update audio status vector for RSCI */
+                Parameters.Lock();
+                Parameters.vecbiAudioFrameStatus.Add(1);
+                Parameters.Unlock();
+            }
+        }
+        else if (eAudioCoding == CAudioParam::AC_CELP)
+        {
+            if (bCELPCRC == TRUE)
+            {
+                /* Prepare CRC object and data stream */
+                CELPCRCObject.Reset(8);
+                celp_frame[j].ResetBitAccess();
+
+                for (i = 0; i < iNumHigherProtectedBits; i++)
+                    CELPCRCObject.AddBit((_BINARY) celp_frame[j].Separate(1));
+
+                bCurBlockOK = CELPCRCObject.CheckCRC(celp_crc_bits[j]);
+            }
+            else
+                bCurBlockOK = TRUE;
+
+            /* OPH: update audio status vector for RSCI */
+            Parameters.Lock();
+            Parameters.vecbiAudioFrameStatus.Add(bCurBlockOK == TRUE ? 0 : 1);
+            Parameters.Unlock();
+
+            int iTotNumBits =
+                iNumHigherProtectedBits + iNumLowerProtectedBits;
+            if (bWriteToFile && pFile!=NULL)
+            {
+                int iNewFrL = (iTotNumBits + 7) / 8; //(int) Ceil((CReal) iTotNumBits / 8);
+                fwrite((void *) &iNewFrL, size_t(4), size_t(1), pFile);	// frame length
+                celp_frame[j].ResetBitAccess();
+                for (i = 0; i < iNewFrL; i++)
+                {
+                    int iNumBits = Min(iTotNumBits - i * 8, 8);
+                    _BYTE bCurVal = (_BYTE) celp_frame[j].Separate(iNumBits);
+                    fwrite((void *) &bCurVal, size_t(1), size_t(1), pFile);	// data
+                }
+                fflush(pFile);
+            }
+
+#ifdef USE_CELP_DECODER
+
+            /* Write zeros in current output buffer since we do not have a decoder */
+            for (i = 0; i < iResOutBlockSize; i++)
+            {
+                vecTempResBufOutCurLeft[i] = (_REAL) 0.0;
+                vecTempResBufOutCurRight[i] = (_REAL) 0.0;
+            }
+
+#endif
+
+        }
+        else if (eAudioCoding == CAudioParam::AC_HVXC)
+        {
+
+            bCurBlockOK = TRUE; /* CRC always ignored */
+
+            if (bWriteToFile && pFile!=NULL)
+            {
+                int iNewFrL = (iNumHvxcBits + 7) / 8; //(int) Ceil((CReal) iNumHvxcBits / 8);
+                fwrite((void *) &iNewFrL, size_t(4), size_t(1), pFile);	// frame length
+                hvxc_frame[j].ResetBitAccess();
+                for (i = 0; i < iNewFrL; i++)
+                {
+                    int iNumBits = Min(iNumHvxcBits - i * 8, 8);
+                    _BYTE bCurVal = (_BYTE) hvxc_frame[j].Separate(iNumBits);
+                    fwrite((void *) &bCurVal, size_t(1), size_t(1), pFile);	// data
+                }
+                fflush(pFile);
+            }
+
+#ifdef USE_HVXC_DECODER
+
+            /* Write zeros in current output buffer since we do not have a decoder */
+            for (i = 0; i < iResOutBlockSize; i++)
+            {
+                vecTempResBufOutCurLeft[i] = (_REAL) 0.0;
+                vecTempResBufOutCurRight[i] = (_REAL) 0.0;
+            }
+
+#endif
+
+        }
+        else
+            bCurBlockOK = FALSE;
+
+// This code is independent of particular audio source type and should work
+// fine with CELP and HVXC
+
+        /* Postprocessing of audio blocks, status informations -------------- */
+		ETypeRxStatus status = DATA_ERROR;
+        if (bCurBlockOK == FALSE)
+        {
+            if (bAudioWasOK == TRUE)
+            {
+                /* Post message to show that CRC was wrong (yellow light) */
+				status = DATA_ERROR;
+
+                /* Fade-out old block to avoid "clicks" in audio. We use linear
+                   fading which gives a log-fading impression */
+                for (i = 0; i < iResOutBlockSize; i++)
+                {
+                    /* Linear attenuation with time of OLD buffer */
+                    const _REAL rAtt =
+                        (_REAL) 1.0 - (_REAL) i / iResOutBlockSize;
+
+                    vecTempResBufOutOldLeft[i] *= rAtt;
+                    vecTempResBufOutOldRight[i] *= rAtt;
+
+                    if (bUseReverbEffect == TRUE)
+                    {
+                        /* Fade in input signal for reverberation to avoid
+                           clicks */
+                        const _REAL rAttRev = (_REAL) i / iResOutBlockSize;
+
+                        /* Cross-fade reverberation effect */
+                        const _REAL rRevSam = (1.0 - rAtt) * AudioRev.
+                                              ProcessSample(vecTempResBufOutOldLeft[i] *
+                                                            rAttRev,
+                                                            vecTempResBufOutOldRight[i] *
+                                                            rAttRev);
+
+                        /* Mono reverbration signal */
+                        vecTempResBufOutOldLeft[i] += rRevSam;
+                        vecTempResBufOutOldRight[i] += rRevSam;
+                    }
+                }
+
+                /* Set flag to show that audio block was bad */
+                bAudioWasOK = FALSE;
+            }
+            else
+            {
+				status = CRC_ERROR;
+
+                if (bUseReverbEffect == TRUE)
+                {
+                    /* Add Reverberation effect */
+                    for (i = 0; i < iResOutBlockSize; i++)
+                    {
+                        /* Mono reverberation signal */
+                        vecTempResBufOutOldLeft[i] =
+                            vecTempResBufOutOldRight[i] = AudioRev.
+                                                          ProcessSample(0, 0);
+                    }
+                }
+            }
+
+            /* Write zeros in current output buffer */
+            for (i = 0; i < iResOutBlockSize; i++)
+            {
+                vecTempResBufOutCurLeft[i] = (_REAL) 0.0;
+                vecTempResBufOutCurRight[i] = (_REAL) 0.0;
+            }
+        }
+        else
+        {
+            /* Increment correctly decoded audio blocks counter */
+			if (bCurBlockFaulty) {
+				status = DATA_ERROR;
+			}
+			else {
+                iNumCorDecAudio++;
+				status = RX_OK;
+			}
+
+
+            if (bAudioWasOK == FALSE)
+            {
+                if (bUseReverbEffect == TRUE)
+                {
+                    /* Add "last" reverbration only to old block */
+                    for (i = 0; i < iResOutBlockSize; i++)
+                    {
+                        /* Mono reverberation signal */
+                        vecTempResBufOutOldLeft[i] =
+                            vecTempResBufOutOldRight[i] = AudioRev.
+                                                          ProcessSample(vecTempResBufOutOldLeft[i],
+                                                                  vecTempResBufOutOldRight[i]);
+                    }
+                }
+
+                /* Fade-in new block to avoid "clicks" in audio. We use linear
+                   fading which gives a log-fading impression */
+                for (i = 0; i < iResOutBlockSize; i++)
+                {
+                    /* Linear attenuation with time */
+                    const _REAL rAtt = (_REAL) i / iResOutBlockSize;
+
+                    vecTempResBufOutCurLeft[i] *= rAtt;
+                    vecTempResBufOutCurRight[i] *= rAtt;
+
+                    if (bUseReverbEffect == TRUE)
+                    {
+                        /* Cross-fade reverberation effect */
+                        const _REAL rRevSam = (1.0 - rAtt) * AudioRev.
+                                              ProcessSample(0, 0);
+
+                        /* Mono reverberation signal */
+                        vecTempResBufOutCurLeft[i] += rRevSam;
+                        vecTempResBufOutCurRight[i] += rRevSam;
+                    }
+                }
+
+                /* Reset flag */
+                bAudioWasOK = TRUE;
+            }
+        }
+        Parameters.Lock();
+        Parameters.ReceiveStatus.SLAudio.SetStatus(status);
+        Parameters.ReceiveStatus.LLAudio.SetStatus(status);
+		Parameters.AudioComponentStatus[Parameters.GetCurSelAudioService()].SetStatus(status);
+        Parameters.Unlock();
+
+        /* Conversion from _REAL to _SAMPLE with special function */
+        for (i = 0; i < iResOutBlockSize; i++)
+        {
+            (*pvecOutputData)[iOutputBlockSize + i * 2] = Real2Sample(vecTempResBufOutOldLeft[i]);	/* Left channel */
+            (*pvecOutputData)[iOutputBlockSize + i * 2 + 1] = Real2Sample(vecTempResBufOutOldRight[i]);	/* Right channel */
+        }
+
+        /* Add new block to output block size ("* 2" for stereo output block) */
+        iOutputBlockSize += iResOutBlockSize * 2;
+
+        /* Store current audio block */
+        for (i = 0; i < iResOutBlockSize; i++)
+        {
+            vecTempResBufOutOldLeft[i] = vecTempResBufOutCurLeft[i];
+            vecTempResBufOutOldRight[i] = vecTempResBufOutCurRight[i];
+        }
+    }
+}
+
+void
+CAudioSourceDecoder::InitInternal(CParameter & Parameters)
+{
+    /* Close previous decoder instance if any */
+    CloseDecoder();
+
+    /*
+    	Since we use the exception mechanism in this init routine, the sequence of
+    	the individual initializations is very important!
+    	Requirement for text message is "stream is used" and "audio service".
+    	Requirement for AAC decoding are the requirements above plus "audio coding
+    	is AAC"
+    */
+    int iCurAudioStreamID;
+    int iMaxLenResamplerOutput;
+    int iCurSelServ;
+    int iAudioSampleRate;
+
+    /* Init error flags and output block size parameter. The output block
+       size is set in the processing routine. We must set it here in case
+       of an error in the initialization, this part in the processing
+       routine is not being called */
+    DoNotProcessAudDecoder = FALSE;
+    DoNotProcessData = FALSE;
+    iOutputBlockSize = 0;
+
+    /* Set audiodecoder to empty string - means "unknown" and "can't decode" to GUI */
+    audiodecoder = "";
+
+    try
+    {
+        Parameters.Lock();
+
+        /* Init counter for correctly decoded audio blocks */
+        iNumCorDecAudio = 0;
+
+        /* Init "audio was ok" flag */
+        bAudioWasOK = TRUE;
+
+        /* Get number of total input bits for this module */
+        iInputBlockSize = Parameters.iNumAudioDecoderBits;
+
+        /* Get current selected audio service */
+        iCurSelServ = Parameters.GetCurSelAudioService();
+
+        /* Get current selected audio param */
+        CAudioParam& AudioParam(Parameters.Service[iCurSelServ].AudioParam);
+
+        /* Get current audio coding */
+        eAudioCoding = AudioParam.eAudioCoding;
+
+        /* Current audio stream ID */
+        iCurAudioStreamID = AudioParam.iStreamID;
+
+        /* The requirement for this module is that the stream is used and the
+           service is an audio service. Check it here */
+        if ((Parameters.Service[iCurSelServ].eAudDataFlag != CService::SF_AUDIO) ||
+                (iCurAudioStreamID == STREAM_ID_NOT_USED))
+        {
+            throw CInitErr(ET_ALL);
+        }
+
+        /* Init text message application ------------------------------------ */
+        switch (AudioParam.bTextflag)
+        {
+        case TRUE:
+            bTextMessageUsed = TRUE;
+
+            /* Get a pointer to the string */
+            TextMessage.Init(&AudioParam.strTextMessage);
+
+            /* Total frame size is input block size minus the bytes for the text
+               message */
+            iTotalFrameSize = iInputBlockSize -
+                              SIZEOF__BYTE * NUM_BYTES_TEXT_MESS_IN_AUD_STR;
+
+            /* Init vector for text message bytes */
+            vecbiTextMessBuf.Init(SIZEOF__BYTE *
+                                  NUM_BYTES_TEXT_MESS_IN_AUD_STR);
+            break;
+
+        case FALSE:
+            bTextMessageUsed = FALSE;
+
+            /* All bytes are used for AAC data, no text message present */
+            iTotalFrameSize = iInputBlockSize;
+            break;
+        }
+
+        /* Get decoder instance */
+        codec = CAudioCodec::GetDecoder(eAudioCoding);
+
+        if (codec->CanDecode(eAudioCoding))
+            audiodecoder = codec->DecGetVersion();
+
+        if (eAudioCoding == CAudioParam::AC_AAC)
+        {
+            /* Init for AAC decoding ---------------------------------------- */
+            int iNumHeaderBytes;
+
+            /* Length of higher protected part of audio stream */
+            const int iLenAudHigh =
+                Parameters.Stream[iCurAudioStreamID].iLenPartA;
+
+            /* Set number of AAC frames in a AAC super-frame */
+            switch (AudioParam.eAudioSamplRate)	/* Only 12 kHz and 24 kHz is allowed */
+            {
+            case CAudioParam::AS_12KHZ:
+                iNumAudioFrames = 5;
+                iNumHeaderBytes = 6;
+                break;
+
+            case CAudioParam::AS_24KHZ:
+                iNumAudioFrames = 10;
+                iNumHeaderBytes = 14;
+                break;
+
+            default:
+                /* Some error occurred, throw error */
+                throw CInitErr(ET_AUDDECODER);
+                break;
+            }
+
+            /* Number of borders */
+            iNumBorders = iNumAudioFrames - 1;
+
+            /* The audio_payload_length is derived from the length of the audio
+               super frame (data_length_of_part_A + data_length_of_part_B)
+               subtracting the audio super frame overhead (bytes used for the
+               audio super frame header() and for the aac_crc_bits)
+               (5.3.1.1, Table 5) */
+            iAudioPayloadLen = iTotalFrameSize / SIZEOF__BYTE -
+                               iNumHeaderBytes - iNumAudioFrames;
+
+            /* Check iAudioPayloadLen value, only positive values make sense */
+            if (iAudioPayloadLen < 0)
+                throw CInitErr(ET_AUDDECODER);
+
+            /* Calculate number of bytes for higher protected blocks */
+            iNumHigherProtectedBytes = (iLenAudHigh - iNumHeaderBytes -
+                                        iNumAudioFrames /* CRC bytes */ ) /
+                                        iNumAudioFrames;
+
+            if (iNumHigherProtectedBytes < 0)
+                iNumHigherProtectedBytes = 0;
+
+            /* The maximum length for one audio frame is "iAudioPayloadLen". The
+               regular size will be much shorter since all audio frames share
+               the total size, but we do not know at this time how the data is
+               split in the transmitter source coder */
+            iMaxLenOneAudFrame = iAudioPayloadLen;
+
+            /* Init AAC decoder */
+			codec->DecOpen(AudioParam, &iAudioSampleRate, &iLenDecOutPerChan);
+
+            if(bWriteToFile)
+            {
+                string fn = AACFileName(Parameters);
+                if(pFile)
+                    fclose(pFile);
+                pFile = fopen(fn.c_str(), "wb");
+            }
+        }
+        else if (eAudioCoding == CAudioParam::AC_CELP)
+        {
+            /* Init for CELP decoding --------------------------------------- */
+            int iCurCelpIdx, iCelpFrameLength;
+
+            /* Set number of frames in a super-frame */
+            switch (AudioParam.eAudioSamplRate)	/* Only 8000 and 16000 is allowed */
+            {
+            case CAudioParam::AS_8_KHZ:
+                /* Check range */
+                iCurCelpIdx = AudioParam.iCELPIndex;
+
+                if ((iCurCelpIdx > 0) &&
+                        (iCurCelpIdx < LEN_CELP_8KHZ_UEP_PARAMS_TAB))
+                {
+                    /* CELP frame length */
+                    iCelpFrameLength =
+                        iTableCELP8kHzUEPParams[iCurCelpIdx][1];
+
+                    /* Number of bits for lower and higher protected parts */
+                    iNumHigherProtectedBits =
+                        iTableCELP8kHzUEPParams[iCurCelpIdx][2];
+                    iNumLowerProtectedBits =
+                        iTableCELP8kHzUEPParams[iCurCelpIdx][3];
+                }
+                else
+                    throw CInitErr(ET_AUDDECODER);
+
+                /* Set audio sample rate */
+                iAudioSampleRate = 8000;
+                break;
+
+            case CAudioParam::AS_16KHZ:
+                /* Check range */
+                iCurCelpIdx = AudioParam.iCELPIndex;
+
+                if ((iCurCelpIdx > 0) &&
+                        (iCurCelpIdx < LEN_CELP_16KHZ_UEP_PARAMS_TAB))
+                {
+                    /* CELP frame length */
+                    iCelpFrameLength =
+                        iTableCELP16kHzUEPParams[iCurCelpIdx][1];
+
+                    /* Number of bits for lower and higher protected parts */
+                    iNumHigherProtectedBits =
+                        iTableCELP16kHzUEPParams[iCurCelpIdx][2];
+                    iNumLowerProtectedBits =
+                        iTableCELP16kHzUEPParams[iCurCelpIdx][3];
+                }
+                else
+                    throw CInitErr(ET_AUDDECODER);
+
+                /* Set audio sample rate */
+                iAudioSampleRate = 16000;
+                break;
+
+            default:
+                /* Some error occurred, throw error */
+                throw CInitErr(ET_AUDDECODER);
+                break;
+            }
+
+            /* Check lengths of iNumHigherProtectedBits and
+               iNumLowerProtectedBits for overrun */
+            const int iTotalNumCELPBits =
+                iNumHigherProtectedBits + iNumLowerProtectedBits;
+
+            if (iTotalNumCELPBits * SIZEOF__BYTE > iTotalFrameSize)
+                throw CInitErr(ET_AUDDECODER);
+
+            /* Calculate number of audio frames (one audio super frame is
+               always 400 ms long) */
+            iNumAudioFrames = 400 /* ms */  / iCelpFrameLength /* ms */ ;
+
+            /* Set CELP CRC flag */
+            bCELPCRC = AudioParam.bCELPCRC;
+
+            /* Init vectors storing the CELP raw data and CRCs */
+            celp_frame.Init(iNumAudioFrames, iTotalNumCELPBits);
+            celp_crc_bits.Init(iNumAudioFrames);
+
+// TEST
+            iLenDecOutPerChan = 0;
+
+
+#ifdef USE_CELP_DECODER
+
+// TODO put decoder initialization here
+            bWriteToFile = TRUE;
+            if(bWriteToFile)
+            {
+                string fn = CELPFileName(Parameters);
+                if(pFile)
+                    fclose(pFile);
+                pFile = fopen(fn.c_str(), "wb");
+            }
+
+#else
+            /* No CELP decoder available */
+            throw CInitErr(ET_AUDDECODER);
+#endif
+        }
+        else if (eAudioCoding == CAudioParam::AC_HVXC)
+        {
+            /* Init for HVXC decoding --------------------------------------- */
+
+			iAudioSampleRate = 8000;
+            iNumAudioFrames = 400 / 20;
+
+            iLenDecOutPerChan = 0;
+
+            iNumHvxcBits = 0;
+            if (AudioParam.eHVXCRate == CAudioParam::HR_2_KBIT)
+            {
+                iNumHvxcBits = 40;
+                if (AudioParam.bHVXCCRC)
+                {
+                    iNumHvxcBits += 8;
+                }
+            }
+            else if (AudioParam.eHVXCRate == CAudioParam::HR_4_KBIT)
+            {
+                iNumHvxcBits = 80;
+                if (AudioParam.bHVXCCRC)
+                {
+                    iNumHvxcBits += 13;
+                }
+            }
+
+            if ( ! iNumHvxcBits ) {
+                throw CInitErr(ET_AUDDECODER);
+            }
+
+            hvxc_frame.Init(iNumAudioFrames, iNumHvxcBits);
+
+#ifdef USE_HVXC_DECODER
+
+// TODO put decoder initialization here
+            bWriteToFile = TRUE;
+            if(bWriteToFile)
+            {
+                string fn = HVXCFileName(Parameters);
+                if(pFile)
+                    fclose(pFile);
+#ifdef _WIN32
+                _mkdir("test");
+#else
+                mkdir("test", 0777);
+#endif
+                pFile = fopen(fn.c_str(), "wb");
+            }
+
+#else
+            /* No HVXC decoder available */
+            throw CInitErr(ET_AUDDECODER);
+#endif
+        }
+        else if (eAudioCoding == CAudioParam::AC_OPUS)
+        {
+            /* Init for OPUS decoding ---------------------------------------- */
+
+            /* Length of higher protected part of audio stream */
+            const int iLenAudHigh =
+                Parameters.Stream[iCurAudioStreamID].iLenPartA;
+
+            /* Number of audio frame */
+            iNumAudioFrames = 20;
+
+            /* Number of borders */
+            iNumBorders = iNumAudioFrames;
+
+            /* The audio_payload_length is derived from the length of the audio
+               super frame (data_length_of_part_A + data_length_of_part_B)
+               subtracting the audio super frame overhead (bytes used for the
+               audio super frame header() and for the aac_crc_bits)
+               (5.3.1.1, Table 5) */
+            iAudioPayloadLen = iTotalFrameSize / SIZEOF__BYTE - iNumAudioFrames;
+
+            /* Check iAudioPayloadLen value, only positive values make sense */
+            if (iAudioPayloadLen < 0)
+                throw CInitErr(ET_AUDDECODER);
+
+            /* Calculate number of bytes for higher protected blocks */
+            iNumHigherProtectedBytes = (iLenAudHigh -
+                                        iNumAudioFrames /* CRC bytes */ ) /
+                                        iNumAudioFrames;
+
+            if (iNumHigherProtectedBytes < 0)
+                iNumHigherProtectedBytes = 0;
+
+            /* The maximum length for one audio frame is "iAudioPayloadLen". The
+               regular size will be much shorter since all audio frames share
+               the total size, but we do not know at this time how the data is
+               split in the transmitter source coder */
+            iMaxLenOneAudFrame = iAudioPayloadLen;
+
+            /* Init Opus decoder */
+			codec->DecOpen(AudioParam, &iAudioSampleRate, &iLenDecOutPerChan);
+        }
+        else
+        {
+            /* Audio codec not supported */
+            throw CInitErr(ET_AUDDECODER);
+        }
+
+        /* set string for GUI */
+        Parameters.audiodecoder = audiodecoder;
+
+        /* Set number of Audio frames for log file */
+        Parameters.iNumAudioFrames = iNumAudioFrames;
+
+        /* Since we do not correct for sample rate offsets here (yet), we do not
+           have to consider larger buffers. An audio frame always corresponds
+           to 400 ms */
+        iMaxLenResamplerOutput = (int) ((_REAL) Parameters.GetAudSampleRate() *
+                                        (_REAL) 0.4 /* 400ms */  *
+                                        2 /* for stereo */ );
+
+        iResOutBlockSize = (int) ((_REAL) iLenDecOutPerChan *
+                                  Parameters.GetAudSampleRate() / iAudioSampleRate);
+
+        /* Additional buffers needed for resampling since we need conversation
+           between _REAL and _SAMPLE. We have to init the buffers with
+           zeros since it can happen, that we have bad CRC right at the
+           start of audio blocks */
+        vecTempResBufInLeft.Init(iLenDecOutPerChan, (_REAL) 0.0);
+        vecTempResBufInRight.Init(iLenDecOutPerChan, (_REAL) 0.0);
+        vecTempResBufOutCurLeft.Init(iResOutBlockSize, (_REAL) 0.0);
+        vecTempResBufOutCurRight.Init(iResOutBlockSize, (_REAL) 0.0);
+        vecTempResBufOutOldLeft.Init(iResOutBlockSize, (_REAL) 0.0);
+        vecTempResBufOutOldRight.Init(iResOutBlockSize, (_REAL) 0.0);
+
+        /* Init resample objects */
+        ResampleObjL.Init(iLenDecOutPerChan,
+                          (_REAL) Parameters.GetAudSampleRate() / iAudioSampleRate);
+        ResampleObjR.Init(iLenDecOutPerChan,
+                          (_REAL) Parameters.GetAudSampleRate() / iAudioSampleRate);
+
+        /* Clear reverberation object */
+        AudioRev.Init(1.0 /* seconds delay */, Parameters.GetAudSampleRate());
+        AudioRev.Clear();
+
+        /* With this parameter we define the maximum lenght of the output
+           buffer. The cyclic buffer is only needed if we do a sample rate
+           correction due to a difference compared to the transmitter. But for
+           now we do not correct and we could stay with a single buffer
+           Maybe TODO: sample rate correction to avoid audio dropouts */
+        iMaxOutputBlockSize = iMaxLenResamplerOutput;
+
+        Parameters.Unlock();
+    }
+
+    catch(CInitErr CurErr)
+    {
+        Parameters.Unlock();
+
+        switch (CurErr.eErrType)
+        {
+        case ET_ALL:
+            /* An init error occurred, do not process data in this module */
+            DoNotProcessData = TRUE;
+            break;
+
+        case ET_AUDDECODER:
+            /* Audio part should not be decdoded, set flag */
+            DoNotProcessAudDecoder = TRUE;
+            break;
+
+        default:
+            DoNotProcessData = TRUE;
+        }
+
+        /* In all cases set output size to zero */
+        iOutputBlockSize = 0;
+    }
+}
+
+int
+CAudioSourceDecoder::GetNumCorDecAudio()
+{
+    /* Return number of correctly decoded audio blocks. Reset counter
+       afterwards */
+    const int iRet = iNumCorDecAudio;
+
+    iNumCorDecAudio = 0;
+
+    return iRet;
+}
+
+void
+CAudioSourceDecoder::CloseDecoder()
+{
+    if (codec != NULL)
+        codec->DecClose();
+}
+
diff --git a/src/sourcedecoders/AudioSourceDecoder.h b/src/sourcedecoders/AudioSourceDecoder.h
new file mode 100644
index 0000000..6879811
--- /dev/null
+++ b/src/sourcedecoders/AudioSourceDecoder.h
@@ -0,0 +1,239 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ * Volker Fischer, Ollie Haffenden
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#ifndef _AUIDOSOURCEDECODER_H_INCLUDED_
+#define _AUIDOSOURCEDECODER_H_INCLUDED_
+
+#include "../GlobalDefinitions.h"
+#include "../Parameter.h"
+#include "../util/Modul.h"
+#include "../util/CRC.h"
+#include "../TextMessage.h"
+#include "../resample/Resample.h"
+#include "../datadecoding/DataDecoder.h"
+#include "../util/Utilities.h"
+#include "AudioCodec.h"
+
+/* Definitions ****************************************************************/
+
+// TEST -> for now only use CRC calculation
+#define USE_CELP_DECODER
+
+#define USE_HVXC_DECODER
+
+
+/* Elements of table for UEP parameters for CELP:
+ - CELP bit rate index
+ - Bit rate (bits / s)
+ - Audio frame length (ms)
+ - Higher protected part (bits/audio frame)
+ - Lower protected part (bits/audio frame)
+ - Higher protected part (bytes/audio super frame)
+ - Lower protected part (bytes/audio super frame)
+ - Audio super frame length (bytes) */
+/* 8 kHz sampling rate */
+#define LEN_CELP_8KHZ_UEP_PARAMS_TAB 27
+const int iTableCELP8kHzUEPParams[LEN_CELP_8KHZ_UEP_PARAMS_TAB][8] = {
+    { 3850, 40, 36, 118,  45, 148, 193},
+    { 4250, 40, 36, 134,  45, 168, 213},
+    { 4650, 40, 36, 150,  45, 188, 233},
+    {    0,  0,  0,   0,   0,   0,   0},
+    {    0,  0,  0,   0,   0,   0,   0},
+    {    0,  0,  0,   0,   0,   0,   0},
+    { 5700, 20, 24,  90,  60, 225, 285},
+    { 6000, 20, 24,  96,  60, 240, 300},
+    { 6300, 20, 24, 102,  60, 255, 315},
+    { 6600, 20, 24, 108,  60, 270, 330},
+    { 6900, 20, 24, 114,  60, 285, 345},
+    { 7100, 20, 24, 118,  60, 295, 355},
+    { 7300, 20, 24, 122,  60, 305, 365},
+    { 7700, 20, 36, 118,  90, 295, 385},
+    { 8300, 20, 36, 130,  90, 325, 415},
+    { 8700, 20, 36, 138,  90, 345, 435},
+    { 9100, 20, 36, 146,  90, 365, 455},
+    { 9500, 20, 36, 154,  90, 385, 475},
+    { 9900, 20, 36, 162,  90, 405, 495},
+    {10300, 20, 36, 170,  90, 425, 515},
+    {10500, 20, 36, 174,  90, 435, 525},
+    {10700, 20, 36, 178,  90, 445, 535},
+    {11000, 10, 24,  86, 120, 430, 550},
+    {11400, 10, 24,  90, 120, 450, 570},
+    {11800, 10, 24,  94, 120, 470, 590},
+    {12000, 10, 24,  96, 120, 480, 600},
+    {12200, 10, 24,  98, 120, 490, 610}
+};
+
+/* 16 kHz sampling rate */
+#define LEN_CELP_16KHZ_UEP_PARAMS_TAB 32
+const int iTableCELP16kHzUEPParams[LEN_CELP_16KHZ_UEP_PARAMS_TAB][8] = {
+    {10900, 20, 64, 154, 160, 385, 545},
+    {11500, 20, 64, 166, 160, 415, 575},
+    {12100, 20, 64, 178, 160, 445, 605},
+    {12700, 20, 64, 190, 160, 475, 635},
+    {13300, 20, 64, 202, 160, 505, 665},
+    {13900, 20, 64, 214, 160, 535, 695},
+    {14300, 20, 64, 222, 160, 555, 715},
+    {    0,  0,  0,   0,   0,   0,   0},
+    {14700, 20, 92, 202, 230, 505, 735},
+    {15900, 20, 92, 226, 230, 565, 795},
+    {17100, 20, 92, 250, 230, 625, 855},
+    {17900, 20, 92, 266, 230, 665, 895},
+    {18700, 20, 92, 282, 230, 705, 935},
+    {19500, 20, 92, 298, 230, 745, 975},
+    {20300, 20, 92, 314, 230, 785, 1015},
+    {21100, 20, 92, 330, 230, 825, 1055},
+    {13600, 10, 50,  86, 250, 430, 680},
+    {14200, 10, 50,  92, 250, 460, 710},
+    {14800, 10, 50,  98, 250, 490, 740},
+    {15400, 10, 50, 104, 250, 520, 770},
+    {16000, 10, 50, 110, 250, 550, 800},
+    {16600, 10, 50, 116, 250, 580, 830},
+    {17000, 10, 50, 120, 250, 600, 850},
+    {    0,  0,  0,   0,   0,   0,   0},
+    {17400, 10, 64, 110, 320, 550, 870},
+    {18600, 10, 64, 122, 320, 610, 930},
+    {19800, 10, 64, 134, 320, 670, 990},
+    {20600, 10, 64, 142, 320, 710, 1030},
+    {21400, 10, 64, 150, 320, 750, 1070},
+    {22200, 10, 64, 158, 320, 790, 1110},
+    {23000, 10, 64, 166, 320, 830, 1150},
+    {23800, 10, 64, 174, 320, 870, 1190}
+};
+
+
+/* Classes ********************************************************************/
+
+class CAudioSourceDecoder : public CReceiverModul<_BINARY, _SAMPLE>
+{
+public:
+    CAudioSourceDecoder();
+
+    virtual ~CAudioSourceDecoder();
+
+    bool CanDecode(CAudioParam::EAudCod eAudCod) {
+        switch (eAudCod)
+        {
+        case CAudioParam::AC_NONE: return true;
+        case CAudioParam::AC_AAC:  return bCanDecodeAAC;
+        case CAudioParam::AC_CELP: return bCanDecodeCELP;
+        case CAudioParam::AC_HVXC: return bCanDecodeHVXC;
+        case CAudioParam::AC_OPUS: return bCanDecodeOPUS;
+        case CAudioParam::AC_xHE_AAC: return false;
+        }
+        return false;
+    }
+    int GetNumCorDecAudio();
+    void SetReverbEffect(const _BOOLEAN bNER) {
+        bUseReverbEffect = bNER;
+    }
+    _BOOLEAN GetReverbEffect() {
+        return bUseReverbEffect;
+    }
+
+    _BOOLEAN bWriteToFile;
+
+protected:
+    enum EInitErr {ET_ALL, ET_AUDDECODER}; /* ET: Error type */
+    class CInitErr
+    {
+    public:
+        CInitErr(EInitErr eNewErrType) : eErrType(eNewErrType) {}
+        EInitErr eErrType;
+    };
+
+    /* General */
+    _BOOLEAN DoNotProcessData;
+    _BOOLEAN DoNotProcessAudDecoder;
+    int iTotalFrameSize;
+    int iNumCorDecAudio;
+
+    /* Text message */
+    _BOOLEAN bTextMessageUsed;
+    CTextMessageDecoder TextMessage;
+    CVector<_BINARY> vecbiTextMessBuf;
+
+    /* Resampling */
+    int iResOutBlockSize;
+
+    CAudioResample ResampleObjL;
+    CAudioResample ResampleObjR;
+
+    CVector<_REAL> vecTempResBufInLeft;
+    CVector<_REAL> vecTempResBufInRight;
+    CVector<_REAL> vecTempResBufOutCurLeft;
+    CVector<_REAL> vecTempResBufOutCurRight;
+    CVector<_REAL> vecTempResBufOutOldLeft;
+    CVector<_REAL> vecTempResBufOutOldRight;
+
+    /* Drop-out masking (reverberation) */
+    _BOOLEAN bAudioWasOK;
+    _BOOLEAN bUseReverbEffect;
+    CAudioReverb AudioRev;
+
+    int iLenDecOutPerChan;
+    int iNumAudioFrames;
+
+    CAudioParam::EAudCod eAudioCoding;
+	CAudioCodec* codec;
+
+    int iNumBorders;
+    int iNumHigherProtectedBytes;
+    int iMaxLenOneAudFrame;
+
+    int iBadBlockCount;
+    int iAudioPayloadLen;
+
+    /* HVXC decoding */
+    CMatrix<_BINARY> hvxc_frame;
+    int iNumHvxcBits;
+
+    /* CELP decoding */
+    CMatrix<_BINARY> celp_frame;
+    CVector<_BYTE> celp_crc_bits;
+    int iNumHigherProtectedBits;
+    int iNumLowerProtectedBits;
+    _BOOLEAN bCELPCRC;
+    CCRC CELPCRCObject;
+
+    string audiodecoder;
+    bool bCanDecodeAAC;
+    bool bCanDecodeCELP;
+    bool bCanDecodeHVXC;
+    bool bCanDecodeOPUS;
+
+    FILE *pFile;
+
+#ifdef USE_CELP_DECODER
+    /* TODO put here decoder specific things */
+#endif
+    virtual void InitInternal(CParameter& Parameters);
+    virtual void ProcessDataInternal(CParameter& Parameters);
+    string AACFileName(CParameter&);
+    string CELPFileName(CParameter&);
+    string HVXCFileName(CParameter&);
+	void CloseDecoder();
+};
+
+#endif // _AUIDOSOURCEDECODER_H_INCLUDED_
diff --git a/src/sourcedecoders/AudioSourceEncoder.cpp b/src/sourcedecoders/AudioSourceEncoder.cpp
new file mode 100644
index 0000000..36e227f
--- /dev/null
+++ b/src/sourcedecoders/AudioSourceEncoder.cpp
@@ -0,0 +1,656 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer, Ollie Haffenden
+ *
+ * Description:
+ *	Audio source encoder/decoder
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "AudioSourceEncoder.h"
+#include <iostream>
+
+
+/* Implementation *************************************************************/
+
+CAudioSourceEncoderImplementation::CAudioSourceEncoderImplementation()
+    : bUsingTextMessage(FALSE), codec(NULL)
+{
+    /* Initialize Audio Codec List */
+    CAudioCodec::InitCodecList();
+
+    /* In case codec might be dereferenced before initialised this will
+       get us a null codec at least, it is safer than other codec */
+    codec = CAudioCodec::GetEncoder(AC_NULL);
+
+    /* Needed by TransmDlg.cpp to report available codec */
+    bCanEncodeAAC  = CAudioCodec::GetEncoder(CAudioParam::AC_AAC,  true) != NULL;
+    bCanEncodeOPUS = CAudioCodec::GetEncoder(CAudioParam::AC_OPUS, true) != NULL;
+}
+
+CAudioSourceEncoderImplementation::~CAudioSourceEncoderImplementation()
+{
+    /* Unreference Audio Codec List */
+    CAudioCodec::UnrefCodecList();
+}
+
+void
+CAudioSourceEncoderImplementation::ProcessDataInternal(CParameter& Parameters,
+        CVectorEx < _SAMPLE >
+        *pvecInputData,
+        CVectorEx < _BINARY >
+        *pvecOutputData,
+        int &iInputBlockSize,
+        int &iOutputBlockSize)
+{
+    int iCurSelServ = 0;
+
+    /* Reset data to zero. This is important since usually not all data is used
+       and this data has to be set to zero as defined in the DRM standard */
+    for (int i = 0; i < iOutputBlockSize; i++)
+        (*pvecOutputData)[i] = 0;
+
+    if (bIsDataService == FALSE)
+    {
+        /* Check if audio param have changed */
+        Parameters.Lock();
+
+        /* Get audio param for audio service */
+        CAudioParam& AudioParam(Parameters.Service[iCurSelServ].AudioParam);
+
+        if (AudioParam.bParamChanged)
+        {
+            AudioParam.bParamChanged = FALSE;
+            codec->EncUpdate(AudioParam);
+        }
+        Parameters.Unlock();
+
+        /* Resample data to encoder bit-rate */
+        /* Change type of data (short -> real) */
+        /* The input data is always stereo, if the encoder
+           if set to mono we take the left channel only */
+        for (int j = 0; j < iInputBlockSize / 2; j++)
+        {
+            for (int i = 0; i < iNumChannels; i++)
+                vecTempResBufIn[i][j] = (*pvecInputData)[j * 2 + i];
+        }
+
+        /* Resample data */
+        for (int i = 0; i < iNumChannels; i++)
+            ResampleObj[i].Resample(vecTempResBufIn[i], vecTempResBufOut[i]);
+
+        /* Split data in individual audio blocks */
+        for (int j = 0; j < iNumAudioFrames; j++)
+        {
+            int bytesEncoded;
+            CVector < unsigned char >vecsTmpData(lMaxBytesEncOut);
+
+            /* Convert _REAL type to _SAMPLE type, copy in smaller buffer */
+            for (unsigned long k = 0; k < lNumSampEncIn; k++)
+            {
+                for (int i = 0; i < iNumChannels; i++)
+                    vecsEncInData[k * iNumChannels + i] =
+                        Real2Sample(vecTempResBufOut[i][j * lNumSampEncIn + k]);
+            }
+
+            /* Actual encoding */
+            bytesEncoded = codec->Encode(vecsEncInData, lNumSampEncIn * iNumChannels, vecsTmpData, lMaxBytesEncOut);
+            if (bytesEncoded > 0)
+            {
+                /* Extract CRC */
+                aac_crc_bits[j] = vecsTmpData[0];
+
+                /* Extract actual data */
+                for (int i = 0; i < bytesEncoded - 1 /* "-1" for CRC */ ; i++)
+                    audio_frame[j][i] = vecsTmpData[i + 1];
+
+                /* Store block lengths for boarders in AAC super-frame-header */
+                veciFrameLength[j] = bytesEncoded - 1;
+            }
+            else
+            {
+                /* Encoder is in initialization phase, reset CRC and length */
+                aac_crc_bits[j] = 0;
+                veciFrameLength[j] = 0;
+            }
+        }
+
+        /* Write data to output vector */
+        /* First init buffer with zeros */
+        for (int i = 0; i < iOutputBlockSize; i++)
+            (*pvecOutputData)[i] = 0;
+
+        /* Reset bit extraction access */
+        (*pvecOutputData).ResetBitAccess();
+
+        /* Audio super-frame-header */
+        int iAudioFrameLength = 0;
+        for (int j = 0; j < iNumBorders; j++)
+        {
+            /* Accumulate audio frame length */
+            iAudioFrameLength += veciFrameLength[j];
+
+            /* Frame border in bytes (12 bits) */
+            (*pvecOutputData).Enqueue(iAudioFrameLength, 12);
+        }
+
+        /* Byte-alignment (4 bits) in case of odd number of borders */
+        if (iNumBorders & 1)
+            (*pvecOutputData).Enqueue(0, 4);
+
+        /* Higher protected part */
+        int iCurNumBytes = 0;
+        for (int j = 0; j < iNumAudioFrames; j++)
+        {
+            /* Data */
+            for (int i = 0; i < iNumHigherProtectedBytes; i++)
+            {
+                /* Check if enough data is available, set data to 0 if not */
+                if (i < veciFrameLength[j])
+                    (*pvecOutputData).Enqueue(audio_frame[j][i], 8);
+                else
+                    (*pvecOutputData).Enqueue(0, 8);
+
+                iCurNumBytes++;
+            }
+
+            /* CRCs */
+            (*pvecOutputData).Enqueue(aac_crc_bits[j], 8);
+        }
+
+        /* Lower protected part */
+        for (int j = 0; j < iNumAudioFrames; j++)
+        {
+            for (int i = iNumHigherProtectedBytes; i < veciFrameLength[j]; i++)
+            {
+                /* If encoder produced too many bits, we have to drop them */
+                if (iCurNumBytes < iAudioPayloadLen)
+                    (*pvecOutputData).Enqueue(audio_frame[j][i], 8);
+
+                iCurNumBytes++;
+            }
+        }
+
+#ifdef _DEBUG_
+        /* Save number of bits actually used by audio encoder */
+        static FILE *pFile = fopen("test/audbits.dat", "w");
+        fprintf(pFile, "%d %d\n", iAudioPayloadLen, iCurNumBytes);
+        fflush(pFile);
+#endif
+    }
+
+    /* Data service and text message application ---------------------------- */
+    if (bIsDataService == TRUE)
+    {
+        // TODO: make a separate modul for data encoding
+        /* Write data packets in stream */
+        CVector < _BINARY > vecbiData;
+        const int iNumPack = iOutputBlockSize / iTotPacketSize;
+        int iPos = 0;
+
+        for (int j = 0; j < iNumPack; j++)
+        {
+            /* Get new packet */
+            DataEncoder.GeneratePacket(vecbiData);
+
+            /* Put it on stream */
+            for (int i = 0; i < iTotPacketSize; i++)
+            {
+                (*pvecOutputData)[iPos] = vecbiData[i];
+                iPos++;
+            }
+        }
+    }
+    else
+    {
+        /* Text message application. Last four bytes in stream are written */
+        if (bUsingTextMessage == TRUE)
+        {
+            /* Always four bytes for text message "piece" */
+            CVector < _BINARY >
+            vecbiTextMessBuf(SIZEOF__BYTE *
+                             NUM_BYTES_TEXT_MESS_IN_AUD_STR);
+
+            /* Get a "piece" */
+            TextMessage.Encode(vecbiTextMessBuf);
+
+            /* Calculate start point for text message */
+            const int iByteStartTextMess =
+                iTotNumBitsForUsage -
+                SIZEOF__BYTE * NUM_BYTES_TEXT_MESS_IN_AUD_STR;
+
+            /* Add text message bytes to output stream */
+            for (int i = iByteStartTextMess; i < iTotNumBitsForUsage; i++)
+                (*pvecOutputData)[i] =
+                    vecbiTextMessBuf[i - iByteStartTextMess];
+        }
+    }
+}
+
+void
+CAudioSourceEncoderImplementation::InitInternalTx(CParameter & Parameters,
+        int &iInputBlockSize,
+        int &iOutputBlockSize)
+{
+    int iCurStreamID;
+
+    int iCurSelServ = 0;		// TEST
+
+    Parameters.Lock();
+
+    /* Close previous encoder instance if any */
+    CloseEncoder();
+
+    /* Calculate number of input samples in mono. Audio block are always
+       400 ms long */
+    const int iNumInSamplesMono = (int) ((_REAL) Parameters.GetAudSampleRate() *
+                                         (_REAL) 0.4 /* 400 ms */ );
+
+    /* Set the total available number of bits, byte aligned */
+    iTotNumBitsForUsage =
+        (Parameters.iNumDecodedBitsMSC / SIZEOF__BYTE) * SIZEOF__BYTE;
+
+    /* Total number of bytes which can be used for data and audio */
+    const int iTotNumBytesForUsage = iTotNumBitsForUsage / SIZEOF__BYTE;
+
+    if (Parameters.iNumDataService == 1)
+    {
+        /* Data service ----------------------------------------------------- */
+        bIsDataService = TRUE;
+        iTotPacketSize = DataEncoder.Init(Parameters);
+
+        /* Get stream ID for data service */
+        iCurStreamID = Parameters.Service[iCurSelServ].DataParam.iStreamID;
+    }
+    else
+    {
+        /* Audio service ---------------------------------------------------- */
+        bIsDataService = FALSE;
+
+        /* Get stream ID and codec type for audio service */
+        iCurStreamID = Parameters.Service[iCurSelServ].AudioParam.iStreamID;
+        CAudioParam::EAudCod eAudioCoding = Parameters.Service[iCurSelServ].AudioParam.eAudioCoding;
+
+        /* Get encoder instance */
+        codec = CAudioCodec::GetEncoder(eAudioCoding);
+
+        /* Total frame size is input block size minus the bytes for the text
+           message (if text message is used) */
+        int iTotAudFraSizeBits = iTotNumBitsForUsage;
+        if (bUsingTextMessage == TRUE)
+            iTotAudFraSizeBits -=
+                SIZEOF__BYTE * NUM_BYTES_TEXT_MESS_IN_AUD_STR;
+
+        int iNumHeaderBytes;
+
+        switch (eAudioCoding)
+        {
+        case CAudioParam::AC_AAC:
+        {
+            int iTimeEachAudBloMS = 40;
+
+            /* Set encoder number of channels, faac support only mono */
+            iNumChannels = 1;
+
+            /* Set encoder sample rate. This parameter decides other parameters */
+            // TEST make threshold decision TODO: improvement
+            if (iTotAudFraSizeBits > 7000)	/* in bits! */
+                lEncSamprate = 24000;
+            else
+                lEncSamprate = 12000;
+
+            switch (lEncSamprate)
+            {
+            case 12000:
+                iTimeEachAudBloMS = 80;	/* ms */
+                iNumAudioFrames = 5;
+                Parameters.Service[iCurSelServ].AudioParam.eAudioSamplRate = CAudioParam::AS_12KHZ;	/* Set parameter in global struct */
+                break;
+
+            case 24000:
+                iTimeEachAudBloMS = 40;	/* ms */
+                iNumAudioFrames = 10;
+                Parameters.Service[iCurSelServ].AudioParam.eAudioSamplRate = CAudioParam::AS_24KHZ;	/* Set parameter in global struct */
+                break;
+            }
+
+            /* Number of borders, the border of the last frame is not included because
+               the audio frame size of the last frame is the frame remaining bytes */
+            iNumBorders = iNumAudioFrames - 1;
+
+            /* Calculate the number of header bytes */
+            iNumHeaderBytes = (iNumBorders * 12 + 7) / 8;
+
+            /* The audio_payload_length is derived from the length of the audio
+               super frame (data_length_of_part_A + data_length_of_part_B)
+               subtracting the audio super frame overhead (bytes used for the audio
+               super frame header() and for the aac_crc_bits) (5.3.1.1, Table 5) */
+            iAudioPayloadLen = iTotAudFraSizeBits / SIZEOF__BYTE - iNumHeaderBytes - iNumAudioFrames /* for CRCs */ ;
+
+            const int iActEncOutBytes = (int) (iAudioPayloadLen / iNumAudioFrames);
+
+            /* Open encoder instance */
+            codec->EncOpen(lEncSamprate, iNumChannels, &lNumSampEncIn, &lMaxBytesEncOut);
+            lNumSampEncIn /= iNumChannels;
+
+            /* Calculate bitrate, bit per second */
+            const int iBitRate = iActEncOutBytes * SIZEOF__BYTE * AUD_DEC_TRANSFROM_LENGTH / lNumSampEncIn / iTimeEachAudBloMS * 1000;
+            codec->EncSetBitrate(iBitRate);
+        }
+        break;
+
+        case CAudioParam::AC_OPUS:
+        {
+            /* Set various encoder parameters */
+            lEncSamprate = 48000;
+            iNumChannels = 2;
+            iNumAudioFrames = 20;
+            Parameters.Service[iCurSelServ].AudioParam.eAudioSamplRate = CAudioParam::AS_48KHZ;	/* Set parameter in global struct */
+
+            /* Number of borders, opus decoder need to know the exact frame size,
+               thus the number of borders equal the number of audio frames */
+            iNumBorders = iNumAudioFrames;
+
+            /* Calculate the number of header bytes */
+            iNumHeaderBytes = (iNumBorders * 12 + 7) / 8;
+
+            /* The audio_payload_length is derived from the length of the audio
+               super frame (data_length_of_part_A + data_length_of_part_B)
+               subtracting the audio super frame overhead (bytes used for the audio
+               super frame header()) */
+            iAudioPayloadLen = iTotAudFraSizeBits / SIZEOF__BYTE - iNumHeaderBytes;
+
+            const int iActEncOutBytes = (int) (iAudioPayloadLen / iNumAudioFrames);
+
+            /* Open encoder instance */
+            codec->EncOpen(lEncSamprate, iNumChannels, &lNumSampEncIn, &lMaxBytesEncOut);
+            lNumSampEncIn /= iNumChannels;
+
+            /* Calculate bitrate, bit per frame */
+            const int iBitRate = iActEncOutBytes * SIZEOF__BYTE;
+            codec->EncSetBitrate(iBitRate);
+
+            /* Set flags to reset and init codec params on first ProcessDataInternal call */
+            Parameters.Service[iCurSelServ].AudioParam.bOPUSRequestReset = TRUE;
+            Parameters.Service[iCurSelServ].AudioParam.bParamChanged = TRUE;
+        }
+        break;
+
+        default:
+            /* Unsupported encoder, parameters must be safe */
+            lEncSamprate = 12000;
+            iNumChannels = 1;
+            iNumAudioFrames = 1;
+            iNumBorders = 0;
+            iNumHeaderBytes = 0;
+        }
+
+        /* Set parameter in global struct */
+        Parameters.Service[iCurSelServ].AudioParam.eAudioMode =
+            iNumChannels >= 2 ? CAudioParam::AM_STEREO : CAudioParam::AM_MONO;
+
+        /* Init storage for actual data, CRCs and frame lengths */
+        audio_frame.Init(iNumAudioFrames, lMaxBytesEncOut);
+        vecsEncInData.Init(lNumSampEncIn * iNumChannels);
+        aac_crc_bits.Init(iNumAudioFrames);
+        veciFrameLength.Init(iNumAudioFrames);
+
+        for (int i = 0; i < iNumChannels; i++)
+        {
+            /* Additional buffers needed for resampling since we need conversation
+               between _SAMPLE and _REAL */
+            vecTempResBufIn[i].Init(iNumInSamplesMono);
+            vecTempResBufOut[i].Init(lNumSampEncIn * iNumAudioFrames, (_REAL) 0.0);
+
+            /* Init resample objects */
+            ResampleObj[i].Init(iNumInSamplesMono,
+                (_REAL) lEncSamprate / (_REAL) Parameters.GetAudSampleRate() *
+                (_REAL) lNumSampEncIn / (_REAL) AUD_DEC_TRANSFROM_LENGTH);
+        }
+
+        /* Calculate number of bytes for higher protected blocks */
+        iNumHigherProtectedBytes =
+            (Parameters.Stream[iCurStreamID].iLenPartA
+             - iNumHeaderBytes -
+             iNumAudioFrames /* CRC bytes */ ) / iNumAudioFrames;
+
+        if (iNumHigherProtectedBytes < 0)
+            iNumHigherProtectedBytes = 0;
+    }
+
+    /* Adjust part B length for SDC stream. Notice, that the
+       "Parameters.iNumDecodedBitsMSC" parameter depends on these settings.
+       Thus, length part A and B have to be set before, preferably in the
+       DRMTransmitter initialization */
+    if ((Parameters.Stream[iCurStreamID].iLenPartA == 0) ||
+            (iTotNumBytesForUsage < Parameters.Stream[iCurStreamID].iLenPartA))
+    {
+        /* Equal error protection was chosen or protection part A was chosen too
+           high, set to equal error protection! */
+        Parameters.Stream[iCurStreamID].iLenPartA = 0;
+        Parameters.Stream[iCurStreamID].iLenPartB = iTotNumBytesForUsage;
+    }
+    else
+        Parameters.Stream[iCurStreamID].iLenPartB = iTotNumBytesForUsage -
+                Parameters.Stream[iCurStreamID].iLenPartA;
+
+    /* Define input and output block size */
+    iOutputBlockSize = Parameters.iNumDecodedBitsMSC;
+    iInputBlockSize = iNumInSamplesMono * 2 /* stereo */ ;
+
+    Parameters.Unlock();
+}
+
+void
+CAudioSourceEncoderImplementation::InitInternalRx(CParameter& Parameters,
+        int &iInputBlockSize,
+        int &iOutputBlockSize)
+{
+    Parameters.Lock();
+
+    /* Close previous encoder instance if any */
+    CloseEncoder();
+
+    /* Calculate number of input samples in mono. Audio block are always 400 ms long */
+    const int iNumInSamplesMono = (int) ((_REAL) Parameters.GetAudSampleRate() *
+                                         (_REAL) 0.4 /* 400 ms */ );
+
+    /* Set the total available number of bits, byte aligned */
+    iTotNumBitsForUsage =
+        (Parameters.Stream[0].iLenPartA + Parameters.Stream[0].iLenPartB) * SIZEOF__BYTE;
+
+    /* Total number of bytes which can be used for data and audio */
+    //const int iTotNumBytesForUsage = iTotNumBitsForUsage / SIZEOF__BYTE;
+
+    /* Audio service ---------------------------------------------------- */
+    bIsDataService = FALSE;
+
+    /* Total frame size is input block size minus the bytes for the text
+       message (if text message is used) */
+    int iTotAudFraSizeBits = iTotNumBitsForUsage;
+    if (bUsingTextMessage == TRUE)
+        iTotAudFraSizeBits -= SIZEOF__BYTE * NUM_BYTES_TEXT_MESS_IN_AUD_STR;
+
+    /* Get encoder instance */
+    codec = CAudioCodec::GetEncoder(Parameters.Service[0].AudioParam.eAudioCoding);
+
+    switch (Parameters.Service[0].AudioParam.eAudioCoding) {
+
+    case CAudioParam::AC_AAC:
+    {
+        int iTimeEachAudBloMS = 40;
+
+        /* Set encoder number of channels, faac support only mono */
+        iNumChannels = 1;
+
+        /* Set encoder sample rate. This parameter decides other parameters */
+        // TEST make threshold decision TODO: improvement
+        if (iTotAudFraSizeBits > 7000)	/* in bits! */
+            lEncSamprate = 24000;
+        else
+            lEncSamprate = 12000;
+
+        switch (lEncSamprate)
+        {
+        case 12000:
+            iTimeEachAudBloMS = 80;	/* ms */
+            iNumAudioFrames = 5;
+            Parameters.Service[0].AudioParam.eAudioSamplRate = CAudioParam::AS_12KHZ;	/* Set parameter in global struct */
+            break;
+
+        case 24000:
+            iTimeEachAudBloMS = 40;	/* ms */
+            iNumAudioFrames = 10;
+            Parameters.Service[0].AudioParam.eAudioSamplRate = CAudioParam::AS_24KHZ;	/* Set parameter in global struct */
+            break;
+        }
+
+        /* Number of borders, the border of the last frame is not included because
+           the audio frame size of the last frame is the frame remaining bytes */
+        iNumBorders = iNumAudioFrames - 1;
+
+        /* Calculate the number of header bytes */
+        int iNumHeaderBytes = (iNumBorders * 12 + 7) / 8;
+
+        /* The audio_payload_length is derived from the length of the audio
+           super frame (data_length_of_part_A + data_length_of_part_B)
+           subtracting the audio super frame overhead (bytes used for the audio
+           super frame header() and for the aac_crc_bits) (5.3.1.1, Table 5) */
+        iAudioPayloadLen = iTotAudFraSizeBits / SIZEOF__BYTE - iNumHeaderBytes - iNumAudioFrames /* for CRCs */ ;
+
+        const int iActEncOutBytes = (int) (iAudioPayloadLen / iNumAudioFrames);
+
+        /* Open encoder instance */
+        codec->EncOpen(lEncSamprate, iNumChannels, &lNumSampEncIn, &lMaxBytesEncOut);
+        lNumSampEncIn /= iNumChannels;
+
+        /* Calculate bitrate, bit per second */
+        const int iBitRate = iActEncOutBytes * SIZEOF__BYTE * AUD_DEC_TRANSFROM_LENGTH / lNumSampEncIn / iTimeEachAudBloMS * 1000;
+        codec->EncSetBitrate(iBitRate);
+    }
+    break;
+
+    case CAudioParam::AC_OPUS:
+    {
+        /* Set various encoder parameters */
+        lEncSamprate = 48000;
+        iNumChannels = 2;
+        iNumAudioFrames = 20;
+        Parameters.Service[0].AudioParam.eAudioSamplRate = CAudioParam::AS_48KHZ;	/* Set parameter in global struct */
+
+        /* Number of borders, opus decoder need to know the exact frame size,
+           thus the number of borders equal the number of audio frames */
+        iNumBorders = iNumAudioFrames;
+
+        /* Calculate the number of header bytes */
+        int iNumHeaderBytes = (iNumBorders * 12 + 7) / 8;
+
+        /* The audio_payload_length is derived from the length of the audio
+           super frame (data_length_of_part_A + data_length_of_part_B)
+           subtracting the audio super frame overhead (bytes used for the audio
+           super frame header()) */
+        iAudioPayloadLen = iTotAudFraSizeBits / SIZEOF__BYTE - iNumHeaderBytes;
+
+        const int iActEncOutBytes = (int) (iAudioPayloadLen / iNumAudioFrames);
+
+        /* Open encoder instance */
+        codec->EncOpen(lEncSamprate, iNumChannels, &lNumSampEncIn, &lMaxBytesEncOut);
+        lNumSampEncIn /= iNumChannels;
+
+        /* Calculate bitrate, bit per frame */
+        const int iBitRate = iActEncOutBytes * SIZEOF__BYTE;
+        codec->EncSetBitrate(iBitRate);
+
+        /* Set flags to reset and init codec params on first ProcessDataInternal call */
+        Parameters.Service[0].AudioParam.bOPUSRequestReset = TRUE;
+        Parameters.Service[0].AudioParam.bParamChanged = TRUE;
+    }
+    break;
+
+    default:
+        /* Unsupported encoder, parameters must be safe */
+        lEncSamprate = 12000;
+        iNumChannels = 1;
+        iNumAudioFrames = 1;
+        iNumBorders = 0;
+    }
+
+    /* Set parameter in global struct */
+    Parameters.Service[0].AudioParam.eAudioMode =
+        iNumChannels == 2 ? CAudioParam::AM_STEREO : CAudioParam::AM_MONO;
+
+    /* Init storage for actual data, CRCs and frame lengths */
+    audio_frame.Init(iNumAudioFrames, lMaxBytesEncOut);
+    vecsEncInData.Init(lNumSampEncIn * iNumChannels);
+    aac_crc_bits.Init(iNumAudioFrames);
+    veciFrameLength.Init(iNumAudioFrames);
+
+    for (int i = 0; i < iNumChannels; i++)
+    {
+        /* Additional buffers needed for resampling since we need conversation
+           between _SAMPLE and _REAL */
+        vecTempResBufIn[i].Init(iNumInSamplesMono);
+        vecTempResBufOut[i].Init(lNumSampEncIn * iNumAudioFrames, (_REAL) 0.0);
+
+        /* Init resample objects */
+        ResampleObj[i].Init(iNumInSamplesMono,
+            (_REAL) lEncSamprate / (_REAL) Parameters.GetAudSampleRate() *
+            (_REAL) lNumSampEncIn / (_REAL) AUD_DEC_TRANSFROM_LENGTH);
+    }
+
+    /* Calculate number of bytes for higher protected blocks */
+    iNumHigherProtectedBytes = 0;
+
+    /* Define input and output block size */
+    iOutputBlockSize = iTotNumBitsForUsage;
+    iInputBlockSize = iNumInSamplesMono * 2 /* stereo */ ;
+
+    Parameters.Unlock();
+}
+
+void
+CAudioSourceEncoderImplementation::CloseEncoder()
+{
+    if (codec != NULL)
+        codec->EncClose();
+}
+
+void
+CAudioSourceEncoderImplementation::SetTextMessage(const string & strText)
+{
+    /* Set text message in text message object */
+    TextMessage.SetMessage(strText);
+
+    /* Set text message flag */
+    bUsingTextMessage = TRUE;
+}
+
+void
+CAudioSourceEncoderImplementation::ClearTextMessage()
+{
+    /* Clear all text segments */
+    TextMessage.ClearAllText();
+
+    /* Clear text message flag */
+    bUsingTextMessage = FALSE;
+}
+
diff --git a/src/sourcedecoders/AudioSourceEncoder.h b/src/sourcedecoders/AudioSourceEncoder.h
new file mode 100644
index 0000000..a9429dd
--- /dev/null
+++ b/src/sourcedecoders/AudioSourceEncoder.h
@@ -0,0 +1,172 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer, Ollie Haffenden
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#ifndef _AUDIOSOURCEENCODER_H_INCLUDED_
+#define _AUDIOSOURCEENCODER_H_INCLUDED_
+
+#include "../GlobalDefinitions.h"
+#include "../Parameter.h"
+#include "../util/Modul.h"
+#include "../util/CRC.h"
+#include "../TextMessage.h"
+#include "../resample/Resample.h"
+#include "../datadecoding/DataEncoder.h"
+#include "../util/Utilities.h"
+#include "AudioCodec.h"
+
+/* Definition */
+#define MAX_ENCODED_CHANNELS 2
+
+
+/* Classes ********************************************************************/
+class CAudioSourceEncoderImplementation
+{
+public:
+	CAudioSourceEncoderImplementation();
+	virtual ~CAudioSourceEncoderImplementation();
+
+	void SetTextMessage(const string& strText);
+	void ClearTextMessage();
+
+	void SetPicFileName(const string& strFileName, const string& strFormat)
+		{DataEncoder.GetSliShowEnc()->AddFileName(strFileName, strFormat);}
+	void ClearPicFileNames()
+		{DataEncoder.GetSliShowEnc()->ClearAllFileNames();}
+	void SetPathRemoval(_BOOLEAN bRemovePath)
+		{DataEncoder.GetSliShowEnc()->SetPathRemoval(bRemovePath);}
+	_BOOLEAN GetTransStat(string& strCPi, _REAL& rCPe)
+		{return DataEncoder.GetSliShowEnc()->GetTransStat(strCPi, rCPe);}
+
+    bool CanEncode(CAudioParam::EAudCod eAudCod) {
+        switch (eAudCod)
+        {
+        case CAudioParam::AC_NONE: return true;
+        case CAudioParam::AC_AAC:  return bCanEncodeAAC;
+        case CAudioParam::AC_CELP: return false;
+        case CAudioParam::AC_HVXC: return false;
+        case CAudioParam::AC_OPUS: return bCanEncodeOPUS;
+        case CAudioParam::AC_xHE_AAC: return false;
+        }
+        return false;
+    }
+
+protected:
+	void CloseEncoder();
+
+	CTextMessageEncoder		TextMessage;
+	_BOOLEAN				bUsingTextMessage;
+	CDataEncoder			DataEncoder;
+	int						iTotPacketSize;
+	_BOOLEAN				bIsDataService;
+	int						iTotNumBitsForUsage;
+
+	CAudioCodec*			codec;
+
+	unsigned long			lNumSampEncIn;
+	unsigned long			lMaxBytesEncOut;
+	unsigned long			lEncSamprate;
+	CVector<_BYTE>			aac_crc_bits;
+	CVector<_SAMPLE>		vecsEncInData;
+	CMatrix<_BYTE>			audio_frame;
+	CVector<int>			veciFrameLength;
+	int						iNumChannels;
+	int						iNumAudioFrames;
+	int						iNumBorders;
+	int						iAudioPayloadLen;
+	int						iNumHigherProtectedBytes;
+
+	CAudioResample			ResampleObj[MAX_ENCODED_CHANNELS];
+	CVector<_REAL>			vecTempResBufIn[MAX_ENCODED_CHANNELS];
+	CVector<_REAL>			vecTempResBufOut[MAX_ENCODED_CHANNELS];
+
+	_BOOLEAN				bCanEncodeAAC;
+	_BOOLEAN				bCanEncodeOPUS;
+
+public:
+	virtual void InitInternalTx(CParameter& Parameters, int &iInputBlockSize, int &iOutputBlockSize);
+	virtual void InitInternalRx(CParameter& Parameters, int &iInputBlockSize, int &iOutputBlockSize);
+	virtual void ProcessDataInternal(CParameter& Parameters, CVectorEx<_SAMPLE>* pvecInputData,
+					CVectorEx<_BINARY>* pvecOutputData, int &iInputBlockSize, int &iOutputBlockSize);
+};
+
+class CAudioSourceEncoderRx : public CReceiverModul<_SAMPLE, _BINARY>
+{
+public:
+	CAudioSourceEncoderRx() {}
+	virtual ~CAudioSourceEncoderRx() {}
+
+protected:
+	CAudioSourceEncoderImplementation AudioSourceEncoderImpl;
+
+	virtual void InitInternal(CParameter& Parameters)
+	{
+		AudioSourceEncoderImpl.InitInternalRx(Parameters, iInputBlockSize, iOutputBlockSize);
+	}
+
+	virtual void ProcessDataInternal(CParameter& Parameters)
+	{
+		AudioSourceEncoderImpl.ProcessDataInternal(Parameters, pvecInputData, pvecOutputData, iInputBlockSize, iOutputBlockSize);
+	}
+};
+
+class CAudioSourceEncoder : public CTransmitterModul<_SAMPLE, _BINARY>
+{
+public:
+	CAudioSourceEncoder() {}
+	virtual ~CAudioSourceEncoder() {}
+
+	void SetTextMessage(const string& strText) {AudioSourceEncoderImpl.SetTextMessage(strText);}
+	void ClearTextMessage() {AudioSourceEncoderImpl.ClearTextMessage();}
+
+	void SetPicFileName(const string& strFileName, const string& strFormat)
+			{AudioSourceEncoderImpl.SetPicFileName(strFileName, strFormat);}
+
+	void ClearPicFileNames() {AudioSourceEncoderImpl.ClearPicFileNames();}
+
+	void SetPathRemoval(_BOOLEAN bRemovePath)
+			{AudioSourceEncoderImpl.SetPathRemoval(bRemovePath);}
+
+	_BOOLEAN GetTransStat(string& strCPi, _REAL& rCPe)
+			{return AudioSourceEncoderImpl.GetTransStat(strCPi, rCPe);}
+
+	bool CanEncode(CAudioParam::EAudCod eAudCod)
+			{return AudioSourceEncoderImpl.CanEncode(eAudCod);}
+
+protected:
+	CAudioSourceEncoderImplementation AudioSourceEncoderImpl;
+
+	virtual void InitInternal(CParameter& Parameters)
+	{
+		AudioSourceEncoderImpl.InitInternalTx(Parameters, iInputBlockSize, iOutputBlockSize);
+	}
+
+	virtual void ProcessDataInternal(CParameter& Parameters)
+	{
+		AudioSourceEncoderImpl.ProcessDataInternal(Parameters, pvecInputData, pvecOutputData, iInputBlockSize, iOutputBlockSize);
+	}
+
+};
+
+#endif // _AUDIOSOURCEENCODER_H_INCLUDED_
diff --git a/src/sourcedecoders/aac_codec.cpp b/src/sourcedecoders/aac_codec.cpp
new file mode 100644
index 0000000..780c0bb
--- /dev/null
+++ b/src/sourcedecoders/aac_codec.cpp
@@ -0,0 +1,324 @@
+/******************************************************************************\
+ *
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *  David Flamand
+ *
+ * Description:
+ *  AAC codec class
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "aac_codec.h"
+#if !defined(USE_FAAD2_LIBRARY) || !defined(USE_FAAC_LIBRARY)
+# include "../util/LibraryLoader.h"
+#endif
+
+
+#ifndef USE_FAAD2_LIBRARY
+static void* hFaadLib;
+static NeAACDecOpen_t *NeAACDecOpen;
+static NeAACDecInitDRM_t *NeAACDecInitDRM;
+static NeAACDecClose_t *NeAACDecClose;
+static NeAACDecDecode_t *NeAACDecDecode;
+static const LIBFUNC FaadLibFuncs[] = {
+	{ "NeAACDecOpen",    (void**)&NeAACDecOpen,    (void*)NULL },
+	{ "NeAACDecInitDRM", (void**)&NeAACDecInitDRM, (void*)NULL },
+	{ "NeAACDecClose",   (void**)&NeAACDecClose,   (void*)NULL },
+	{ "NeAACDecDecode",  (void**)&NeAACDecDecode,  (void*)NULL },
+	{ NULL, NULL, NULL }
+};
+# if defined(_WIN32)
+static const char* FaadLibNames[] = { "faad2_drm.dll", "libfaad2_drm.dll", "faad_drm.dll", "libfaad2.dll", NULL };
+# elif defined(__APPLE__)
+static const char* FaadLibNames[] = { "@executable_path/../Frameworks/libfaad2_drm.dylib", NULL };
+# else
+static const char* FaadLibNames[] = { "libfaad2_drm.so", "libfaad_drm.so", "libfaad.so.2", NULL };
+# endif
+#endif
+
+
+#ifndef USE_FAAC_LIBRARY
+static void* hFaacLib;
+static faacEncGetVersion_t* faacEncGetVersion;
+static faacEncGetCurrentConfiguration_t* faacEncGetCurrentConfiguration;
+static faacEncSetConfiguration_t* faacEncSetConfiguration;
+static faacEncOpen_t* faacEncOpen;
+static faacEncEncode_t* faacEncEncode;
+static faacEncClose_t* faacEncClose;
+static const LIBFUNC FaacLibFuncs[] = {
+	{ "faacEncGetVersion",              (void**)&faacEncGetVersion,              (void*)NULL },
+	{ "faacEncGetCurrentConfiguration", (void**)&faacEncGetCurrentConfiguration, (void*)NULL },
+	{ "faacEncSetConfiguration",        (void**)&faacEncSetConfiguration,        (void*)NULL },
+	{ "faacEncOpen",                    (void**)&faacEncOpen,                    (void*)NULL },
+	{ "faacEncEncode",                  (void**)&faacEncEncode,                  (void*)NULL },
+	{ "faacEncClose",                   (void**)&faacEncClose,                   (void*)NULL },
+	{ NULL, NULL, NULL }
+};
+# if defined(_WIN32)
+static const char* FaacLibNames[] = { "faac_drm.dll", "libfaac_drm.dll", "libfaac.dll", "faac.dll", NULL };
+# elif defined(__APPLE__)
+static const char* FaacLibNames[] = { "@executable_path/../Frameworks/libfaac_drm.dylib", NULL };
+# else
+static const char* FaacLibNames[] = { "libfaac_drm.so", "libfaac.so.0", NULL };
+# endif
+static bool FaacCheckCallback()
+{
+    bool bLibOk = false;
+    unsigned long lNumSampEncIn = 0;
+    unsigned long lMaxBytesEncOut = 0;
+    faacEncHandle hEncoder = faacEncOpen(24000, 1, &lNumSampEncIn, &lMaxBytesEncOut);
+    if (hEncoder != NULL)
+    {
+        /* lMaxBytesEncOut is odd when DRM is supported */
+        bLibOk = lMaxBytesEncOut & 1;
+        faacEncClose(hEncoder);
+    }
+    return bLibOk;
+}
+#endif
+
+
+/******************************************************************************/
+/* Implementation *************************************************************/
+
+AacCodec::AacCodec() :
+	hFaadDecoder(NULL), hFaacEncoder(NULL)
+{
+#ifndef USE_FAAD2_LIBRARY
+	if (hFaadLib == NULL)
+	{
+		hFaadLib = CLibraryLoader::Load(FaadLibNames, FaadLibFuncs);
+		if (!hFaadLib)
+		    cerr << "No usable FAAD2 aac decoder library found" << endl;
+		else
+		    cerr << "Got FAAD2 library" << endl;
+	}
+#endif
+#ifndef USE_FAAC_LIBRARY
+    if (hFaacLib == NULL)
+    {
+        hFaacLib = CLibraryLoader::Load(FaacLibNames, FaacLibFuncs, FaacCheckCallback);
+        if (!hFaacLib)
+            cerr << "No usable FAAC aac encoder library found" << endl;
+        else
+            cerr << "Got FAAC library" << endl;
+    }
+#endif
+}
+AacCodec::~AacCodec()
+{
+	DecClose();
+	EncClose();
+}
+
+/******************************************************************************/
+/* Decoder Implementation *****************************************************/
+
+string
+AacCodec::DecGetVersion()
+{
+	return string("Nero AAC version: ") + FAAD2_VERSION;
+}
+
+bool
+AacCodec::CanDecode(CAudioParam::EAudCod eAudioCoding)
+{
+#ifndef USE_FAAD2_LIBRARY
+	return hFaadLib && eAudioCoding == CAudioParam::AC_AAC;
+#else
+	return eAudioCoding == CAudioParam::AC_AAC;
+#endif
+}
+
+bool
+AacCodec::DecOpen(CAudioParam& AudioParam, int *iAudioSampleRate, int *iLenDecOutPerChan)
+{
+	int iAACSampleRate = 12000;
+	if (hFaadDecoder == NULL)
+		hFaadDecoder = NeAACDecOpen();
+	if (hFaadDecoder != NULL)
+	{
+		int iDRMchanMode = DRMCH_MONO;
+		/* Only 12 kHz and 24 kHz is allowed */
+		switch (AudioParam.eAudioSamplRate)
+		{
+		case CAudioParam::AS_12KHZ:
+			iAACSampleRate = 12000;
+			break;
+
+		case CAudioParam::AS_24KHZ:
+			iAACSampleRate = 24000;
+			break;
+
+		default:
+			break;
+		}
+		/* Number of channels for AAC: Mono, PStereo, Stereo */
+		switch (AudioParam.eAudioMode)
+		{
+		case CAudioParam::AM_MONO:
+			if (AudioParam.eSBRFlag == CAudioParam::SB_USED)
+				iDRMchanMode = DRMCH_SBR_MONO;
+			else
+				iDRMchanMode = DRMCH_MONO;
+			break;
+
+		case CAudioParam::AM_P_STEREO:
+			/* Low-complexity only defined in SBR mode */
+			iDRMchanMode = DRMCH_SBR_PS_STEREO;
+			break;
+
+		case CAudioParam::AM_STEREO:
+			if (AudioParam.eSBRFlag == CAudioParam::SB_USED)
+				iDRMchanMode = DRMCH_SBR_STEREO;
+			else
+				iDRMchanMode = DRMCH_STEREO;
+			break;
+		}
+		NeAACDecInitDRM(&hFaadDecoder, iAACSampleRate,
+			(unsigned char)iDRMchanMode);
+	}
+    /* In case of SBR, AAC sample rate is half the total sample rate.
+       Length of output is doubled if SBR is used */
+    if (AudioParam.eSBRFlag == CAudioParam::SB_USED)
+    {
+        *iAudioSampleRate = iAACSampleRate * 2;
+        *iLenDecOutPerChan = AUD_DEC_TRANSFROM_LENGTH * 2;
+    }
+    else
+    {
+        *iAudioSampleRate = iAACSampleRate;
+        *iLenDecOutPerChan = AUD_DEC_TRANSFROM_LENGTH;
+    }
+	return hFaadDecoder != NULL;
+}
+
+_SAMPLE*
+AacCodec::Decode(CVector<uint8_t>& vecbyPrepAudioFrame, int *iChannels, CAudioCodec::EDecError *eDecError)
+{
+	_SAMPLE* psDecOutSampleBuf = NULL;
+	NeAACDecFrameInfo DecFrameInfo;
+	DecFrameInfo.channels = 1;
+	DecFrameInfo.error = 1;
+	if (hFaadDecoder != NULL)
+	{
+		psDecOutSampleBuf = (_SAMPLE*) NeAACDecDecode(hFaadDecoder,
+			&DecFrameInfo, &vecbyPrepAudioFrame[0], vecbyPrepAudioFrame.size());
+	}
+	*iChannels = DecFrameInfo.channels;
+	*eDecError = DecFrameInfo.error ? CAudioCodec::DECODER_ERROR_UNKNOWN : CAudioCodec::DECODER_ERROR_OK;
+	return psDecOutSampleBuf;
+}
+
+void
+AacCodec::DecClose()
+{
+	if (hFaadDecoder != NULL)
+	{
+		NeAACDecClose(hFaadDecoder);
+		hFaadDecoder = NULL;
+	}
+}
+
+void
+AacCodec::DecUpdate(CAudioParam&)
+{
+}
+
+/******************************************************************************/
+/* Encoder Implementation *****************************************************/
+
+string
+AacCodec::EncGetVersion()
+{
+	char nul = 0;
+	char *faac_id_string = &nul;
+	char *faac_copyright_string = &nul;
+	faacEncGetVersion(&faac_id_string, &faac_copyright_string);
+	return string("FAAC version: ") + faac_id_string;
+}
+
+bool
+AacCodec::CanEncode(CAudioParam::EAudCod eAudioCoding)
+{
+#ifndef USE_FAAC_LIBRARY
+	return hFaacLib && eAudioCoding == CAudioParam::AC_AAC;
+#else
+	return eAudioCoding == CAudioParam::AC_AAC;
+#endif
+}
+
+bool
+AacCodec::EncOpen(int iSampleRate, int iChannels, unsigned long *lNumSampEncIn, unsigned long *lMaxBytesEncOut)
+{
+	hFaacEncoder = faacEncOpen(iSampleRate, iChannels,
+		lNumSampEncIn, lMaxBytesEncOut);
+	return hFaacEncoder != NULL;
+}
+
+int
+AacCodec::Encode(CVector<_SAMPLE>& vecsEncInData, unsigned long lNumSampEncIn, CVector<uint8_t>& vecsEncOutData, unsigned long lMaxBytesEncOut)
+{
+	int bytesEncoded = 0;
+	if (hFaacEncoder != NULL)
+	{
+		bytesEncoded = faacEncEncode(hFaacEncoder,
+			(int32_t *) &vecsEncInData[0],
+			lNumSampEncIn, &vecsEncOutData[0],
+			lMaxBytesEncOut);
+	}
+	return bytesEncoded;
+}
+
+void
+AacCodec::EncClose()
+{
+	if (hFaacEncoder != NULL)
+	{
+		faacEncClose(hFaacEncoder);
+		hFaacEncoder = NULL;
+	}
+}
+
+void
+AacCodec::EncSetBitrate(int iBitRate)
+{
+	if (hFaacEncoder != NULL)
+	{
+		/* Set encoder configuration */
+		faacEncConfigurationPtr CurEncFormat;
+		CurEncFormat = faacEncGetCurrentConfiguration(hFaacEncoder);
+		CurEncFormat->inputFormat = FAAC_INPUT_16BIT;
+		CurEncFormat->useTns = 1;
+		CurEncFormat->aacObjectType = LOW;
+		CurEncFormat->mpegVersion = MPEG4;
+		CurEncFormat->outputFormat = 0;	/* (0 = Raw; 1 = ADTS -> Raw) */
+		CurEncFormat->bitRate = iBitRate;
+		CurEncFormat->bandWidth = 0;	/* Let the encoder choose the bandwidth */
+		faacEncSetConfiguration(hFaacEncoder, CurEncFormat);
+	}
+}
+
+void
+AacCodec::EncUpdate(CAudioParam&)
+{
+}
+
diff --git a/src/sourcedecoders/aac_codec.h b/src/sourcedecoders/aac_codec.h
new file mode 100644
index 0000000..4e621af
--- /dev/null
+++ b/src/sourcedecoders/aac_codec.h
@@ -0,0 +1,69 @@
+/******************************************************************************\
+ *
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *  David Flamand
+ *
+ * Description:
+ *  See aac_codec.cpp
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#ifndef _AAC_CODEC_H_
+#define _AAC_CODEC_H_
+
+#include "AudioCodec.h"
+#ifdef USE_FAAD2_LIBRARY
+# include <neaacdec.h>
+#else
+# include "neaacdec_dll.h"
+#endif
+#ifdef USE_FAAC_LIBRARY
+# include <faac.h>
+#else
+# include "faac_dll.h"
+#endif
+
+class AacCodec : public CAudioCodec
+{
+public:
+	AacCodec();
+	virtual ~AacCodec();
+	/* Decoder */
+	virtual string DecGetVersion();
+	virtual bool CanDecode(CAudioParam::EAudCod eAudioCoding);
+	virtual bool DecOpen(CAudioParam& AudioParam, int *iAudioSampleRate, int *iLenDecOutPerChan);
+	virtual _SAMPLE* Decode(CVector<uint8_t>& vecbyPrepAudioFrame, int *iChannels, CAudioCodec::EDecError *eDecError);
+	virtual void DecClose();
+	virtual void DecUpdate(CAudioParam& AudioParam);
+	/* Encoder */
+	virtual string EncGetVersion();
+	virtual bool CanEncode(CAudioParam::EAudCod eAudioCoding);
+	virtual bool EncOpen(int iSampleRate, int iChannels, unsigned long *lNumSampEncIn, unsigned long *lMaxBytesEncOut);
+	virtual int Encode(CVector<_SAMPLE>& vecsEncInData, unsigned long lNumSampEncIn, CVector<uint8_t>& vecsEncOutData, unsigned long lMaxBytesEncOut);
+	virtual void EncClose();
+	virtual void EncSetBitrate(int iBitRate);
+	virtual void EncUpdate(CAudioParam& AudioParam);
+protected:
+	NeAACDecHandle hFaadDecoder;
+	faacEncHandle hFaacEncoder;
+};
+
+#endif // _AAC_CODEC_H_
diff --git a/src/sourcedecoders/faac_dll.h b/src/sourcedecoders/faac_dll.h
new file mode 100644
index 0000000..21b869a
--- /dev/null
+++ b/src/sourcedecoders/faac_dll.h
@@ -0,0 +1,143 @@
+#ifndef __FAAC_DLL_H
+# define __FAAC_DLL_H
+
+#ifdef _WIN32
+# include <windows.h>
+#else
+# include <dlfcn.h>
+#endif
+#if defined(_WIN32) && !defined(__MINGW32__)
+# ifndef FAACAPI
+#  define FAACAPI __stdcall
+# endif
+#else
+# ifndef FAACAPI
+#  define FAACAPI
+# endif
+#endif
+#pragma pack(push, 1)
+typedef struct {
+  void *ptr;
+  char *name;
+}
+psymodellist_t;
+
+typedef struct faacEncConfiguration
+{
+    /* config version */
+    int version;
+
+    /* library version */
+    char *name;
+
+    /* copyright string */
+    char *copyright;
+
+    /* MPEG version, 2 or 4 */
+    unsigned int mpegVersion;
+
+    /* AAC object type */
+    unsigned int aacObjectType;
+
+    /* Allow mid/side coding */
+    unsigned int allowMidside;
+
+    /* Use one of the channels as LFE channel */
+    unsigned int useLfe;
+
+    /* Use Temporal Noise Shaping */
+    unsigned int useTns;
+
+    /* bitrate / channel of AAC file */
+    unsigned long bitRate;
+
+    /* AAC file frequency bandwidth */
+    unsigned int bandWidth;
+
+    /* Quantizer quality */
+    unsigned long quantqual;
+
+    /* Bitstream output format (0 = Raw; 1 = ADTS) */
+    unsigned int outputFormat;
+
+    /* psychoacoustic model list */
+    psymodellist_t *psymodellist;
+
+    /* selected index in psymodellist */
+    unsigned int psymodelidx;
+
+    /*
+		PCM Sample Input Format
+		0	FAAC_INPUT_NULL			invalid, signifies a misconfigured config
+		1	FAAC_INPUT_16BIT		native endian 16bit
+		2	FAAC_INPUT_24BIT		native endian 24bit in 24 bits		(not implemented)
+		3	FAAC_INPUT_32BIT		native endian 24bit in 32 bits		(DEFAULT)
+		4	FAAC_INPUT_FLOAT		32bit floating point
+    */
+    unsigned int inputFormat;
+
+    /* block type enforcing (SHORTCTL_NORMAL/SHORTCTL_NOSHORT/SHORTCTL_NOLONG) */
+    int shortctl;
+
+	/*
+		Channel Remapping
+
+		Default			0, 1, 2, 3 ... 63  (64 is MAX_CHANNELS in coder.h)
+
+		WAVE 4.0		2, 0, 1, 3
+		WAVE 5.0		2, 0, 1, 3, 4
+		WAVE 5.1		2, 0, 1, 4, 5, 3
+		AIFF 5.1		2, 0, 3, 1, 4, 5
+	*/
+	int channel_map[64];
+
+} faacEncConfiguration, *faacEncConfigurationPtr;
+#  pragma pack(pop)
+
+/* MPEG ID's */
+#define MPEG2 1
+#define MPEG4 0
+
+/* AAC object types */
+#define MAIN 1
+#define LOW  2
+#define SSR  3
+#define LTP  4
+
+/* Input Formats */
+#define FAAC_INPUT_NULL    0
+#define FAAC_INPUT_16BIT   1
+#define FAAC_INPUT_24BIT   2
+#define FAAC_INPUT_32BIT   3
+#define FAAC_INPUT_FLOAT   4
+
+typedef void *faacEncHandle;
+typedef int (FAACAPI faacEncGetVersion_t)(char **, char **);
+
+
+typedef faacEncConfigurationPtr
+  (FAACAPI faacEncGetCurrentConfiguration_t)(faacEncHandle);
+
+
+typedef int (FAACAPI faacEncSetConfiguration_t)(faacEncHandle,
+				    faacEncConfigurationPtr);
+
+
+typedef faacEncHandle (FAACAPI faacEncOpen_t)(unsigned long,
+				  unsigned int,
+				  unsigned long *,
+				  unsigned long *);
+
+
+typedef int (FAACAPI faacEncGetDecoderSpecificInfo_t)(faacEncHandle, unsigned char **,
+					  unsigned long *);
+
+
+typedef int (FAACAPI faacEncEncode_t)(faacEncHandle, int32_t *, unsigned int,
+			 unsigned char *,
+			 unsigned int);
+
+
+typedef int (FAACAPI faacEncClose_t)(faacEncHandle);
+
+#endif
diff --git a/src/sourcedecoders/neaacdec_dll.h b/src/sourcedecoders/neaacdec_dll.h
new file mode 100644
index 0000000..5c227f8
--- /dev/null
+++ b/src/sourcedecoders/neaacdec_dll.h
@@ -0,0 +1,63 @@
+#ifndef __NEAACDEC_DLL_H
+#define __NEAACDEC_DLL_H
+
+#ifdef _WIN32
+# include <windows.h>
+# pragma pack(push, 8)
+# ifndef NEAACDECAPI
+#  ifdef _MSC_VER
+#    define NEAACDECAPI
+#  else
+#   define NEAACDECAPI __cdecl
+#  endif
+# endif
+#else
+# include <dlfcn.h>
+# ifndef NEAACDECAPI
+#  define NEAACDECAPI
+# endif
+#endif
+#define DRMCH_MONO          1
+#define DRMCH_STEREO        2
+#define DRMCH_SBR_MONO      3
+#define DRMCH_SBR_STEREO    4
+#define DRMCH_SBR_PS_STEREO 5
+
+typedef void *NeAACDecHandle;
+
+typedef struct NeAACDecFrameInfo
+{
+    unsigned long bytesconsumed;
+    unsigned long samples;
+    unsigned char channels;
+    unsigned char error;
+    unsigned long samplerate;
+
+    /* SBR: 0: off, 1: on; upsample, 2: on; downsampled, 3: off; upsampled */
+    unsigned char sbr;
+
+    /* MPEG-4 ObjectType */
+    unsigned char object_type;
+
+    /* AAC header type; MP4 will be signalled as RAW also */
+    unsigned char header_type;
+
+    /* multichannel configuration */
+    unsigned char num_front_channels;
+    unsigned char num_side_channels;
+    unsigned char num_back_channels;
+    unsigned char num_lfe_channels;
+    unsigned char channel_position[64];
+
+    /* PS: 0: off, 1: on */
+    unsigned char ps;
+} NeAACDecFrameInfo;
+
+typedef NeAACDecHandle (NEAACDECAPI NeAACDecOpen_t)(void);
+typedef char (NEAACDECAPI NeAACDecInitDRM_t)(NeAACDecHandle*, unsigned long, unsigned char);
+typedef void (NEAACDECAPI NeAACDecClose_t)(NeAACDecHandle);
+typedef void* (NEAACDECAPI NeAACDecDecode_t)(NeAACDecHandle,NeAACDecFrameInfo*,unsigned char *,unsigned long);
+
+#define FAAD2_VERSION "(dynamically loaded)"
+
+#endif
diff --git a/src/sourcedecoders/null_codec.cpp b/src/sourcedecoders/null_codec.cpp
new file mode 100644
index 0000000..489dcb9
--- /dev/null
+++ b/src/sourcedecoders/null_codec.cpp
@@ -0,0 +1,145 @@
+/******************************************************************************\
+ *
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *  David Flamand
+ *
+ * Description:
+ *  Null codec class, this codec is used when the requested codec is not
+ *  available.
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "null_codec.h"
+
+NullCodec::NullCodec()
+{
+}
+
+NullCodec::~NullCodec()
+{
+}
+
+/* Decoder */
+
+string NullCodec::DecGetVersion()
+{
+	return string();
+}
+
+bool NullCodec::CanDecode(CAudioParam::EAudCod eAudioCoding)
+{
+	(void)eAudioCoding;
+	return false;
+}
+
+bool NullCodec::DecOpen(CAudioParam& AudioParam, int *iAudioSampleRate, int *iLenDecOutPerChan)
+{
+	int iSampleRate = 24000;
+	switch (AudioParam.eAudioSamplRate)
+	{
+	case CAudioParam::AS_8_KHZ:
+		iSampleRate = 8000;
+		break;
+	case CAudioParam::AS_12KHZ:
+		iSampleRate = 12000;
+		break;
+	case CAudioParam::AS_16KHZ:
+		iSampleRate = 16000;
+		break;
+	case CAudioParam::AS_24KHZ:
+		iSampleRate = 24000;
+		break;
+	case CAudioParam::AS_48KHZ:
+		iSampleRate = 48000;
+		break;
+        case CAudioParam::AS_19_2KHZ: // TODO
+        case CAudioParam::AS_32KHZ: // TODO
+        case CAudioParam::AS_38_4KHZ: // TODO
+        case CAudioParam::AS_9_6_KHZ: // TODO
+        case CAudioParam::AS_RESERVED: // can't happen
+		;
+	}
+	*iAudioSampleRate = iSampleRate;
+    *iLenDecOutPerChan = AUD_DEC_TRANSFROM_LENGTH;
+	return false;
+}
+
+_SAMPLE* NullCodec::Decode(CVector<uint8_t>& vecbyPrepAudioFrame, int *iChannels, EDecError *eDecError)
+{
+	(void)vecbyPrepAudioFrame;
+	*iChannels = 1;
+	*eDecError = DECODER_ERROR_UNKNOWN;
+	return NULL;
+}
+
+void NullCodec::DecClose()
+{
+}
+
+void NullCodec::DecUpdate(CAudioParam& AudioParam)
+{
+	(void)AudioParam;
+}
+
+/* Encoder */
+
+string NullCodec::EncGetVersion()
+{
+	return string();
+}
+
+bool NullCodec::CanEncode(CAudioParam::EAudCod eAudioCoding)
+{
+	(void)eAudioCoding;
+	return false;
+}
+
+bool NullCodec::EncOpen(int iSampleRate, int iChannels, unsigned long *lNumSampEncIn, unsigned long *lMaxBytesEncOut)
+{
+	(void)iSampleRate;
+	(void)iChannels;
+	*lNumSampEncIn = 1;
+	*lMaxBytesEncOut = 1;
+	return false;
+}
+
+int NullCodec::Encode(CVector<_SAMPLE>& vecsEncInData, unsigned long lNumSampEncIn, CVector<uint8_t>& vecsEncOutData, unsigned long lMaxBytesEncOut)
+{
+	(void)vecsEncInData;
+	(void)lNumSampEncIn;
+	(void)vecsEncOutData;
+	(void)lMaxBytesEncOut;
+	return 0;
+}
+
+void NullCodec::EncClose()
+{
+}
+
+void NullCodec::EncSetBitrate(int iBitRate)
+{
+	(void)iBitRate;
+}
+
+void NullCodec::EncUpdate(CAudioParam& AudioParam)
+{
+	(void)AudioParam;
+}
diff --git a/src/sourcedecoders/null_codec.h b/src/sourcedecoders/null_codec.h
new file mode 100644
index 0000000..3d53d31
--- /dev/null
+++ b/src/sourcedecoders/null_codec.h
@@ -0,0 +1,56 @@
+/******************************************************************************\
+ *
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *  David Flamand
+ *
+ * Description:
+ *  See null_codec.cpp
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#ifndef _NULL_CODEC_H_
+#define _NULL_CODEC_H_
+
+#include "AudioCodec.h"
+
+class NullCodec : public CAudioCodec
+{
+public:
+	NullCodec();
+	virtual ~NullCodec();
+	/* Decoder */
+	virtual string DecGetVersion();
+	virtual bool CanDecode(CAudioParam::EAudCod eAudioCoding);
+	virtual bool DecOpen(CAudioParam& AudioParam, int *iAudioSampleRate, int *iLenDecOutPerChan);
+	virtual _SAMPLE* Decode(CVector<uint8_t>& vecbyPrepAudioFrame, int *iChannels, CAudioCodec::EDecError *eDecError);
+	virtual void DecClose();
+	virtual void DecUpdate(CAudioParam& AudioParam);
+	/* Encoder */
+	virtual string EncGetVersion();
+	virtual bool CanEncode(CAudioParam::EAudCod eAudioCoding);
+	virtual bool EncOpen(int iSampleRate, int iChannels, unsigned long *lNumSampEncIn, unsigned long *lMaxBytesEncOut);
+	virtual int Encode(CVector<_SAMPLE>& vecsEncInData, unsigned long lNumSampEncIn, CVector<uint8_t>& vecsEncOutData, unsigned long lMaxBytesEncOut);
+	virtual void EncClose();
+	virtual void EncSetBitrate(int iBitRate);
+	virtual void EncUpdate(CAudioParam& AudioParam);
+};
+
+#endif // _NULL_CODEC_H_
diff --git a/src/sourcedecoders/opus_codec.cpp b/src/sourcedecoders/opus_codec.cpp
new file mode 100644
index 0000000..43e645d
--- /dev/null
+++ b/src/sourcedecoders/opus_codec.cpp
@@ -0,0 +1,671 @@
+/******************************************************************************\
+ *
+ * Copyright (c) 2001-2014-2001-2014
+ *
+ * Author(s):
+ *  David Flamand
+ *
+ * Description:
+ *  Opus codec class
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include <cstdlib>
+#include <cstdio>
+#include <cstring>
+#include "opus_codec.h"
+#ifndef USE_OPUS_LIBRARY
+# include "../util/LibraryLoader.h"
+#endif
+
+#undef EPRINTF
+#define EPRINTF(...) do {fprintf(stderr, __VA_ARGS__); fflush(stderr);} while(0)
+//#define EPRINTF(...) {}
+#undef CRC_BYTES
+#define CRC_BYTES 1 // For testing purpose, MUST be set to ONE
+
+
+#ifndef USE_OPUS_LIBRARY
+static void* hOpusLib;
+static opus_encode_t *opus_encode;
+static opus_encoder_create_t *opus_encoder_create;
+static opus_encoder_ctl_t *opus_encoder_ctl;
+static opus_encoder_destroy_t *opus_encoder_destroy;
+static opus_decode_t *opus_decode;
+static opus_decoder_create_t *opus_decoder_create;
+static opus_decoder_ctl_t *opus_decoder_ctl;
+static opus_decoder_destroy_t *opus_decoder_destroy;
+static opus_get_version_string_t *opus_get_version_string;
+static opus_strerror_t *opus_strerror;
+static const LIBFUNC LibFuncs[] = {
+	{ "opus_decode",             (void**)&opus_decode,             (void*)NULL },
+	{ "opus_decoder_create",     (void**)&opus_decoder_create,     (void*)NULL },
+	{ "opus_decoder_ctl",        (void**)&opus_decoder_ctl,        (void*)NULL },
+	{ "opus_decoder_destroy",    (void**)&opus_decoder_destroy,    (void*)NULL },
+	{ "opus_encode",             (void**)&opus_encode,             (void*)NULL },
+	{ "opus_encoder_create",     (void**)&opus_encoder_create,     (void*)NULL },
+	{ "opus_encoder_ctl",        (void**)&opus_encoder_ctl,        (void*)NULL },
+	{ "opus_encoder_destroy",    (void**)&opus_encoder_destroy,    (void*)NULL },
+	{ "opus_get_version_string", (void**)&opus_get_version_string, (void*)NULL },
+	{ "opus_strerror",           (void**)&opus_strerror,           (void*)NULL },
+	{ NULL, NULL, NULL }
+};
+# if defined(_WIN32)
+static const char* LibNames[] = { "libopus-0.dll", "libopus.dll", "opus.dll", NULL };
+# elif defined(__APPLE__)
+static const char* LibNames[] = { "@executable_path/../Frameworks/libopus.dylib", NULL };
+# else
+static const char* LibNames[] = { "libopus.so.0", "libopus.so", NULL };
+# endif
+#endif
+
+
+//###################################################################################################
+//# Common
+
+
+const char *opusGetVersion(
+	void
+	)
+{
+	return opus_get_version_string();
+}
+
+void opusSetupParam(
+	CAudioParam &AudioParam,
+	int toc
+	)
+{
+	static const CAudioParam::EOPUSBandwidth bandwidth_silk[] =
+		{ CAudioParam::OB_NB, CAudioParam::OB_MB, CAudioParam::OB_WB };
+	static const CAudioParam::EOPUSBandwidth bandwidth_celt[] =
+		{ CAudioParam::OB_NB, CAudioParam::OB_WB, CAudioParam::OB_SWB, CAudioParam::OB_FB };
+	int stereo, config, mode;
+	stereo = (toc >> 2) & 0x01;
+	config = (toc >> 3) & 0x1F;
+	mode = (config >> 2) & 0x07;
+	if (config < 12)
+	{
+		AudioParam.eOPUSSubCod = CAudioParam::OS_SILK;
+		AudioParam.eOPUSBandwidth = bandwidth_silk[mode];
+	}
+	else if (config < 16)
+	{
+		AudioParam.eOPUSSubCod = CAudioParam::OS_HYBRID;
+		AudioParam.eOPUSBandwidth = bandwidth_celt[((config >> 1) & 1) + 2];
+	}
+	else
+	{
+		AudioParam.eOPUSSubCod = CAudioParam::OS_CELT;
+		AudioParam.eOPUSBandwidth = bandwidth_celt[mode-4];
+	}
+	AudioParam.eOPUSChan = stereo ? CAudioParam::OC_STEREO : CAudioParam::OC_MONO;
+}
+
+
+//###################################################################################################
+//# Encoder
+
+
+opus_encoder *opusEncOpen(
+	unsigned long sampleRate,
+	unsigned int numChannels,
+	unsigned int bytes_per_frame,
+	unsigned long *inputSamples,
+	unsigned long *maxOutputBytes
+	)
+{
+	opus_encoder *enc;
+	OpusEncoder *oe;
+	int ret;
+
+	enc = (opus_encoder*)calloc(1, sizeof(opus_encoder));
+	if (!enc)
+	{
+		return NULL;
+	}
+	enc->CRCObject = new CCRC();
+	if (!enc->CRCObject)
+	{
+		free(enc);
+		return NULL;
+	}
+
+	enc->samples_per_channel = OPUS_PCM_FRAME_SIZE;
+	enc->samplerate = sampleRate;
+	enc->channels   = numChannels;
+	enc->bytes_per_frame = bytes_per_frame;
+	int frequency = (int)((float)enc->samplerate / (float)enc->samples_per_channel);
+	int frame_extra_bytes = CRC_BYTES;
+	int frames_per_packet = (int)((float)enc->samples_per_channel / (float)enc->samplerate / (1.0f / (float)frequency));
+//	int bitrate_by_bytes = enc->samplerate * 8 / enc->samples_per_channel;
+//	int bitrate = bitrate_by_bytes * (bytes_per_frame - frame_extra_bytes);
+	enc->frames_per_packet = frames_per_packet;
+
+    *inputSamples = enc->samples_per_channel * numChannels;
+    *maxOutputBytes = OPUS_MAX_DATA_FRAME;
+    *maxOutputBytes += frame_extra_bytes;
+
+//	EPRINTF("opusEncOpen: sampleRate=%i numChannels=%i inputSamples=%i maxOutputBytes=%i bytes_per_frame=%i bitrate=%i\n", (int)sampleRate, (int)numChannels, (int)*inputSamples, (int)*maxOutputBytes, (int)bytes_per_frame, bitrate);
+
+	oe = opus_encoder_create(sampleRate, numChannels, OPUS_APPLICATION_AUDIO, &ret);
+	if (!oe)
+		EPRINTF("opusEncOpen: opus_encoder_create returned: %s\n", opus_strerror(ret));
+/*	ret = opus_encoder_ctl(oe, OPUS_SET_FORCE_CHANNELS(numChannels));
+	if (ret != OPUS_OK)
+		EPRINTF("opusEncOpen: OPUS_SET_FORCE_CHANNELS returned: %s\n", opus_strerror(ret));
+	ret = opus_encoder_ctl(oe, OPUS_SET_BANDWIDTH(bandwidth));
+	if (ret != OPUS_OK)
+		EPRINTF("opusEncOpen: OPUS_SET_BANDWIDTH returned: %s\n", opus_strerror(ret));
+	ret = opus_encoder_ctl(oe, OPUS_SET_MAX_BANDWIDTH(bandwidth));
+	if (ret != OPUS_OK)
+		EPRINTF("opusEncOpen: OPUS_SET_MAX_BANDWIDTH returned: %s\n", opus_strerror(ret));
+	ret = opus_encoder_ctl(oe, OPUS_SET_BITRATE(bitrate));
+	if (ret != OPUS_OK)
+		EPRINTF("opusEncOpen: OPUS_SET_BITRATE returned: %s\n", opus_strerror(ret));
+*/	ret = opus_encoder_ctl(oe, OPUS_SET_VBR(0));
+	if (ret != OPUS_OK)
+		EPRINTF("opusEncOpen: OPUS_SET_VBR returned: %s\n", opus_strerror(ret));
+	ret = opus_encoder_ctl(oe, OPUS_SET_VBR_CONSTRAINT(0));
+	if (ret != OPUS_OK)
+		EPRINTF("opusEncOpen: OPUS_SET_VBR_CONSTRAINT returned: %s\n", opus_strerror(ret));
+	ret = opus_encoder_ctl(oe, OPUS_SET_COMPLEXITY(10));
+	if (ret != OPUS_OK)
+		EPRINTF("opusEncOpen: OPUS_SET_COMPLEXITY returned: %s\n", opus_strerror(ret));
+/*	ret = opus_encoder_ctl(oe, OPUS_SET_PACKET_LOSS_PERC(0));
+	if (ret != OPUS_OK)
+		EPRINTF("opusEncOpen: OPUS_SET_PACKET_LOSS_PERC returned: %s\n", opus_strerror(ret));
+*/	ret = opus_encoder_ctl(oe, OPUS_SET_LSB_DEPTH(16));
+	if (ret != OPUS_OK)
+		EPRINTF("opusEncOpen: OPUS_SET_LSB_DEPTH returned: %s\n", opus_strerror(ret));
+/*	ret = opus_encoder_ctl(oe, OPUS_SET_INBAND_FEC(0));
+	if (ret != OPUS_OK)
+		EPRINTF("opusEncOpen: OPUS_SET_INBAND_FEC returned: %s\n", opus_strerror(ret));
+	ret = opus_encoder_ctl(oe, OPUS_SET_SIGNAL(OPUS_SIGNAL_MUSIC));
+	if (ret != OPUS_OK)
+		EPRINTF("opusEncOpen: OPUS_SET_SIGNAL returned: %s\n", opus_strerror(ret));
+*/	ret = opus_encoder_ctl(oe, OPUS_SET_DTX(0));
+	if (ret != OPUS_OK)
+		EPRINTF("opusEncOpen: OPUS_SET_DTX_REQUEST returned: %s\n", opus_strerror(ret));
+
+	enc->oe = oe;
+	return enc;
+}
+
+
+int opusEncEncode(opus_encoder *enc,
+	opus_int16 *inputBuffer,
+	unsigned int samplesInput,
+	unsigned char *outputBuffer,
+	unsigned int bufferSize
+	)
+{
+	if (bufferSize < (OPUS_MAX_DATA_FRAME + CRC_BYTES))
+	{
+		EPRINTF("opusEncEncode: bufferSize %i < %i\n", bufferSize, OPUS_MAX_DATA_FRAME + CRC_BYTES);
+		return 0;
+	}
+	OpusEncoder *oe = enc->oe;
+
+	int frame_extra_bytes = CRC_BYTES;
+	int frame_bytes, i, pcm_pos;
+	int channels = enc->channels;
+	int frames_per_packet = 1;//enc->frames_per_packet;
+	int samples_per_channel = samplesInput / channels / frames_per_packet;
+//	int max_data = (bufferSize-frame_extra_bytes) / frames_per_packet;
+	int max_data = enc->bytes_per_frame - frame_extra_bytes;
+//	EPRINTF("opusEncEncode: samplesInput=%i samples_per_channel=%i\n", (int)samplesInput, samples_per_channel);
+	for (i=0, frame_bytes=0, pcm_pos=0; i<frames_per_packet; i++, pcm_pos+=samples_per_channel*channels)
+	{
+		frame_bytes += opus_encode(oe, ((opus_int16*)inputBuffer)+pcm_pos, samples_per_channel, &outputBuffer[frame_extra_bytes+frame_bytes], max_data);
+		if (frame_bytes < 0)
+			EPRINTF("opusEncEncode: opus_encode returned: %s\n", opus_strerror(frame_bytes));
+	}
+#if CRC_BYTES != 0
+	enc->CRCObject->Reset(8*CRC_BYTES);
+	for (i=CRC_BYTES; i<frame_bytes; i++)
+		enc->CRCObject->AddByte(outputBuffer[i]);
+	int crc = enc->CRCObject->GetCRC();
+# if CRC_BYTES == 1
+	outputBuffer[0] = crc;
+# elif CRC_BYTES == 2
+	outputBuffer[0] = (crc >> 8) & 0xFF;
+	outputBuffer[1] = (crc >> 0) & 0xFF;
+# else
+#  error wrong CRC_BYTES
+# endif
+#endif
+	return frame_bytes + frame_extra_bytes;
+}
+
+
+int opusEncClose(
+	opus_encoder *enc
+	)
+{
+//	EPRINTF("opusEncClose\n");
+	if (enc)
+	{
+		if (enc->CRCObject)
+			delete enc->CRCObject;
+		if (enc->oe)
+			opus_encoder_destroy(enc->oe);
+		free(enc);
+	}
+	return 0;
+}
+
+void opusEncSetParam(opus_encoder *enc,
+		CAudioParam& AudioParam
+	)
+{
+	int ret, value;
+
+	/* Reset, must be the first */
+	if (AudioParam.bOPUSRequestReset)
+	{
+		ret = opus_encoder_ctl(enc->oe, OPUS_RESET_STATE);
+		if (ret != OPUS_OK)
+			EPRINTF("opusEncSetParam: OPUS_RESET_STATE returned: %s\n", opus_strerror(ret));
+	}
+
+	/* Channels */
+	switch (AudioParam.eOPUSChan)
+	{
+	case CAudioParam::OC_MONO:
+		value = 1;
+		break;
+	default:
+	case CAudioParam::OC_STEREO:
+		value = 2;
+		break;
+	}
+	ret = opus_encoder_ctl(enc->oe, OPUS_SET_FORCE_CHANNELS(value));
+	if (ret != OPUS_OK)
+		EPRINTF("opusEncSetParam: OPUS_SET_FORCE_CHANNELS returned: %s\n", opus_strerror(ret));
+
+	/* Bandwidth */
+	switch (AudioParam.eOPUSBandwidth)
+	{
+	case CAudioParam::OB_NB:
+		value = OPUS_BANDWIDTH_NARROWBAND;
+		break;
+	case CAudioParam::OB_MB:
+		value = OPUS_BANDWIDTH_MEDIUMBAND;
+		break;
+	case CAudioParam::OB_WB:
+		value = OPUS_BANDWIDTH_WIDEBAND;
+		break;
+	case CAudioParam::OB_SWB:
+		value = OPUS_BANDWIDTH_SUPERWIDEBAND;
+		break;
+	default:
+	case CAudioParam::OB_FB:
+		value = OPUS_BANDWIDTH_FULLBAND;
+		break;
+	}
+	ret = opus_encoder_ctl(enc->oe, OPUS_SET_BANDWIDTH(value));
+	if (ret != OPUS_OK)
+		EPRINTF("opusEncSetParam: OPUS_SET_BANDWIDTH returned: %s\n", opus_strerror(ret));
+	ret = opus_encoder_ctl(enc->oe, OPUS_SET_MAX_BANDWIDTH(value));
+	if (ret != OPUS_OK)
+		EPRINTF("opusEncSetParam: OPUS_SET_MAX_BANDWIDTH returned: %s\n", opus_strerror(ret));
+
+	/* FEC */
+    value = AudioParam.bOPUSForwardErrorCorrection;
+	ret = opus_encoder_ctl(enc->oe, OPUS_SET_INBAND_FEC(value));
+	if (ret != OPUS_OK)
+		EPRINTF("opusEncSetParam: OPUS_SET_INBAND_FEC returned: %s\n", opus_strerror(ret));
+	ret = opus_encoder_ctl(enc->oe, OPUS_SET_PACKET_LOSS_PERC(value ? 100 : 0));
+	if (ret != OPUS_OK)
+		EPRINTF("opusEncSetParam: OPUS_SET_PACKET_LOSS_PERC returned: %s\n", opus_strerror(ret));
+
+	if (AudioParam.bOPUSRequestReset)
+	{
+		AudioParam.bOPUSRequestReset = FALSE;
+
+		/* Signal */
+		switch (AudioParam.eOPUSSignal)
+		{
+		case CAudioParam::OG_VOICE:
+			value = OPUS_SIGNAL_VOICE;
+			break;
+		default:
+		case CAudioParam::OG_MUSIC:
+			value = OPUS_SIGNAL_MUSIC;
+			break;
+		}
+		ret = opus_encoder_ctl(enc->oe, OPUS_SET_SIGNAL(value));
+		if (ret != OPUS_OK)
+			EPRINTF("opusEncSetParam: OPUS_SET_SIGNAL returned: %s\n", opus_strerror(ret));
+
+		/* Application */
+		switch (AudioParam.eOPUSApplication)
+		{
+		case CAudioParam::OA_VOIP:
+			value = OPUS_APPLICATION_VOIP;
+			break;
+		default:
+		case CAudioParam::OA_AUDIO:
+			value = OPUS_APPLICATION_AUDIO;
+			break;
+		}
+		ret = opus_encoder_ctl(enc->oe, OPUS_SET_APPLICATION(value));
+		if (ret != OPUS_OK)
+			EPRINTF("opusEncSetParam: OPUS_SET_APPLICATION returned: %s\n", opus_strerror(ret));
+	}
+}
+
+
+//###################################################################################################
+//# Decoder
+
+
+opus_decoder *opusDecOpen(
+	void
+	)
+{
+//	EPRINTF("opusDecOpen\n");
+	opus_decoder *dec = (opus_decoder*)calloc(1, sizeof(opus_decoder));
+	if (dec)
+	{
+		dec->CRCObject = new CCRC();
+		if (!dec->CRCObject)
+		{
+			free(dec);
+			dec = NULL;
+		}
+	}
+	return dec;
+}
+
+void opusDecClose(
+	opus_decoder *dec
+	)
+{
+//	EPRINTF("opusDecClose\n");
+	if (dec)
+	{
+		if (dec->CRCObject)
+			delete dec->CRCObject;
+		if (dec->od)
+			opus_decoder_destroy(dec->od);
+		free(dec);
+	}
+}
+
+int opusDecInit(
+	opus_decoder *dec,
+	unsigned long samplerate,
+	unsigned char channels
+	)
+{
+	/* Check for invalid param */
+	if (!dec || !samplerate || channels<1 || channels>2)
+	{
+		EPRINTF("opusDecInit: invalid param: dec=%p samplerate=%lu channels=%i\n", dec, samplerate, (int)channels);
+		return 1; /* error */
+	}
+	/* Check if something have changed */
+	if (!dec->changed && dec->samplerate==(int)samplerate && dec->channels==(int)channels)
+		return 0;
+	if (dec->od)
+	{
+		int ret = opus_decoder_ctl(dec->od, OPUS_RESET_STATE);
+		if (ret != OPUS_OK)
+			EPRINTF("opusDecInit: OPUS_RESET_STATE returned: %s\n", opus_strerror(ret));
+	}
+	else
+	{
+		int error;
+		OpusDecoder *od = opus_decoder_create(samplerate, channels, &error);
+		if (!od)
+			EPRINTF("opusDecInit: opus_decoder_create returned: %s\n", opus_strerror(error));
+		dec->od = od;
+	}
+	dec->samplerate = samplerate;
+	dec->channels = channels;
+	dec->changed = 0;
+	return 0;
+}
+
+void *opusDecDecode(
+	opus_decoder *dec,
+	CAudioCodec::EDecError *eDecError,
+	int *iChannels,
+	unsigned char *buffer,
+	unsigned long buffer_size
+	)
+{
+	int frames_per_packet, pcm_len, frame_bytes, sub_frame_bytes, i, pos, pcm_pos;
+	int crc_ok=0, corrupted=0;
+	int frame_extra_bytes = CRC_BYTES;
+	frames_per_packet = 1;
+	frame_bytes = buffer_size - frame_extra_bytes;
+	if (frame_bytes>=1 && frame_bytes<=OPUS_MAX_DATA_FRAME)
+	{
+#if CRC_BYTES != 0
+		dec->CRCObject->Reset(8*CRC_BYTES);
+		for (i=CRC_BYTES; i<frame_bytes; i++)
+			dec->CRCObject->AddByte(buffer[i]);
+		int crc = dec->CRCObject->GetCRC();
+# if CRC_BYTES == 1
+		crc_ok = crc == buffer[0];
+# elif CRC_BYTES == 2
+		crc_ok = crc == ((buffer[0]<<8)|buffer[1]);
+# else
+#  error wrong CRC_BYTES
+# endif
+#endif
+		sub_frame_bytes = frame_bytes / frames_per_packet;
+		for (i=0,pos=0,pcm_pos=0; i<frames_per_packet; i++, pos+=sub_frame_bytes, pcm_pos+=pcm_len*dec->channels)
+		{
+			pcm_len = opus_decode(dec->od, &buffer[frame_extra_bytes+pos], sub_frame_bytes, dec->out_pcm+pcm_pos, OPUS_MAX_PCM_FRAME, !crc_ok);
+			if (pcm_len < 0)
+			{
+//				EPRINTF("opusDecDecode: opus_decode returned: %s\n", opus_strerror(pcm_len));
+				pcm_len = 0;
+				corrupted = 1;
+			}
+		}
+	}
+	else
+	{
+		corrupted = 1;
+	}
+
+	if (corrupted)
+	{
+		memset(dec->out_pcm, 0, OPUS_PCM_FRAME_SIZE * sizeof(opus_int16) * dec->channels);
+		EPRINTF("opusDecDecode: DECODER_ERROR_CORRUPTED\n");
+		*eDecError =  CAudioCodec::DECODER_ERROR_CORRUPTED;
+	}
+	else if (!crc_ok)
+	{
+		EPRINTF("opusDecDecode: DECODER_ERROR_CRC\n");
+		*eDecError =  CAudioCodec::DECODER_ERROR_CRC;
+	}
+	else
+	{
+		*eDecError = CAudioCodec::DECODER_ERROR_OK;
+		if (frame_bytes >= 1)
+			dec->last_good_toc = buffer[frame_extra_bytes];
+	}
+
+	*iChannels = dec->channels;
+	dec->changed = 1;
+	return dec->out_pcm;
+}
+
+
+/******************************************************************************/
+/* Implementation *************************************************************/
+
+OpusCodec::OpusCodec() :
+	hOpusDecoder(NULL), hOpusEncoder(NULL)
+{
+#ifndef USE_OPUS_LIBRARY
+	if (hOpusLib == NULL)
+	{
+		hOpusLib = CLibraryLoader::Load(LibNames, LibFuncs);
+		if (!hOpusLib)
+			cerr << "No usable Opus library found" << endl;
+		else
+			cerr << "Got Opus library" << endl;
+	}
+#endif
+}
+OpusCodec::~OpusCodec()
+{
+	DecClose();
+	EncClose();
+}
+
+/******************************************************************************/
+/* Decoder Implementation *****************************************************/
+
+string
+OpusCodec::DecGetVersion()
+{
+	return string("Opus version: ") + opusGetVersion();
+}
+
+bool
+OpusCodec::CanDecode(CAudioParam::EAudCod eAudioCoding)
+{
+#ifndef USE_OPUS_LIBRARY
+	return hOpusLib && eAudioCoding == CAudioParam::AC_OPUS;
+#else
+	return eAudioCoding == CAudioParam::AC_OPUS;
+#endif
+}
+
+bool
+OpusCodec::DecOpen(CAudioParam& AudioParam, int *iAudioSampleRate, int *iLenDecOutPerChan)
+{
+	(void)AudioParam;
+	const int iSampleRate = 48000;
+	if (hOpusDecoder == NULL)
+		hOpusDecoder = opusDecOpen();
+	if (hOpusDecoder != NULL)
+		opusDecInit(hOpusDecoder, iSampleRate, 2);
+	*iAudioSampleRate = iSampleRate;
+	*iLenDecOutPerChan = AUD_DEC_TRANSFROM_LENGTH;
+	return hOpusDecoder != NULL;
+}
+
+_SAMPLE*
+OpusCodec::Decode(CVector<uint8_t>& vecbyPrepAudioFrame, int *iChannels, CAudioCodec::EDecError *eDecError)
+{
+	_SAMPLE *sample = NULL;
+	if (hOpusDecoder != NULL)
+	{
+		sample = (_SAMPLE *)opusDecDecode(hOpusDecoder,
+			eDecError,
+			iChannels,
+			&vecbyPrepAudioFrame[0],
+			vecbyPrepAudioFrame.size());
+	}
+	return sample;
+}
+
+void
+OpusCodec::DecClose()
+{
+	if (hOpusDecoder != NULL)
+	{
+		opusDecClose(hOpusDecoder);
+		hOpusDecoder = NULL;
+	}
+}
+
+void
+OpusCodec::DecUpdate(CAudioParam& AudioParam)
+{
+	if (hOpusDecoder != NULL)
+	{
+        opusSetupParam(AudioParam, hOpusDecoder->last_good_toc);
+	}
+}
+
+/******************************************************************************/
+/* Encoder Implementation *****************************************************/
+
+string
+OpusCodec::EncGetVersion()
+{
+	return DecGetVersion();
+}
+
+bool
+OpusCodec::CanEncode(CAudioParam::EAudCod eAudioCoding)
+{
+	return CanDecode(eAudioCoding);
+}
+
+bool
+OpusCodec::EncOpen(int iSampleRate, int iChannels, unsigned long *lNumSampEncIn, unsigned long *lMaxBytesEncOut)
+{
+	hOpusEncoder = opusEncOpen(iSampleRate, iChannels,
+		0, lNumSampEncIn, lMaxBytesEncOut);
+	return hOpusEncoder != NULL;
+}
+
+int
+OpusCodec::Encode(CVector<_SAMPLE>& vecsEncInData, unsigned long lNumSampEncIn, CVector<uint8_t>& vecsEncOutData, unsigned long lMaxBytesEncOut)
+{
+	int bytesEncoded = 0;
+	if (hOpusEncoder != NULL)
+	{
+		bytesEncoded = opusEncEncode(hOpusEncoder,
+			(opus_int16 *) &vecsEncInData[0],
+			lNumSampEncIn, &vecsEncOutData[0],
+			lMaxBytesEncOut);
+	}
+	return bytesEncoded;
+}
+
+void
+OpusCodec::EncClose()
+{
+	if (hOpusEncoder != NULL)
+	{
+		opusEncClose(hOpusEncoder);
+		hOpusEncoder = NULL;
+	}
+}
+
+void
+OpusCodec::EncSetBitrate(int iBitRate)
+{
+	if (hOpusEncoder != NULL)
+	{
+		hOpusEncoder->bytes_per_frame = iBitRate / SIZEOF__BYTE;
+	}
+}
+
+void
+OpusCodec::EncUpdate(CAudioParam& AudioParam)
+{
+	if (hOpusEncoder != NULL)
+	{
+		opusEncSetParam(hOpusEncoder, AudioParam);
+	}
+}
+
diff --git a/src/sourcedecoders/opus_codec.h b/src/sourcedecoders/opus_codec.h
new file mode 100644
index 0000000..7c06dc2
--- /dev/null
+++ b/src/sourcedecoders/opus_codec.h
@@ -0,0 +1,168 @@
+/******************************************************************************\
+ *
+ * Copyright (c) 2001-2014-2001-2014
+ *
+ * Author(s):
+ *  David Flamand
+ *
+ * Description:
+ *  See opus_codec.cpp
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#ifndef _OPUS_CODEC_H_
+#define _OPUS_CODEC_H_
+
+#include "AudioCodec.h"
+#include "../GlobalDefinitions.h"
+#include "../Parameter.h"
+#include "../util/CRC.h"
+#ifdef USE_OPUS_LIBRARY
+# include <opus/opus.h>
+#else
+# include "opus_dll.h"
+#endif
+
+#define OPUS_DESCRIPTION "Opus Interactive Audio Codec"
+#define OPUS_WEBSITE_LINK "http://www.opus-codec.org"
+#define OPUS_PCM_FRAME_SIZE 960  // (in samples) = 48000Hz * 0.020ms
+#define OPUS_MAX_PCM_FRAME 3840  // (in samples) = 48000Hz * 0.060ms
+#define OPUS_MAX_DATA_FRAME 1276 // (in bytes)   = CELT CBR BITRATE 510400
+
+/*************
+ *  generic
+ */
+
+bool opus_init(
+	void
+	);
+
+const char *opusGetVersion(
+	void
+	);
+
+void opusSetupParam(
+	CAudioParam &AudioParam,
+	int toc
+	);
+
+/*************
+ *  encoder
+ */
+
+typedef struct _opus_encoder {
+	OpusEncoder *oe;
+	int samplerate;
+	int channels;
+	int bitrate;
+	int samples_per_channel;
+	int frames_per_packet;
+	int bytes_per_frame;
+	CCRC *CRCObject;
+} opus_encoder;
+
+opus_encoder *opusEncOpen(
+	unsigned long sampleRate,
+	unsigned int numChannels,
+	unsigned int bytes_per_frame,
+	unsigned long *inputSamples,
+	unsigned long *maxOutputBytes
+	);
+
+int opusEncEncode(opus_encoder *enc,
+	int32_t *inputBuffer,
+	unsigned int samplesInput,
+	unsigned char *outputBuffer,
+	unsigned int bufferSize
+	);
+
+int opusEncClose(
+	opus_encoder *enc
+	);
+
+void opusEncSetParam(opus_encoder *enc,
+	CAudioParam& AudioParam
+	);
+
+/*************
+ *  decoder
+ */
+
+typedef struct _opus_decoder {
+	OpusDecoder *od;
+	int samplerate;
+	int channels;
+	int changed;
+	int last_good_toc;
+	CCRC *CRCObject;
+	opus_int16 out_pcm[OPUS_MAX_PCM_FRAME * 2]; // 2 = stereo
+} opus_decoder;
+
+opus_decoder *opusDecOpen(
+	void
+	);
+
+void opusDecClose(
+	opus_decoder *dec
+	);
+
+int opusDecInit(
+	opus_decoder *dec,
+	unsigned long samplerate,
+	unsigned char channels
+	);
+
+void *opusDecDecode(
+	opus_decoder *dec,
+	unsigned char *error,
+	unsigned char *channels,
+	unsigned char *buffer,
+	unsigned long buffer_size
+	);
+
+/*************
+ *  class
+ */
+
+class OpusCodec : public CAudioCodec
+{
+public:
+	OpusCodec();
+	virtual ~OpusCodec();
+	/* Decoder */
+	virtual string DecGetVersion();
+	virtual bool CanDecode(CAudioParam::EAudCod eAudioCoding);
+	virtual bool DecOpen(CAudioParam& AudioParam, int *iAudioSampleRate, int *iLenDecOutPerChan);
+	virtual _SAMPLE* Decode(CVector<uint8_t>& vecbyPrepAudioFrame, int *iChannels, CAudioCodec::EDecError *eDecError);
+	virtual void DecClose();
+	virtual void DecUpdate(CAudioParam& AudioParam);
+	/* Encoder */
+	virtual string EncGetVersion();
+	virtual bool CanEncode(CAudioParam::EAudCod eAudioCoding);
+	virtual bool EncOpen(int iSampleRate, int iChannels, unsigned long *lNumSampEncIn, unsigned long *lMaxBytesEncOut);
+	virtual int Encode(CVector<_SAMPLE>& vecsEncInData, unsigned long lNumSampEncIn, CVector<uint8_t>& vecsEncOutData, unsigned long lMaxBytesEncOut);
+	virtual void EncClose();
+	virtual void EncSetBitrate(int iBitRate);
+	virtual void EncUpdate(CAudioParam& AudioParam);
+protected:
+	opus_decoder *hOpusDecoder;
+	opus_encoder *hOpusEncoder;
+};
+
+#endif // _OPUS_CODEC_H_
diff --git a/src/sourcedecoders/opus_dll.h b/src/sourcedecoders/opus_dll.h
new file mode 100644
index 0000000..a8f9c2b
--- /dev/null
+++ b/src/sourcedecoders/opus_dll.h
@@ -0,0 +1,1426 @@
+#ifndef __OPUS_DLL_H
+#define __OPUS_DLL_H
+
+#ifdef _WIN32
+# include <windows.h>
+#else
+# include <dlfcn.h>
+#endif
+
+/* (C) COPYRIGHT 1994-2002 Xiph.Org Foundation */
+/* Modified by Jean-Marc Valin */
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - 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.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``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 COPYRIGHT OWNER
+   OR CONTRIBUTORS 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.
+*/
+/* opus_types.h based on ogg_types.h from libogg */
+
+/**
+   @file opus_types.h
+   @brief Opus reference implementation types
+*/
+#ifndef OPUS_TYPES_H
+#define OPUS_TYPES_H
+
+/* Use the real stdint.h if it's there (taken from Paul Hsieh's pstdint.h) */
+#if (defined(__STDC__) && __STDC__ && __STDC_VERSION__ >= 199901L) || (defined(__GNUC__) && (defined(_STDINT_H) || defined(_STDINT_H_)) || defined (HAVE_STDINT_H))
+#include <stdint.h>
+
+   typedef int16_t opus_int16;
+   typedef uint16_t opus_uint16;
+   typedef int32_t opus_int32;
+   typedef uint32_t opus_uint32;
+#elif defined(_WIN32)
+
+#  if defined(__CYGWIN__)
+#    include <_G_config.h>
+     typedef _G_int32_t opus_int32;
+     typedef _G_uint32_t opus_uint32;
+     typedef _G_int16 opus_int16;
+     typedef _G_uint16 opus_uint16;
+#  elif defined(__MINGW32__)
+     typedef short opus_int16;
+     typedef unsigned short opus_uint16;
+     typedef int opus_int32;
+     typedef unsigned int opus_uint32;
+#  elif defined(__MWERKS__)
+     typedef int opus_int32;
+     typedef unsigned int opus_uint32;
+     typedef short opus_int16;
+     typedef unsigned short opus_uint16;
+#  else
+     /* MSVC/Borland */
+     typedef __int32 opus_int32;
+     typedef unsigned __int32 opus_uint32;
+     typedef __int16 opus_int16;
+     typedef unsigned __int16 opus_uint16;
+#  endif
+
+#elif defined(__MACOS__)
+
+#  include <sys/types.h>
+   typedef SInt16 opus_int16;
+   typedef UInt16 opus_uint16;
+   typedef SInt32 opus_int32;
+   typedef UInt32 opus_uint32;
+
+#elif (defined(__APPLE__) && defined(__MACH__)) /* MacOS X Framework build */
+
+#  include <sys/types.h>
+   typedef int16_t opus_int16;
+   typedef u_int16_t opus_uint16;
+   typedef int32_t opus_int32;
+   typedef u_int32_t opus_uint32;
+
+#elif defined(__BEOS__)
+
+   /* Be */
+#  include <inttypes.h>
+   typedef int16 opus_int16;
+   typedef u_int16 opus_uint16;
+   typedef int32_t opus_int32;
+   typedef u_int32_t opus_uint32;
+
+#elif defined (__EMX__)
+
+   /* OS/2 GCC */
+   typedef short opus_int16;
+   typedef unsigned short opus_uint16;
+   typedef int opus_int32;
+   typedef unsigned int opus_uint32;
+
+#elif defined (DJGPP)
+
+   /* DJGPP */
+   typedef short opus_int16;
+   typedef unsigned short opus_uint16;
+   typedef int opus_int32;
+   typedef unsigned int opus_uint32;
+
+#elif defined(R5900)
+
+   /* PS2 EE */
+   typedef int opus_int32;
+   typedef unsigned opus_uint32;
+   typedef short opus_int16;
+   typedef unsigned short opus_uint16;
+
+#elif defined(__SYMBIAN32__)
+
+   /* Symbian GCC */
+   typedef signed short opus_int16;
+   typedef unsigned short opus_uint16;
+   typedef signed int opus_int32;
+   typedef unsigned int opus_uint32;
+
+#elif defined(CONFIG_TI_C54X) || defined (CONFIG_TI_C55X)
+
+   typedef short opus_int16;
+   typedef unsigned short opus_uint16;
+   typedef long opus_int32;
+   typedef unsigned long opus_uint32;
+
+#elif defined(CONFIG_TI_C6X)
+
+   typedef short opus_int16;
+   typedef unsigned short opus_uint16;
+   typedef int opus_int32;
+   typedef unsigned int opus_uint32;
+
+#else
+
+   /* Give up, take a reasonable guess */
+   typedef short opus_int16;
+   typedef unsigned short opus_uint16;
+   typedef int opus_int32;
+   typedef unsigned int opus_uint32;
+
+#endif
+
+#define opus_int         int                     /* used for counters etc; at least 16 bits */
+#define opus_int64       long long
+#define opus_int8        signed char
+
+#define opus_uint        unsigned int            /* used for counters etc; at least 16 bits */
+#define opus_uint64      unsigned long long
+#define opus_uint8       unsigned char
+
+#endif  /* OPUS_TYPES_H */
+/* Copyright (c) 2010-2011 Xiph.Org Foundation, Skype Limited
+   Written by Jean-Marc Valin and Koen Vos */
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - 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.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``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 COPYRIGHT OWNER
+   OR CONTRIBUTORS 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.
+*/
+
+/**
+ * @file opus_defines.h
+ * @brief Opus reference implementation constants
+ */
+
+#ifndef OPUS_DEFINES_H
+#define OPUS_DEFINES_H
+
+/*#include "opus_types.h"*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @defgroup opus_errorcodes Error codes
+ * @{
+ */
+/** No error @hideinitializer*/
+#define OPUS_OK                0
+/** One or more invalid/out of range arguments @hideinitializer*/
+#define OPUS_BAD_ARG          -1
+/** The mode struct passed is invalid @hideinitializer*/
+#define OPUS_BUFFER_TOO_SMALL -2
+/** An internal error was detected @hideinitializer*/
+#define OPUS_INTERNAL_ERROR   -3
+/** The compressed data passed is corrupted @hideinitializer*/
+#define OPUS_INVALID_PACKET   -4
+/** Invalid/unsupported request number @hideinitializer*/
+#define OPUS_UNIMPLEMENTED    -5
+/** An encoder or decoder structure is invalid or already freed @hideinitializer*/
+#define OPUS_INVALID_STATE    -6
+/** Memory allocation has failed @hideinitializer*/
+#define OPUS_ALLOC_FAIL       -7
+/**@}*/
+
+/** @cond OPUS_INTERNAL_DOC */
+/**Export control for opus functions */
+
+#if defined(__GNUC__) && defined(OPUS_BUILD)
+# define OPUS_EXPORT __attribute__ ((visibility ("default")))
+#elif defined(WIN32) && !defined(__MINGW32__)
+# ifdef OPUS_BUILD
+#   define OPUS_EXPORT __declspec(dllexport)
+# else
+#   define OPUS_EXPORT
+# endif
+#else
+# define OPUS_EXPORT
+#endif
+
+# if !defined(OPUS_GNUC_PREREQ)
+#  if defined(__GNUC__)&&defined(__GNUC_MINOR__)
+#   define OPUS_GNUC_PREREQ(_maj,_min) \
+ ((__GNUC__<<16)+__GNUC_MINOR__>=((_maj)<<16)+(_min))
+#  else
+#   define OPUS_GNUC_PREREQ(_maj,_min) 0
+#  endif
+# endif
+
+#if (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L) )
+# if OPUS_GNUC_PREREQ(3,0)
+#  define OPUS_RESTRICT __restrict__
+# elif (defined(_MSC_VER) && _MSC_VER >= 1400)
+#  define OPUS_RESTRICT __restrict
+# else
+#  define OPUS_RESTRICT
+# endif
+#else
+# define OPUS_RESTRICT restrict
+#endif
+
+/**Warning attributes for opus functions
+  * NONNULL is not used in OPUS_BUILD to avoid the compiler optimizing out
+  * some paranoid null checks. */
+#if defined(__GNUC__) && OPUS_GNUC_PREREQ(3, 4)
+# define OPUS_WARN_UNUSED_RESULT __attribute__ ((__warn_unused_result__))
+#else
+# define OPUS_WARN_UNUSED_RESULT
+#endif
+#if !defined(OPUS_BUILD) && defined(__GNUC__) && OPUS_GNUC_PREREQ(3, 4)
+# define OPUS_ARG_NONNULL(_x)  __attribute__ ((__nonnull__(_x)))
+#else
+# define OPUS_ARG_NONNULL(_x)
+#endif
+
+/** These are the actual Encoder CTL ID numbers.
+  * They should not be used directly by applications.
+  * In general, SETs should be even and GETs should be odd.*/
+#define OPUS_SET_APPLICATION_REQUEST         4000
+#define OPUS_GET_APPLICATION_REQUEST         4001
+#define OPUS_SET_BITRATE_REQUEST             4002
+#define OPUS_GET_BITRATE_REQUEST             4003
+#define OPUS_SET_MAX_BANDWIDTH_REQUEST       4004
+#define OPUS_GET_MAX_BANDWIDTH_REQUEST       4005
+#define OPUS_SET_VBR_REQUEST                 4006
+#define OPUS_GET_VBR_REQUEST                 4007
+#define OPUS_SET_BANDWIDTH_REQUEST           4008
+#define OPUS_GET_BANDWIDTH_REQUEST           4009
+#define OPUS_SET_COMPLEXITY_REQUEST          4010
+#define OPUS_GET_COMPLEXITY_REQUEST          4011
+#define OPUS_SET_INBAND_FEC_REQUEST          4012
+#define OPUS_GET_INBAND_FEC_REQUEST          4013
+#define OPUS_SET_PACKET_LOSS_PERC_REQUEST    4014
+#define OPUS_GET_PACKET_LOSS_PERC_REQUEST    4015
+#define OPUS_SET_DTX_REQUEST                 4016
+#define OPUS_GET_DTX_REQUEST                 4017
+#define OPUS_SET_VBR_CONSTRAINT_REQUEST      4020
+#define OPUS_GET_VBR_CONSTRAINT_REQUEST      4021
+#define OPUS_SET_FORCE_CHANNELS_REQUEST      4022
+#define OPUS_GET_FORCE_CHANNELS_REQUEST      4023
+#define OPUS_SET_SIGNAL_REQUEST              4024
+#define OPUS_GET_SIGNAL_REQUEST              4025
+#define OPUS_GET_LOOKAHEAD_REQUEST           4027
+/* #define OPUS_RESET_STATE 4028 */
+#define OPUS_GET_SAMPLE_RATE_REQUEST         4029
+#define OPUS_GET_FINAL_RANGE_REQUEST         4031
+#define OPUS_GET_PITCH_REQUEST               4033
+#define OPUS_SET_GAIN_REQUEST                4034
+#define OPUS_GET_GAIN_REQUEST                4045
+#define OPUS_SET_LSB_DEPTH_REQUEST           4036
+#define OPUS_GET_LSB_DEPTH_REQUEST           4037
+
+/* Macros to trigger compilation errors when the wrong types are provided to a CTL */
+#define __opus_check_int(x) (((void)((x) == (opus_int32)0)), (opus_int32)(x))
+#define __opus_check_int_ptr(ptr) ((ptr) + ((ptr) - (opus_int32*)(ptr)))
+#define __opus_check_uint_ptr(ptr) ((ptr) + ((ptr) - (opus_uint32*)(ptr)))
+/** @endcond */
+
+/** @defgroup opus_ctlvalues Pre-defined values for CTL interface
+  * @see opus_genericctls, opus_encoderctls
+  * @{
+  */
+/* Values for the various encoder CTLs */
+#define OPUS_AUTO                           -1000 /**<Auto/default setting @hideinitializer*/
+#define OPUS_BITRATE_MAX                       -1 /**<Maximum bitrate @hideinitializer*/
+
+/** Best for most VoIP/videoconference applications where listening quality and intelligibility matter most
+ * @hideinitializer */
+#define OPUS_APPLICATION_VOIP                2048
+/** Best for broadcast/high-fidelity application where the decoded audio should be as close as possible to the input
+ * @hideinitializer */
+#define OPUS_APPLICATION_AUDIO               2049
+/** Only use when lowest-achievable latency is what matters most. Voice-optimized modes cannot be used.
+ * @hideinitializer */
+#define OPUS_APPLICATION_RESTRICTED_LOWDELAY 2051
+
+#define OPUS_SIGNAL_VOICE                    3001 /**< Signal being encoded is voice */
+#define OPUS_SIGNAL_MUSIC                    3002 /**< Signal being encoded is music */
+#define OPUS_BANDWIDTH_NARROWBAND            1101 /**< 4 kHz bandpass @hideinitializer*/
+#define OPUS_BANDWIDTH_MEDIUMBAND            1102 /**< 6 kHz bandpass @hideinitializer*/
+#define OPUS_BANDWIDTH_WIDEBAND              1103 /**< 8 kHz bandpass @hideinitializer*/
+#define OPUS_BANDWIDTH_SUPERWIDEBAND         1104 /**<12 kHz bandpass @hideinitializer*/
+#define OPUS_BANDWIDTH_FULLBAND              1105 /**<20 kHz bandpass @hideinitializer*/
+
+/**@}*/
+
+
+/** @defgroup opus_encoderctls Encoder related CTLs
+  *
+  * These are convenience macros for use with the \c opus_encode_ctl
+  * interface. They are used to generate the appropriate series of
+  * arguments for that call, passing the correct type, size and so
+  * on as expected for each particular request.
+  *
+  * Some usage examples:
+  *
+  * @code
+  * int ret;
+  * ret = opus_encoder_ctl(enc_ctx, OPUS_SET_BANDWIDTH(OPUS_AUTO));
+  * if (ret != OPUS_OK) return ret;
+  *
+  * opus_int32 rate;
+  * opus_encoder_ctl(enc_ctx, OPUS_GET_BANDWIDTH(&rate));
+  *
+  * opus_encoder_ctl(enc_ctx, OPUS_RESET_STATE);
+  * @endcode
+  *
+  * @see opus_genericctls, opus_encoder
+  * @{
+  */
+
+/** Configures the encoder's computational complexity.
+  * The supported range is 0-10 inclusive with 10 representing the highest complexity.
+  * @see OPUS_GET_COMPLEXITY
+  * @param[in] x <tt>opus_int32</tt>: Allowed values: 0-10, inclusive.
+  *
+  * @hideinitializer */
+#define OPUS_SET_COMPLEXITY(x) OPUS_SET_COMPLEXITY_REQUEST, __opus_check_int(x)
+/** Gets the encoder's complexity configuration.
+  * @see OPUS_SET_COMPLEXITY
+  * @param[out] x <tt>opus_int32 *</tt>: Returns a value in the range 0-10,
+  *                                      inclusive.
+  * @hideinitializer */
+#define OPUS_GET_COMPLEXITY(x) OPUS_GET_COMPLEXITY_REQUEST, __opus_check_int_ptr(x)
+
+/** Configures the bitrate in the encoder.
+  * Rates from 500 to 512000 bits per second are meaningful, as well as the
+  * special values #OPUS_AUTO and #OPUS_BITRATE_MAX.
+  * The value #OPUS_BITRATE_MAX can be used to cause the codec to use as much
+  * rate as it can, which is useful for controlling the rate by adjusting the
+  * output buffer size.
+  * @see OPUS_GET_BITRATE
+  * @param[in] x <tt>opus_int32</tt>: Bitrate in bits per second. The default
+  *                                   is determined based on the number of
+  *                                   channels and the input sampling rate.
+  * @hideinitializer */
+#define OPUS_SET_BITRATE(x) OPUS_SET_BITRATE_REQUEST, __opus_check_int(x)
+/** Gets the encoder's bitrate configuration.
+  * @see OPUS_SET_BITRATE
+  * @param[out] x <tt>opus_int32 *</tt>: Returns the bitrate in bits per second.
+  *                                      The default is determined based on the
+  *                                      number of channels and the input
+  *                                      sampling rate.
+  * @hideinitializer */
+#define OPUS_GET_BITRATE(x) OPUS_GET_BITRATE_REQUEST, __opus_check_int_ptr(x)
+
+/** Enables or disables variable bitrate (VBR) in the encoder.
+  * The configured bitrate may not be met exactly because frames must
+  * be an integer number of bytes in length.
+  * @warning Only the MDCT mode of Opus can provide hard CBR behavior.
+  * @see OPUS_GET_VBR
+  * @see OPUS_SET_VBR_CONSTRAINT
+  * @param[in] x <tt>opus_int32</tt>: Allowed values:
+  * <dl>
+  * <dt>0</dt><dd>Hard CBR. For LPC/hybrid modes at very low bit-rate, this can
+  *               cause noticeable quality degradation.</dd>
+  * <dt>1</dt><dd>VBR (default). The exact type of VBR is controlled by
+  *               #OPUS_SET_VBR_CONSTRAINT.</dd>
+  * </dl>
+  * @hideinitializer */
+#define OPUS_SET_VBR(x) OPUS_SET_VBR_REQUEST, __opus_check_int(x)
+/** Determine if variable bitrate (VBR) is enabled in the encoder.
+  * @see OPUS_SET_VBR
+  * @see OPUS_GET_VBR_CONSTRAINT
+  * @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
+  * <dl>
+  * <dt>0</dt><dd>Hard CBR.</dd>
+  * <dt>1</dt><dd>VBR (default). The exact type of VBR may be retrieved via
+  *               #OPUS_GET_VBR_CONSTRAINT.</dd>
+  * </dl>
+  * @hideinitializer */
+#define OPUS_GET_VBR(x) OPUS_GET_VBR_REQUEST, __opus_check_int_ptr(x)
+
+/** Enables or disables constrained VBR in the encoder.
+  * This setting is ignored when the encoder is in CBR mode.
+  * @warning Only the MDCT mode of Opus currently heeds the constraint.
+  *  Speech mode ignores it completely, hybrid mode may fail to obey it
+  *  if the LPC layer uses more bitrate than the constraint would have
+  *  permitted.
+  * @see OPUS_GET_VBR_CONSTRAINT
+  * @see OPUS_SET_VBR
+  * @param[in] x <tt>opus_int32</tt>: Allowed values:
+  * <dl>
+  * <dt>0</dt><dd>Unconstrained VBR.</dd>
+  * <dt>1</dt><dd>Constrained VBR (default). This creates a maximum of one
+  *               frame of buffering delay assuming a transport with a
+  *               serialization speed of the nominal bitrate.</dd>
+  * </dl>
+  * @hideinitializer */
+#define OPUS_SET_VBR_CONSTRAINT(x) OPUS_SET_VBR_CONSTRAINT_REQUEST, __opus_check_int(x)
+/** Determine if constrained VBR is enabled in the encoder.
+  * @see OPUS_SET_VBR_CONSTRAINT
+  * @see OPUS_GET_VBR
+  * @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
+  * <dl>
+  * <dt>0</dt><dd>Unconstrained VBR.</dd>
+  * <dt>1</dt><dd>Constrained VBR (default).</dd>
+  * </dl>
+  * @hideinitializer */
+#define OPUS_GET_VBR_CONSTRAINT(x) OPUS_GET_VBR_CONSTRAINT_REQUEST, __opus_check_int_ptr(x)
+
+/** Configures mono/stereo forcing in the encoder.
+  * This can force the encoder to produce packets encoded as either mono or
+  * stereo, regardless of the format of the input audio. This is useful when
+  * the caller knows that the input signal is currently a mono source embedded
+  * in a stereo stream.
+  * @see OPUS_GET_FORCE_CHANNELS
+  * @param[in] x <tt>opus_int32</tt>: Allowed values:
+  * <dl>
+  * <dt>#OPUS_AUTO</dt><dd>Not forced (default)</dd>
+  * <dt>1</dt>         <dd>Forced mono</dd>
+  * <dt>2</dt>         <dd>Forced stereo</dd>
+  * </dl>
+  * @hideinitializer */
+#define OPUS_SET_FORCE_CHANNELS(x) OPUS_SET_FORCE_CHANNELS_REQUEST, __opus_check_int(x)
+/** Gets the encoder's forced channel configuration.
+  * @see OPUS_SET_FORCE_CHANNELS
+  * @param[out] x <tt>opus_int32 *</tt>:
+  * <dl>
+  * <dt>#OPUS_AUTO</dt><dd>Not forced (default)</dd>
+  * <dt>1</dt>         <dd>Forced mono</dd>
+  * <dt>2</dt>         <dd>Forced stereo</dd>
+  * </dl>
+  * @hideinitializer */
+#define OPUS_GET_FORCE_CHANNELS(x) OPUS_GET_FORCE_CHANNELS_REQUEST, __opus_check_int_ptr(x)
+
+/** Configures the maximum bandpass that the encoder will select automatically.
+  * Applications should normally use this instead of #OPUS_SET_BANDWIDTH
+  * (leaving that set to the default, #OPUS_AUTO). This allows the
+  * application to set an upper bound based on the type of input it is
+  * providing, but still gives the encoder the freedom to reduce the bandpass
+  * when the bitrate becomes too low, for better overall quality.
+  * @see OPUS_GET_MAX_BANDWIDTH
+  * @param[in] x <tt>opus_int32</tt>: Allowed values:
+  * <dl>
+  * <dt>OPUS_BANDWIDTH_NARROWBAND</dt>    <dd>4 kHz passband</dd>
+  * <dt>OPUS_BANDWIDTH_MEDIUMBAND</dt>    <dd>6 kHz passband</dd>
+  * <dt>OPUS_BANDWIDTH_WIDEBAND</dt>      <dd>8 kHz passband</dd>
+  * <dt>OPUS_BANDWIDTH_SUPERWIDEBAND</dt><dd>12 kHz passband</dd>
+  * <dt>OPUS_BANDWIDTH_FULLBAND</dt>     <dd>20 kHz passband (default)</dd>
+  * </dl>
+  * @hideinitializer */
+#define OPUS_SET_MAX_BANDWIDTH(x) OPUS_SET_MAX_BANDWIDTH_REQUEST, __opus_check_int(x)
+
+/** Gets the encoder's configured maximum allowed bandpass.
+  * @see OPUS_SET_MAX_BANDWIDTH
+  * @param[out] x <tt>opus_int32 *</tt>: Allowed values:
+  * <dl>
+  * <dt>#OPUS_BANDWIDTH_NARROWBAND</dt>    <dd>4 kHz passband</dd>
+  * <dt>#OPUS_BANDWIDTH_MEDIUMBAND</dt>    <dd>6 kHz passband</dd>
+  * <dt>#OPUS_BANDWIDTH_WIDEBAND</dt>      <dd>8 kHz passband</dd>
+  * <dt>#OPUS_BANDWIDTH_SUPERWIDEBAND</dt><dd>12 kHz passband</dd>
+  * <dt>#OPUS_BANDWIDTH_FULLBAND</dt>     <dd>20 kHz passband (default)</dd>
+  * </dl>
+  * @hideinitializer */
+#define OPUS_GET_MAX_BANDWIDTH(x) OPUS_GET_MAX_BANDWIDTH_REQUEST, __opus_check_int_ptr(x)
+
+/** Sets the encoder's bandpass to a specific value.
+  * This prevents the encoder from automatically selecting the bandpass based
+  * on the available bitrate. If an application knows the bandpass of the input
+  * audio it is providing, it should normally use #OPUS_SET_MAX_BANDWIDTH
+  * instead, which still gives the encoder the freedom to reduce the bandpass
+  * when the bitrate becomes too low, for better overall quality.
+  * @see OPUS_GET_BANDWIDTH
+  * @param[in] x <tt>opus_int32</tt>: Allowed values:
+  * <dl>
+  * <dt>#OPUS_AUTO</dt>                    <dd>(default)</dd>
+  * <dt>#OPUS_BANDWIDTH_NARROWBAND</dt>    <dd>4 kHz passband</dd>
+  * <dt>#OPUS_BANDWIDTH_MEDIUMBAND</dt>    <dd>6 kHz passband</dd>
+  * <dt>#OPUS_BANDWIDTH_WIDEBAND</dt>      <dd>8 kHz passband</dd>
+  * <dt>#OPUS_BANDWIDTH_SUPERWIDEBAND</dt><dd>12 kHz passband</dd>
+  * <dt>#OPUS_BANDWIDTH_FULLBAND</dt>     <dd>20 kHz passband</dd>
+  * </dl>
+  * @hideinitializer */
+#define OPUS_SET_BANDWIDTH(x) OPUS_SET_BANDWIDTH_REQUEST, __opus_check_int(x)
+
+/** Configures the type of signal being encoded.
+  * This is a hint which helps the encoder's mode selection.
+  * @see OPUS_GET_SIGNAL
+  * @param[in] x <tt>opus_int32</tt>: Allowed values:
+  * <dl>
+  * <dt>#OPUS_AUTO</dt>        <dd>(default)</dd>
+  * <dt>#OPUS_SIGNAL_VOICE</dt><dd>Bias thresholds towards choosing LPC or Hybrid modes.</dd>
+  * <dt>#OPUS_SIGNAL_MUSIC</dt><dd>Bias thresholds towards choosing MDCT modes.</dd>
+  * </dl>
+  * @hideinitializer */
+#define OPUS_SET_SIGNAL(x) OPUS_SET_SIGNAL_REQUEST, __opus_check_int(x)
+/** Gets the encoder's configured signal type.
+  * @see OPUS_SET_SIGNAL
+  * @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
+  * <dl>
+  * <dt>#OPUS_AUTO</dt>        <dd>(default)</dd>
+  * <dt>#OPUS_SIGNAL_VOICE</dt><dd>Bias thresholds towards choosing LPC or Hybrid modes.</dd>
+  * <dt>#OPUS_SIGNAL_MUSIC</dt><dd>Bias thresholds towards choosing MDCT modes.</dd>
+  * </dl>
+  * @hideinitializer */
+#define OPUS_GET_SIGNAL(x) OPUS_GET_SIGNAL_REQUEST, __opus_check_int_ptr(x)
+
+
+/** Configures the encoder's intended application.
+  * The initial value is a mandatory argument to the encoder_create function.
+  * @see OPUS_GET_APPLICATION
+  * @param[in] x <tt>opus_int32</tt>: Returns one of the following values:
+  * <dl>
+  * <dt>#OPUS_APPLICATION_VOIP</dt>
+  * <dd>Process signal for improved speech intelligibility.</dd>
+  * <dt>#OPUS_APPLICATION_AUDIO</dt>
+  * <dd>Favor faithfulness to the original input.</dd>
+  * <dt>#OPUS_APPLICATION_RESTRICTED_LOWDELAY</dt>
+  * <dd>Configure the minimum possible coding delay by disabling certain modes
+  * of operation.</dd>
+  * </dl>
+  * @hideinitializer */
+#define OPUS_SET_APPLICATION(x) OPUS_SET_APPLICATION_REQUEST, __opus_check_int(x)
+/** Gets the encoder's configured application.
+  * @see OPUS_SET_APPLICATION
+  * @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
+  * <dl>
+  * <dt>#OPUS_APPLICATION_VOIP</dt>
+  * <dd>Process signal for improved speech intelligibility.</dd>
+  * <dt>#OPUS_APPLICATION_AUDIO</dt>
+  * <dd>Favor faithfulness to the original input.</dd>
+  * <dt>#OPUS_APPLICATION_RESTRICTED_LOWDELAY</dt>
+  * <dd>Configure the minimum possible coding delay by disabling certain modes
+  * of operation.</dd>
+  * </dl>
+  * @hideinitializer */
+#define OPUS_GET_APPLICATION(x) OPUS_GET_APPLICATION_REQUEST, __opus_check_int_ptr(x)
+
+/** Gets the sampling rate the encoder or decoder was initialized with.
+  * This simply returns the <code>Fs</code> value passed to opus_encoder_init()
+  * or opus_decoder_init().
+  * @param[out] x <tt>opus_int32 *</tt>: Sampling rate of encoder or decoder.
+  * @hideinitializer
+  */
+#define OPUS_GET_SAMPLE_RATE(x) OPUS_GET_SAMPLE_RATE_REQUEST, __opus_check_int_ptr(x)
+
+/** Gets the total samples of delay added by the entire codec.
+  * This can be queried by the encoder and then the provided number of samples can be
+  * skipped on from the start of the decoder's output to provide time aligned input
+  * and output. From the perspective of a decoding application the real data begins this many
+  * samples late.
+  *
+  * The decoder contribution to this delay is identical for all decoders, but the
+  * encoder portion of the delay may vary from implementation to implementation,
+  * version to version, or even depend on the encoder's initial configuration.
+  * Applications needing delay compensation should call this CTL rather than
+  * hard-coding a value.
+  * @param[out] x <tt>opus_int32 *</tt>:   Number of lookahead samples
+  * @hideinitializer */
+#define OPUS_GET_LOOKAHEAD(x) OPUS_GET_LOOKAHEAD_REQUEST, __opus_check_int_ptr(x)
+
+/** Configures the encoder's use of inband forward error correction (FEC).
+  * @note This is only applicable to the LPC layer
+  * @see OPUS_GET_INBAND_FEC
+  * @param[in] x <tt>opus_int32</tt>: Allowed values:
+  * <dl>
+  * <dt>0</dt><dd>Disable inband FEC (default).</dd>
+  * <dt>1</dt><dd>Enable inband FEC.</dd>
+  * </dl>
+  * @hideinitializer */
+#define OPUS_SET_INBAND_FEC(x) OPUS_SET_INBAND_FEC_REQUEST, __opus_check_int(x)
+/** Gets encoder's configured use of inband forward error correction.
+  * @see OPUS_SET_INBAND_FEC
+  * @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
+  * <dl>
+  * <dt>0</dt><dd>Inband FEC disabled (default).</dd>
+  * <dt>1</dt><dd>Inband FEC enabled.</dd>
+  * </dl>
+  * @hideinitializer */
+#define OPUS_GET_INBAND_FEC(x) OPUS_GET_INBAND_FEC_REQUEST, __opus_check_int_ptr(x)
+
+/** Configures the encoder's expected packet loss percentage.
+  * Higher values with trigger progressively more loss resistant behavior in the encoder
+  * at the expense of quality at a given bitrate in the lossless case, but greater quality
+  * under loss.
+  * @see OPUS_GET_PACKET_LOSS_PERC
+  * @param[in] x <tt>opus_int32</tt>:   Loss percentage in the range 0-100, inclusive (default: 0).
+  * @hideinitializer */
+#define OPUS_SET_PACKET_LOSS_PERC(x) OPUS_SET_PACKET_LOSS_PERC_REQUEST, __opus_check_int(x)
+/** Gets the encoder's configured packet loss percentage.
+  * @see OPUS_SET_PACKET_LOSS_PERC
+  * @param[out] x <tt>opus_int32 *</tt>: Returns the configured loss percentage
+  *                                      in the range 0-100, inclusive (default: 0).
+  * @hideinitializer */
+#define OPUS_GET_PACKET_LOSS_PERC(x) OPUS_GET_PACKET_LOSS_PERC_REQUEST, __opus_check_int_ptr(x)
+
+/** Configures the encoder's use of discontinuous transmission (DTX).
+  * @note This is only applicable to the LPC layer
+  * @see OPUS_GET_DTX
+  * @param[in] x <tt>opus_int32</tt>: Allowed values:
+  * <dl>
+  * <dt>0</dt><dd>Disable DTX (default).</dd>
+  * <dt>1</dt><dd>Enabled DTX.</dd>
+  * </dl>
+  * @hideinitializer */
+#define OPUS_SET_DTX(x) OPUS_SET_DTX_REQUEST, __opus_check_int(x)
+/** Gets encoder's configured use of discontinuous transmission.
+  * @see OPUS_SET_DTX
+  * @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
+  * <dl>
+  * <dt>0</dt><dd>DTX disabled (default).</dd>
+  * <dt>1</dt><dd>DTX enabled.</dd>
+  * </dl>
+  * @hideinitializer */
+#define OPUS_GET_DTX(x) OPUS_GET_DTX_REQUEST, __opus_check_int_ptr(x)
+/**@}*/
+
+/** @defgroup opus_genericctls Generic CTLs
+  *
+  * These macros are used with the \c opus_decoder_ctl and
+  * \c opus_encoder_ctl calls to generate a particular
+  * request.
+  *
+  * When called on an \c OpusDecoder they apply to that
+  * particular decoder instance. When called on an
+  * \c OpusEncoder they apply to the corresponding setting
+  * on that encoder instance, if present.
+  *
+  * Some usage examples:
+  *
+  * @code
+  * int ret;
+  * opus_int32 pitch;
+  * ret = opus_decoder_ctl(dec_ctx, OPUS_GET_PITCH(&pitch));
+  * if (ret == OPUS_OK) return ret;
+  *
+  * opus_encoder_ctl(enc_ctx, OPUS_RESET_STATE);
+  * opus_decoder_ctl(dec_ctx, OPUS_RESET_STATE);
+  *
+  * opus_int32 enc_bw, dec_bw;
+  * opus_encoder_ctl(enc_ctx, OPUS_GET_BANDWIDTH(&enc_bw));
+  * opus_decoder_ctl(dec_ctx, OPUS_GET_BANDWIDTH(&dec_bw));
+  * if (enc_bw != dec_bw) {
+  *   printf("packet bandwidth mismatch!\n");
+  * }
+  * @endcode
+  *
+  * @see opus_encoder, opus_decoder_ctl, opus_encoder_ctl, opus_decoderctls, opus_encoderctls
+  * @{
+  */
+
+/** Resets the codec state to be equivalent to a freshly initialized state.
+  * This should be called when switching streams in order to prevent
+  * the back to back decoding from giving different results from
+  * one at a time decoding.
+  * @hideinitializer */
+#define OPUS_RESET_STATE 4028
+
+/** Gets the final state of the codec's entropy coder.
+  * This is used for testing purposes,
+  * The encoder and decoder state should be identical after coding a payload
+  * (assuming no data corruption or software bugs)
+  *
+  * @param[out] x <tt>opus_uint32 *</tt>: Entropy coder state
+  *
+  * @hideinitializer */
+#define OPUS_GET_FINAL_RANGE(x) OPUS_GET_FINAL_RANGE_REQUEST, __opus_check_uint_ptr(x)
+
+/** Gets the pitch of the last decoded frame, if available.
+  * This can be used for any post-processing algorithm requiring the use of pitch,
+  * e.g. time stretching/shortening. If the last frame was not voiced, or if the
+  * pitch was not coded in the frame, then zero is returned.
+  *
+  * This CTL is only implemented for decoder instances.
+  *
+  * @param[out] x <tt>opus_int32 *</tt>: pitch period at 48 kHz (or 0 if not available)
+  *
+  * @hideinitializer */
+#define OPUS_GET_PITCH(x) OPUS_GET_PITCH_REQUEST, __opus_check_int_ptr(x)
+
+/** Gets the encoder's configured bandpass or the decoder's last bandpass.
+  * @see OPUS_SET_BANDWIDTH
+  * @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
+  * <dl>
+  * <dt>#OPUS_AUTO</dt>                    <dd>(default)</dd>
+  * <dt>#OPUS_BANDWIDTH_NARROWBAND</dt>    <dd>4 kHz passband</dd>
+  * <dt>#OPUS_BANDWIDTH_MEDIUMBAND</dt>    <dd>6 kHz passband</dd>
+  * <dt>#OPUS_BANDWIDTH_WIDEBAND</dt>      <dd>8 kHz passband</dd>
+  * <dt>#OPUS_BANDWIDTH_SUPERWIDEBAND</dt><dd>12 kHz passband</dd>
+  * <dt>#OPUS_BANDWIDTH_FULLBAND</dt>     <dd>20 kHz passband</dd>
+  * </dl>
+  * @hideinitializer */
+#define OPUS_GET_BANDWIDTH(x) OPUS_GET_BANDWIDTH_REQUEST, __opus_check_int_ptr(x)
+
+/** Configures the depth of signal being encoded.
+  * This is a hint which helps the encoder identify silence and near-silence.
+  * @see OPUS_GET_LSB_DEPTH
+  * @param[in] x <tt>opus_int32</tt>: Input precision in bits, between 8 and 24
+  *                                   (default: 24).
+  * @hideinitializer */
+#define OPUS_SET_LSB_DEPTH(x) OPUS_SET_LSB_DEPTH_REQUEST, __opus_check_int(x)
+/** Gets the encoder's configured signal depth.
+  * @see OPUS_SET_LSB_DEPTH
+  * @param[out] x <tt>opus_int32 *</tt>: Input precision in bits, between 8 and
+  *                                      24 (default: 24).
+  * @hideinitializer */
+#define OPUS_GET_LSB_DEPTH(x) OPUS_GET_LSB_DEPTH_REQUEST, __opus_check_int_ptr(x)
+/**@}*/
+
+/** @defgroup opus_decoderctls Decoder related CTLs
+  * @see opus_genericctls, opus_encoderctls, opus_decoder
+  * @{
+  */
+
+/** Configures decoder gain adjustment.
+  * Scales the decoded output by a factor specified in Q8 dB units.
+  * This has a maximum range of -32768 to 32767 inclusive, and returns
+  * OPUS_BAD_ARG otherwise. The default is zero indicating no adjustment.
+  * This setting survives decoder reset.
+  *
+  * gain = pow(10, x/(20.0*256))
+  *
+  * @param[in] x <tt>opus_int32</tt>:   Amount to scale PCM signal by in Q8 dB units.
+  * @hideinitializer */
+#define OPUS_SET_GAIN(x) OPUS_SET_GAIN_REQUEST, __opus_check_int(x)
+/** Gets the decoder's configured gain adjustment. @see OPUS_SET_GAIN
+  *
+  * @param[out] x <tt>opus_int32 *</tt>: Amount to scale PCM signal by in Q8 dB units.
+  * @hideinitializer */
+#define OPUS_GET_GAIN(x) OPUS_GET_GAIN_REQUEST, __opus_check_int_ptr(x)
+
+/**@}*/
+
+/** @defgroup opus_libinfo Opus library information functions
+  * @{
+  */
+
+/** Converts an opus error code into a human readable string.
+  *
+  * @param[in] error <tt>int</tt>: Error number
+  * @returns Error string
+  */
+/*OPUS_EXPORT const char *opus_strerror(int error);*/
+
+/** Gets the libopus version string.
+  *
+  * @returns Version string
+  */
+/*OPUS_EXPORT const char *opus_get_version_string(void);*/
+/**@}*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* OPUS_DEFINES_H */
+/* Copyright (c) 2010-2011 Xiph.Org Foundation, Skype Limited
+   Written by Jean-Marc Valin and Koen Vos */
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - 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.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``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 COPYRIGHT OWNER
+   OR CONTRIBUTORS 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.
+*/
+
+/**
+ * @file opus.h
+ * @brief Opus reference implementation API
+ */
+
+#ifndef OPUS_H
+#define OPUS_H
+
+/*#include "opus_types.h"*/
+/*#include "opus_defines.h"*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @mainpage Opus
+ *
+ * The Opus codec is designed for interactive speech and audio transmission over the Internet.
+ * It is designed by the IETF Codec Working Group and incorporates technology from
+ * Skype's SILK codec and Xiph.Org's CELT codec.
+ *
+ * The Opus codec is designed to handle a wide range of interactive audio applications,
+ * including Voice over IP, videoconferencing, in-game chat, and even remote live music
+ * performances. It can scale from low bit-rate narrowband speech to very high quality
+ * stereo music. Its main features are:
+
+ * @li Sampling rates from 8 to 48 kHz
+ * @li Bit-rates from 6 kb/s to 510 kb/s
+ * @li Support for both constant bit-rate (CBR) and variable bit-rate (VBR)
+ * @li Audio bandwidth from narrowband to full-band
+ * @li Support for speech and music
+ * @li Support for mono and stereo
+ * @li Support for multichannel (up to 255 channels)
+ * @li Frame sizes from 2.5 ms to 60 ms
+ * @li Good loss robustness and packet loss concealment (PLC)
+ * @li Floating point and fixed-point implementation
+ *
+ * Documentation sections:
+ * @li @ref opus_encoder
+ * @li @ref opus_decoder
+ * @li @ref opus_repacketizer
+ * @li @ref opus_libinfo
+ * @li @ref opus_custom
+ */
+
+/** @defgroup opus_encoder Opus Encoder
+  * @{
+  *
+  * @brief This page describes the process and functions used to encode Opus.
+  *
+  * Since Opus is a stateful codec, the encoding process starts with creating an encoder
+  * state. This can be done with:
+  *
+  * @code
+  * int          error;
+  * OpusEncoder *enc;
+  * enc = opus_encoder_create(Fs, channels, application, &error);
+  * @endcode
+  *
+  * From this point, @c enc can be used for encoding an audio stream. An encoder state
+  * @b must @b not be used for more than one stream at the same time. Similarly, the encoder
+  * state @b must @b not be re-initialized for each frame.
+  *
+  * While opus_encoder_create() allocates memory for the state, it's also possible
+  * to initialize pre-allocated memory:
+  *
+  * @code
+  * int          size;
+  * int          error;
+  * OpusEncoder *enc;
+  * size = opus_encoder_get_size(channels);
+  * enc = malloc(size);
+  * error = opus_encoder_init(enc, Fs, channels, application);
+  * @endcode
+  *
+  * where opus_encoder_get_size() returns the required size for the encoder state. Note that
+  * future versions of this code may change the size, so no assuptions should be made about it.
+  *
+  * The encoder state is always continuous in memory and only a shallow copy is sufficient
+  * to copy it (e.g. memcpy())
+  *
+  * It is possible to change some of the encoder's settings using the opus_encoder_ctl()
+  * interface. All these settings already default to the recommended value, so they should
+  * only be changed when necessary. The most common settings one may want to change are:
+  *
+  * @code
+  * opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrate));
+  * opus_encoder_ctl(enc, OPUS_SET_COMPLEXITY(complexity));
+  * opus_encoder_ctl(enc, OPUS_SET_SIGNAL(signal_type));
+  * @endcode
+  *
+  * where
+  *
+  * @arg bitrate is in bits per second (b/s)
+  * @arg complexity is a value from 1 to 10, where 1 is the lowest complexity and 10 is the highest
+  * @arg signal_type is either OPUS_AUTO (default), OPUS_SIGNAL_VOICE, or OPUS_SIGNAL_MUSIC
+  *
+  * See @ref opus_encoderctls and @ref opus_genericctls for a complete list of parameters that can be set or queried. Most parameters can be set or changed at any time during a stream.
+  *
+  * To encode a frame, opus_encode() or opus_encode_float() must be called with exactly one frame (2.5, 5, 10, 20, 40 or 60 ms) of audio data:
+  * @code
+  * len = opus_encode(enc, audio_frame, frame_size, packet, max_packet);
+  * @endcode
+  *
+  * where
+  * <ul>
+  * <li>audio_frame is the audio data in opus_int16 (or float for opus_encode_float())</li>
+  * <li>frame_size is the duration of the frame in samples (per channel)</li>
+  * <li>packet is the byte array to which the compressed data is written</li>
+  * <li>max_packet is the maximum number of bytes that can be written in the packet (4000 bytes is recommended)</li>
+  * </ul>
+  *
+  * opus_encode() and opus_encode_frame() return the number of bytes actually written to the packet.
+  * The return value <b>can be negative</b>, which indicates that an error has occurred. If the return value
+  * is 1 byte, then the packet does not need to be transmitted (DTX).
+  *
+  * Once the encoder state if no longer needed, it can be destroyed with
+  *
+  * @code
+  * opus_encoder_destroy(enc);
+  * @endcode
+  *
+  * If the encoder was created with opus_encoder_init() rather than opus_encoder_create(),
+  * then no action is required aside from potentially freeing the memory that was manually
+  * allocated for it (calling free(enc) for the example above)
+  *
+  */
+
+/** Opus encoder state.
+  * This contains the complete state of an Opus encoder.
+  * It is position independent and can be freely copied.
+  * @see opus_encoder_create,opus_encoder_init
+  */
+typedef struct OpusEncoder OpusEncoder;
+
+/*OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_encoder_get_size(int channels);*/
+
+/**
+ */
+
+/** Allocates and initializes an encoder state.
+ * There are three coding modes:
+ *
+ * @ref OPUS_APPLICATION_VOIP gives best quality at a given bitrate for voice
+ *    signals. It enhances the  input signal by high-pass filtering and
+ *    emphasizing formants and harmonics. Optionally  it includes in-band
+ *    forward error correction to protect against packet loss. Use this
+ *    mode for typical VoIP applications. Because of the enhancement,
+ *    even at high bitrates the output may sound different from the input.
+ *
+ * @ref OPUS_APPLICATION_AUDIO gives best quality at a given bitrate for most
+ *    non-voice signals like music. Use this mode for music and mixed
+ *    (music/voice) content, broadcast, and applications requiring less
+ *    than 15 ms of coding delay.
+ *
+ * @ref OPUS_APPLICATION_RESTRICTED_LOWDELAY configures low-delay mode that
+ *    disables the speech-optimized mode in exchange for slightly reduced delay.
+ *    This mode can only be set on an newly initialized or freshly reset encoder
+ *    because it changes the codec delay.
+ *
+ * This is useful when the caller knows that the speech-optimized modes will not be needed (use with caution).
+ * @param [in] Fs <tt>opus_int32</tt>: Sampling rate of input signal (Hz)
+ * @param [in] channels <tt>int</tt>: Number of channels (1/2) in input signal
+ * @param [in] application <tt>int</tt>: Coding mode (@ref OPUS_APPLICATION_VOIP/@ref OPUS_APPLICATION_AUDIO/@ref OPUS_APPLICATION_RESTRICTED_LOWDELAY)
+ * @param [out] error <tt>int*</tt>: @ref opus_errorcodes
+ * @note Regardless of the sampling rate and number channels selected, the Opus encoder
+ * can switch to a lower audio audio bandwidth or number of channels if the bitrate
+ * selected is too low. This also means that it is safe to always use 48 kHz stereo input
+ * and let the encoder optimize the encoding.
+ */
+/*OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusEncoder *opus_encoder_create(
+    opus_int32 Fs,
+    int channels,
+    int application,
+    int *error
+);*/
+
+/** Initializes a previously allocated encoder state
+  * The memory pointed to by st must be the size returned by opus_encoder_get_size.
+  * This is intended for applications which use their own allocator instead of malloc.
+  * @see opus_encoder_create(),opus_encoder_get_size()
+  * To reset a previously initialized state use the OPUS_RESET_STATE CTL.
+  * @param [in] st <tt>OpusEncoder*</tt>: Encoder state
+  * @param [in] Fs <tt>opus_int32</tt>: Sampling rate of input signal (Hz)
+  * @param [in] channels <tt>int</tt>: Number of channels (1/2) in input signal
+  * @param [in] application <tt>int</tt>: Coding mode (OPUS_APPLICATION_VOIP/OPUS_APPLICATION_AUDIO/OPUS_APPLICATION_RESTRICTED_LOWDELAY)
+  * @retval OPUS_OK Success or @ref opus_errorcodes
+  */
+/*OPUS_EXPORT int opus_encoder_init(
+    OpusEncoder *st,
+    opus_int32 Fs,
+    int channels,
+    int application
+) OPUS_ARG_NONNULL(1);*/
+
+/** Encodes an Opus frame.
+  * The passed frame_size must an opus frame size for the encoder's sampling rate.
+  * For example, at 48kHz the permitted values are 120, 240, 480, 960, 1920, and 2880.
+  * Passing in a duration of less than 10ms (480 samples at 48kHz) will
+  * prevent the encoder from using the LPC or hybrid modes.
+  * @param [in] st <tt>OpusEncoder*</tt>: Encoder state
+  * @param [in] pcm <tt>opus_int16*</tt>: Input signal (interleaved if 2 channels). length is frame_size*channels*sizeof(opus_int16)
+  * @param [in] frame_size <tt>int</tt>: Number of samples per frame of input signal
+  * @param [out] data <tt>char*</tt>: Output payload (at least max_data_bytes long)
+  * @param [in] max_data_bytes <tt>opus_int32</tt>: Allocated memory for payload; don't use for controlling bitrate
+  * @returns length of the data payload (in bytes) or @ref opus_errorcodes
+  */
+/*OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_encode(
+    OpusEncoder *st,
+    const opus_int16 *pcm,
+    int frame_size,
+    unsigned char *data,
+    opus_int32 max_data_bytes
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);*/
+
+/** Encodes an Opus frame from floating point input.
+  * The passed frame_size must an opus frame size for the encoder's sampling rate.
+  * For example, at 48kHz the permitted values are 120, 240, 480, 960, 1920, and 2880.
+  * Passing in a duration of less than 10ms (480 samples at 48kHz) will
+  * prevent the encoder from using the LPC or hybrid modes.
+  * @param [in] st <tt>OpusEncoder*</tt>: Encoder state
+  * @param [in] pcm <tt>float*</tt>: Input in float format (interleaved if 2 channels), with a normal range of +/-1.0.
+  *          Samples with a range beyond +/-1.0 are supported but will
+  *          be clipped by decoders using the integer API and should
+  *          only be used if it is known that the far end supports
+  *          extended dynamic range.
+  *          length is frame_size*channels*sizeof(float)
+  * @param [in] frame_size <tt>int</tt>: Number of samples per frame of input signal
+  * @param [out] data <tt>char*</tt>: Output payload (at least max_data_bytes long)
+  * @param [in] max_data_bytes <tt>opus_int32</tt>: Allocated memory for payload; don't use for controlling bitrate
+  * @returns length of the data payload (in bytes) or @ref opus_errorcodes
+  */
+/*OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_encode_float(
+    OpusEncoder *st,
+    const float *pcm,
+    int frame_size,
+    unsigned char *data,
+    opus_int32 max_data_bytes
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);*/
+
+/** Frees an OpusEncoder allocated by opus_encoder_create.
+  * @param[in] st <tt>OpusEncoder*</tt>: State to be freed.
+  */
+/*OPUS_EXPORT void opus_encoder_destroy(OpusEncoder *st);*/
+
+/** Perform a CTL function on an Opus encoder.
+  *
+  * Generally the request and subsequent arguments are generated
+  * by a convenience macro.
+  * @see opus_encoderctls
+  */
+/*OPUS_EXPORT int opus_encoder_ctl(OpusEncoder *st, int request, ...) OPUS_ARG_NONNULL(1);*/
+/**@}*/
+
+/** @defgroup opus_decoder Opus Decoder
+  * @{
+  *
+  * @brief This page describes the process and functions used to decode Opus.
+  *
+  * The decoding process also starts with creating a decoder
+  * state. This can be done with:
+  * @code
+  * int          error;
+  * OpusDecoder *dec;
+  * dec = opus_decoder_create(Fs, channels, &error);
+  * @endcode
+  * where
+  * @li Fs is the sampling rate and must be 8000, 12000, 16000, 24000, or 48000
+  * @li channels is the number of channels (1 or 2)
+  * @li error will hold the error code in case or failure (or OPUS_OK on success)
+  * @li the return value is a newly created decoder state to be used for decoding
+  *
+  * While opus_decoder_create() allocates memory for the state, it's also possible
+  * to initialize pre-allocated memory:
+  * @code
+  * int          size;
+  * int          error;
+  * OpusDecoder *dec;
+  * size = opus_decoder_get_size(channels);
+  * dec = malloc(size);
+  * error = opus_decoder_init(dec, Fs, channels);
+  * @endcode
+  * where opus_decoder_get_size() returns the required size for the decoder state. Note that
+  * future versions of this code may change the size, so no assuptions should be made about it.
+  *
+  * The decoder state is always continuous in memory and only a shallow copy is sufficient
+  * to copy it (e.g. memcpy())
+  *
+  * To decode a frame, opus_decode() or opus_decode_float() must be called with a packet of compressed audio data:
+  * @code
+  * frame_size = opus_decode(dec, packet, len, decoded, max_size, 0);
+  * @endcode
+  * where
+  *
+  * @li packet is the byte array containing the compressed data
+  * @li len is the exact number of bytes contained in the packet
+  * @li decoded is the decoded audio data in opus_int16 (or float for opus_decode_float())
+  * @li max_size is the max duration of the frame in samples (per channel) that can fit into the decoded_frame array
+  *
+  * opus_decode() and opus_decode_float() return the number of samples (per channel) decoded from the packet.
+  * If that value is negative, then an error has occured. This can occur if the packet is corrupted or if the audio
+  * buffer is too small to hold the decoded audio.
+  *
+  * Opus is a stateful codec with overlapping blocks and as a result Opus
+  * packets are not coded independently of each other. Packets must be
+  * passed into the decoder serially and in the correct order for a correct
+  * decode. Lost packets can be replaced with loss concealment by calling
+  * the decoder with a null pointer and zero length for the missing packet.
+  *
+  * A single codec state may only be accessed from a single thread at
+  * a time and any required locking must be performed by the caller. Separate
+  * streams must be decoded with separate decoder states and can be decoded
+  * in parallel unless the library was compiled with NONTHREADSAFE_PSEUDOSTACK
+  * defined.
+  *
+  */
+
+/** Opus decoder state.
+  * This contains the complete state of an Opus decoder.
+  * It is position independent and can be freely copied.
+  * @see opus_decoder_create,opus_decoder_init
+  */
+typedef struct OpusDecoder OpusDecoder;
+
+/** Gets the size of an OpusDecoder structure.
+  * @param [in] channels <tt>int</tt>: Number of channels
+  * @returns size
+  */
+/*OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_decoder_get_size(int channels);*/
+
+/** Allocates and initializes a decoder state.
+  * @param [in] Fs <tt>opus_int32</tt>: Sample rate to decode at (Hz)
+  * @param [in] channels <tt>int</tt>: Number of channels (1/2) to decode
+  * @param [out] error <tt>int*</tt>: OPUS_OK Success or @ref opus_errorcodes
+  *
+  * Internally Opus stores data at 48000 Hz, so that should be the default
+  * value for Fs. However, the decoder can efficiently decode to buffers
+  * at 8, 12, 16, and 24 kHz so if for some reason the caller cannot use
+  * data at the full sample rate, or knows the compressed data doesn't
+  * use the full frequency range, it can request decoding at a reduced
+  * rate. Likewise, the decoder is capable of filling in either mono or
+  * interleaved stereo pcm buffers, at the caller's request.
+  */
+/*OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusDecoder *opus_decoder_create(
+    opus_int32 Fs,
+    int channels,
+    int *error
+);*/
+
+/** Initializes a previously allocated decoder state.
+  * The state must be the size returned by opus_decoder_get_size.
+  * This is intended for applications which use their own allocator instead of malloc. @see opus_decoder_create,opus_decoder_get_size
+  * To reset a previously initialized state use the OPUS_RESET_STATE CTL.
+  * @param [in] st <tt>OpusDecoder*</tt>: Decoder state.
+  * @param [in] Fs <tt>opus_int32</tt>: Sampling rate to decode to (Hz)
+  * @param [in] channels <tt>int</tt>: Number of channels (1/2) to decode
+  * @retval OPUS_OK Success or @ref opus_errorcodes
+  */
+/*OPUS_EXPORT int opus_decoder_init(
+    OpusDecoder *st,
+    opus_int32 Fs,
+    int channels
+) OPUS_ARG_NONNULL(1);*/
+
+/** Decode an Opus frame
+  * @param [in] st <tt>OpusDecoder*</tt>: Decoder state
+  * @param [in] data <tt>char*</tt>: Input payload. Use a NULL pointer to indicate packet loss
+  * @param [in] len <tt>opus_int32</tt>: Number of bytes in payload*
+  * @param [out] pcm <tt>opus_int16*</tt>: Output signal (interleaved if 2 channels). length
+  *  is frame_size*channels*sizeof(opus_int16)
+  * @param [in] frame_size Number of samples per channel of available space in *pcm,
+  *  if less than the maximum frame size (120ms) some frames can not be decoded
+  * @param [in] decode_fec <tt>int</tt>: Flag (0/1) to request that any in-band forward error correction data be
+  *  decoded. If no such data is available the frame is decoded as if it were lost.
+  * @returns Number of decoded samples or @ref opus_errorcodes
+  */
+/*OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_decode(
+    OpusDecoder *st,
+    const unsigned char *data,
+    opus_int32 len,
+    opus_int16 *pcm,
+    int frame_size,
+    int decode_fec
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);*/
+
+/** Decode an opus frame with floating point output
+  * @param [in] st <tt>OpusDecoder*</tt>: Decoder state
+  * @param [in] data <tt>char*</tt>: Input payload. Use a NULL pointer to indicate packet loss
+  * @param [in] len <tt>opus_int32</tt>: Number of bytes in payload
+  * @param [out] pcm <tt>float*</tt>: Output signal (interleaved if 2 channels). length
+  *  is frame_size*channels*sizeof(float)
+  * @param [in] frame_size Number of samples per channel of available space in *pcm,
+  *  if less than the maximum frame size (120ms) some frames can not be decoded
+  * @param [in] decode_fec <tt>int</tt>: Flag (0/1) to request that any in-band forward error correction data be
+  *  decoded. If no such data is available the frame is decoded as if it were lost.
+  * @returns Number of decoded samples or @ref opus_errorcodes
+  */
+/*OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_decode_float(
+    OpusDecoder *st,
+    const unsigned char *data,
+    opus_int32 len,
+    float *pcm,
+    int frame_size,
+    int decode_fec
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);*/
+
+/** Perform a CTL function on an Opus decoder.
+  *
+  * Generally the request and subsequent arguments are generated
+  * by a convenience macro.
+  * @see opus_genericctls
+  */
+/*OPUS_EXPORT int opus_decoder_ctl(OpusDecoder *st, int request, ...) OPUS_ARG_NONNULL(1);*/
+
+/** Frees an OpusDecoder allocated by opus_decoder_create.
+  * @param[in] st <tt>OpusDecoder*</tt>: State to be freed.
+  */
+/*OPUS_EXPORT void opus_decoder_destroy(OpusDecoder *st);*/
+
+/** Parse an opus packet into one or more frames.
+  * Opus_decode will perform this operation internally so most applications do
+  * not need to use this function.
+  * This function does not copy the frames, the returned pointers are pointers into
+  * the input packet.
+  * @param [in] data <tt>char*</tt>: Opus packet to be parsed
+  * @param [in] len <tt>opus_int32</tt>: size of data
+  * @param [out] out_toc <tt>char*</tt>: TOC pointer
+  * @param [out] frames <tt>char*[48]</tt> encapsulated frames
+  * @param [out] size <tt>short[48]</tt> sizes of the encapsulated frames
+  * @param [out] payload_offset <tt>int*</tt>: returns the position of the payload within the packet (in bytes)
+  * @returns number of frames
+  */
+/*OPUS_EXPORT int opus_packet_parse(
+   const unsigned char *data,
+   opus_int32 len,
+   unsigned char *out_toc,
+   const unsigned char *frames[48],
+   short size[48],
+   int *payload_offset
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);*/
+
+/** Gets the bandwidth of an Opus packet.
+  * @param [in] data <tt>char*</tt>: Opus packet
+  * @retval OPUS_BANDWIDTH_NARROWBAND Narrowband (4kHz bandpass)
+  * @retval OPUS_BANDWIDTH_MEDIUMBAND Mediumband (6kHz bandpass)
+  * @retval OPUS_BANDWIDTH_WIDEBAND Wideband (8kHz bandpass)
+  * @retval OPUS_BANDWIDTH_SUPERWIDEBAND Superwideband (12kHz bandpass)
+  * @retval OPUS_BANDWIDTH_FULLBAND Fullband (20kHz bandpass)
+  * @retval OPUS_INVALID_PACKET The compressed data passed is corrupted or of an unsupported type
+  */
+/*OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_packet_get_bandwidth(const unsigned char *data) OPUS_ARG_NONNULL(1);*/
+
+/** Gets the number of samples per frame from an Opus packet.
+  * @param [in] data <tt>char*</tt>: Opus packet
+  * @param [in] Fs <tt>opus_int32</tt>: Sampling rate in Hz
+  * @returns Number of samples per frame
+  * @retval OPUS_INVALID_PACKET The compressed data passed is corrupted or of an unsupported type
+  */
+/*OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_packet_get_samples_per_frame(const unsigned char *data, opus_int32 Fs) OPUS_ARG_NONNULL(1);*/
+
+/** Gets the number of channels from an Opus packet.
+  * @param [in] data <tt>char*</tt>: Opus packet
+  * @returns Number of channels
+  * @retval OPUS_INVALID_PACKET The compressed data passed is corrupted or of an unsupported type
+  */
+/*OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_packet_get_nb_channels(const unsigned char *data) OPUS_ARG_NONNULL(1);*/
+
+/** Gets the number of frames in an Opus packet.
+  * @param [in] packet <tt>char*</tt>: Opus packet
+  * @param [in] len <tt>opus_int32</tt>: Length of packet
+  * @returns Number of frames
+  * @retval OPUS_INVALID_PACKET The compressed data passed is corrupted or of an unsupported type
+  */
+/*OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_packet_get_nb_frames(const unsigned char packet[], opus_int32 len) OPUS_ARG_NONNULL(1);*/
+
+/** Gets the number of samples of an Opus packet.
+  * @param [in] dec <tt>OpusDecoder*</tt>: Decoder state
+  * @param [in] packet <tt>char*</tt>: Opus packet
+  * @param [in] len <tt>opus_int32</tt>: Length of packet
+  * @returns Number of samples
+  * @retval OPUS_INVALID_PACKET The compressed data passed is corrupted or of an unsupported type
+  */
+/*OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_decoder_get_nb_samples(const OpusDecoder *dec, const unsigned char packet[], opus_int32 len) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2);*/
+/**@}*/
+
+/** @defgroup opus_repacketizer Repacketizer
+  * @{
+  *
+  * The repacketizer can be used to merge multiple Opus packets into a single packet
+  * or alternatively to split Opus packets that have previously been merged.
+  *
+  */
+/*
+typedef struct OpusRepacketizer OpusRepacketizer;
+
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_repacketizer_get_size(void);
+
+OPUS_EXPORT OpusRepacketizer *opus_repacketizer_init(OpusRepacketizer *rp) OPUS_ARG_NONNULL(1);
+
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusRepacketizer *opus_repacketizer_create(void);
+
+OPUS_EXPORT void opus_repacketizer_destroy(OpusRepacketizer *rp);
+
+OPUS_EXPORT int opus_repacketizer_cat(OpusRepacketizer *rp, const unsigned char *data, opus_int32 len) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2);
+
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_repacketizer_out_range(OpusRepacketizer *rp, int begin, int end, unsigned char *data, opus_int32 maxlen) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
+
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_repacketizer_get_nb_frames(OpusRepacketizer *rp) OPUS_ARG_NONNULL(1);
+
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_repacketizer_out(OpusRepacketizer *rp, unsigned char *data, opus_int32 maxlen) OPUS_ARG_NONNULL(1);
+*/
+/**@}*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* OPUS_H */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef OPUS_EXPORT const char *(opus_get_version_string_t)(
+    void
+    );
+
+typedef OPUS_EXPORT const char *(opus_strerror_t)(
+    int error
+    );
+
+typedef OPUS_EXPORT OpusEncoder *(opus_encoder_create_t)(
+    opus_int32 Fs,
+    int channels,
+    int application,
+    int *error
+    );
+
+typedef OPUS_EXPORT int (opus_encoder_ctl_t)(
+    OpusEncoder *st,
+    int request,
+    ...
+    );
+
+typedef OPUS_EXPORT opus_int32 (opus_encode_t)(
+    OpusEncoder *st,
+    const opus_int16 *pcm,
+    int frame_size,
+    unsigned char *data,
+    opus_int32 max_data_bytes
+    );
+
+typedef OPUS_EXPORT void (opus_encoder_destroy_t)(
+    OpusEncoder *st
+    );
+
+typedef OPUS_EXPORT OpusDecoder *(opus_decoder_create_t)(
+    opus_int32 Fs,
+    int channels,
+    int *error
+    );
+
+typedef OPUS_EXPORT int (opus_decoder_ctl_t)(
+    OpusDecoder *st,
+    int request,
+    ...
+    );
+
+typedef OPUS_EXPORT int (opus_decode_t)(
+    OpusDecoder *st,
+    const unsigned char *data,
+    opus_int32 len,
+    opus_int16 *pcm,
+    int frame_size,
+    int decode_fec
+    );
+
+typedef OPUS_EXPORT void (opus_decoder_destroy_t)(
+    OpusDecoder *st
+    );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/sync/FreqSyncAcq.cpp b/src/sync/FreqSyncAcq.cpp
new file mode 100644
index 0000000..bab8907
--- /dev/null
+++ b/src/sync/FreqSyncAcq.cpp
@@ -0,0 +1,509 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *	Frequency synchronization acquisition (FFT-based)
+ *
+ * The input data is not modified by this module, it is just a measurement
+ * of the frequency offset. The data is fed through this module.
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later 
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT 
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "FreqSyncAcq.h"
+
+/* Implementation *************************************************************/
+void CFreqSyncAcq::ProcessDataInternal(CParameter& Parameters)
+{
+	int			i;
+	int			iMaxIndex=0;
+	CReal		rMaxValue = 0.0;
+	int			iNumDetPeaks;
+	//int			iDiffTemp;
+	//CReal		rLevDiff;
+	_BOOLEAN	bNoPeaksLeft;
+	CRealVector	vecrPSDPilPoin(3);
+
+	Parameters.Lock(); 
+
+	/* OPH: update free-running symbol counter */
+	iFreeSymbolCounter++;
+	if (iFreeSymbolCounter >= Parameters.CellMappingTable.iNumSymPerFrame)
+	{
+		iFreeSymbolCounter = 0;
+	}
+
+	if (bAquisition == TRUE)
+	{
+
+		/* Do not transfer any data to the next block if no frequency
+		   acquisition was successfully done */
+		iOutputBlockSize = 0;
+
+		/* Add new symbol in history (shift register) */
+		vecrFFTHistory.AddEnd((*pvecInputData), iInputBlockSize);
+
+
+		/* Start algorithm when history memory is filled -------------------- */
+		/* Wait until history memory is filled for the first FFT operation.
+		   ("> 1" since, e.g., if we would have only one buffer, we can start
+		   immediately) */
+		if (iAquisitionCounter > 1)
+		{
+			/* Decrease counter */
+			iAquisitionCounter--;
+		}
+		else
+		{
+			/* Copy vector to matlib vector and calculate real-valued FFT */
+			const int iStartIdx = iHistBufSize - iFrAcFFTSize;
+			for (i = 0; i < iFrAcFFTSize; i++)
+				vecrFFTInput[i] = vecrFFTHistory[i + iStartIdx];
+
+			static CMatlibVector<CReal> vecRet;
+			vecRet.Init(vecrFFTInput.GetSize(), VTY_TEMP);
+
+			for (int k = 0; k < vecrFFTInput.GetSize(); k++)
+				vecRet[k] = vecrFFTInput[k] * vecrHammingWin[k];
+
+			/* Calculate power spectrum (X = real(F)^2 + imag(F)^2) */
+			vecrSqMagFFTOut =
+				SqMag(rfft(vecRet, FftPlan));
+
+			/* Calculate moving average for better estimate of PSD */
+			vvrPSDMovAv.Add(vecrSqMagFFTOut);
+
+			/* Wait until we have sufficient data for averaging */
+			if (iAverageCounter > 1)
+			{
+				/* Decrease counter */
+				iAverageCounter--;
+			}
+			else
+			{
+				/* Get PSD estimate */
+				const CRealVector vecrPSD(vvrPSDMovAv.GetAverage());
+
+
+				/* -------------------------------------------------------------
+				   Low pass filtering over frequency axis. We do the filtering
+				   from both sides, once from right to left and then from left
+				   to the right side. Afterwards, these results are averaged
+				   This way, the noise floor is estimated */
+
+// TODO: Introduce offset to debar peak at DC frequency (cause by DC offset of
+// sound cards). Set "iStartFilt" in Init() routine!
+const int iStartFilt = 0; // <- no offset right now
+
+				/* Reset vectors for intermediate filtered result */
+				vecrFiltResLR.Reset((CReal) 0.0);
+				vecrFiltResRL.Reset((CReal) 0.0);
+
+				/* From the left edge to the right edge */
+				vecrFiltResLR[iStartFilt] = vecrPSD[iStartFilt];
+				for (i = iStartFilt + 1; i < iHalfBuffer; i++)
+				{
+					vecrFiltResLR[i] = (vecrFiltResLR[i - 1] - vecrPSD[i]) *
+						LAMBDA_FREQ_IIR_FILT + vecrPSD[i];
+				}
+
+				/* From the right edge to the left edge */
+				vecrFiltResRL[iHalfBuffer - 1] =
+					vecrPSD[iHalfBuffer - 1];
+				for (i = iHalfBuffer - 2; i >= iStartFilt; i--)
+				{
+					vecrFiltResRL[i] = (vecrFiltResRL[i + 1] - vecrPSD[i]) *
+						LAMBDA_FREQ_IIR_FILT + vecrPSD[i];
+				}
+
+				/* Average RL and LR filter outputs */
+				vecrFiltRes = (vecrFiltResLR + vecrFiltResRL) / 2;
+
+#ifdef _DEBUG_
+#if 0
+/* Stores curves for PSD estimation and filtering */
+FILE* pFile2 = fopen("test/freqacqFilt.dat", "w");
+for (i = 0; i < iHalfBuffer; i++)
+	fprintf(pFile2, "%e %e\n", vecrPSD[i], vecrFiltRes[i]);
+fclose(pFile2);
+#endif
+#endif
+
+				/* Equalize PSD by "noise floor estimate" */
+				for (i = 0; i < iHalfBuffer; i++)
+				{
+					/* Make sure we do not devide by zero */
+					if (vecrFiltRes[i] != 0.0)
+						vecrPSD[i] /= vecrFiltRes[i];
+					else
+						vecrPSD[i] = 0.0;
+				}
+
+				/* Correlate known frequency-pilot structure with equalized
+				   power spectrum */
+				for (i = 0; i < iSearchWinSize; i++)
+				{
+					vecrPSDPilCor[i] =
+						vecrPSD[i + veciTableFreqPilots[0]] +
+						vecrPSD[i + veciTableFreqPilots[1]] +
+						vecrPSD[i + veciTableFreqPilots[2]];
+				}
+
+
+				/* Detect peaks --------------------------------------------- */
+				/* Get peak indices of detected peaks */
+				iNumDetPeaks = 0;
+				for (i = iStartDCSearch; i < iEndDCSearch; i++)
+				{
+					/* Test peaks against a bound */
+					if (vecrPSDPilCor[i] > rPeakBoundFiltToSig)
+					{
+						veciPeakIndex[iNumDetPeaks] = i;
+						iNumDetPeaks++;
+					}
+				}
+
+				/* Check, if at least one peak was detected */
+				if (iNumDetPeaks > 0)
+				{
+					/* ---------------------------------------------------------
+					   The following test shall exclude sinusoid interferers in
+					   the received spectrum */
+					CVector<int> vecbFlagVec(iNumDetPeaks, 1);
+
+					/* Check all detected peaks in the "PSD-domain" if there are
+					   at least two peaks with approx the same power at the
+					   correct places (positions of the desired pilots) */
+					for (i = 0; i < iNumDetPeaks; i++)
+					{
+						/* Fill the vector with the values at the desired
+						   pilot positions */
+						vecrPSDPilPoin[0] =
+							vecrPSD[veciPeakIndex[i] + veciTableFreqPilots[0]];
+						vecrPSDPilPoin[1] =
+							vecrPSD[veciPeakIndex[i] + veciTableFreqPilots[1]];
+						vecrPSDPilPoin[2] =
+							vecrPSD[veciPeakIndex[i] + veciTableFreqPilots[2]];
+
+						/* Sort, to extract the highest and second highest
+						   peak */
+						vecrPSDPilPoin = Sort(vecrPSDPilPoin);
+
+						/* Debar peak, if it is much higher than second highest
+						   peak (most probably a sinusoid interferer). The
+						   highest peak is stored at "vecrPSDPilPoin[2]". Also
+						   test for lowest peak */
+						if ((vecrPSDPilPoin[1] / vecrPSDPilPoin[2] <
+							MAX_RAT_PEAKS_AT_PIL_POS_HIGH) &&
+							(vecrPSDPilPoin[0] / vecrPSDPilPoin[2] <
+							MAX_RAT_PEAKS_AT_PIL_POS_LOW))
+						{
+							/* Reset "good-flag" */
+							vecbFlagVec[i] = 0;
+						}
+					}
+
+
+					/* Get maximum ------------------------------------------ */
+					/* First, get the first valid peak entry and init the
+					   maximum with this value. We also detect, if a peak is
+					   left */
+					bNoPeaksLeft = TRUE;
+					for (i = 0; i < iNumDetPeaks; i++)
+					{
+						if (vecbFlagVec[i] == 1)
+						{
+							/* At least one peak is left */
+							bNoPeaksLeft = FALSE;
+
+							/* Init max value */
+							iMaxIndex = veciPeakIndex[i];
+							rMaxValue = vecrPSDPilCor[veciPeakIndex[i]];
+						}
+					}
+
+					if (bNoPeaksLeft == FALSE)
+					{
+						/* Actual maximum detection, take the remaining peak
+						   which has the highest value */
+						for (i = 0; i < iNumDetPeaks; i++)
+						{
+							if ((vecbFlagVec[i] == 1) &&
+								(vecrPSDPilCor[veciPeakIndex[i]] >
+								rMaxValue))
+							{
+								iMaxIndex = veciPeakIndex[i];
+								rMaxValue = vecrPSDPilCor[veciPeakIndex[i]];
+							}
+						}
+
+#ifdef _DEBUG_
+/* Stores all important parameters for last shot */
+FILE* pFile1 = fopen("test/freqacq.dat", "w");
+int iPeakCnt = 0;
+for (i = 1; i < iSearchWinSize; i++) {
+	_REAL rPM, rFinPM; /* rPM: peak marker, rFinPM: final peak marker */
+	if (iPeakCnt < iNumDetPeaks) {
+		if (i == veciPeakIndex[iPeakCnt]) {
+			rPM = vecrPSDPilCor[i];
+			if (vecbFlagVec[iPeakCnt] == 1) rFinPM = vecrPSDPilCor[i]; else rFinPM = 0;
+			iPeakCnt++;
+		} else {rPM = 0; rFinPM = 0;}
+	} else {rPM = 0; rFinPM = 0;}
+	fprintf(pFile1, "%e %e %e\n", vecrPSDPilCor[i], rPM, rFinPM);
+}
+fclose(pFile1);
+// close all;load freqacq.dat;load freqacqFilt.dat;subplot(211),semilogy(freqacq(:,1));hold;plot(freqacq(:,2),'*y');plot(freqacq(:,3),'*k');subplot(212),semilogy(freqacqFilt)
+// close all;load freqacq.dat;semilogy(freqacq(:,1));hold;plot(freqacq(:,2),'*y');plot(freqacq(:,3),'*k');
+#endif
+
+
+						/* -----------------------------------------------------
+						   An acquisition frequency offest estimation was
+						   found */
+						/* Calculate frequency offset and set global parameter
+						   for offset */
+						Parameters.rFreqOffsetAcqui =
+							(_REAL) iMaxIndex / iFrAcFFTSize;
+
+						/* Reset acquisition flag */
+						bAquisition = FALSE;
+
+
+						/* Send out the data stored for FFT calculation ----- */
+						/* This does not work for bandpass filter. TODO: make
+						   this possible for bandpass filter, too */
+						if (bUseRecFilter == FALSE)
+						{
+							iOutputBlockSize = iHistBufSize;
+
+							/* Frequency offset correction */
+							const _REAL rNormCurFreqOffsFst = (_REAL) 2.0 * crPi *
+								(Parameters.rFreqOffsetAcqui - rInternIFNorm);
+
+							for (i = 0; i < iHistBufSize; i++)
+							{
+								/* Multiply with exp(j omega t) */
+								(*pvecOutputData)[i] = vecrFFTHistory[i] *
+									_COMPLEX(Cos(i * rNormCurFreqOffsFst),
+									Sin(-i * rNormCurFreqOffsFst));
+							}
+
+							/* Init "exp-step" for regular frequency shift which
+							   is used in tracking mode to get contiuous mixing
+							   signal */
+							cCurExp =
+								_COMPLEX(Cos(iHistBufSize * rNormCurFreqOffsFst),
+								Sin(-iHistBufSize * rNormCurFreqOffsFst));
+						}
+					}
+				}
+			}
+		}
+	}
+	else
+	{
+		/* If synchronized DRM input stream is used, overwrite the detected
+		   frequency offest estimate by the desired frequency, because we know
+		   this value */
+		if (bSyncInput == TRUE)
+		{
+			Parameters.rFreqOffsetAcqui =
+				(_REAL) Parameters.CellMappingTable.iIndexDCFreq / Parameters.CellMappingTable.iFFTSizeN;
+		}
+
+		/* Use the same block size as input block size */
+		iOutputBlockSize = iInputBlockSize;
+
+
+		/* Frequency offset correction -------------------------------------- */
+		/* Total frequency offset from acquisition and tracking (we calculate
+		   the normalized frequency offset) */
+		const _REAL rNormCurFreqOffset =
+			(_REAL) 2.0 * crPi * (Parameters.rFreqOffsetAcqui +
+			Parameters.rFreqOffsetTrack - rInternIFNorm);
+
+		/* New rotation vector for exp() calculation */
+		const _COMPLEX cExpStep =
+			_COMPLEX(Cos(rNormCurFreqOffset), Sin(rNormCurFreqOffset));
+
+		/* Input data is real, make complex and compensate for frequency
+		   offset */
+		for (i = 0; i < iOutputBlockSize; i++)
+		{
+			(*pvecOutputData)[i] = (*pvecInputData)[i] * Conj(cCurExp);
+
+			/* Rotate exp-pointer on step further by complex multiplication with
+			   precalculated rotation vector cExpStep. This saves us from
+			   calling sin() and cos() functions all the time (iterative
+			   calculation of these functions) */
+			cCurExp *= cExpStep;
+		}
+
+
+		/* Bandpass filter -------------------------------------------------- */
+		if (bUseRecFilter == TRUE)
+			BPFilter.Process(*pvecOutputData);
+
+	}
+	Parameters.Unlock(); 
+}
+
+void CFreqSyncAcq::InitInternal(CParameter& Parameters)
+{
+	Parameters.Lock(); 
+
+	/* Get sample rate */
+	const int iSampleRate = Parameters.GetSigSampleRate();
+
+	/* Needed for calculating offset in Hertz in case of synchronized input
+	   (for simulation) */
+	iFFTSize = Parameters.CellMappingTable.iFFTSizeN;
+
+	/* We using parameters from robustness mode B as pattern for the desired
+	   frequency pilot positions */
+	veciTableFreqPilots[0] =
+		iTableFreqPilRobModB[0][0] * NUM_BLOCKS_4_FREQ_ACQU;
+	veciTableFreqPilots[1] =
+		iTableFreqPilRobModB[1][0] * NUM_BLOCKS_4_FREQ_ACQU;
+	veciTableFreqPilots[2] =
+		iTableFreqPilRobModB[2][0] * NUM_BLOCKS_4_FREQ_ACQU;
+
+	/* Size of FFT */
+	iFrAcFFTSize = ADJ_FOR_SRATE(RMB_FFT_SIZE_N, iSampleRate) * NUM_BLOCKS_4_FREQ_ACQU;
+
+
+	/* -------------------------------------------------------------------------
+	   Set start- and endpoint of search window for DC carrier after the
+	   correlation with the known pilot structure */
+	/* Normalize the desired position and window size which are in Hertz */
+	const _REAL rNormDesPos   = rCenterFreq < 0.0 ? 0.5 : rCenterFreq / iSampleRate * 2;
+	const _REAL rNormHalfWinSize = rWinSize < 0.0 ? 0.5 : rWinSize    / iSampleRate;
+
+	/* Length of the half of the spectrum of real input signal (the other half
+	   is the same because of the real input signal). We have to consider the
+	   Nyquist frequency ("iFrAcFFTSize" is always even!) */
+	iHalfBuffer = iFrAcFFTSize / 2 + 1;
+
+	/* Search window is smaller than haft-buffer size because of correlation
+	   with pilot positions */
+	iSearchWinSize = iHalfBuffer - veciTableFreqPilots[2];
+
+	/* Calculate actual indices of start and end of search window */
+	iStartDCSearch =
+		(int) Floor((rNormDesPos - rNormHalfWinSize) * iHalfBuffer);
+	iEndDCSearch = (int) Ceil((rNormDesPos + rNormHalfWinSize) * iHalfBuffer);
+
+	/* Check range. If out of range -> correct */
+	if (!((iStartDCSearch > 0) && (iStartDCSearch < iSearchWinSize)))
+		iStartDCSearch = 0;
+
+	if (!((iEndDCSearch > 0) && (iEndDCSearch < iSearchWinSize)))
+		iEndDCSearch = iSearchWinSize;
+
+	/* Set bound for ratio between filtered signal to signal. Use a lower bound
+	   if the search window is smaller */
+	if (((_REAL) iEndDCSearch - iStartDCSearch) / iHalfBuffer < (_REAL) 0.042)
+		rPeakBoundFiltToSig = PEAK_BOUND_FILT2SIGNAL_0_042;
+	else
+		rPeakBoundFiltToSig = PEAK_BOUND_FILT2SIGNAL_1;
+
+
+	/* Init vectors and FFT-plan -------------------------------------------- */
+	/* Allocate memory for FFT-histories and init with zeros */
+	iHistBufSize = iFrAcFFTSize * NUM_BLOCKS_USED_FOR_AV;
+	vecrFFTHistory.Init(iHistBufSize, (_REAL) 0.0);
+	vecrFFTInput.Init(iFrAcFFTSize);
+	vecrSqMagFFTOut.Init(iHalfBuffer);
+
+	/* Allocate memory for PSD after pilot correlation */
+	vecrPSDPilCor.Init(iHalfBuffer);
+
+	/* Init vectors for filtering in frequency direction */
+	vecrFiltResLR.Init(iHalfBuffer);
+	vecrFiltResRL.Init(iHalfBuffer);
+	vecrFiltRes.Init(iHalfBuffer);
+
+	/* Index memory for detected peaks (assume worst case with the size) */
+	veciPeakIndex.Init(iHalfBuffer);
+
+	/* Init plans for FFT (faster processing of Fft and Ifft commands) */
+	FftPlan.Init(iFrAcFFTSize);
+
+	/* Init Hamming window */
+	vecrHammingWin.Init(iFrAcFFTSize);
+	vecrHammingWin = Hamming(iFrAcFFTSize);
+
+	/* Init moving average class for SqMag FFT results */
+	vvrPSDMovAv.InitVec(NUM_FFT_RES_AV_BLOCKS, iHalfBuffer);
+
+
+	/* Frequency correction */
+	/* Start with phase null (arbitrary) */
+	cCurExp = (_REAL) 1.0;
+	rInternIFNorm = (_REAL) Parameters.CellMappingTable.iIndexDCFreq / iFFTSize;
+
+
+	/* Init bandpass filter object */
+	BPFilter.Init(iSampleRate, Parameters.CellMappingTable.iSymbolBlockSize, VIRTUAL_INTERMED_FREQ,
+		Parameters.GetSpectrumOccup(), CDRMBandpassFilt::FT_RECEIVER);
+
+
+	/* Define block-sizes for input (The output block size is set inside
+	   the processing routine, therefore only a maximum block size is set
+	   here) */
+	iInputBlockSize = Parameters.CellMappingTable.iSymbolBlockSize;
+
+	/* We have to consider that the next module can take up to two symbols per
+	   step. This can be satisfied be multiplying with "3". We also want to ship
+	   the whole FFT buffer after finishing the frequency acquisition so that
+	   these samples can be reused for synchronization and do not get lost */
+	iMaxOutputBlockSize = 3 * Parameters.CellMappingTable.iSymbolBlockSize + iHistBufSize;
+
+	/* OPH: init free-running symbol counter */
+	iFreeSymbolCounter = 0;
+
+	Parameters.Unlock(); 
+}
+
+void CFreqSyncAcq::SetSearchWindow(_REAL rNewCenterFreq, _REAL rNewWinSize)
+{
+	/* Set internal parameters */
+	rCenterFreq = rNewCenterFreq;
+	rWinSize = rNewWinSize;
+
+	/* Set flag to initialize the module to the new parameters */
+	SetInitFlag();
+}
+
+void CFreqSyncAcq::StartAcquisition()
+{
+	/* Set flag so that the actual acquisition routine is entered */
+	bAquisition = TRUE;
+
+	/* Reset (or init) counters */
+	iAquisitionCounter = NUM_BLOCKS_4_FREQ_ACQU;
+	iAverageCounter = NUM_FFT_RES_AV_BLOCKS;
+
+	/* Reset FFT-history */
+	vecrFFTHistory.Reset((_REAL) 0.0);
+}
diff --git a/src/sync/FreqSyncAcq.h b/src/sync/FreqSyncAcq.h
new file mode 100644
index 0000000..c40539c
--- /dev/null
+++ b/src/sync/FreqSyncAcq.h
@@ -0,0 +1,147 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *	See FreqSyncAcq.cpp
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later 
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT 
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#if !defined(FREQSYNC_H__3B0BA660EDOINBEROUEBGF4344_BB2B_23E7912__INCLUDED_)
+#define FREQSYNC_H__3B0BA660EDOINBEROUEBGF4344_BB2B_23E7912__INCLUDED_
+
+#include "../Parameter.h"
+#include "../util/Modul.h"
+#include "../matlib/Matlib.h"
+#include "../util/Utilities.h"
+
+/* Definitions ****************************************************************/
+/* Bound for peak detection between filtered signal (in frequency direction) 
+   and the unfiltered signal. Define different bounds for different relative
+   search window sizes */
+#define PEAK_BOUND_FILT2SIGNAL_1		((CReal) 9)
+#define PEAK_BOUND_FILT2SIGNAL_0_042	((CReal) 7)
+
+/* This value MUST BE AT LEAST 2, because otherwise we would get an overrun
+   when we try to add a complete symbol to the buffer! */
+#ifdef USE_FRQOFFS_TRACK_GUARDCORR
+# define NUM_BLOCKS_4_FREQ_ACQU			30 /* Accuracy must be higher */
+#else
+# define NUM_BLOCKS_4_FREQ_ACQU			6
+#endif
+
+/* Number of block used for averaging */
+#define NUM_BLOCKS_USED_FOR_AV			3
+
+/* Lambda for IIR filter for estimating noise floor in frequency domain */
+#define LAMBDA_FREQ_IIR_FILT			((CReal) 0.87)
+
+/* Ratio between highest and second highest peak at the frequency pilot
+   positions in the PSD estimation (after peak detection) */
+#define MAX_RAT_PEAKS_AT_PIL_POS_HIGH	((CReal) 0.99)
+
+/* Ratio between highest and lowest peak at frequency pilot positions (see
+   above) */
+#define MAX_RAT_PEAKS_AT_PIL_POS_LOW	((CReal) 0.8)
+
+/* Number of blocks storing the squared magnitude of FFT used for
+   averaging */
+#define NUM_FFT_RES_AV_BLOCKS			(NUM_BLOCKS_4_FREQ_ACQU * (NUM_BLOCKS_USED_FOR_AV - 1) + 1)
+
+
+/* Classes ********************************************************************/
+class CFreqSyncAcq : public CReceiverModul<_REAL, _COMPLEX>
+{
+public:
+	CFreqSyncAcq() : 
+		veciTableFreqPilots(3), /* 3 frequency pilots */
+		bAquisition(FALSE), bSyncInput(FALSE),
+		rCenterFreq(0), rWinSize(0),
+		bUseRecFilter(FALSE)
+		{}
+	virtual ~CFreqSyncAcq() {}
+
+	void SetSearchWindow(_REAL rNewCenterFreq, _REAL rNewWinSize);
+
+	void StartAcquisition();
+	void StopAcquisition() {bAquisition = FALSE;}
+	_BOOLEAN GetAcquisition() {return bAquisition;}
+
+	void SetRecFilter(const _BOOLEAN bNewF) {bUseRecFilter = bNewF;}
+	_BOOLEAN GetRecFilter() {return bUseRecFilter;}
+	_BOOLEAN GetUnlockedFrameBoundary() {return iFreeSymbolCounter==0;}
+
+	/* To set the module up for synchronized DRM input data stream */
+	void SetSyncInput(_BOOLEAN bNewS) {bSyncInput = bNewS;}
+
+protected:
+	CVector<int>				veciTableFreqPilots;
+	CShiftRegister<_REAL>		vecrFFTHistory;
+
+	CFftPlans					FftPlan;
+	CRealVector					vecrFFTInput;
+	CRealVector					vecrSqMagFFTOut;
+	CRealVector					vecrHammingWin;
+	CMovingAv<CRealVector>		vvrPSDMovAv;
+
+	int							iFrAcFFTSize;
+	int							iHistBufSize;
+
+	int							iFFTSize;
+
+	_BOOLEAN					bAquisition;
+
+	int							iAquisitionCounter;
+	int							iAverageCounter;
+
+	_BOOLEAN					bSyncInput;
+
+	_REAL						rCenterFreq;
+	_REAL						rWinSize;
+	int							iStartDCSearch;
+	int							iEndDCSearch;
+	_REAL						rPeakBoundFiltToSig;
+
+	CRealVector					vecrPSDPilCor;
+	int							iHalfBuffer;
+	int							iSearchWinSize;
+	CRealVector					vecrFiltResLR;
+	CRealVector					vecrFiltResRL;
+	CRealVector					vecrFiltRes;
+	CVector<int>				veciPeakIndex;
+
+	_COMPLEX					cCurExp;
+	_REAL						rInternIFNorm;
+
+	CDRMBandpassFilt			BPFilter;
+	_BOOLEAN					bUseRecFilter;
+
+	/* OPH: counter to count symbols within a frame in order to generate */
+	/* RSCI output even when unlocked */
+	int							iFreeSymbolCounter;
+
+	virtual void InitInternal(CParameter& Parameters);
+	virtual void ProcessDataInternal(CParameter& Parameters);
+};
+
+
+#endif // !defined(FREQSYNC_H__3B0BA660EDOINBEROUEBGF4344_BB2B_23E7912__INCLUDED_)
diff --git a/src/sync/SyncUsingPil.cpp b/src/sync/SyncUsingPil.cpp
new file mode 100644
index 0000000..0bcf16f
--- /dev/null
+++ b/src/sync/SyncUsingPil.cpp
@@ -0,0 +1,452 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *	Frame synchronization (Using time-pilots), frequency sync tracking
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "SyncUsingPil.h"
+
+
+/* Implementation *************************************************************/
+void CSyncUsingPil::ProcessDataInternal(CParameter& Parameters)
+{
+	int i;
+
+	Parameters.Lock(); 
+
+	/**************************************************************************\
+	* Frame synchronization detection										   *
+	\**************************************************************************/
+	_BOOLEAN bSymbolIDHasChanged = FALSE;
+
+	if ((bSyncInput == FALSE) && (bAquisition == TRUE))
+	{
+		/* DRM frame synchronization based on time pilots ------------------- */
+		/* Calculate correlation of received cells with pilot pairs */
+		CReal rResultPilPairCorr = (CReal) 0.0;
+		for (i = 0; i < iNumPilPairs; i++)
+		{
+			/* Actual correlation */
+			const CComplex cCorrRes = (*pvecInputData)[vecPilCorr[i].iIdx1] *
+				Conj(vecPilCorr[i].cPil1) *
+				Conj((*pvecInputData)[vecPilCorr[i].iIdx2]) *
+				vecPilCorr[i].cPil2 * cR_HH;
+
+			rResultPilPairCorr += Real(cCorrRes);
+		}
+
+		/* Store correlation results in a shift register for finding the peak */
+		vecrCorrHistory.AddEnd(rResultPilPairCorr);
+
+
+		/* Finding beginning of DRM frame in results ------------------------ */
+		/* Wait until history is filled completly */
+		if (iInitCntFraSy > 0)
+			iInitCntFraSy--;
+		else
+		{
+			/* Search for maximum */
+			int iMaxIndex = 0;
+			CReal rMaxValue = -_MAXREAL;
+			for (i = 0; i < iNumSymPerFrame; i++)
+			{
+				if (vecrCorrHistory[i] > rMaxValue)
+				{
+					rMaxValue = vecrCorrHistory[i];
+					iMaxIndex = i;
+				}
+			}
+
+			/* For initial frame synchronization, use maximum directly */
+			if (bInitFrameSync == TRUE)
+			{
+				/* Reset init flag */
+				bInitFrameSync = FALSE;
+
+				/* Set symbol ID index according to received data */
+				iSymbCntFraSy = iNumSymPerFrame - iMaxIndex - 1;
+			}
+			else
+			{
+				/* If maximum is in the middle of the interval
+				   (check frame sync) */
+				if (iMaxIndex == iMiddleOfInterval)
+				{
+					if (iSymbCntFraSy == iNumSymPerFrame - iMiddleOfInterval - 1)
+					{
+						/* Reset flags */
+						bBadFrameSync = FALSE;
+						bFrameSyncWasOK = TRUE;
+
+						/* Post Message for GUI (Good frame sync) */
+						Parameters.ReceiveStatus.FSync.SetStatus(RX_OK);
+					}
+					else
+					{
+						if (bBadFrameSync == TRUE)
+						{
+							/* Reset symbol ID index according to received
+							   data */
+							iSymbCntFraSy =
+								iNumSymPerFrame - iMiddleOfInterval - 1;
+
+							/* Inform that symbol ID has changed */
+							bSymbolIDHasChanged = TRUE;
+
+							/* Reset flag */
+							bBadFrameSync = FALSE;
+
+							Parameters.ReceiveStatus.FSync.SetStatus(CRC_ERROR);
+						}
+						else
+						{
+							/* One false detected frame sync should not reset
+							   the actual frame sync because the measurement
+							   could be wrong. Sometimes the frame sync
+							   detection gets false results. If the next time
+							   the frame sync is still unequal to the
+							   measurement, then correct it */
+							bBadFrameSync = TRUE;
+
+							if (bFrameSyncWasOK == TRUE)
+							{
+								/* Post Message that frame sync was wrong but
+								   was not yet corrected (yellow light) */
+								Parameters.ReceiveStatus.FSync.SetStatus(DATA_ERROR);
+							}
+							else
+								Parameters.ReceiveStatus.FSync.SetStatus(CRC_ERROR);
+						}
+
+						/* Set flag for bad sync */
+						bFrameSyncWasOK = FALSE;
+					}
+				}
+			}
+		}
+	}
+	else
+	{
+		/* Frame synchronization has successfully finished, show always green
+		   light */
+		Parameters.ReceiveStatus.FSync.SetStatus(RX_OK);
+	}
+
+	/* Set current symbol ID and flag in extended data of output vector */
+	(*pvecOutputData).GetExData().iSymbolID = iSymbCntFraSy;
+	(*pvecOutputData).GetExData().bSymbolIDHasChanged = bSymbolIDHasChanged;
+
+	/* Increase symbol counter and take care of wrap around */
+	iSymbCntFraSy++;
+	if (iSymbCntFraSy >= iNumSymPerFrame)
+		iSymbCntFraSy = 0;
+
+
+	/**************************************************************************\
+	* Using Frequency pilot information										   *
+	\**************************************************************************/
+	if ((bSyncInput == FALSE) && (bTrackPil == TRUE))
+	{
+		CComplex cFreqOffEstVecSym = CComplex((CReal) 0.0, (CReal) 0.0);
+
+		for (i = 0; i < NUM_FREQ_PILOTS; i++)
+		{
+			/* The old pilots must be rotated due to timing corrections */
+			const CComplex cOldFreqPilCorr =
+				Rotate(cOldFreqPil[i], iPosFreqPil[i],
+				(*pvecInputData).GetExData().iCurTimeCorr);
+
+			/* Calculate the inner product of the sum */
+			const CComplex cCurPilMult =
+				(*pvecInputData)[iPosFreqPil[i]] * Conj(cOldFreqPilCorr);
+
+			/* Save "old" frequency pilots for next symbol. Special treatment
+			   for robustness mode D (carriers 7 and 21) necessary 
+			   (See 8.4.2.2) */
+
+// TODO: take care of initialization phase: do not start using estimates until
+// the first "old pilots" were stored. Also, an "initial frequecy offset
+// estimate" should be made and rFreqOffsetTrack should be set to this value!
+
+			if ((Parameters.GetWaveMode() == RM_ROBUSTNESS_MODE_D) &&
+				(i < 2))
+			{
+				cOldFreqPil[i] = -(*pvecInputData)[iPosFreqPil[i]];
+			}
+			else
+				cOldFreqPil[i] = (*pvecInputData)[iPosFreqPil[i]];
+
+#ifdef USE_SAMOFFS_TRACK_FRE_PIL
+			/* Get phase difference for sample rate offset estimation. Average
+			   the vector, real and imaginary part separately */
+			IIR1(cFreqPilotPhDiff[i], cCurPilMult, rLamSamRaOff);
+#endif
+
+			/* Calculate estimation of frequency offset */
+			cFreqOffEstVecSym += cCurPilMult;
+		}
+
+
+		/* Frequency offset ------------------------------------------------- */
+		/* Correct frequency offset estimation for resample offset corrections.
+		   When a sample rate offset correction was applied, the frequency
+		   offset is shifted proportional to this correction. The correction
+		   is mandatory if large sample rate offsets occur */
+
+		/* Get sample rate offset change */
+		const CReal rDiffSamOffset =
+			rPrevSamRateOffset - Parameters.rResampleOffset;
+
+		/* Save current resample offset for next symbol */
+		rPrevSamRateOffset = Parameters.rResampleOffset;
+
+		/* Correct sample-rate offset correction according to the proportional
+		   rule. Use relative DC frequency offset plus relative average offset
+		   of frequency pilots to the DC frequency. Normalize this offset so
+		   that it can be used as a phase correction for frequency offset
+		   estimation  */
+		CReal rPhaseCorr = (Parameters.rFreqOffsetAcqui +
+			Parameters.rFreqOffsetTrack + rAvFreqPilDistToDC) *
+			rDiffSamOffset / Parameters.GetSigSampleRate() / rNormConstFOE;
+
+		/* Actual correction (rotate vector) */
+		cFreqOffVec *= CComplex(Cos(rPhaseCorr), Sin(rPhaseCorr));
+
+
+		/* Average vector, real and imaginary part separately */
+		IIR1(cFreqOffVec, cFreqOffEstVecSym, rLamFreqOff);
+
+		/* Calculate argument */
+		const CReal rFreqOffsetEst = Angle(cFreqOffVec);
+
+		/* Correct measurement average for actually applied frequency
+		   correction */
+		cFreqOffVec *= CComplex(Cos(-rFreqOffsetEst), Sin(-rFreqOffsetEst));
+
+#ifndef USE_FRQOFFS_TRACK_GUARDCORR
+		/* Integrate the result for controling the frequency offset, normalize
+		   estimate */
+		Parameters.rFreqOffsetTrack += rFreqOffsetEst * rNormConstFOE;
+#endif
+
+
+#ifdef USE_SAMOFFS_TRACK_FRE_PIL
+		/* Sample rate offset ----------------------------------------------- */
+		/* Calculate estimation of sample frequency offset. We use the different
+		   frequency offset estimations of the frequency pilots. We normalize
+		   them with the distance between them and average the result (/ 2.0) */
+		CReal rSampFreqOffsetEst =
+			((Angle(cFreqPilotPhDiff[1]) - Angle(cFreqPilotPhDiff[0])) /
+			(iPosFreqPil[1] - iPosFreqPil[0]) +
+			(Angle(cFreqPilotPhDiff[2]) - Angle(cFreqPilotPhDiff[0])) /
+			(iPosFreqPil[2] - iPosFreqPil[0])) / (CReal) 2.0;
+
+		/* Integrate the result for controling the resampling */
+		Parameters.rResampleOffset +=
+			CONTR_SAMP_OFF_INTEGRATION * rSampFreqOffsetEst;
+#endif
+
+#ifdef _DEBUG_
+/* Save frequency and sample rate tracking */
+static FILE* pFile = fopen("test/freqtrack.dat", "w");
+fprintf(pFile, "%e %e\n", Parameters.GetSigSampleRate() * Parameters.rFreqOffsetTrack,
+	Parameters.rResampleOffset);
+fflush(pFile);
+#endif
+	}
+
+
+	/* If synchronized DRM input stream is used, overwrite the detected
+	   frequency offest estimate by "0", because we know this value */
+	if (bSyncInput == TRUE)
+		Parameters.rFreqOffsetTrack = (CReal) 0.0;
+
+	/* Do not ship data before first frame synchronization was done. The flag
+	   "bAquisition" must not be set to FALSE since in that case we would run
+	   into an infinite loop since we would not ever ship any data. But since
+	   the flag is set after this module, we should be fine with that. */
+	if ((bInitFrameSync == TRUE) && (bSyncInput == FALSE))
+		iOutputBlockSize = 0;
+	else
+	{
+		iOutputBlockSize = iNumCarrier;
+
+		/* Copy data from input to the output. Data is not modified in this
+		   module */
+		for (i = 0; i < iOutputBlockSize; i++)
+			(*pvecOutputData)[i] = (*pvecInputData)[i];
+	}
+
+	Parameters.Unlock(); 
+}
+
+void CSyncUsingPil::InitInternal(CParameter& Parameters)
+{
+	int			i;
+	_COMPLEX	cPhaseCorTermDivi;
+
+	Parameters.Lock(); 
+
+	/* Init base class for modifying the pilots (rotation) */
+	CPilotModiClass::InitRot(Parameters);
+
+	/* Init internal parameters from global struct */
+	iNumCarrier = Parameters.CellMappingTable.iNumCarrier;
+	eCurRobMode = Parameters.GetWaveMode();
+
+	/* Check if symbol number per frame has changed. If yes, reset the
+	   symbol counter */
+	if (iNumSymPerFrame != Parameters.CellMappingTable.iNumSymPerFrame)
+	{
+		/* Init internal counter for symbol number */
+		iSymbCntFraSy = 0;
+
+		/* Refresh parameter */
+		iNumSymPerFrame = Parameters.CellMappingTable.iNumSymPerFrame;
+	}
+
+	/* Allocate memory for histories. Init history with small values, because
+	   we search for maximum! */
+	vecrCorrHistory.Init(iNumSymPerFrame, -_MAXREAL);
+
+	/* Set middle of observation interval */
+	iMiddleOfInterval = iNumSymPerFrame / 2;
+
+
+	/* DRM frame synchronization based on time pilots, inits ---------------- */
+	/* Allocate memory for storing pilots and indices. Since we do
+	   not know the resulting "iNumPilPairs" we allocate memory for the
+	   worst case, i.e. "iNumCarrier" */
+	vecPilCorr.Init(iNumCarrier);
+
+	/* Store pilots and indices for calculating the correlation. Use only first
+	   symbol of "matcPilotCells", because there are the pilots for
+	   Frame-synchronization */
+	iNumPilPairs = 0;
+
+	for (i = 0; i < iNumCarrier - 1; i++)
+	{
+		/* Only successive pilots (in frequency direction) are used */
+		if (_IsPilot(Parameters.CellMappingTable.matiMapTab[0][i]) &&
+			_IsPilot(Parameters.CellMappingTable.matiMapTab[0][i + 1]))
+		{
+			/* Store indices and complex numbers */
+			vecPilCorr[iNumPilPairs].iIdx1 = i;
+			vecPilCorr[iNumPilPairs].iIdx2 = i + 1;
+			vecPilCorr[iNumPilPairs].cPil1 = Parameters.CellMappingTable.matcPilotCells[0][i];
+			vecPilCorr[iNumPilPairs].cPil2 = Parameters.CellMappingTable.matcPilotCells[0][i + 1];
+
+			iNumPilPairs++;
+		}
+	}
+
+	/* Calculate channel correlation in frequency direction. Use rectangular
+	   shaped PDS with the length of the guard-interval */
+	const CReal rArgSinc =
+		(CReal) Parameters.CellMappingTable.iGuardSize / Parameters.CellMappingTable.iFFTSizeN;
+	const CReal rArgExp = crPi * rArgSinc;
+
+	cR_HH = Sinc(rArgSinc) * CComplex(Cos(rArgExp), -Sin(rArgExp));
+
+
+	/* Frequency offset estimation ------------------------------------------ */
+	/* Get position of frequency pilots */
+	int iFreqPilCount = 0;
+	int iAvPilPos = 0;
+	for (i = 0; i < iNumCarrier - 1; i++)
+	{
+		if (_IsFreqPil(Parameters.CellMappingTable.matiMapTab[0][i]))
+		{
+			/* For average frequency pilot position to DC carrier */
+			iAvPilPos += i + Parameters.CellMappingTable.iCarrierKmin;
+			
+			iPosFreqPil[iFreqPilCount] = i;
+			iFreqPilCount++;
+		}
+	}
+
+	/* Average distance of the frequency pilots from the DC carrier. Needed for
+	   corrections for sample rate offset changes. Normalized to sample rate! */
+	rAvFreqPilDistToDC =
+		(CReal) iAvPilPos / NUM_FREQ_PILOTS / Parameters.CellMappingTable.iFFTSizeN;
+
+	/* Init memory for "old" frequency pilots */
+	for (i = 0; i < NUM_FREQ_PILOTS; i++)
+		cOldFreqPil[i] = CComplex((CReal) 0.0, (CReal) 0.0);
+	
+	/* Nomalization constant for frequency offset estimation */
+	rNormConstFOE =
+		(CReal) 1.0 / ((CReal) 2.0 * crPi * Parameters.CellMappingTable.iSymbolBlockSize);
+
+	/* Init time constant for IIR filter for frequency offset estimation */
+	rLamFreqOff = IIR1Lam(TICONST_FREQ_OFF_EST, (CReal) Parameters.GetSigSampleRate() /
+		Parameters.CellMappingTable.iSymbolBlockSize);
+
+	/* Init vector for averaging the frequency offset estimation */
+	cFreqOffVec = CComplex((CReal) 0.0, (CReal) 0.0);
+
+	/* Init value for previous estimated sample rate offset with the current
+	   setting. This can be non-zero if, e.g., an initial sample rate offset
+	   was set by command line arguments */
+	rPrevSamRateOffset = Parameters.rResampleOffset;
+
+
+#ifdef USE_SAMOFFS_TRACK_FRE_PIL
+	/* Inits for sample rate offset estimation algorithm -------------------- */
+	/* Init memory for actual phase differences */
+	for (i = 0; i < NUM_FREQ_PILOTS; i++)
+		cFreqPilotPhDiff[i] = CComplex((CReal) 0.0, (CReal) 0.0);
+
+	/* Init time constant for IIR filter for sample rate offset estimation */
+	rLamSamRaOff = IIR1Lam(TICONST_SAMRATE_OFF_EST,
+		(CReal) Parameters.GetSigSampleRate() / Parameters.CellMappingTable.iSymbolBlockSize);
+#endif
+
+
+	/* Define block-sizes for input and output */
+	iInputBlockSize = iNumCarrier;
+	iMaxOutputBlockSize = iNumCarrier;
+
+	Parameters.Unlock(); 
+}
+
+void CSyncUsingPil::StartAcquisition()
+{
+	/* Init internal counter for symbol number */
+	iSymbCntFraSy = 0;
+
+	/* Reset correlation history */
+	vecrCorrHistory.Reset(-_MAXREAL);
+
+	bAquisition = TRUE;
+
+	/* After an initialization the frame sync must be adjusted */
+	bBadFrameSync = TRUE;
+	bInitFrameSync = TRUE; /* Set flag to show that (re)-init was done */
+	bFrameSyncWasOK = FALSE;
+
+	/* Initialize count for filling the history buffer */
+	iInitCntFraSy = iNumSymPerFrame;
+}
diff --git a/src/sync/SyncUsingPil.h b/src/sync/SyncUsingPil.h
new file mode 100644
index 0000000..91473ad
--- /dev/null
+++ b/src/sync/SyncUsingPil.h
@@ -0,0 +1,135 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *	See SyncUsingPil.cpp
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later 
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT 
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#if !defined(SYNCUSINGPIL_H__3B0BA660_CA63_434OBUVEE7A0D31912__INCLUDED_)
+#define SYNCUSINGPIL_H__3B0BA660_CA63_434OBUVEE7A0D31912__INCLUDED_
+
+#include "../Parameter.h"
+#include "../util/Modul.h"
+#include "../util/Vector.h"
+#include "../chanest/ChanEstTime.h"
+
+
+/* Definitions ****************************************************************/
+/* Time constant for IIR averaging of frequency offset estimation */
+#define TICONST_FREQ_OFF_EST			((CReal) 1.0) /* sec */
+
+#ifdef USE_SAMOFFS_TRACK_FRE_PIL
+/* Time constant for IIR averaging of sample rate offset estimation */
+# define TICONST_SAMRATE_OFF_EST		((CReal) 20.0) /* sec */
+# define CONTR_SAMP_OFF_INTEGRATION		((_REAL) 3.0)
+#endif
+
+
+/* Classes ********************************************************************/
+class CSyncUsingPil : public CReceiverModul<_COMPLEX, _COMPLEX>, 
+					  public CPilotModiClass
+{
+public:
+	CSyncUsingPil() :
+		iPosFreqPil(NUM_FREQ_PILOTS),
+		cOldFreqPil(NUM_FREQ_PILOTS),
+		iSymbCntFraSy(0),
+		iNumSymPerFrame(0),
+		bSyncInput(FALSE), bAquisition(FALSE),
+		bTrackPil(FALSE)
+#ifdef USE_SAMOFFS_TRACK_FRE_PIL
+		, cFreqPilotPhDiff(NUM_FREQ_PILOTS)
+#endif
+	  {}
+	virtual ~CSyncUsingPil() {}
+
+	/* To set the module up for synchronized DRM input data stream */
+	void SetSyncInput(_BOOLEAN bNewS) {bSyncInput = bNewS;}
+
+	void StartAcquisition();
+	void StopAcquisition() {bAquisition = FALSE;}
+
+	void StartTrackPil() {bTrackPil = TRUE;}
+	void StopTrackPil() {bTrackPil = FALSE;}
+
+protected:
+	class CPilotCorr
+	{
+	public:
+		int			iIdx1, iIdx2;
+		CComplex	cPil1, cPil2;
+	};
+
+	/* Variables for frequency pilot estimation */
+	CVector<int>			iPosFreqPil;
+	CVector<CComplex>		cOldFreqPil;
+
+	CReal					rNormConstFOE;
+	CReal					rSampleFreqEst;
+
+	int						iSymbCntFraSy;
+	int						iInitCntFraSy;
+
+	int						iNumSymPerFrame;
+	int						iNumCarrier;
+
+	_BOOLEAN				bBadFrameSync;
+	_BOOLEAN				bInitFrameSync;
+	_BOOLEAN				bFrameSyncWasOK;
+
+	_BOOLEAN				bSyncInput;
+
+	_BOOLEAN				bAquisition;
+	_BOOLEAN				bTrackPil;
+
+	int						iMiddleOfInterval;
+
+	CReal					rLamFreqOff;
+	CComplex				cFreqOffVec;
+
+
+	/* Variables for frame synchronization */
+	CShiftRegister<CReal>	vecrCorrHistory;
+
+	/* DRM frame synchronization based on time pilots */
+	CVector<CPilotCorr>		vecPilCorr;
+	int						iNumPilPairs;
+	CComplex				cR_HH;
+
+	ERobMode				eCurRobMode;
+
+	CReal					rAvFreqPilDistToDC;
+	CReal					rPrevSamRateOffset;
+
+#ifdef USE_SAMOFFS_TRACK_FRE_PIL
+	CReal					rLamSamRaOff;
+	CVector<CComplex>		cFreqPilotPhDiff;
+#endif
+
+	virtual void InitInternal(CParameter& Parameters);
+	virtual void ProcessDataInternal(CParameter& Parameters);
+};
+
+
+#endif // !defined(SYNCUSINGPIL_H__3B0BA660_CA63_434OBUVEE7A0D31912__INCLUDED_)
diff --git a/src/sync/TimeSync.cpp b/src/sync/TimeSync.cpp
new file mode 100644
index 0000000..763cba9
--- /dev/null
+++ b/src/sync/TimeSync.cpp
@@ -0,0 +1,946 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *	Time synchronization
+ * This module can have different amounts of input data. If two
+ * possible FFT-window positions are found, the next time no new block is
+ * requested.
+ *
+ * Robustness-mode detection
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "TimeSync.h"
+
+
+/* Implementation *************************************************************/
+void CTimeSync::ProcessDataInternal(CParameter& Parameters)
+{
+	int				i, j, k;
+	int				iMaxIndex;
+	int				iIntDiffToCenter;
+	int				iCurPos;
+	int				iDecInpuSize;
+	CReal			rMaxValue;
+	CReal			rMaxValRMCorr;
+	CReal			rSecHighPeak;
+	//CReal			rFreqOffsetEst;
+	CComplexVector	cvecInpTmp;
+	CRealVector		rResMode(NUM_ROBUSTNESS_MODES);
+	int				iNewStIndCount = 0;
+	/* Max number of detected peaks ("5" for safety reasons. Could be "2") */
+	CVector<int>	iNewStartIndexField(5);
+
+	/* Init start index (in case no timing could be detected or init phase) */
+	int iStartIndex = iSymbolBlockSize;
+
+	/* Write new block of data at the end of shift register */
+	HistoryBuf.AddEnd(*pvecInputData, iInputBlockSize);
+
+	/* In case the time domain frequency offset estimation method is activated,
+	   the hilbert filtering of input signal must always be applied */
+#ifndef USE_FRQOFFS_TRACK_GUARDCORR
+	if ((bTimingAcqu == TRUE) || (bRobModAcqu == TRUE))
+#endif
+	{
+		/* ---------------------------------------------------------------------
+		   Data must be band-pass-filtered before applying the algorithms,
+		   because we do not know which mode is active when we synchronize
+		   the timing and we must assume the worst-case, therefore use only
+		   from DC to 4.5 kHz. If the macro "USE_10_KHZ_HILBFILT" is defined,
+		   a bandwith of approx. 10 kHz is used. In this case, we have better
+		   performance with the most probable 10 kHz mode but may have worse
+		   performance with the 4.5 or 5 kHz modes (for the acquisition) */
+
+		/* The FIR filter intermediate buffer must be adjusted to the new
+		   input block size since the size can be vary with time */
+		cvecInpTmp.Init(iInputBlockSize);
+
+		/* Copy CVector data in CMatlibVector */
+		for (i = 0; i < iInputBlockSize; i++)
+			cvecInpTmp[i] = (*pvecInputData)[i];
+
+		/* Complex Hilbert filter. We use the copy constructor for storing
+		   the result since the sizes of the output vector varies with time.
+		   We decimate the signal with this function, too, because we only
+		   analyze a spectrum bandwith of approx. 5 [10] kHz */
+		CComplexVector cvecOutTmp(
+			FirFiltDec(cvecB, cvecInpTmp, cvecZ, iGrdcrrDecFact));
+
+		/* Get size of new output vector */
+		iDecInpuSize = cvecOutTmp.GetSize();
+
+		/* Copy data from Matlib vector in regular vector for storing in
+		   shift register
+		   TODO: Make vector types compatible (or maybe only use matlib vectors
+		   everywhere) */
+		cvecOutTmpInterm.Init(iDecInpuSize);
+		for (i = 0; i < iDecInpuSize; i++)
+		{
+			cvecOutTmpInterm[i] = cvecOutTmp[i];
+//			float value[2] = {cvecOutTmp[i].real()/8192, cvecOutTmp[i].imag()/8192};
+//			write(1000, &value, sizeof(value));
+		}
+
+		/* Write new block of data at the end of shift register */
+		HistoryBufCorr.AddEnd(cvecOutTmpInterm, iDecInpuSize);
+
+
+#ifdef USE_FRQOFFS_TRACK_GUARDCORR
+		/* ---------------------------------------------------------------------
+		   Frequency offset tracking estimation method based on guard-interval
+		   correlation.
+		   Problem: The tracking frequency range is "GRDCRR_DEC_FACT"-times
+		   smaller than the one in the frequency domain tracking algorithm.
+		   Therefore, the acquisition unit must work more precisely
+		   (see FreqSyncAcq.h) */
+
+		/* Guard-interval correlation at ML estimated timing position */
+		/* Calculate start points for correlation. Consider delay from
+		   Hilbert-filter */
+		const int iHalHilFilDelDec = iNumTapsHilbFilt / 2 / iGrdcrrDecFact;
+		const int iCorrPosFirst = iDecSymBS + iHalHilFilDelDec;
+		const int iCorrPosSec =
+			iDecSymBS + iHalHilFilDelDec + iLenUsefPart[iSelectedMode];
+
+		/* Actual correlation over entire guard-interval */
+		CComplex cGuardCorrFreqTrack = 0.0;
+		for (i = 0; i < iLenGuardInt[iSelectedMode]; i++)
+		{
+			/* Use start point from ML timing estimation. The input stream is
+			   automatically adjusted to have this point at "iDecSymBS" */
+			cGuardCorrFreqTrack += HistoryBufCorr[i + iCorrPosFirst] *
+				Conj(HistoryBufCorr[i + iCorrPosSec]);
+		}
+
+		/* Average vector, real and imaginary part separately */
+		IIR1(cFreqOffAv, cGuardCorrFreqTrack, rLamFreqOff);
+
+		/* Calculate argument */
+		const CReal rFreqOffsetEst = Angle(cFreqOffAv);
+
+		/* Correct measurement average for actually applied frequency
+		   correction */
+		cFreqOffAv *= CComplex(Cos(-rFreqOffsetEst), Sin(-rFreqOffsetEst));
+
+		/* Integrate the result for controling the frequency offset, normalize
+		   estimate */
+		Parameters.Lock(); 
+		Parameters.rFreqOffsetTrack -= rFreqOffsetEst * rNormConstFOE;
+		Parameters.Unlock(); 
+#endif
+
+
+		if ((bTimingAcqu == TRUE) || (bRobModAcqu == TRUE))
+		{
+			/* Guard-interval correlation ----------------------------------- */
+			/* Set position pointer back for this block */
+			iTimeSyncPos -= iDecInpuSize;
+
+			/* Init start-index count */
+			iNewStIndCount = 0;
+
+			/* We use the block in the middle of the buffer for observation */
+			for (i = iDecSymBS + iDecSymBS - iDecInpuSize;
+				i < iDecSymBS + iDecSymBS; i++)
+			{
+				/* Only every "iStepSizeGuardCorr"'th value is calculated for
+				   efficiency reasons */
+				if (i == iTimeSyncPos)
+				{
+					/* Do the following guard interval correlation for all
+					   possible robustness modes (this is needed for robustness
+					   mode detection) */
+					for (j = 0; j < NUM_ROBUSTNESS_MODES; j++)
+					{
+						/* Guard-interval correlation ----------------------- */
+						/* Speed optimized calculation of the guard-interval
+						   correlation. We devide the total block, which has to
+						   be computed, in parts of length "iStepSizeGuardCorr".
+						   The results of these blocks are stored in a vector.
+						   Now, only one new part has to be calculated and one
+						   old one has to be subtracted from the global result.
+						   Special care has to be taken since "iGuardSize" must
+						   not be a multiple of "iStepSizeGuardCorr". Therefore
+						   the "if"-condition */
+						/* First subtract correlation values shifted out */
+						cGuardCorr[j] -= 
+							veccIntermCorrRes[j][iPosInIntermCResBuf[j]];
+						rGuardPow[j] -= 
+							vecrIntermPowRes[j][iPosInIntermCResBuf[j]];
+
+						/* Calculate new block and add in memory */
+						for (k = iLengthOverlap[j]; k < iLenGuardInt[j]; k++)
+						{
+							/* Actual correlation */
+							iCurPos = iTimeSyncPos + k;
+							cGuardCorrBlock[j] += HistoryBufCorr[iCurPos] * 
+								Conj(HistoryBufCorr[iCurPos + iLenUsefPart[j]]);
+
+							/* Energy calculation for ML solution */
+							rGuardPowBlock[j] +=
+								SqMag(HistoryBufCorr[iCurPos]) +
+								SqMag(HistoryBufCorr[iCurPos + iLenUsefPart[j]]);
+
+							/* If one complete block is ready -> store it. We
+							   need to add "1" to the k, because otherwise
+							   "iLengthOverlap" would satisfy the
+							   "if"-condition */
+							if (((k + 1) % iStepSizeGuardCorr) == 0)
+							{
+								veccIntermCorrRes[j][iPosInIntermCResBuf[j]] =
+									cGuardCorrBlock[j];
+
+								vecrIntermPowRes[j][iPosInIntermCResBuf[j]] =
+									rGuardPowBlock[j];
+
+								/* Add the new block to the global result */
+								cGuardCorr[j] += cGuardCorrBlock[j];
+								rGuardPow[j] += rGuardPowBlock[j];
+
+								/* Reset block result */
+								cGuardCorrBlock[j] = (CReal) 0.0;
+								rGuardPowBlock[j] = (CReal) 0.0;
+
+								/* Increase position pointer and test if wrap */
+								iPosInIntermCResBuf[j]++;
+								if (iPosInIntermCResBuf[j] == iLengthIntermCRes[j])
+									iPosInIntermCResBuf[j] = 0;
+							}
+						}
+
+						/* Save correlation results in shift register */
+						for (k = 0; k < iRMCorrBufSize - 1; k++)
+							vecrRMCorrBuffer[j][k] = vecrRMCorrBuffer[j][k + 1];
+
+						/* ML solution */
+						vecrRMCorrBuffer[j][iRMCorrBufSize - 1] =
+							abs(cGuardCorr[j] + cGuardCorrBlock[j]) - 
+							(rGuardPow[j] + rGuardPowBlock[j]) / 2;
+					}
+
+					/* Energy of guard intervall calculation and detection of
+					   peak is only needed if timing aquisition is true */
+					if (bTimingAcqu == TRUE)
+					{
+						/* Start timing detection not until initialization phase
+						   is finished */
+						if (iTiSyncInitCnt > 1)
+						{
+							/* Decrease counter */
+							iTiSyncInitCnt--;
+						}
+						else
+						{
+							/* Average the correlation results */
+							IIR1(vecCorrAvBuf[iCorrAvInd],
+								vecrRMCorrBuffer[iSelectedMode][iRMCorrBufSize - 1],
+								1 - rLambdaCoAv);
+
+
+							/* Energy of guard-interval correlation calculation
+							   (this is simply a moving average operation) */
+							vecrGuardEnMovAv.Add(vecCorrAvBuf[iCorrAvInd]);
+
+
+							/* Taking care of correlation average buffer ---- */
+							/* We use a "cyclic buffer" structure. This index
+							   defines the position in the buffer */
+							iCorrAvInd++;
+							if (iCorrAvInd == iMaxDetBufSize)
+							{
+								/* Adaptation of the lambda parameter for
+								   guard-interval correlation averaging IIR
+								   filter. With this adaptation we achieve
+								   better averaging results. A lower bound is
+								   defined for this parameter */
+								if (rLambdaCoAv <= 0.1)
+									rLambdaCoAv = 0.1;
+								else
+									rLambdaCoAv /= 2;
+
+								iCorrAvInd = 0;
+							}
+
+
+							/* Detection buffer ----------------------------- */
+							/* Update buffer for storing the moving average
+							   results */
+							pMaxDetBuffer.AddEnd(vecrGuardEnMovAv.GetAverage());
+
+							/* Search for maximum */
+							iMaxIndex = 0;
+							rMaxValue = (CReal) -_MAXREAL; /* Init value */
+							for (k = 0; k < iMaxDetBufSize; k++)
+							{
+								if (pMaxDetBuffer[k] > rMaxValue)
+								{
+									rMaxValue = pMaxDetBuffer[k];
+									iMaxIndex = k;
+								}
+							}
+
+							/* If maximum is in the middle of the interval, mark
+							   position as the beginning of the FFT window */
+							if (iMaxIndex == iCenterOfMaxDetBuf)
+							{
+								/* The optimal start position for the FFT-window
+								   is the middle of the "MaxDetBuffer" */
+								iNewStartIndexField[iNewStIndCount] = 
+									iTimeSyncPos * iGrdcrrDecFact -
+									iSymbolBlockSize / 2 -
+									/* Compensate for Hilbert-filter delay. The
+									   delay is introduced in the downsampled
+									   domain, therefore devide it by
+									   "GRDCRR_DEC_FACT" */
+									iNumTapsHilbFilt / 2 / iGrdcrrDecFact;
+
+								iNewStIndCount++;
+							}
+						}
+					}
+
+					/* Set position pointer to next step */
+					iTimeSyncPos += iStepSizeGuardCorr;
+				}
+			}
+
+
+			/* Robustness mode detection ------------------------------------ */
+			if (bRobModAcqu == TRUE)
+			{
+				/* Start robustness mode detection not until the buffer is
+				   filled */
+				if (iRobModInitCnt > 1)
+				{
+					/* Decrease counter */
+					iRobModInitCnt--;
+				}
+				else
+				{
+					int	iDetectedRModeInd=-1; /* ensures test fails if no assigment in loop */
+					/* Correlation of guard-interval correlation with prepared
+					   cos-vector. Store highest peak */
+					rMaxValRMCorr = (CReal) 0.0;
+					for (j = 0; j < NUM_ROBUSTNESS_MODES; j++)
+					{
+						/* Correlation with symbol rate frequency (Correlations
+						   must be normalized to be comparable!
+						   ("/ iGuardSizeX")) */
+						rResMode[j] =
+							Abs(Sum(vecrRMCorrBuffer[j] * vecrCos[j])) /
+							iLenGuardInt[j];
+
+						/* Search for maximum */
+						if (rResMode[j] > rMaxValRMCorr)
+						{
+							rMaxValRMCorr = rResMode[j];
+							iDetectedRModeInd = j;
+						}
+					}
+
+					/* Get second highest peak */
+					rSecHighPeak = (CReal) 0.0;
+					for (j = 0; j < NUM_ROBUSTNESS_MODES; j++)
+					{
+						if ((rResMode[j] > rSecHighPeak) &&
+							(iDetectedRModeInd != j))
+						{
+							rSecHighPeak = rResMode[j];
+						}
+					}
+
+					/* Find out if we have a reliable measure
+					   (distance to next peak) */
+					if ((rMaxValRMCorr / rSecHighPeak) > THRESHOLD_RELI_MEASURE)
+					{
+						/* Reset aquisition flag for robustness mode detection */
+						bRobModAcqu = FALSE;
+
+						/* Set wave mode */
+						Parameters.Lock(); 
+						if (Parameters.
+							SetWaveMode(GetRModeFromInd(iDetectedRModeInd)) == TRUE)
+						{
+							/* Reset output cyclic-buffer because wave mode has
+							   changed and the data written in the buffer is not
+							   valid anymore */
+							SetBufReset1();
+						}
+						Parameters.Unlock(); 
+					}
+				}
+			}
+		}
+	}
+
+	if (bTimingAcqu == TRUE)
+	{
+		/* Use all measured FFT-window start points for determining the "real"
+		   one */	
+		for (i = 0; i < iNewStIndCount; i++)
+		{
+			/* Check if new measurement is in range of predefined bound. This
+			   bound shall eliminate outliers for the calculation of the
+			   filtered result */
+			if (((iNewStartIndexField[i] < (iCenterOfBuf + TIMING_BOUND_ABS)) &&
+				(iNewStartIndexField[i] > (iCenterOfBuf - TIMING_BOUND_ABS))))
+			{
+				/* New measurement is in range -> use it for filtering */
+				/* Low-pass filter detected start of frame */
+				IIR1(rStartIndex, (CReal) iNewStartIndexField[i],
+					LAMBDA_LOW_PASS_START);
+
+				/* Reset counters for non-linear correction algorithm */
+				iCorrCounter = 0;
+				iAveCorr = 0;
+
+				/* GUI message that timing is ok */
+				Parameters.Lock(); 
+				Parameters.ReceiveStatus.TSync.SetStatus(RX_OK);
+				Parameters.Unlock(); 
+
+				/* Acquisition was successful, reset init flag (just in case it
+				   was not reset by the non-linear correction unit */
+				bInitTimingAcqu = FALSE;
+			}
+			else
+			{
+				/* Non-linear correction of the filter-output to ged rid of
+				   large differences between current measurement and
+				   filter-output */
+				iCorrCounter++;
+
+				/* Average the NUM_SYM_BEFORE_RESET measurements for reset
+				   rStartIndex */
+				iAveCorr += iNewStartIndexField[i];
+
+				/* If pre-defined number of outliers is exceed, correct */
+				if (iCorrCounter > NUM_SYM_BEFORE_RESET)
+				{
+					/* If this is the first correction after an initialization
+					   was done, reset flag and do not show red light */
+					if (bInitTimingAcqu == TRUE)
+					{
+						/* Reset flag */
+						bInitTimingAcqu = FALSE;
+
+						/* Right after initialization, the first estimate is
+						   used for correction */
+						rStartIndex = (CReal) iNewStartIndexField[i];
+					}
+					else
+					{
+						/* Correct filter-output */
+						rStartIndex =
+							(CReal) iAveCorr / (NUM_SYM_BEFORE_RESET + 1);
+
+						/* GUI message that timing was corrected (red light) */
+						Parameters.Lock(); 
+						Parameters.ReceiveStatus.TSync.SetStatus(CRC_ERROR);
+						Parameters.Unlock(); 
+					}
+
+					/* Reset counters */
+					iCorrCounter = 0;
+					iAveCorr = 0;
+				}
+				else
+				{
+					/* GUI message that timing is yet ok (yellow light). Do not
+					   show any light if init was done right before this */
+					if (bInitTimingAcqu == FALSE)
+					{
+						Parameters.Lock(); 
+						Parameters.ReceiveStatus.TSync.SetStatus(DATA_ERROR);
+						Parameters.Unlock(); 
+					}
+				}
+			}
+
+#ifdef _DEBUG_
+/* Save estimated positions of timing (acquisition) */
+static FILE* pFile = fopen("test/testtime.dat", "w");
+fprintf(pFile, "%d %d\n", iNewStartIndexField[i], iInputBlockSize);
+fflush(pFile);
+#endif
+		}
+
+		/* Convert result to integer format for cutting out the FFT-window */
+		iStartIndex = (int) rStartIndex;
+	}
+	else
+	{
+		Parameters.Lock(); 
+		/* Detect situation when acquisition was deactivated right now */
+		if (bAcqWasActive == TRUE)
+		{
+			bAcqWasActive = FALSE;
+
+			/* Reset also the tracking value since the tracking could not get
+			   right parameters since the timing was not yet correct */
+			Parameters.iTimingOffsTrack = 0;
+		}
+
+		/* In case of tracking only, use final acquisition result "rStartIndex"
+		   (which is not updated any more) and add tracking correction */
+		iStartIndex = (int) rStartIndex + Parameters.iTimingOffsTrack;
+
+		/* Timing acquisition was successfully finished, show always green
+		   light */
+		Parameters.ReceiveStatus.TSync.SetStatus(RX_OK);
+
+		Parameters.Unlock(); 
+
+#ifdef _DEBUG_
+/* Save estimated positions of timing (tracking) */
+static FILE* pFile = fopen("test/testtimetrack.dat", "w");
+static int iTimeTrackAbs = 0;
+iTimeTrackAbs += Parameters.iTimingOffsTrack; /* Integration */
+fprintf(pFile, "%d\n", iTimeTrackAbs);
+fflush(pFile);
+#endif
+	}
+
+
+	/* -------------------------------------------------------------------------
+	   Cut out the estimated optimal time window and write it to the output
+	   vector. Add the acquisition and tracking offset together for the final
+	   timing */
+	/* Check range of "iStartIndex" to prevent from vector overwrites. It must
+	   be larger than "0" since then the input block size would be also "0" and
+	   than the processing routine of the modul would not be called any more */
+	const int i2SymBlSize = iSymbolBlockSize + iSymbolBlockSize;
+	if (iStartIndex <= 0)
+		iStartIndex = 1;
+	if (iStartIndex >= i2SymBlSize)
+		iStartIndex = i2SymBlSize;
+
+	/* Cut out the useful part of the OFDM symbol */
+	for (k = iStartIndex; k < iStartIndex + iDFTSize; k++)
+		(*pvecOutputData)[k - iStartIndex] = HistoryBuf[k];
+
+	/* If synchronized DRM input stream is used, overwrite the detected
+	   timing */
+	if (bSyncInput == TRUE)
+	{
+		/* Set fixed timing position */
+		iStartIndex = iSymbolBlockSize;
+
+		/* Cut out guard-interval at right position -> no channel estimation
+		   needed when having only one path. No delay introduced in this
+		   module  */
+		for (k = iGuardSize; k < iSymbolBlockSize; k++)
+		{
+			(*pvecOutputData)[k - iGuardSize] = 
+				HistoryBuf[iTotalBufferSize - iInputBlockSize + k];
+		}
+	}
+
+
+	/* -------------------------------------------------------------------------
+	   Adjust filtered measurement so that it is back in the center of the
+	   buffer */
+	/* Integer part of the difference between filtered measurement and the
+	   center of the buffer */
+	iIntDiffToCenter = iCenterOfBuf - iStartIndex;
+
+	/* Set input block size for next block and reset filtered measurement. This
+	   is equal to a global shift of the observation window by the
+	   rearrangement of the filtered measurement */
+	iInputBlockSize = iSymbolBlockSize - iIntDiffToCenter;
+
+	/* In acquisition mode, correct start index */
+	if (bTimingAcqu == TRUE)
+		rStartIndex += (CReal) iIntDiffToCenter;
+
+
+	/* -------------------------------------------------------------------------
+	   The channel estimation needs information about timing corrections,
+	   because it is using information from the symbol memory. After a
+	   timing correction all old symbols must be corrected by a phase
+	   rotation as well */
+	(*pvecOutputData).GetExData().iCurTimeCorr = iIntDiffToCenter;
+}
+
+void CTimeSync::InitInternal(CParameter& Parameters)
+{
+	int	i, j;
+	int	iMaxSymbolBlockSize;
+	int	iObservedFreqBin;
+	CReal	rArgTemp;
+	int	iCorrBuffSize;
+
+	Parameters.Lock(); 
+
+	/* Get parameters from info class */
+	iSampleRate = Parameters.GetSigSampleRate();
+
+	/* Adjusting fft size to sample rate */
+	const int iRMAFFTSizeN = ADJ_FOR_SRATE(RMA_FFT_SIZE_N, iSampleRate);
+	const int iRMBFFTSizeN = ADJ_FOR_SRATE(RMB_FFT_SIZE_N, iSampleRate);
+	const int iRMCFFTSizeN = ADJ_FOR_SRATE(RMC_FFT_SIZE_N, iSampleRate);
+	const int iRMDFFTSizeN = ADJ_FOR_SRATE(RMD_FFT_SIZE_N, iSampleRate);
+
+	/* Adjusting GRDCRR_DEC_FACT to sample rate */
+	iGrdcrrDecFact = ADJ_FOR_SRATE(GRDCRR_DEC_FACT, iSampleRate);
+
+	/* Set Hilbert-filter parameters according to sample rate */
+	switch (iSampleRate)
+	{
+#if NUM_TAPS_HILB_FILT_24 > 0
+	case 24000:
+		iNumTapsHilbFilt = NUM_TAPS_HILB_FILT_24;
+# ifdef USE_10_KHZ_HILBFILT
+		fHilLPProt = fHilLPProt10_24;
+# else
+		fHilLPProt = fHilLPProt5_24;
+# endif
+		break;
+#endif
+#if NUM_TAPS_HILB_FILT_48 > 0
+	case 48000:
+		iNumTapsHilbFilt = NUM_TAPS_HILB_FILT_48;
+# ifdef USE_10_KHZ_HILBFILT
+		fHilLPProt = fHilLPProt10_48;
+# else
+		fHilLPProt = fHilLPProt5_48
+# endif
+		break;
+#endif
+#if NUM_TAPS_HILB_FILT_96 > 0
+	case 96000:
+		iNumTapsHilbFilt = NUM_TAPS_HILB_FILT_96;
+# ifdef USE_10_KHZ_HILBFILT
+		fHilLPProt = fHilLPProt10_96;
+# else
+		fHilLPProt = fHilLPProt5_96;
+# endif
+		break;
+#endif
+#if NUM_TAPS_HILB_FILT_192 > 0
+	case 192000:
+		iNumTapsHilbFilt = NUM_TAPS_HILB_FILT_192;
+# ifdef USE_10_KHZ_HILBFILT
+		fHilLPProt = fHilLPProt10_192;
+# else
+		fHilLPProt = fHilLPProt5_192;
+# endif
+		break;
+#endif
+#if NUM_TAPS_HILB_FILT_384 > 0
+	case 384000:
+		iNumTapsHilbFilt = NUM_TAPS_HILB_FILT_384;
+# ifdef USE_10_KHZ_HILBFILT
+		fHilLPProt = fHilLPProt10_384;
+# else
+		fHilLPProt = fHilLPProt5_384;
+# endif
+		break;
+#endif
+	}
+
+	/* Init Hilbert filter. Since the frequency offset correction was
+	   done in the previous module, the offset for the filter is
+	   always "VIRTUAL_INTERMED_FREQ" */
+	SetFilterTaps((CReal) VIRTUAL_INTERMED_FREQ / iSampleRate);
+
+	iGuardSize = Parameters.CellMappingTable.iGuardSize;
+	iDFTSize = Parameters.CellMappingTable.iFFTSizeN;
+	iSymbolBlockSize = Parameters.CellMappingTable.iSymbolBlockSize;
+
+	/* Decimated symbol block size */
+	iDecSymBS = iSymbolBlockSize / iGrdcrrDecFact;
+
+	/* Calculate maximum symbol block size (This is Rob. Mode A) */
+	iMaxSymbolBlockSize = iRMAFFTSizeN + 
+		iRMAFFTSizeN * RMA_ENUM_TG_TU / RMA_DENOM_TG_TU;
+
+	/* We need at least two blocks of data for determining the timing */
+	iTotalBufferSize = 2 * iSymbolBlockSize + iMaxSymbolBlockSize;
+	iCorrBuffSize = iTotalBufferSize / iGrdcrrDecFact;
+
+	/* Set step size of the guard-interval correlation */
+	iStepSizeGuardCorr = STEP_SIZE_GUARD_CORR;
+
+	/* Size for moving average buffer for guard-interval correlation */
+	iMovAvBufSize = 
+		(int) ((CReal) iGuardSize / iGrdcrrDecFact / iStepSizeGuardCorr);
+
+	/* Size of buffer, storing the moving-average results for 
+	   maximum detection */
+	iMaxDetBufSize = 
+		(int) ((CReal) iDecSymBS / iStepSizeGuardCorr);
+
+	/* Center of maximum detection buffer */
+	iCenterOfMaxDetBuf = (iMaxDetBufSize - 1) / 2;
+
+	/* Init Energy calculation after guard-interval correlation (moving
+	   average) */
+	vecrGuardEnMovAv.Init(iMovAvBufSize);
+
+	/* Start position of this value must be at the end of the observation
+       window because we reset it at the beginning of the loop */
+	iTimeSyncPos = 2 * iDecSymBS;
+
+	/* Calculate center of buffer */
+	iCenterOfBuf = iSymbolBlockSize;
+
+	/* Init rStartIndex only if acquisition was activated */
+	if (bTimingAcqu == TRUE)
+		rStartIndex = (CReal) iCenterOfBuf;
+
+	/* Some inits */
+	iAveCorr = 0;
+	bInitTimingAcqu = TRUE; /* Flag to show that init was done */
+
+	/* Set correction counter so that a non-linear correction is performed right
+	   at the beginning */
+	iCorrCounter = NUM_SYM_BEFORE_RESET;
+
+
+	/* Allocate memory for vectors and zero out */
+	HistoryBuf.Init(iTotalBufferSize, (CReal) 0.0);
+	pMaxDetBuffer.Init(iMaxDetBufSize, (CReal) 0.0);
+	HistoryBufCorr.Init(iCorrBuffSize, (CReal) 0.0);
+
+
+	/* Inits for averaging the guard-interval correlation */
+	vecCorrAvBuf.Init(iMaxDetBufSize, (CReal) 0.0);
+	iCorrAvInd = 0;
+
+
+	/* Set the selected robustness mode index */
+	iSelectedMode = GetIndFromRMode(Parameters.GetWaveMode());
+
+	/* Init init count for timing sync (one symbol) */
+	iTiSyncInitCnt = iDecSymBS / iStepSizeGuardCorr;
+
+
+	/* Inits for guard-interval correlation and robustness mode detection --- */
+	/* Size for robustness mode correlation buffer */
+	iRMCorrBufSize = (int) ((CReal) NUM_BLOCKS_FOR_RM_CORR * iDecSymBS
+		/ STEP_SIZE_GUARD_CORR);
+
+	/* Init init count for robustness mode detection (do not use the very first
+	   block) */
+	iRobModInitCnt = NUM_BLOCKS_FOR_RM_CORR + 1;
+
+	for (i = 0; i < NUM_ROBUSTNESS_MODES; i++)
+	{
+		cGuardCorr[i] = (CReal) 0.0;
+		cGuardCorrBlock[i] = (CReal) 0.0;
+		rGuardPow[i] = (CReal) 0.0;
+		rGuardPowBlock[i] = (CReal) 0.0;
+		iPosInIntermCResBuf[i] = 0;
+
+		/* Set length of the useful part of the symbol and guard size */
+		switch (i)
+		{
+		case 0:
+			iLenUsefPart[i] = iRMAFFTSizeN / iGrdcrrDecFact;
+			iLenGuardInt[i] = (int) ((CReal) iRMAFFTSizeN * 
+				RMA_ENUM_TG_TU / RMA_DENOM_TG_TU / iGrdcrrDecFact);
+			break;
+
+		case 1:
+			iLenUsefPart[i] = iRMBFFTSizeN / iGrdcrrDecFact;
+			iLenGuardInt[i] = (int) ((CReal) iRMBFFTSizeN * 
+				RMB_ENUM_TG_TU / RMB_DENOM_TG_TU / iGrdcrrDecFact);
+			break;
+
+		case 2:
+			iLenUsefPart[i] = iRMCFFTSizeN / iGrdcrrDecFact;
+			iLenGuardInt[i] = (int) ((CReal) iRMCFFTSizeN * 
+				RMC_ENUM_TG_TU / RMC_DENOM_TG_TU / iGrdcrrDecFact);
+			break;
+
+		case 3:
+			iLenUsefPart[i] = iRMDFFTSizeN / iGrdcrrDecFact;
+			iLenGuardInt[i] = (int) ((CReal) iRMDFFTSizeN * 
+				RMD_ENUM_TG_TU / RMD_DENOM_TG_TU / iGrdcrrDecFact);
+			break;
+		}
+
+		/* Number of correlation result blocks to be stored in a vector. This is
+		   the total length of the guard-interval divided by the step size.
+		   Since the guard-size must not be a multiple of "iStepSizeGuardCorr",
+		   we need to cut-off the fractional part */
+		iLengthIntermCRes[i] = (int) ((CReal) iLenGuardInt[i] / 
+			iStepSizeGuardCorr);
+
+		/* This length is the start point for the "for"-loop */
+		iLengthOverlap[i] = iLenGuardInt[i] - 
+			iStepSizeGuardCorr;
+
+		/* Intermediate correlation results vector (init, zero out) */
+		veccIntermCorrRes[i].Init(iLengthIntermCRes[i], (CReal) 0.0);
+		vecrIntermPowRes[i].Init(iLengthIntermCRes[i], (CReal) 0.0);
+
+		/* Allocate memory for correlation input buffers */
+		vecrRMCorrBuffer[i].Init(iRMCorrBufSize);
+		vecrRMCorrBuffer[i] = Zeros(iRMCorrBufSize);
+
+		/* Tables for sin and cos function for the desired frequency band */
+		/* First, allocate memory for vector */
+		vecrCos[i].Init(iRMCorrBufSize);
+
+		/* Build table */
+		for (j = 0; j < iRMCorrBufSize; j++)
+		{
+			/* Calculate frequency bins which has to be observed for each
+			   mode.
+			   Mode A: f_A = 1 / T_s = 1 / 26.66 ms = 37.5 Hz
+			   Mode B: f_B = 1 / T_s = 1 / 26.66 ms = 37.5 Hz
+			   Mode C: f_C = 1 / T_s = 1 / 20 ms = 50 Hz
+			   Mode D: f_D = 1 / T_s = 1 / 16.66 ms = 60 Hz */
+			iObservedFreqBin = 
+				(int) ((CReal) iRMCorrBufSize * STEP_SIZE_GUARD_CORR /
+				(iLenUsefPart[i] + iLenGuardInt[i]));
+
+			rArgTemp = (CReal) 2.0 * crPi / iRMCorrBufSize * j;
+
+			vecrCos[i][j] = cos(rArgTemp * iObservedFreqBin);
+		}
+	}
+
+#ifdef USE_FRQOFFS_TRACK_GUARDCORR
+	/* Init vector for averaging the frequency offset estimation */
+	cFreqOffAv = CComplex((CReal) 0.0, (CReal) 0.0);
+
+	/* Init time constant for IIR filter for frequency offset estimation */
+	rLamFreqOff = IIR1Lam(TICONST_FREQ_OFF_EST_GUCORR,
+		(CReal) iSampleRate / Parameters.iSymbolBlockSize);
+
+	/* Nomalization constant for frequency offset estimation */
+	rNormConstFOE = (CReal) 1.0 /
+		((CReal) 2.0 * crPi * Parameters.iFFTSizeN * iGrdcrrDecFact);
+#endif
+
+	/* Define block-sizes for input and output */
+	iInputBlockSize = iSymbolBlockSize; /* For the first loop */
+	iOutputBlockSize = iDFTSize;
+
+	Parameters.Unlock(); 
+}
+
+void CTimeSync::StartAcquisition()
+{
+
+// TODO: check which initialization should be done here and which should be
+// moved to / from the "InitInternal()" function
+
+	/* The regular acquisition flags */
+	bTimingAcqu = TRUE;
+	bRobModAcqu = TRUE;
+
+	/* Set the init flag so that the "rStartIndex" can be initialized with the
+	   center of the buffer and other important settings can be done */
+	SetInitFlag();
+	
+	/* This second flag is to determine the moment when the acquisition just
+	   finished. In this case, the tracking value must be reset */
+	bAcqWasActive = TRUE;
+
+	iCorrCounter = NUM_SYM_BEFORE_RESET;
+
+	/* Reset the buffers which are storing data for correlation (for robustness
+	   mode detection) */
+	//for (int i = 0; i < NUM_ROBUSTNESS_MODES; i++)
+	//	vecrRMCorrBuffer[i] = Zeros(iRMCorrBufSize);
+
+	/* Reset lambda for averaging the guard-interval correlation results */
+	rLambdaCoAv = (CReal) 1.0;
+	iCorrAvInd = 0;
+}
+
+void CTimeSync::SetFilterTaps(CReal rNewOffsetNorm)
+{
+#ifndef USE_10_KHZ_HILBFILT
+	/* The filter should be on the right of the DC carrier in 5 kHz mode */
+	rNewOffsetNorm += (CReal) HILB_FILT_BNDWIDTH / 2 / iSampleRate;
+#endif
+
+	/* Calculate filter taps for complex Hilbert filter */
+	cvecB.Init(iNumTapsHilbFilt);
+
+	for (int i = 0; i < iNumTapsHilbFilt; i++)
+		cvecB[i] = CComplex(
+			fHilLPProt[i] * Cos((CReal) 2.0 * crPi * rNewOffsetNorm * i),
+			fHilLPProt[i] * Sin((CReal) 2.0 * crPi * rNewOffsetNorm * i));
+
+	/* Init state vector for filtering with zeros */
+	cvecZ.Init(iNumTapsHilbFilt - 1, (CReal) 0.0);
+}
+
+CTimeSync::CTimeSync() : iSampleRate(0), iGrdcrrDecFact(0),
+	iNumTapsHilbFilt(0), fHilLPProt(NULL),
+	iTimeSyncPos(0), bSyncInput(FALSE), bTimingAcqu(FALSE),
+	bRobModAcqu(FALSE), bAcqWasActive(FALSE), rLambdaCoAv((CReal) 1.0),
+	iLengthIntermCRes(NUM_ROBUSTNESS_MODES),
+	iPosInIntermCResBuf(NUM_ROBUSTNESS_MODES),
+	iLengthOverlap(NUM_ROBUSTNESS_MODES), iLenUsefPart(NUM_ROBUSTNESS_MODES),
+	iLenGuardInt(NUM_ROBUSTNESS_MODES), cGuardCorr(NUM_ROBUSTNESS_MODES),
+	cGuardCorrBlock(NUM_ROBUSTNESS_MODES), rGuardPow(NUM_ROBUSTNESS_MODES),
+	rGuardPowBlock(NUM_ROBUSTNESS_MODES), vecrRMCorrBuffer()
+{
+}
+
+int CTimeSync::GetIndFromRMode(ERobMode eNewMode)
+{
+	/* Get the robustness mode index. We define:
+	   A: 0, B: 1, C: 2, D: 3 */
+	switch (eNewMode)
+	{
+	case RM_ROBUSTNESS_MODE_A:
+		return 0;
+	case RM_ROBUSTNESS_MODE_B:
+		return 1;
+	case RM_ROBUSTNESS_MODE_C:
+		return 2;
+	case RM_ROBUSTNESS_MODE_D:
+		return 3;
+	default:
+		return 0;
+	}
+}
+
+ERobMode CTimeSync::GetRModeFromInd(int iNewInd)
+{
+	/* Get the robustness mode index. We define:
+	   A: 0, B: 1, C: 2, D: 3 */
+	switch (iNewInd)
+	{
+	case 0:
+		return RM_ROBUSTNESS_MODE_A;
+	case 1:
+		return RM_ROBUSTNESS_MODE_B;
+	case 2:
+		return RM_ROBUSTNESS_MODE_C;
+	case 3:
+		return RM_ROBUSTNESS_MODE_D;
+	default:
+		return RM_ROBUSTNESS_MODE_A;
+	}
+}
diff --git a/src/sync/TimeSync.h b/src/sync/TimeSync.h
new file mode 100644
index 0000000..324db36
--- /dev/null
+++ b/src/sync/TimeSync.h
@@ -0,0 +1,185 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *	See TimeSync.cpp
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later 
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT 
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#if !defined(TIMESYNC_H__3B0BEVJBN872345NBEROUEBGF4344_BB27912__INCLUDED_)
+#define TIMESYNC_H__3B0BEVJBN872345NBEROUEBGF4344_BB27912__INCLUDED_
+
+#include "../Parameter.h"
+#include "../util/Modul.h"
+#include "../util/Vector.h"
+#include "../matlib/Matlib.h"
+#include "TimeSyncFilter.h"
+
+
+/* Definitions ****************************************************************/
+/* Use 5 or 10 kHz bandwidth for guard-interval correlation. 10 kHz bandwidth
+   should be chosen when time domain freuqency offset estimation is used */
+#define USE_10_KHZ_HILBFILT
+
+#define LAMBDA_LOW_PASS_START			((CReal) 0.99)
+#define TIMING_BOUND_ABS				150
+
+/* Non-linear correction of the timing if variation is too big */
+#define NUM_SYM_BEFORE_RESET			5
+
+/* Definitions for robustness mode detection */
+#define NUM_BLOCKS_FOR_RM_CORR			16
+#define THRESHOLD_RELI_MEASURE			((CReal) 8.0)
+
+/* The guard-interval correlation is only updated every "STEP_SIZE_GUARD_CORR"
+   samples to save computations */
+#define STEP_SIZE_GUARD_CORR			4
+
+/* "GRDCRR_DEC_FACT": Downsampling factor. We only use approx. 6 [12] kHz for
+   correlation, therefore we can use a decimation of 8 [4]
+   (i.e., 48 kHz / 8 [4] = 6 [12] kHz). Must be 8 [4] since all symbol and
+   guard-interval lengths at 48000 for all robustness modes are dividable
+   by 8 [4] */
+#ifdef USE_10_KHZ_HILBFILT
+# define GRDCRR_DEC_FACT				4
+# define NUM_TAPS_HILB_FILT_24			NUM_TAPS_HILB_FILT_10_24
+# define NUM_TAPS_HILB_FILT_48			NUM_TAPS_HILB_FILT_10_48
+# define NUM_TAPS_HILB_FILT_96			NUM_TAPS_HILB_FILT_10_96
+# define NUM_TAPS_HILB_FILT_192			NUM_TAPS_HILB_FILT_10_192
+# define NUM_TAPS_HILB_FILT_384			NUM_TAPS_HILB_FILT_10_384
+# define HILB_FILT_BNDWIDTH				HILB_FILT_BNDWIDTH_10
+#else
+# define GRDCRR_DEC_FACT				8
+# define NUM_TAPS_HILB_FILT_24			NUM_TAPS_HILB_FILT_5_24
+# define NUM_TAPS_HILB_FILT_48			NUM_TAPS_HILB_FILT_5_48
+# define NUM_TAPS_HILB_FILT_96			NUM_TAPS_HILB_FILT_5_96
+# define NUM_TAPS_HILB_FILT_192			NUM_TAPS_HILB_FILT_5_192
+# define NUM_TAPS_HILB_FILT_384			NUM_TAPS_HILB_FILT_5_384
+# define HILB_FILT_BNDWIDTH				HILB_FILT_BNDWIDTH_5
+#endif
+
+#ifdef USE_FRQOFFS_TRACK_GUARDCORR
+/* Time constant for IIR averaging of frequency offset estimation */
+# define TICONST_FREQ_OFF_EST_GUCORR	((CReal) 1.0) /* sec */
+#endif
+
+
+/* Classes ********************************************************************/
+class CTimeSync : public CReceiverModul<_COMPLEX, _COMPLEX>
+{
+public:
+	CTimeSync();
+	virtual ~CTimeSync() {}
+
+	/* To set the module up for synchronized DRM input data stream */
+	void SetSyncInput(const _BOOLEAN bNewS) {bSyncInput = bNewS;}
+
+	void StartAcquisition();
+	void StopTimingAcqu() {bTimingAcqu = FALSE;}
+	void StopRMDetAcqu() {bRobModAcqu = FALSE;}
+
+protected:
+	int							iSampleRate;
+	int							iGrdcrrDecFact;
+	int							iNumTapsHilbFilt;
+	const float*				fHilLPProt;
+	int							iCorrCounter;
+	int							iAveCorr;
+	int							iStepSizeGuardCorr;
+
+	CShiftRegister<_COMPLEX>	HistoryBuf;
+	CShiftRegister<_COMPLEX>	HistoryBufCorr;
+	CShiftRegister<_REAL>		pMaxDetBuffer;
+	CRealVector					vecrHistoryFilt;
+	CMovingAv<CReal>			vecrGuardEnMovAv;
+
+	CRealVector					vecCorrAvBuf;
+	int							iCorrAvInd;
+
+	int							iMaxDetBufSize;
+	int							iCenterOfMaxDetBuf;
+
+	int							iMovAvBufSize;
+	int							iTotalBufferSize;
+	int							iSymbolBlockSize;
+	int							iDecSymBS;
+	int							iGuardSize;
+	int							iTimeSyncPos;
+	int							iDFTSize;
+	CReal						rStartIndex;
+
+	int							iCenterOfBuf;
+
+	_BOOLEAN					bSyncInput;
+
+	_BOOLEAN					bInitTimingAcqu;
+	_BOOLEAN					bTimingAcqu;
+	_BOOLEAN					bRobModAcqu;
+	_BOOLEAN					bAcqWasActive;
+
+	int							iTiSyncInitCnt;
+	int							iRobModInitCnt;
+
+	int							iSelectedMode;
+
+	CComplexVector				cvecZ;
+	CComplexVector				cvecB;
+	CVector<_COMPLEX>			cvecOutTmpInterm;
+
+	CReal						rLambdaCoAv;
+
+
+	/* Intermediate correlation results and robustness mode detection */
+	CComplexVector				veccIntermCorrRes[NUM_ROBUSTNESS_MODES];
+	CRealVector					vecrIntermPowRes[NUM_ROBUSTNESS_MODES];
+	CVector<int>				iLengthIntermCRes;
+	CVector<int>				iPosInIntermCResBuf;
+	CVector<int>				iLengthOverlap;
+	CVector<int>				iLenUsefPart;
+	CVector<int>				iLenGuardInt;
+
+	CComplexVector				cGuardCorr;
+	CComplexVector				cGuardCorrBlock;
+	CRealVector					rGuardPow;
+	CRealVector					rGuardPowBlock;
+
+	CRealVector					vecrRMCorrBuffer[NUM_ROBUSTNESS_MODES];
+	CRealVector					vecrCos[NUM_ROBUSTNESS_MODES];
+	int							iRMCorrBufSize;
+
+#ifdef USE_FRQOFFS_TRACK_GUARDCORR
+	CComplex					cFreqOffAv;
+	CReal						rLamFreqOff;
+	CReal						rNormConstFOE;
+#endif
+
+	int			GetIndFromRMode(ERobMode eNewMode);
+	ERobMode	GetRModeFromInd(int iNewInd);
+	void		SetFilterTaps(CReal rNewOffsetNorm);
+
+	virtual void InitInternal(CParameter& Parameters);
+	virtual void ProcessDataInternal(CParameter& Parameters);
+};
+
+
+#endif // !defined(TIMESYNC_H__3B0BEVJBN872345NBEROUEBGF4344_BB27912__INCLUDED_)
diff --git a/src/sync/TimeSyncFilter.cpp b/src/sync/TimeSyncFilter.cpp
new file mode 100644
index 0000000..6e5567f
--- /dev/null
+++ b/src/sync/TimeSyncFilter.cpp
@@ -0,0 +1,2552 @@
+/* Automatically generated file with GNU Octave */
+
+/* File name: "TimeSyncFilter.octave" */
+/* Filter taps in time-domain */
+
+#include "TimeSyncFilter.h"
+
+/*********************************************************/
+/* Filter taps for 24000  Hz sample rate                 */
+/* Low pass prototype for Hilbert-filter 5 kHz bandwidth */
+const float fHilLPProt5_24[NUM_TAPS_HILB_FILT_5_24] =
+{
+	-5.690765506755788780e-03f,
+	-2.636034308612325572e-02f,
+	-2.937823007744868112e-02f,
+	-3.641852325814370211e-02f,
+	-3.142942181939990809e-02f,
+	-1.637537410250772263e-02f,
+	6.567476364383844321e-03f,
+	2.973961497116888592e-02f,
+	4.354267422415943056e-02f,
+	3.979947985889148443e-02f,
+	1.591873397251728633e-02f,
+	-2.252779213687858273e-02f,
+	-6.193643121947790126e-02f,
+	-8.415439076086959902e-02f,
+	-7.240212520555380782e-02f,
+	-1.778818567713004797e-02f,
+	7.614474571814264237e-02f,
+	1.927647977469577056e-01f,
+	3.061451345381377975e-01f,
+	3.884881585084563049e-01f,
+	4.185831413997523343e-01f,
+	3.884881585084563049e-01f,
+	3.061451345381377975e-01f,
+	1.927647977469577056e-01f,
+	7.614474571814264237e-02f,
+	-1.778818567713004797e-02f,
+	-7.240212520555380782e-02f,
+	-8.415439076086959902e-02f,
+	-6.193643121947790126e-02f,
+	-2.252779213687858273e-02f,
+	1.591873397251728633e-02f,
+	3.979947985889148443e-02f,
+	4.354267422415943056e-02f,
+	2.973961497116888592e-02f,
+	6.567476364383844321e-03f,
+	-1.637537410250772263e-02f,
+	-3.142942181939990809e-02f,
+	-3.641852325814370211e-02f,
+	-2.937823007744868112e-02f,
+	-2.636034308612325572e-02f,
+	-5.690765506755788780e-03f
+};
+/* Low pass prototype for Hilbert-filter 10 kHz bandwidth */
+const float fHilLPProt10_24[NUM_TAPS_HILB_FILT_10_24] =
+{
+	-1.126468176123466419e-02f,
+	-4.573315426073081696e-02f,
+	-4.613359715612273815e-02f,
+	-1.553969363799070913e-02f,
+	2.609020026415660373e-02f,
+	2.581015289726837705e-02f,
+	-1.557387400464138594e-02f,
+	-3.833506043935425850e-02f,
+	-1.876879425080380101e-03f,
+	4.667501349941612782e-02f,
+	2.908420049591232265e-02f,
+	-4.322475920237642266e-02f,
+	-6.357648622222950019e-02f,
+	2.023288609187070403e-02f,
+	1.006109096027490851e-01f,
+	3.349542543589328208e-02f,
+	-1.336819491244388980e-01f,
+	-1.493834548624827230e-01f,
+	1.565682055503051784e-01f,
+	6.144920265760304146e-01f,
+	8.352178015390475663e-01f,
+	6.144920265760304146e-01f,
+	1.565682055503051784e-01f,
+	-1.493834548624827230e-01f,
+	-1.336819491244388980e-01f,
+	3.349542543589328208e-02f,
+	1.006109096027490851e-01f,
+	2.023288609187070403e-02f,
+	-6.357648622222950019e-02f,
+	-4.322475920237642266e-02f,
+	2.908420049591232265e-02f,
+	4.667501349941612782e-02f,
+	-1.876879425080380101e-03f,
+	-3.833506043935425850e-02f,
+	-1.557387400464138594e-02f,
+	2.581015289726837705e-02f,
+	2.609020026415660373e-02f,
+	-1.553969363799070913e-02f,
+	-4.613359715612273815e-02f,
+	-4.573315426073081696e-02f,
+	-1.126468176123466419e-02f
+};
+
+/*********************************************************/
+/* Filter taps for 48000  Hz sample rate                 */
+/* Low pass prototype for Hilbert-filter 5 kHz bandwidth */
+const float fHilLPProt5_48[NUM_TAPS_HILB_FILT_5_48] =
+{
+	-2.347869013559899663e-04f,
+	-1.413273123257565052e-02f,
+	-1.017230192682962338e-02f,
+	-1.304125403484751242e-02f,
+	-1.544581885437787058e-02f,
+	-1.719189314304302857e-02f,
+	-1.797805913050802562e-02f,
+	-1.756078453316530993e-02f,
+	-1.578934312697760980e-02f,
+	-1.263195529532759077e-02f,
+	-8.203321233087559200e-03f,
+	-2.773387292218262596e-03f,
+	3.244273143115733882e-03f,
+	9.318507482475217943e-03f,
+	1.484033371446751709e-02f,
+	1.918022356749162285e-02f,
+	2.175595657975005690e-02f,
+	2.209542479897394149e-02f,
+	1.990530294260488622e-02f,
+	1.513474285260030250e-02f,
+	7.973308620764014976e-03f,
+	-1.059045368509266933e-03f,
+	-1.125337053287578555e-02f,
+	-2.158415494814015095e-02f,
+	-3.095323089368840971e-02f,
+	-3.817105049025057428e-02f,
+	-4.207091334282069689e-02f,
+	-4.166127154048478859e-02f,
+	-3.620461906153087106e-02f,
+	-2.528991674297844522e-02f,
+	-8.909298521715233038e-03f,
+	1.249919843339511449e-02f,
+	3.806462188251723971e-02f,
+	6.653898928215996877e-02f,
+	9.637633415758371791e-02f,
+	1.258301028214320050e-01f,
+	1.530821596417983599e-01f,
+	1.763998697377569813e-01f,
+	1.942647671607092008e-01f,
+	2.054825144278191185e-01f,
+	2.093140402818348678e-01f,
+	2.054825144278191185e-01f,
+	1.942647671607092008e-01f,
+	1.763998697377569813e-01f,
+	1.530821596417983599e-01f,
+	1.258301028214320050e-01f,
+	9.637633415758371791e-02f,
+	6.653898928215996877e-02f,
+	3.806462188251723971e-02f,
+	1.249919843339511449e-02f,
+	-8.909298521715233038e-03f,
+	-2.528991674297844522e-02f,
+	-3.620461906153087106e-02f,
+	-4.166127154048478859e-02f,
+	-4.207091334282069689e-02f,
+	-3.817105049025057428e-02f,
+	-3.095323089368840971e-02f,
+	-2.158415494814015095e-02f,
+	-1.125337053287578555e-02f,
+	-1.059045368509266933e-03f,
+	7.973308620764014976e-03f,
+	1.513474285260030250e-02f,
+	1.990530294260488622e-02f,
+	2.209542479897394149e-02f,
+	2.175595657975005690e-02f,
+	1.918022356749162285e-02f,
+	1.484033371446751709e-02f,
+	9.318507482475217943e-03f,
+	3.244273143115733882e-03f,
+	-2.773387292218262596e-03f,
+	-8.203321233087559200e-03f,
+	-1.263195529532759077e-02f,
+	-1.578934312697760980e-02f,
+	-1.756078453316530993e-02f,
+	-1.797805913050802562e-02f,
+	-1.719189314304302857e-02f,
+	-1.544581885437787058e-02f,
+	-1.304125403484751242e-02f,
+	-1.017230192682962338e-02f,
+	-1.413273123257565052e-02f,
+	-2.347869013559899663e-04f
+};
+/* Low pass prototype for Hilbert-filter 10 kHz bandwidth */
+const float fHilLPProt10_48[NUM_TAPS_HILB_FILT_10_48] =
+{
+	-2.658028396416113256e-03f,
+	-1.970912920536988661e-02f,
+	-1.968785016839483606e-02f,
+	-2.461003801677347572e-02f,
+	-2.377152869170011396e-02f,
+	-1.784125782630162013e-02f,
+	-7.747410648438814509e-03f,
+	3.670112822227527064e-03f,
+	1.274005286505880061e-02f,
+	1.627980915842414458e-02f,
+	1.287464243669448477e-02f,
+	3.698464472565560733e-03f,
+	-7.734965186287633652e-03f,
+	-1.669723654801230639e-02f,
+	-1.911669051862374333e-02f,
+	-1.331282246842796328e-02f,
+	-9.614184073078339615e-04f,
+	1.324303685995057052e-02f,
+	2.329220468584962053e-02f,
+	2.423221662315279759e-02f,
+	1.451613102673328902e-02f,
+	-2.993435930238266644e-03f,
+	-2.163090369786577205e-02f,
+	-3.329909879823830104e-02f,
+	-3.181434789619437542e-02f,
+	-1.576875824581750601e-02f,
+	1.010047032122583788e-02f,
+	3.597569824192357879e-02f,
+	5.032854697617934747e-02f,
+	4.449817137639855424e-02f,
+	1.680392433297665106e-02f,
+	-2.538219901248268615e-02f,
+	-6.680857669836365309e-02f,
+	-8.865984466169557487e-02f,
+	-7.471364357013575430e-02f,
+	-1.742631653997888871e-02f,
+	7.826912309879234531e-02f,
+	1.950278554244037899e-01f,
+	3.072584275820657851e-01f,
+	3.881862828560951884e-01f,
+	4.176516075148942742e-01f,
+	3.881862828560951884e-01f,
+	3.072584275820657851e-01f,
+	1.950278554244037899e-01f,
+	7.826912309879234531e-02f,
+	-1.742631653997888871e-02f,
+	-7.471364357013575430e-02f,
+	-8.865984466169557487e-02f,
+	-6.680857669836365309e-02f,
+	-2.538219901248268615e-02f,
+	1.680392433297665106e-02f,
+	4.449817137639855424e-02f,
+	5.032854697617934747e-02f,
+	3.597569824192357879e-02f,
+	1.010047032122583788e-02f,
+	-1.576875824581750601e-02f,
+	-3.181434789619437542e-02f,
+	-3.329909879823830104e-02f,
+	-2.163090369786577205e-02f,
+	-2.993435930238266644e-03f,
+	1.451613102673328902e-02f,
+	2.423221662315279759e-02f,
+	2.329220468584962053e-02f,
+	1.324303685995057052e-02f,
+	-9.614184073078339615e-04f,
+	-1.331282246842796328e-02f,
+	-1.911669051862374333e-02f,
+	-1.669723654801230639e-02f,
+	-7.734965186287633652e-03f,
+	3.698464472565560733e-03f,
+	1.287464243669448477e-02f,
+	1.627980915842414458e-02f,
+	1.274005286505880061e-02f,
+	3.670112822227527064e-03f,
+	-7.747410648438814509e-03f,
+	-1.784125782630162013e-02f,
+	-2.377152869170011396e-02f,
+	-2.461003801677347572e-02f,
+	-1.968785016839483606e-02f,
+	-1.970912920536988661e-02f,
+	-2.658028396416113256e-03f
+};
+
+/*********************************************************/
+/* Filter taps for 96000  Hz sample rate                 */
+/* Low pass prototype for Hilbert-filter 5 kHz bandwidth */
+const float fHilLPProt5_96[NUM_TAPS_HILB_FILT_5_96] =
+{
+	3.443517435080679923e-03f,
+	-9.252786660891458570e-03f,
+	-5.581097282704975023e-03f,
+	-4.983835116610630701e-03f,
+	-5.306160613487146370e-03f,
+	-5.893803957896741504e-03f,
+	-6.537401214160739465e-03f,
+	-7.160122799589819370e-03f,
+	-7.728184638440023860e-03f,
+	-8.216442192682509721e-03f,
+	-8.602306655264568835e-03f,
+	-8.866889027042324303e-03f,
+	-8.995400616543604982e-03f,
+	-8.972278725504738081e-03f,
+	-8.785972160421704966e-03f,
+	-8.430741451958512558e-03f,
+	-7.899657290109097368e-03f,
+	-7.194882112165804956e-03f,
+	-6.321600337755895437e-03f,
+	-5.286642032013960310e-03f,
+	-4.108692130987095029e-03f,
+	-2.802483798685586995e-03f,
+	-1.395121795503115455e-03f,
+	8.747448821593897252e-05f,
+	1.612785756626880767e-03f,
+	3.146056235518719917e-03f,
+	4.650071835787347729e-03f,
+	6.085127868305777177e-03f,
+	7.412682304718777419e-03f,
+	8.591110536141114903e-03f,
+	9.584752703481604769e-03f,
+	1.035579051182581450e-02f,
+	1.087317510357018596e-02f,
+	1.111014418734333417e-02f,
+	1.104327872205521088e-02f,
+	1.065959640958474147e-02f,
+	9.950095862447241174e-03f,
+	8.915039800967224440e-03f,
+	7.564168058288840354e-03f,
+	5.913442108901625222e-03f,
+	3.989858455332331508e-03f,
+	1.827932155464682571e-03f,
+	-5.291189927675773183e-04f,
+	-3.030750941750716496e-03f,
+	-5.618414320502324727e-03f,
+	-8.225646027697670198e-03f,
+	-1.079169464381161958e-02f,
+	-1.322346999139634161e-02f,
+	-1.547919515286888537e-02f,
+	-1.743980734542945749e-02f,
+	-1.907502030420905881e-02f,
+	-2.029786951388848348e-02f,
+	-2.102552484619302567e-02f,
+	-2.121826214378224815e-02f,
+	-2.082868326392792874e-02f,
+	-1.980172006189571260e-02f,
+	-1.809945171760379834e-02f,
+	-1.570989061424140493e-02f,
+	-1.263436893043458874e-02f,
+	-8.876933532224429504e-03f,
+	-4.450210619269675920e-03f,
+	6.104429657555857395e-04f,
+	6.252037896732887817e-03f,
+	1.241960164038924744e-02f,
+	1.903740358187556297e-02f,
+	2.601834651971359283e-02f,
+	3.327718710200216340e-02f,
+	4.070199593795786885e-02f,
+	4.819495035104086333e-02f,
+	5.563743473218094038e-02f,
+	6.291924609621986353e-02f,
+	6.992544587146180823e-02f,
+	7.654474645721114079e-02f,
+	8.267062871755088971e-02f,
+	8.820267891354671708e-02f,
+	9.305050403474991738e-02f,
+	9.713211588782331984e-02f,
+	1.003810088760326846e-01f,
+	1.027412003733498697e-01f,
+	1.041732499366033737e-01f,
+	1.046539291478811307e-01f,
+	1.041732499366033737e-01f,
+	1.027412003733498697e-01f,
+	1.003810088760326846e-01f,
+	9.713211588782331984e-02f,
+	9.305050403474991738e-02f,
+	8.820267891354671708e-02f,
+	8.267062871755088971e-02f,
+	7.654474645721114079e-02f,
+	6.992544587146180823e-02f,
+	6.291924609621986353e-02f,
+	5.563743473218094038e-02f,
+	4.819495035104086333e-02f,
+	4.070199593795786885e-02f,
+	3.327718710200216340e-02f,
+	2.601834651971359283e-02f,
+	1.903740358187556297e-02f,
+	1.241960164038924744e-02f,
+	6.252037896732887817e-03f,
+	6.104429657555857395e-04f,
+	-4.450210619269675920e-03f,
+	-8.876933532224429504e-03f,
+	-1.263436893043458874e-02f,
+	-1.570989061424140493e-02f,
+	-1.809945171760379834e-02f,
+	-1.980172006189571260e-02f,
+	-2.082868326392792874e-02f,
+	-2.121826214378224815e-02f,
+	-2.102552484619302567e-02f,
+	-2.029786951388848348e-02f,
+	-1.907502030420905881e-02f,
+	-1.743980734542945749e-02f,
+	-1.547919515286888537e-02f,
+	-1.322346999139634161e-02f,
+	-1.079169464381161958e-02f,
+	-8.225646027697670198e-03f,
+	-5.618414320502324727e-03f,
+	-3.030750941750716496e-03f,
+	-5.291189927675773183e-04f,
+	1.827932155464682571e-03f,
+	3.989858455332331508e-03f,
+	5.913442108901625222e-03f,
+	7.564168058288840354e-03f,
+	8.915039800967224440e-03f,
+	9.950095862447241174e-03f,
+	1.065959640958474147e-02f,
+	1.104327872205521088e-02f,
+	1.111014418734333417e-02f,
+	1.087317510357018596e-02f,
+	1.035579051182581450e-02f,
+	9.584752703481604769e-03f,
+	8.591110536141114903e-03f,
+	7.412682304718777419e-03f,
+	6.085127868305777177e-03f,
+	4.650071835787347729e-03f,
+	3.146056235518719917e-03f,
+	1.612785756626880767e-03f,
+	8.747448821593897252e-05f,
+	-1.395121795503115455e-03f,
+	-2.802483798685586995e-03f,
+	-4.108692130987095029e-03f,
+	-5.286642032013960310e-03f,
+	-6.321600337755895437e-03f,
+	-7.194882112165804956e-03f,
+	-7.899657290109097368e-03f,
+	-8.430741451958512558e-03f,
+	-8.785972160421704966e-03f,
+	-8.972278725504738081e-03f,
+	-8.995400616543604982e-03f,
+	-8.866889027042324303e-03f,
+	-8.602306655264568835e-03f,
+	-8.216442192682509721e-03f,
+	-7.728184638440023860e-03f,
+	-7.160122799589819370e-03f,
+	-6.537401214160739465e-03f,
+	-5.893803957896741504e-03f,
+	-5.306160613487146370e-03f,
+	-4.983835116610630701e-03f,
+	-5.581097282704975023e-03f,
+	-9.252786660891458570e-03f,
+	3.443517435080679923e-03f
+};
+/* Low pass prototype for Hilbert-filter 10 kHz bandwidth */
+const float fHilLPProt10_96[NUM_TAPS_HILB_FILT_10_96] =
+{
+	1.803446494815765834e-03f,
+	-1.124009964748978740e-02f,
+	-7.851801645893772760e-03f,
+	-8.843509894749761527e-03f,
+	-1.028733430513804198e-02f,
+	-1.148777489956089547e-02f,
+	-1.222768511822151793e-02f,
+	-1.238419018663358337e-02f,
+	-1.188721348203487793e-02f,
+	-1.071671218323581691e-02f,
+	-8.915618236546983544e-03f,
+	-6.581412179826619767e-03f,
+	-3.873882180225715361e-03f,
+	-9.915983761191698824e-04f,
+	1.831480485879723955e-03f,
+	4.360466670122105717e-03f,
+	6.367739889451504501e-03f,
+	7.670200634745551541e-03f,
+	8.135499240770968296e-03f,
+	7.713637890656809340e-03f,
+	6.431612681686386772e-03f,
+	4.409843313262943459e-03f,
+	1.839260160850202629e-03f,
+	-1.019217873247608335e-03f,
+	-3.873122718899427077e-03f,
+	-6.411282041677529402e-03f,
+	-8.350401374909428506e-03f,
+	-9.450235232588618042e-03f,
+	-9.556262099187237680e-03f,
+	-8.604729253150722804e-03f,
+	-6.649865946760221899e-03f,
+	-3.849177510002410162e-03f,
+	-4.680213489894908944e-04f,
+	3.158475164889775009e-03f,
+	6.642337033440210564e-03f,
+	9.597216771854119241e-03f,
+	1.166459232275667696e-02f,
+	1.256894798133510738e-02f,
+	1.213665471651462734e-02f,
+	1.033570904691685950e-02f,
+	7.272766475192380189e-03f,
+	3.205356156451419011e-03f,
+	-1.490437339711365213e-03f,
+	-6.337745012194066600e-03f,
+	-1.081748392026036024e-02f,
+	-1.440857752172155018e-02f,
+	-1.665785223749342153e-02f,
+	-1.722101911137990243e-02f,
+	-1.591551049593805528e-02f,
+	-1.274020895431540561e-02f,
+	-7.894644471836655825e-03f,
+	-1.779335733886493838e-03f,
+	5.052888488711422196e-03f,
+	1.187125707115641721e-02f,
+	1.797611401443159618e-02f,
+	2.262289577982389693e-02f,
+	2.515979829824038783e-02f,
+	2.511152213473104994e-02f,
+	2.223827238607434947e-02f,
+	1.655931469413613258e-02f,
+	8.393130465512524743e-03f,
+	-1.649460852659676317e-03f,
+	-1.270073469585174079e-02f,
+	-2.368630919438210677e-02f,
+	-3.341811447416495606e-02f,
+	-4.067946659513506369e-02f,
+	-4.434272493341542831e-02f,
+	-4.345906680067209565e-02f,
+	-3.736737079420434510e-02f,
+	-2.575534941281795720e-02f,
+	-8.723771468089608697e-03f,
+	1.321211127230192094e-02f,
+	3.912482345070567719e-02f,
+	6.774190956764471194e-02f,
+	9.751232355549017961e-02f,
+	1.267292475686685460e-01f,
+	1.536375877382420152e-01f,
+	1.765797811113878346e-01f,
+	1.941051022885869337e-01f,
+	2.050962300485778822e-01f,
+	2.088395370555498620e-01f,
+	2.050962300485778822e-01f,
+	1.941051022885869337e-01f,
+	1.765797811113878346e-01f,
+	1.536375877382420152e-01f,
+	1.267292475686685460e-01f,
+	9.751232355549017961e-02f,
+	6.774190956764471194e-02f,
+	3.912482345070567719e-02f,
+	1.321211127230192094e-02f,
+	-8.723771468089608697e-03f,
+	-2.575534941281795720e-02f,
+	-3.736737079420434510e-02f,
+	-4.345906680067209565e-02f,
+	-4.434272493341542831e-02f,
+	-4.067946659513506369e-02f,
+	-3.341811447416495606e-02f,
+	-2.368630919438210677e-02f,
+	-1.270073469585174079e-02f,
+	-1.649460852659676317e-03f,
+	8.393130465512524743e-03f,
+	1.655931469413613258e-02f,
+	2.223827238607434947e-02f,
+	2.511152213473104994e-02f,
+	2.515979829824038783e-02f,
+	2.262289577982389693e-02f,
+	1.797611401443159618e-02f,
+	1.187125707115641721e-02f,
+	5.052888488711422196e-03f,
+	-1.779335733886493838e-03f,
+	-7.894644471836655825e-03f,
+	-1.274020895431540561e-02f,
+	-1.591551049593805528e-02f,
+	-1.722101911137990243e-02f,
+	-1.665785223749342153e-02f,
+	-1.440857752172155018e-02f,
+	-1.081748392026036024e-02f,
+	-6.337745012194066600e-03f,
+	-1.490437339711365213e-03f,
+	3.205356156451419011e-03f,
+	7.272766475192380189e-03f,
+	1.033570904691685950e-02f,
+	1.213665471651462734e-02f,
+	1.256894798133510738e-02f,
+	1.166459232275667696e-02f,
+	9.597216771854119241e-03f,
+	6.642337033440210564e-03f,
+	3.158475164889775009e-03f,
+	-4.680213489894908944e-04f,
+	-3.849177510002410162e-03f,
+	-6.649865946760221899e-03f,
+	-8.604729253150722804e-03f,
+	-9.556262099187237680e-03f,
+	-9.450235232588618042e-03f,
+	-8.350401374909428506e-03f,
+	-6.411282041677529402e-03f,
+	-3.873122718899427077e-03f,
+	-1.019217873247608335e-03f,
+	1.839260160850202629e-03f,
+	4.409843313262943459e-03f,
+	6.431612681686386772e-03f,
+	7.713637890656809340e-03f,
+	8.135499240770968296e-03f,
+	7.670200634745551541e-03f,
+	6.367739889451504501e-03f,
+	4.360466670122105717e-03f,
+	1.831480485879723955e-03f,
+	-9.915983761191698824e-04f,
+	-3.873882180225715361e-03f,
+	-6.581412179826619767e-03f,
+	-8.915618236546983544e-03f,
+	-1.071671218323581691e-02f,
+	-1.188721348203487793e-02f,
+	-1.238419018663358337e-02f,
+	-1.222768511822151793e-02f,
+	-1.148777489956089547e-02f,
+	-1.028733430513804198e-02f,
+	-8.843509894749761527e-03f,
+	-7.851801645893772760e-03f,
+	-1.124009964748978740e-02f,
+	1.803446494815765834e-03f
+};
+
+/*********************************************************/
+/* Filter taps for 192000 Hz sample rate                 */
+/* Low pass prototype for Hilbert-filter 5 kHz bandwidth */
+const float fHilLPProt5_192[NUM_TAPS_HILB_FILT_5_192] =
+{
+	5.976654588553727103e-03f,
+	-5.997236102325859131e-03f,
+	-4.163433221035619733e-03f,
+	-3.194780446811777610e-03f,
+	-2.720709885851604719e-03f,
+	-2.527250528903323898e-03f,
+	-2.494939600764976666e-03f,
+	-2.552795424510246030e-03f,
+	-2.662804907195960667e-03f,
+	-2.800266775223711653e-03f,
+	-2.953318083724762715e-03f,
+	-3.111499213883294531e-03f,
+	-3.271952818028171523e-03f,
+	-3.429203897317635585e-03f,
+	-3.582412600063559702e-03f,
+	-3.727632731574872117e-03f,
+	-3.865357955417614202e-03f,
+	-3.991976997628426428e-03f,
+	-4.108238062451309916e-03f,
+	-4.210870472868591743e-03f,
+	-4.300701378785334351e-03f,
+	-4.374510990586420039e-03f,
+	-4.433275540948211114e-03f,
+	-4.473864415142309557e-03f,
+	-4.497283372728766611e-03f,
+	-4.500703682114018910e-03f,
+	-4.485640728966826946e-03f,
+	-4.449218066785723229e-03f,
+	-4.392717735004768830e-03f,
+	-4.313845501881775901e-03f,
+	-4.214284584665986197e-03f,
+	-4.091840502675863842e-03f,
+	-3.948728310752390273e-03f,
+	-3.782815263666940413e-03f,
+	-3.596016911548746264e-03f,
+	-3.387275950551940033e-03f,
+	-3.158567028393960072e-03f,
+	-2.909367813089355336e-03f,
+	-2.639403035612291996e-03f,
+	-2.357640946571273009e-03f,
+	-2.044233202392597374e-03f,
+	-1.738251121981324683e-03f,
+	-1.394451454861534616e-03f,
+	-1.047026902176086171e-03f,
+	-6.977013867477196854e-04f,
+	-3.272178988458040831e-04f,
+	5.236701905384985589e-05f,
+	4.300764809652380077e-04f,
+	8.080734397260997976e-04f,
+	1.193881554288486573e-03f,
+	1.580693533994663143e-03f,
+	1.961826528197263986e-03f,
+	2.331520130133905074e-03f,
+	2.693733148452589436e-03f,
+	3.047230875364408294e-03f,
+	3.390490178367127835e-03f,
+	3.715785509148218039e-03f,
+	4.021302559350676056e-03f,
+	4.303023945102660633e-03f,
+	4.562555795803237800e-03f,
+	4.796993256367807455e-03f,
+	5.006445858112734508e-03f,
+	5.185381944862198222e-03f,
+	5.332637604373527233e-03f,
+	5.443831464342546722e-03f,
+	5.519939391896979894e-03f,
+	5.558086237653019936e-03f,
+	5.560194878755317718e-03f,
+	5.523541765050712753e-03f,
+	5.449037911465232607e-03f,
+	5.333664483019751913e-03f,
+	5.178818384345576162e-03f,
+	4.981387291587728236e-03f,
+	4.743492931437378810e-03f,
+	4.463909686855656832e-03f,
+	4.145031892695059776e-03f,
+	3.786636498456256213e-03f,
+	3.391280982799808972e-03f,
+	2.960235799448709786e-03f,
+	2.493439800003710051e-03f,
+	1.998651692244079493e-03f,
+	1.469291205813539128e-03f,
+	9.168403659179120025e-04f,
+	3.386169957294755148e-04f,
+	-2.636698214854497728e-04f,
+	-8.799174903092539437e-04f,
+	-1.512646854029784695e-03f,
+	-2.157452151477750723e-03f,
+	-2.807993895326354669e-03f,
+	-3.459078648793645957e-03f,
+	-4.111687886242203910e-03f,
+	-4.757900661705039523e-03f,
+	-5.393069417127223722e-03f,
+	-6.011456617225671706e-03f,
+	-6.612546163871566018e-03f,
+	-7.188927497382600722e-03f,
+	-7.736306473438081359e-03f,
+	-8.247892786853861305e-03f,
+	-8.723033894988291639e-03f,
+	-9.155158233222181197e-03f,
+	-9.540451549794638775e-03f,
+	-9.871578317632389785e-03f,
+	-1.014753270826629014e-02f,
+	-1.036298711678708927e-02f,
+	-1.051606467260652981e-02f,
+	-1.060024897582311637e-02f,
+	-1.061410790452165832e-02f,
+	-1.055224242832967542e-02f,
+	-1.041461382205480582e-02f,
+	-1.019735985120746521e-02f,
+	-9.900019816356414246e-03f,
+	-9.517681927067603298e-03f,
+	-9.051244125003575156e-03f,
+	-8.497592230924288365e-03f,
+	-7.858226618993120055e-03f,
+	-7.132044064183068292e-03f,
+	-6.320545814845228080e-03f,
+	-5.422300644033744427e-03f,
+	-4.439423858139752467e-03f,
+	-3.373453284877100857e-03f,
+	-2.224811318408709271e-03f,
+	-9.990939518086953876e-04f,
+	3.039613464756316043e-04f,
+	1.680150423010206987e-03f,
+	3.124166061689877868e-03f,
+	4.635765762391910912e-03f,
+	6.207363510576284840e-03f,
+	7.835814649608325438e-03f,
+	9.515644008389150671e-03f,
+	1.124188397409009443e-02f,
+	1.300602083372496588e-02f,
+	1.480623060107431541e-02f,
+	1.663417052205172150e-02f,
+	1.848403207205377707e-02f,
+	2.034723842943865837e-02f,
+	2.222039538699616124e-02f,
+	2.409392254298018191e-02f,
+	2.596185922694409579e-02f,
+	2.781502998710564528e-02f,
+	2.964966269497559814e-02f,
+	3.145620378068833545e-02f,
+	3.322865303602406950e-02f,
+	3.495783862948610710e-02f,
+	3.664039316051079243e-02f,
+	3.826754611338047812e-02f,
+	3.983389666582597827e-02f,
+	4.133050032717214967e-02f,
+	4.275440827610720029e-02f,
+	4.409754280452575503e-02f,
+	4.535552957104477256e-02f,
+	4.652115674557853742e-02f,
+	4.759242302967703342e-02f,
+	4.856225635402061647e-02f,
+	4.942903342286031343e-02f,
+	5.018744358183882537e-02f,
+	5.083485939956271238e-02f,
+	5.136716929486204175e-02f,
+	5.178481263467971107e-02f,
+	5.208395534618442957e-02f,
+	5.226428128764680492e-02f,
+	5.232514598159419134e-02f,
+	5.226428128764680492e-02f,
+	5.208395534618442957e-02f,
+	5.178481263467971107e-02f,
+	5.136716929486204175e-02f,
+	5.083485939956271238e-02f,
+	5.018744358183882537e-02f,
+	4.942903342286031343e-02f,
+	4.856225635402061647e-02f,
+	4.759242302967703342e-02f,
+	4.652115674557853742e-02f,
+	4.535552957104477256e-02f,
+	4.409754280452575503e-02f,
+	4.275440827610720029e-02f,
+	4.133050032717214967e-02f,
+	3.983389666582597827e-02f,
+	3.826754611338047812e-02f,
+	3.664039316051079243e-02f,
+	3.495783862948610710e-02f,
+	3.322865303602406950e-02f,
+	3.145620378068833545e-02f,
+	2.964966269497559814e-02f,
+	2.781502998710564528e-02f,
+	2.596185922694409579e-02f,
+	2.409392254298018191e-02f,
+	2.222039538699616124e-02f,
+	2.034723842943865837e-02f,
+	1.848403207205377707e-02f,
+	1.663417052205172150e-02f,
+	1.480623060107431541e-02f,
+	1.300602083372496588e-02f,
+	1.124188397409009443e-02f,
+	9.515644008389150671e-03f,
+	7.835814649608325438e-03f,
+	6.207363510576284840e-03f,
+	4.635765762391910912e-03f,
+	3.124166061689877868e-03f,
+	1.680150423010206987e-03f,
+	3.039613464756316043e-04f,
+	-9.990939518086953876e-04f,
+	-2.224811318408709271e-03f,
+	-3.373453284877100857e-03f,
+	-4.439423858139752467e-03f,
+	-5.422300644033744427e-03f,
+	-6.320545814845228080e-03f,
+	-7.132044064183068292e-03f,
+	-7.858226618993120055e-03f,
+	-8.497592230924288365e-03f,
+	-9.051244125003575156e-03f,
+	-9.517681927067603298e-03f,
+	-9.900019816356414246e-03f,
+	-1.019735985120746521e-02f,
+	-1.041461382205480582e-02f,
+	-1.055224242832967542e-02f,
+	-1.061410790452165832e-02f,
+	-1.060024897582311637e-02f,
+	-1.051606467260652981e-02f,
+	-1.036298711678708927e-02f,
+	-1.014753270826629014e-02f,
+	-9.871578317632389785e-03f,
+	-9.540451549794638775e-03f,
+	-9.155158233222181197e-03f,
+	-8.723033894988291639e-03f,
+	-8.247892786853861305e-03f,
+	-7.736306473438081359e-03f,
+	-7.188927497382600722e-03f,
+	-6.612546163871566018e-03f,
+	-6.011456617225671706e-03f,
+	-5.393069417127223722e-03f,
+	-4.757900661705039523e-03f,
+	-4.111687886242203910e-03f,
+	-3.459078648793645957e-03f,
+	-2.807993895326354669e-03f,
+	-2.157452151477750723e-03f,
+	-1.512646854029784695e-03f,
+	-8.799174903092539437e-04f,
+	-2.636698214854497728e-04f,
+	3.386169957294755148e-04f,
+	9.168403659179120025e-04f,
+	1.469291205813539128e-03f,
+	1.998651692244079493e-03f,
+	2.493439800003710051e-03f,
+	2.960235799448709786e-03f,
+	3.391280982799808972e-03f,
+	3.786636498456256213e-03f,
+	4.145031892695059776e-03f,
+	4.463909686855656832e-03f,
+	4.743492931437378810e-03f,
+	4.981387291587728236e-03f,
+	5.178818384345576162e-03f,
+	5.333664483019751913e-03f,
+	5.449037911465232607e-03f,
+	5.523541765050712753e-03f,
+	5.560194878755317718e-03f,
+	5.558086237653019936e-03f,
+	5.519939391896979894e-03f,
+	5.443831464342546722e-03f,
+	5.332637604373527233e-03f,
+	5.185381944862198222e-03f,
+	5.006445858112734508e-03f,
+	4.796993256367807455e-03f,
+	4.562555795803237800e-03f,
+	4.303023945102660633e-03f,
+	4.021302559350676056e-03f,
+	3.715785509148218039e-03f,
+	3.390490178367127835e-03f,
+	3.047230875364408294e-03f,
+	2.693733148452589436e-03f,
+	2.331520130133905074e-03f,
+	1.961826528197263986e-03f,
+	1.580693533994663143e-03f,
+	1.193881554288486573e-03f,
+	8.080734397260997976e-04f,
+	4.300764809652380077e-04f,
+	5.236701905384985589e-05f,
+	-3.272178988458040831e-04f,
+	-6.977013867477196854e-04f,
+	-1.047026902176086171e-03f,
+	-1.394451454861534616e-03f,
+	-1.738251121981324683e-03f,
+	-2.044233202392597374e-03f,
+	-2.357640946571273009e-03f,
+	-2.639403035612291996e-03f,
+	-2.909367813089355336e-03f,
+	-3.158567028393960072e-03f,
+	-3.387275950551940033e-03f,
+	-3.596016911548746264e-03f,
+	-3.782815263666940413e-03f,
+	-3.948728310752390273e-03f,
+	-4.091840502675863842e-03f,
+	-4.214284584665986197e-03f,
+	-4.313845501881775901e-03f,
+	-4.392717735004768830e-03f,
+	-4.449218066785723229e-03f,
+	-4.485640728966826946e-03f,
+	-4.500703682114018910e-03f,
+	-4.497283372728766611e-03f,
+	-4.473864415142309557e-03f,
+	-4.433275540948211114e-03f,
+	-4.374510990586420039e-03f,
+	-4.300701378785334351e-03f,
+	-4.210870472868591743e-03f,
+	-4.108238062451309916e-03f,
+	-3.991976997628426428e-03f,
+	-3.865357955417614202e-03f,
+	-3.727632731574872117e-03f,
+	-3.582412600063559702e-03f,
+	-3.429203897317635585e-03f,
+	-3.271952818028171523e-03f,
+	-3.111499213883294531e-03f,
+	-2.953318083724762715e-03f,
+	-2.800266775223711653e-03f,
+	-2.662804907195960667e-03f,
+	-2.552795424510246030e-03f,
+	-2.494939600764976666e-03f,
+	-2.527250528903323898e-03f,
+	-2.720709885851604719e-03f,
+	-3.194780446811777610e-03f,
+	-4.163433221035619733e-03f,
+	-5.997236102325859131e-03f,
+	5.976654588553727103e-03f
+};
+/* Low pass prototype for Hilbert-filter 10 kHz bandwidth */
+const float fHilLPProt10_192[NUM_TAPS_HILB_FILT_10_192] =
+{
+	4.812485753440398639e-03f,
+	-7.165895063960392788e-03f,
+	-4.831048395799579856e-03f,
+	-4.037559794368688476e-03f,
+	-3.932648641771094994e-03f,
+	-4.126802212896754640e-03f,
+	-4.444396567288952556e-03f,
+	-4.798809817603228410e-03f,
+	-5.149314297402056428e-03f,
+	-5.468732768161043908e-03f,
+	-5.743924040769356719e-03f,
+	-5.960909857195470334e-03f,
+	-6.113338082019092318e-03f,
+	-6.191653657744155236e-03f,
+	-6.192896445952451000e-03f,
+	-6.110538432212152780e-03f,
+	-5.945495476426383014e-03f,
+	-5.694165679733870916e-03f,
+	-5.361372113531309887e-03f,
+	-4.947665329578545407e-03f,
+	-4.461251480385169423e-03f,
+	-3.906109830989229308e-03f,
+	-3.294894074375474564e-03f,
+	-2.634611800608504216e-03f,
+	-1.940916477415158183e-03f,
+	-1.223353189140682657e-03f,
+	-4.999556264577502103e-04f,
+	2.181869510058673863e-04f,
+	9.125426626001992281e-04f,
+	1.572021142127112648e-03f,
+	2.177789677296087557e-03f,
+	2.720019676117115155e-03f,
+	3.182476661788773576e-03f,
+	3.557966354716694032e-03f,
+	3.833165576160664674e-03f,
+	4.005766631740910466e-03f,
+	4.066373654294575847e-03f,
+	4.018172374318501085e-03f,
+	3.855704298106697476e-03f,
+	3.588887162321792532e-03f,
+	3.216727952671358422e-03f,
+	2.753772711014197856e-03f,
+	2.210274041706050425e-03f,
+	1.587429640246695514e-03f,
+	9.319074497389880692e-04f,
+	2.147106146389341321e-04f,
+	-5.073244246235212099e-04f,
+	-1.224872789648054957e-03f,
+	-1.932432954026099643e-03f,
+	-2.602620369343465901e-03f,
+	-3.205695955514103763e-03f,
+	-3.733225255495822154e-03f,
+	-4.174989815260770828e-03f,
+	-4.513161277493290408e-03f,
+	-4.730212241818812502e-03f,
+	-4.818223045474917185e-03f,
+	-4.776030645908648301e-03f,
+	-4.604369724803121684e-03f,
+	-4.304327200032044033e-03f,
+	-3.877325698812687880e-03f,
+	-3.331152037540655898e-03f,
+	-2.676428480783275398e-03f,
+	-1.929965387192372848e-03f,
+	-1.110074400973621450e-03f,
+	-2.386449472077333781e-04f,
+	6.637284743763407656e-04f,
+	1.571730865055661133e-03f,
+	2.463390669934690819e-03f,
+	3.312074643616956093e-03f,
+	4.095651619902857844e-03f,
+	4.788398953832554740e-03f,
+	5.371080635111117642e-03f,
+	5.822457514510448635e-03f,
+	6.128674257519531494e-03f,
+	6.274540517669524760e-03f,
+	6.253508505575419707e-03f,
+	6.059213485125209027e-03f,
+	5.693840425149327561e-03f,
+	5.159096986465725246e-03f,
+	4.467321610816687820e-03f,
+	3.629367031403980207e-03f,
+	2.666637290959892811e-03f,
+	1.597174936995397103e-03f,
+	4.506219407358709374e-04f,
+	-7.475061733468048959e-04f,
+	-1.965112183819028337e-03f,
+	-3.167540168810032732e-03f,
+	-4.328329035045136615e-03f,
+	-5.404495627660919378e-03f,
+	-6.373129320502805666e-03f,
+	-7.201341913003087188e-03f,
+	-7.858285920412039563e-03f,
+	-8.324218950240359904e-03f,
+	-8.580276727477222087e-03f,
+	-8.607457775993598154e-03f,
+	-8.398488594389843728e-03f,
+	-7.953320947740384270e-03f,
+	-7.272688120427457312e-03f,
+	-6.364403504790038142e-03f,
+	-5.246301121046087305e-03f,
+	-3.941787834196165685e-03f,
+	-2.476833699683095649e-03f,
+	-8.846553522472256703e-04f,
+	7.972036571787932810e-04f,
+	2.525023120899615777e-03f,
+	4.254675641891149905e-03f,
+	5.940601255382404675e-03f,
+	7.536169087829617391e-03f,
+	8.992613109734821919e-03f,
+	1.026594777024173941e-02f,
+	1.131180242891924835e-02f,
+	1.209467034581716144e-02f,
+	1.257958227088597052e-02f,
+	1.274165590324968268e-02f,
+	1.255830877472648849e-02f,
+	1.201957192001466140e-02f,
+	1.112034081946273144e-02f,
+	9.868828451738949695e-03f,
+	8.278770172948913403e-03f,
+	6.376993968566340050e-03f,
+	4.195508502214678401e-03f,
+	1.778699873738373224e-03f,
+	-8.255539538665466505e-04f,
+	-3.556191391062290836e-03f,
+	-6.350843328336111884e-03f,
+	-9.136876693270887251e-03f,
+	-1.184388842377634941e-02f,
+	-1.439304433703247725e-02f,
+	-1.670884572314251457e-02f,
+	-1.871595360788791060e-02f,
+	-2.033942489649480032e-02f,
+	-2.151319954389355193e-02f,
+	-2.217095459726720411e-02f,
+	-2.225805172382782499e-02f,
+	-2.172955174594901756e-02f,
+	-2.054586704016144252e-02f,
+	-1.868198728094428579e-02f,
+	-1.612651265954864743e-02f,
+	-1.287728390119748101e-02f,
+	-8.945740964760254960e-03f,
+	-4.360378797848121595e-03f,
+	8.402382112046633380e-04f,
+	6.606042129077559742e-03f,
+	1.287214218204225068e-02f,
+	1.956203302438026120e-02f,
+	2.659300704251677666e-02f,
+	3.387060042672338650e-02f,
+	4.129356474076721628e-02f,
+	4.875617685420141623e-02f,
+	5.614905959147694497e-02f,
+	6.336292526550180160e-02f,
+	7.028860185508670200e-02f,
+	7.681720941260644642e-02f,
+	8.284936918997569399e-02f,
+	8.828769563450682145e-02f,
+	9.304781224894062563e-02f,
+	9.705075517780124839e-02f,
+	1.002345426438961962e-01f,
+	1.025456500001917237e-01f,
+	1.039485087458098950e-01f,
+	1.044181353460994777e-01f,
+	1.039485087458098950e-01f,
+	1.025456500001917237e-01f,
+	1.002345426438961962e-01f,
+	9.705075517780124839e-02f,
+	9.304781224894062563e-02f,
+	8.828769563450682145e-02f,
+	8.284936918997569399e-02f,
+	7.681720941260644642e-02f,
+	7.028860185508670200e-02f,
+	6.336292526550180160e-02f,
+	5.614905959147694497e-02f,
+	4.875617685420141623e-02f,
+	4.129356474076721628e-02f,
+	3.387060042672338650e-02f,
+	2.659300704251677666e-02f,
+	1.956203302438026120e-02f,
+	1.287214218204225068e-02f,
+	6.606042129077559742e-03f,
+	8.402382112046633380e-04f,
+	-4.360378797848121595e-03f,
+	-8.945740964760254960e-03f,
+	-1.287728390119748101e-02f,
+	-1.612651265954864743e-02f,
+	-1.868198728094428579e-02f,
+	-2.054586704016144252e-02f,
+	-2.172955174594901756e-02f,
+	-2.225805172382782499e-02f,
+	-2.217095459726720411e-02f,
+	-2.151319954389355193e-02f,
+	-2.033942489649480032e-02f,
+	-1.871595360788791060e-02f,
+	-1.670884572314251457e-02f,
+	-1.439304433703247725e-02f,
+	-1.184388842377634941e-02f,
+	-9.136876693270887251e-03f,
+	-6.350843328336111884e-03f,
+	-3.556191391062290836e-03f,
+	-8.255539538665466505e-04f,
+	1.778699873738373224e-03f,
+	4.195508502214678401e-03f,
+	6.376993968566340050e-03f,
+	8.278770172948913403e-03f,
+	9.868828451738949695e-03f,
+	1.112034081946273144e-02f,
+	1.201957192001466140e-02f,
+	1.255830877472648849e-02f,
+	1.274165590324968268e-02f,
+	1.257958227088597052e-02f,
+	1.209467034581716144e-02f,
+	1.131180242891924835e-02f,
+	1.026594777024173941e-02f,
+	8.992613109734821919e-03f,
+	7.536169087829617391e-03f,
+	5.940601255382404675e-03f,
+	4.254675641891149905e-03f,
+	2.525023120899615777e-03f,
+	7.972036571787932810e-04f,
+	-8.846553522472256703e-04f,
+	-2.476833699683095649e-03f,
+	-3.941787834196165685e-03f,
+	-5.246301121046087305e-03f,
+	-6.364403504790038142e-03f,
+	-7.272688120427457312e-03f,
+	-7.953320947740384270e-03f,
+	-8.398488594389843728e-03f,
+	-8.607457775993598154e-03f,
+	-8.580276727477222087e-03f,
+	-8.324218950240359904e-03f,
+	-7.858285920412039563e-03f,
+	-7.201341913003087188e-03f,
+	-6.373129320502805666e-03f,
+	-5.404495627660919378e-03f,
+	-4.328329035045136615e-03f,
+	-3.167540168810032732e-03f,
+	-1.965112183819028337e-03f,
+	-7.475061733468048959e-04f,
+	4.506219407358709374e-04f,
+	1.597174936995397103e-03f,
+	2.666637290959892811e-03f,
+	3.629367031403980207e-03f,
+	4.467321610816687820e-03f,
+	5.159096986465725246e-03f,
+	5.693840425149327561e-03f,
+	6.059213485125209027e-03f,
+	6.253508505575419707e-03f,
+	6.274540517669524760e-03f,
+	6.128674257519531494e-03f,
+	5.822457514510448635e-03f,
+	5.371080635111117642e-03f,
+	4.788398953832554740e-03f,
+	4.095651619902857844e-03f,
+	3.312074643616956093e-03f,
+	2.463390669934690819e-03f,
+	1.571730865055661133e-03f,
+	6.637284743763407656e-04f,
+	-2.386449472077333781e-04f,
+	-1.110074400973621450e-03f,
+	-1.929965387192372848e-03f,
+	-2.676428480783275398e-03f,
+	-3.331152037540655898e-03f,
+	-3.877325698812687880e-03f,
+	-4.304327200032044033e-03f,
+	-4.604369724803121684e-03f,
+	-4.776030645908648301e-03f,
+	-4.818223045474917185e-03f,
+	-4.730212241818812502e-03f,
+	-4.513161277493290408e-03f,
+	-4.174989815260770828e-03f,
+	-3.733225255495822154e-03f,
+	-3.205695955514103763e-03f,
+	-2.602620369343465901e-03f,
+	-1.932432954026099643e-03f,
+	-1.224872789648054957e-03f,
+	-5.073244246235212099e-04f,
+	2.147106146389341321e-04f,
+	9.319074497389880692e-04f,
+	1.587429640246695514e-03f,
+	2.210274041706050425e-03f,
+	2.753772711014197856e-03f,
+	3.216727952671358422e-03f,
+	3.588887162321792532e-03f,
+	3.855704298106697476e-03f,
+	4.018172374318501085e-03f,
+	4.066373654294575847e-03f,
+	4.005766631740910466e-03f,
+	3.833165576160664674e-03f,
+	3.557966354716694032e-03f,
+	3.182476661788773576e-03f,
+	2.720019676117115155e-03f,
+	2.177789677296087557e-03f,
+	1.572021142127112648e-03f,
+	9.125426626001992281e-04f,
+	2.181869510058673863e-04f,
+	-4.999556264577502103e-04f,
+	-1.223353189140682657e-03f,
+	-1.940916477415158183e-03f,
+	-2.634611800608504216e-03f,
+	-3.294894074375474564e-03f,
+	-3.906109830989229308e-03f,
+	-4.461251480385169423e-03f,
+	-4.947665329578545407e-03f,
+	-5.361372113531309887e-03f,
+	-5.694165679733870916e-03f,
+	-5.945495476426383014e-03f,
+	-6.110538432212152780e-03f,
+	-6.192896445952451000e-03f,
+	-6.191653657744155236e-03f,
+	-6.113338082019092318e-03f,
+	-5.960909857195470334e-03f,
+	-5.743924040769356719e-03f,
+	-5.468732768161043908e-03f,
+	-5.149314297402056428e-03f,
+	-4.798809817603228410e-03f,
+	-4.444396567288952556e-03f,
+	-4.126802212896754640e-03f,
+	-3.932648641771094994e-03f,
+	-4.037559794368688476e-03f,
+	-4.831048395799579856e-03f,
+	-7.165895063960392788e-03f,
+	4.812485753440398639e-03f
+};
+
+/*********************************************************/
+/* Filter taps for 384000 Hz sample rate                 */
+/* Low pass prototype for Hilbert-filter 5 kHz bandwidth */
+const float fHilLPProt5_384[NUM_TAPS_HILB_FILT_5_384] =
+{
+	7.611379875493138637e-03f,
+	-3.557140030354209899e-03f,
+	-2.891709491113995511e-03f,
+	-2.398446815447830179e-03f,
+	-2.033946693814312010e-03f,
+	-1.769058926498227532e-03f,
+	-1.577794626580075353e-03f,
+	-1.444420820940262463e-03f,
+	-1.352998170836033258e-03f,
+	-1.295431553242113462e-03f,
+	-1.261471237118429829e-03f,
+	-1.247676093110160287e-03f,
+	-1.246924069957423917e-03f,
+	-1.258257006125656444e-03f,
+	-1.276455540762199033e-03f,
+	-1.302161835196590086e-03f,
+	-1.331149234067586498e-03f,
+	-1.365006461763774558e-03f,
+	-1.399830168893742869e-03f,
+	-1.438037861307091920e-03f,
+	-1.475879026660373164e-03f,
+	-1.516194105259252708e-03f,
+	-1.555180824781971644e-03f,
+	-1.596225206453755078e-03f,
+	-1.635093110091758416e-03f,
+	-1.675880470169040671e-03f,
+	-1.713844253344104550e-03f,
+	-1.753795105460645475e-03f,
+	-1.790152294171405483e-03f,
+	-1.828766667178651417e-03f,
+	-1.862811381024030493e-03f,
+	-1.900114684605757557e-03f,
+	-1.930972869048331979e-03f,
+	-1.967442920661567184e-03f,
+	-1.992731097977784929e-03f,
+	-2.030446950616142214e-03f,
+	-2.051810851077184687e-03f,
+	-2.076888033986441090e-03f,
+	-2.114632962607296794e-03f,
+	-2.124974837005796230e-03f,
+	-2.147085094366327652e-03f,
+	-2.170075937463497931e-03f,
+	-2.192502477043971418e-03f,
+	-2.203409370837070176e-03f,
+	-2.214475088192078243e-03f,
+	-2.224316096228397700e-03f,
+	-2.237299832605875623e-03f,
+	-2.245690114091244104e-03f,
+	-2.251333881834658573e-03f,
+	-2.250676166469937293e-03f,
+	-2.249014144102850880e-03f,
+	-2.244787816410075219e-03f,
+	-2.241210127571734417e-03f,
+	-2.234643544191589060e-03f,
+	-2.226370095421580011e-03f,
+	-2.213150578496394551e-03f,
+	-2.197338639655533905e-03f,
+	-2.177222256032555758e-03f,
+	-2.155589515463847243e-03f,
+	-2.131071225425520705e-03f,
+	-2.105641529924149376e-03f,
+	-2.077172375550435761e-03f,
+	-2.046987520086473132e-03f,
+	-2.012837491129578372e-03f,
+	-1.976158539167319726e-03f,
+	-1.935348484380292316e-03f,
+	-1.892174313452701451e-03f,
+	-1.845599207103569171e-03f,
+	-1.797299886474045894e-03f,
+	-1.745857401994723064e-03f,
+	-1.693709176093296034e-03f,
+	-1.636573526265532345e-03f,
+	-1.582120970552692478e-03f,
+	-1.517818434715981300e-03f,
+	-1.457716193277297555e-03f,
+	-1.391863815298528036e-03f,
+	-1.321620978431202291e-03f,
+	-1.251198794323876880e-03f,
+	-1.179567323856003068e-03f,
+	-1.102948809823240230e-03f,
+	-1.024774425637252871e-03f,
+	-9.460092877100812793e-04f,
+	-8.666767131033942945e-04f,
+	-7.839237912431253367e-04f,
+	-6.994010271805527245e-04f,
+	-6.133377319745481797e-04f,
+	-5.271963464774671176e-04f,
+	-4.390810370331521182e-04f,
+	-3.493288501814680730e-04f,
+	-2.570168052342517752e-04f,
+	-1.642090876124897316e-04f,
+	-7.040911339701516277e-05f,
+	2.324813900268500152e-05f,
+	1.182702695969081703e-04f,
+	2.137594158484226162e-04f,
+	3.104998081881024294e-04f,
+	4.065614596698848915e-04f,
+	5.028374292195948812e-04f,
+	5.979715493655850169e-04f,
+	6.934600329552267819e-04f,
+	7.881640482798063117e-04f,
+	8.833910293821528245e-04f,
+	9.773793376962093288e-04f,
+	1.071442571389616101e-03f,
+	1.163259279711154450e-03f,
+	1.255259012239529808e-03f,
+	1.344424171586820803e-03f,
+	1.434187841331788487e-03f,
+	1.521319821750537551e-03f,
+	1.607383880811302139e-03f,
+	1.693057166924560094e-03f,
+	1.774141551947332369e-03f,
+	1.854744544418641212e-03f,
+	1.932854808129593751e-03f,
+	2.007250708571191658e-03f,
+	2.079513504406551964e-03f,
+	2.149996081954024234e-03f,
+	2.217025984651658892e-03f,
+	2.280403552017701372e-03f,
+	2.341169227904927284e-03f,
+	2.398902274961839387e-03f,
+	2.452563099963648522e-03f,
+	2.501918365765954961e-03f,
+	2.547855687095583466e-03f,
+	2.590335566007637494e-03f,
+	2.629095822036504968e-03f,
+	2.663387277381585715e-03f,
+	2.693471225649988945e-03f,
+	2.719423799193522884e-03f,
+	2.741414896354936199e-03f,
+	2.758676926885346957e-03f,
+	2.771186760452232136e-03f,
+	2.778561003406229864e-03f,
+	2.781365635017356459e-03f,
+	2.779624429509338322e-03f,
+	2.773361430772598810e-03f,
+	2.761982335017456550e-03f,
+	2.745627427472553932e-03f,
+	2.724010314303314511e-03f,
+	2.697692214652472244e-03f,
+	2.666272034998167905e-03f,
+	2.629767561708499894e-03f,
+	2.588232511201733494e-03f,
+	2.540712449828352176e-03f,
+	2.489048161043688149e-03f,
+	2.431007224529001514e-03f,
+	2.369256763660905051e-03f,
+	2.302282182512669587e-03f,
+	2.229645625822773963e-03f,
+	2.153101993781960950e-03f,
+	2.071124101415585707e-03f,
+	1.983812091549390193e-03f,
+	1.892134609303553969e-03f,
+	1.796133661258653841e-03f,
+	1.694904606681460393e-03f,
+	1.589269063813222209e-03f,
+	1.479494280207919619e-03f,
+	1.365363009436511765e-03f,
+	1.246497464073976786e-03f,
+	1.123952058167431919e-03f,
+	9.978763396044493510e-04f,
+	8.682343242442221382e-04f,
+	7.346937491723865834e-04f,
+	5.977938267554941442e-04f,
+	4.576724864960180091e-04f,
+	3.146759265916663963e-04f,
+	1.684487684897633048e-04f,
+	1.940307184331873958e-05f,
+	-1.320664837462653951e-04f,
+	-2.855332299683458310e-04f,
+	-4.409682655736937027e-04f,
+	-5.981863936781633192e-04f,
+	-7.573110939678925901e-04f,
+	-9.177559621408825068e-04f,
+	-1.079181433289383343e-03f,
+	-1.241366444165691680e-03f,
+	-1.403993062821386846e-03f,
+	-1.567354997905725253e-03f,
+	-1.730455973362579657e-03f,
+	-1.893494839639369657e-03f,
+	-2.055923416262168697e-03f,
+	-2.217307176542991556e-03f,
+	-2.378650972960624776e-03f,
+	-2.537770585711366517e-03f,
+	-2.696271891573889454e-03f,
+	-2.852482541443658939e-03f,
+	-3.006174687509059577e-03f,
+	-3.157482262943470900e-03f,
+	-3.306479321238580630e-03f,
+	-3.451776729453182035e-03f,
+	-3.594066668336024471e-03f,
+	-3.732785291230025088e-03f,
+	-3.867598170121567310e-03f,
+	-3.997717557990570873e-03f,
+	-4.123844444086412382e-03f,
+	-4.245108554222204629e-03f,
+	-4.361255055064157740e-03f,
+	-4.471763619537974868e-03f,
+	-4.577021748429701588e-03f,
+	-4.676080300709567483e-03f,
+	-4.768983537494622671e-03f,
+	-4.855210649723631228e-03f,
+	-4.935083664219692100e-03f,
+	-5.007980116131222244e-03f,
+	-5.073718715101926090e-03f,
+	-5.131481455486673789e-03f,
+	-5.181732499674805530e-03f,
+	-5.223766392300994120e-03f,
+	-5.257760926908437368e-03f,
+	-5.283073191593366282e-03f,
+	-5.299717793936110227e-03f,
+	-5.307353818425330876e-03f,
+	-5.306169907809700145e-03f,
+	-5.295514072361832969e-03f,
+	-5.275778787304113461e-03f,
+	-5.245689774886840885e-03f,
+	-5.206623947950080912e-03f,
+	-5.157018465563253072e-03f,
+	-5.098083258711672526e-03f,
+	-5.028565418777247720e-03f,
+	-4.948536858227839397e-03f,
+	-4.858261956832680799e-03f,
+	-4.757514979751304406e-03f,
+	-4.645863021006229818e-03f,
+	-4.524172500934633967e-03f,
+	-4.391467057815140289e-03f,
+	-4.247904473129570507e-03f,
+	-4.093558706287717293e-03f,
+	-3.928806313223098465e-03f,
+	-3.752748304070987768e-03f,
+	-3.565921923436607670e-03f,
+	-3.368222232871938022e-03f,
+	-3.159840521815048334e-03f,
+	-2.940328969824400774e-03f,
+	-2.710546170915384585e-03f,
+	-2.470119988237139911e-03f,
+	-2.219252954391267088e-03f,
+	-1.957721252210740514e-03f,
+	-1.686154338580459497e-03f,
+	-1.404185177622170513e-03f,
+	-1.112412466716943861e-03f,
+	-8.104093604549785813e-04f,
+	-4.989878141143462478e-04f,
+	-1.780214064768913934e-04f,
+	1.522192972849668944e-04f,
+	4.918785973796621852e-04f,
+	8.402369583326449671e-04f,
+	1.197547244406634449e-03f,
+	1.562837343043727619e-03f,
+	1.936790697733343841e-03f,
+	2.318271923119177673e-03f,
+	2.707838947673167108e-03f,
+	3.104477101526053641e-03f,
+	3.508056557099999660e-03f,
+	3.918470398767492403e-03f,
+	4.335169833065942446e-03f,
+	4.758126123975443302e-03f,
+	5.186908162753916737e-03f,
+	5.620625482845947873e-03f,
+	6.059830357491829099e-03f,
+	6.503636150509565020e-03f,
+	6.951654419741781082e-03f,
+	7.403514759010481130e-03f,
+	7.859057529394617575e-03f,
+	8.317271080552201407e-03f,
+	8.778371882181050523e-03f,
+	9.241897051454299808e-03f,
+	9.707361520065942856e-03f,
+	1.017384431014448955e-02f,
+	1.064161401355775104e-02f,
+	1.110991403566833659e-02f,
+	1.157837340472018042e-02f,
+	1.204640733336614401e-02f,
+	1.251399525989276180e-02f,
+	1.298008200471636835e-02f,
+	1.344467283305781496e-02f,
+	1.390707339243706618e-02f,
+	1.436707804483648709e-02f,
+	1.482404843218210894e-02f,
+	1.527764373106195450e-02f,
+	1.572720847823136370e-02f,
+	1.617287953511281975e-02f,
+	1.661346551451338069e-02f,
+	1.704910076851163039e-02f,
+	1.747887515942801728e-02f,
+	1.790278417542260844e-02f,
+	1.832016242635806091e-02f,
+	1.873048354631740714e-02f,
+	1.913359176276839199e-02f,
+	1.952888596262663395e-02f,
+	1.991612426349772397e-02f,
+	2.029513716616515237e-02f,
+	2.066497334280550588e-02f,
+	2.102582313201171657e-02f,
+	2.137664657171331126e-02f,
+	2.171756028248246484e-02f,
+	2.204823792706822605e-02f,
+	2.236820837185434299e-02f,
+	2.267675245651466776e-02f,
+	2.297427065702456472e-02f,
+	2.326003954871682863e-02f,
+	2.353386929949325551e-02f,
+	2.379537898740429966e-02f,
+	2.404461374840878227e-02f,
+	2.428066541533053721e-02f,
+	2.450377013779640387e-02f,
+	2.471371871688678168e-02f,
+	2.491032278971882369e-02f,
+	2.509281247521447100e-02f,
+	2.526166981665550412e-02f,
+	2.541640305895712798e-02f,
+	2.555696823104279536e-02f,
+	2.568313714659788138e-02f,
+	2.579492515061686600e-02f,
+	2.589180443494390124e-02f,
+	2.597423104070098812e-02f,
+	2.604149942942571641e-02f,
+	2.609419697732707003e-02f,
+	2.613179410789401649e-02f,
+	2.615432379749016087e-02f,
+	2.616185313302369156e-02f,
+	2.615432379749016087e-02f,
+	2.613179410789401649e-02f,
+	2.609419697732707003e-02f,
+	2.604149942942571641e-02f,
+	2.597423104070098812e-02f,
+	2.589180443494390124e-02f,
+	2.579492515061686600e-02f,
+	2.568313714659788138e-02f,
+	2.555696823104279536e-02f,
+	2.541640305895712798e-02f,
+	2.526166981665550412e-02f,
+	2.509281247521447100e-02f,
+	2.491032278971882369e-02f,
+	2.471371871688678168e-02f,
+	2.450377013779640387e-02f,
+	2.428066541533053721e-02f,
+	2.404461374840878227e-02f,
+	2.379537898740429966e-02f,
+	2.353386929949325551e-02f,
+	2.326003954871682863e-02f,
+	2.297427065702456472e-02f,
+	2.267675245651466776e-02f,
+	2.236820837185434299e-02f,
+	2.204823792706822605e-02f,
+	2.171756028248246484e-02f,
+	2.137664657171331126e-02f,
+	2.102582313201171657e-02f,
+	2.066497334280550588e-02f,
+	2.029513716616515237e-02f,
+	1.991612426349772397e-02f,
+	1.952888596262663395e-02f,
+	1.913359176276839199e-02f,
+	1.873048354631740714e-02f,
+	1.832016242635806091e-02f,
+	1.790278417542260844e-02f,
+	1.747887515942801728e-02f,
+	1.704910076851163039e-02f,
+	1.661346551451338069e-02f,
+	1.617287953511281975e-02f,
+	1.572720847823136370e-02f,
+	1.527764373106195450e-02f,
+	1.482404843218210894e-02f,
+	1.436707804483648709e-02f,
+	1.390707339243706618e-02f,
+	1.344467283305781496e-02f,
+	1.298008200471636835e-02f,
+	1.251399525989276180e-02f,
+	1.204640733336614401e-02f,
+	1.157837340472018042e-02f,
+	1.110991403566833659e-02f,
+	1.064161401355775104e-02f,
+	1.017384431014448955e-02f,
+	9.707361520065942856e-03f,
+	9.241897051454299808e-03f,
+	8.778371882181050523e-03f,
+	8.317271080552201407e-03f,
+	7.859057529394617575e-03f,
+	7.403514759010481130e-03f,
+	6.951654419741781082e-03f,
+	6.503636150509565020e-03f,
+	6.059830357491829099e-03f,
+	5.620625482845947873e-03f,
+	5.186908162753916737e-03f,
+	4.758126123975443302e-03f,
+	4.335169833065942446e-03f,
+	3.918470398767492403e-03f,
+	3.508056557099999660e-03f,
+	3.104477101526053641e-03f,
+	2.707838947673167108e-03f,
+	2.318271923119177673e-03f,
+	1.936790697733343841e-03f,
+	1.562837343043727619e-03f,
+	1.197547244406634449e-03f,
+	8.402369583326449671e-04f,
+	4.918785973796621852e-04f,
+	1.522192972849668944e-04f,
+	-1.780214064768913934e-04f,
+	-4.989878141143462478e-04f,
+	-8.104093604549785813e-04f,
+	-1.112412466716943861e-03f,
+	-1.404185177622170513e-03f,
+	-1.686154338580459497e-03f,
+	-1.957721252210740514e-03f,
+	-2.219252954391267088e-03f,
+	-2.470119988237139911e-03f,
+	-2.710546170915384585e-03f,
+	-2.940328969824400774e-03f,
+	-3.159840521815048334e-03f,
+	-3.368222232871938022e-03f,
+	-3.565921923436607670e-03f,
+	-3.752748304070987768e-03f,
+	-3.928806313223098465e-03f,
+	-4.093558706287717293e-03f,
+	-4.247904473129570507e-03f,
+	-4.391467057815140289e-03f,
+	-4.524172500934633967e-03f,
+	-4.645863021006229818e-03f,
+	-4.757514979751304406e-03f,
+	-4.858261956832680799e-03f,
+	-4.948536858227839397e-03f,
+	-5.028565418777247720e-03f,
+	-5.098083258711672526e-03f,
+	-5.157018465563253072e-03f,
+	-5.206623947950080912e-03f,
+	-5.245689774886840885e-03f,
+	-5.275778787304113461e-03f,
+	-5.295514072361832969e-03f,
+	-5.306169907809700145e-03f,
+	-5.307353818425330876e-03f,
+	-5.299717793936110227e-03f,
+	-5.283073191593366282e-03f,
+	-5.257760926908437368e-03f,
+	-5.223766392300994120e-03f,
+	-5.181732499674805530e-03f,
+	-5.131481455486673789e-03f,
+	-5.073718715101926090e-03f,
+	-5.007980116131222244e-03f,
+	-4.935083664219692100e-03f,
+	-4.855210649723631228e-03f,
+	-4.768983537494622671e-03f,
+	-4.676080300709567483e-03f,
+	-4.577021748429701588e-03f,
+	-4.471763619537974868e-03f,
+	-4.361255055064157740e-03f,
+	-4.245108554222204629e-03f,
+	-4.123844444086412382e-03f,
+	-3.997717557990570873e-03f,
+	-3.867598170121567310e-03f,
+	-3.732785291230025088e-03f,
+	-3.594066668336024471e-03f,
+	-3.451776729453182035e-03f,
+	-3.306479321238580630e-03f,
+	-3.157482262943470900e-03f,
+	-3.006174687509059577e-03f,
+	-2.852482541443658939e-03f,
+	-2.696271891573889454e-03f,
+	-2.537770585711366517e-03f,
+	-2.378650972960624776e-03f,
+	-2.217307176542991556e-03f,
+	-2.055923416262168697e-03f,
+	-1.893494839639369657e-03f,
+	-1.730455973362579657e-03f,
+	-1.567354997905725253e-03f,
+	-1.403993062821386846e-03f,
+	-1.241366444165691680e-03f,
+	-1.079181433289383343e-03f,
+	-9.177559621408825068e-04f,
+	-7.573110939678925901e-04f,
+	-5.981863936781633192e-04f,
+	-4.409682655736937027e-04f,
+	-2.855332299683458310e-04f,
+	-1.320664837462653951e-04f,
+	1.940307184331873958e-05f,
+	1.684487684897633048e-04f,
+	3.146759265916663963e-04f,
+	4.576724864960180091e-04f,
+	5.977938267554941442e-04f,
+	7.346937491723865834e-04f,
+	8.682343242442221382e-04f,
+	9.978763396044493510e-04f,
+	1.123952058167431919e-03f,
+	1.246497464073976786e-03f,
+	1.365363009436511765e-03f,
+	1.479494280207919619e-03f,
+	1.589269063813222209e-03f,
+	1.694904606681460393e-03f,
+	1.796133661258653841e-03f,
+	1.892134609303553969e-03f,
+	1.983812091549390193e-03f,
+	2.071124101415585707e-03f,
+	2.153101993781960950e-03f,
+	2.229645625822773963e-03f,
+	2.302282182512669587e-03f,
+	2.369256763660905051e-03f,
+	2.431007224529001514e-03f,
+	2.489048161043688149e-03f,
+	2.540712449828352176e-03f,
+	2.588232511201733494e-03f,
+	2.629767561708499894e-03f,
+	2.666272034998167905e-03f,
+	2.697692214652472244e-03f,
+	2.724010314303314511e-03f,
+	2.745627427472553932e-03f,
+	2.761982335017456550e-03f,
+	2.773361430772598810e-03f,
+	2.779624429509338322e-03f,
+	2.781365635017356459e-03f,
+	2.778561003406229864e-03f,
+	2.771186760452232136e-03f,
+	2.758676926885346957e-03f,
+	2.741414896354936199e-03f,
+	2.719423799193522884e-03f,
+	2.693471225649988945e-03f,
+	2.663387277381585715e-03f,
+	2.629095822036504968e-03f,
+	2.590335566007637494e-03f,
+	2.547855687095583466e-03f,
+	2.501918365765954961e-03f,
+	2.452563099963648522e-03f,
+	2.398902274961839387e-03f,
+	2.341169227904927284e-03f,
+	2.280403552017701372e-03f,
+	2.217025984651658892e-03f,
+	2.149996081954024234e-03f,
+	2.079513504406551964e-03f,
+	2.007250708571191658e-03f,
+	1.932854808129593751e-03f,
+	1.854744544418641212e-03f,
+	1.774141551947332369e-03f,
+	1.693057166924560094e-03f,
+	1.607383880811302139e-03f,
+	1.521319821750537551e-03f,
+	1.434187841331788487e-03f,
+	1.344424171586820803e-03f,
+	1.255259012239529808e-03f,
+	1.163259279711154450e-03f,
+	1.071442571389616101e-03f,
+	9.773793376962093288e-04f,
+	8.833910293821528245e-04f,
+	7.881640482798063117e-04f,
+	6.934600329552267819e-04f,
+	5.979715493655850169e-04f,
+	5.028374292195948812e-04f,
+	4.065614596698848915e-04f,
+	3.104998081881024294e-04f,
+	2.137594158484226162e-04f,
+	1.182702695969081703e-04f,
+	2.324813900268500152e-05f,
+	-7.040911339701516277e-05f,
+	-1.642090876124897316e-04f,
+	-2.570168052342517752e-04f,
+	-3.493288501814680730e-04f,
+	-4.390810370331521182e-04f,
+	-5.271963464774671176e-04f,
+	-6.133377319745481797e-04f,
+	-6.994010271805527245e-04f,
+	-7.839237912431253367e-04f,
+	-8.666767131033942945e-04f,
+	-9.460092877100812793e-04f,
+	-1.024774425637252871e-03f,
+	-1.102948809823240230e-03f,
+	-1.179567323856003068e-03f,
+	-1.251198794323876880e-03f,
+	-1.321620978431202291e-03f,
+	-1.391863815298528036e-03f,
+	-1.457716193277297555e-03f,
+	-1.517818434715981300e-03f,
+	-1.582120970552692478e-03f,
+	-1.636573526265532345e-03f,
+	-1.693709176093296034e-03f,
+	-1.745857401994723064e-03f,
+	-1.797299886474045894e-03f,
+	-1.845599207103569171e-03f,
+	-1.892174313452701451e-03f,
+	-1.935348484380292316e-03f,
+	-1.976158539167319726e-03f,
+	-2.012837491129578372e-03f,
+	-2.046987520086473132e-03f,
+	-2.077172375550435761e-03f,
+	-2.105641529924149376e-03f,
+	-2.131071225425520705e-03f,
+	-2.155589515463847243e-03f,
+	-2.177222256032555758e-03f,
+	-2.197338639655533905e-03f,
+	-2.213150578496394551e-03f,
+	-2.226370095421580011e-03f,
+	-2.234643544191589060e-03f,
+	-2.241210127571734417e-03f,
+	-2.244787816410075219e-03f,
+	-2.249014144102850880e-03f,
+	-2.250676166469937293e-03f,
+	-2.251333881834658573e-03f,
+	-2.245690114091244104e-03f,
+	-2.237299832605875623e-03f,
+	-2.224316096228397700e-03f,
+	-2.214475088192078243e-03f,
+	-2.203409370837070176e-03f,
+	-2.192502477043971418e-03f,
+	-2.170075937463497931e-03f,
+	-2.147085094366327652e-03f,
+	-2.124974837005796230e-03f,
+	-2.114632962607296794e-03f,
+	-2.076888033986441090e-03f,
+	-2.051810851077184687e-03f,
+	-2.030446950616142214e-03f,
+	-1.992731097977784929e-03f,
+	-1.967442920661567184e-03f,
+	-1.930972869048331979e-03f,
+	-1.900114684605757557e-03f,
+	-1.862811381024030493e-03f,
+	-1.828766667178651417e-03f,
+	-1.790152294171405483e-03f,
+	-1.753795105460645475e-03f,
+	-1.713844253344104550e-03f,
+	-1.675880470169040671e-03f,
+	-1.635093110091758416e-03f,
+	-1.596225206453755078e-03f,
+	-1.555180824781971644e-03f,
+	-1.516194105259252708e-03f,
+	-1.475879026660373164e-03f,
+	-1.438037861307091920e-03f,
+	-1.399830168893742869e-03f,
+	-1.365006461763774558e-03f,
+	-1.331149234067586498e-03f,
+	-1.302161835196590086e-03f,
+	-1.276455540762199033e-03f,
+	-1.258257006125656444e-03f,
+	-1.246924069957423917e-03f,
+	-1.247676093110160287e-03f,
+	-1.261471237118429829e-03f,
+	-1.295431553242113462e-03f,
+	-1.352998170836033258e-03f,
+	-1.444420820940262463e-03f,
+	-1.577794626580075353e-03f,
+	-1.769058926498227532e-03f,
+	-2.033946693814312010e-03f,
+	-2.398446815447830179e-03f,
+	-2.891709491113995511e-03f,
+	-3.557140030354209899e-03f,
+	7.611379875493138637e-03f
+};
+/* Low pass prototype for Hilbert-filter 10 kHz bandwidth */
+const float fHilLPProt10_384[NUM_TAPS_HILB_FILT_10_384] =
+{
+	6.758761318511769325e-03f,
+	-4.369545405522427123e-03f,
+	-3.379050597845852447e-03f,
+	-2.745022127282624284e-03f,
+	-2.351442108898825316e-03f,
+	-2.121955513533378170e-03f,
+	-2.002412022315385506e-03f,
+	-1.958317015202609354e-03f,
+	-1.963756492010986301e-03f,
+	-2.003351168661946825e-03f,
+	-2.064205661141766280e-03f,
+	-2.139677722379859474e-03f,
+	-2.222687438215988336e-03f,
+	-2.310817825992059205e-03f,
+	-2.399511185250983395e-03f,
+	-2.488277728817098796e-03f,
+	-2.573781872766172079e-03f,
+	-2.656450233282786622e-03f,
+	-2.733366088163403755e-03f,
+	-2.805594697222182562e-03f,
+	-2.870414276578328767e-03f,
+	-2.929173765819073714e-03f,
+	-2.979180881868471152e-03f,
+	-3.022083721865337531e-03f,
+	-3.055057205008311454e-03f,
+	-3.080199144963444505e-03f,
+	-3.094459880931395030e-03f,
+	-3.100379112034238119e-03f,
+	-3.094608710672835244e-03f,
+	-3.080405359676204654e-03f,
+	-3.053631305497389332e-03f,
+	-3.018670275854707340e-03f,
+	-2.970341994292376771e-03f,
+	-2.914713999951831606e-03f,
+	-2.844405185587222610e-03f,
+	-2.768994510294407740e-03f,
+	-2.677789887563414122e-03f,
+	-2.578657896338684957e-03f,
+	-2.478426427491166751e-03f,
+	-2.346136477694595220e-03f,
+	-2.232047902250976646e-03f,
+	-2.096913954321086727e-03f,
+	-1.949417435584684154e-03f,
+	-1.797273242898582814e-03f,
+	-1.647155815443303783e-03f,
+	-1.486141104669210433e-03f,
+	-1.316917886454150883e-03f,
+	-1.141005331022939802e-03f,
+	-9.665300050533379064e-04f,
+	-7.905846394091048650e-04f,
+	-6.136246006274017695e-04f,
+	-4.318143950642125005e-04f,
+	-2.493456346254276676e-04f,
+	-6.677406178178752556e-05f,
+	1.111626718262373459e-04f,
+	2.857873195372625011e-04f,
+	4.551699060746775861e-04f,
+	6.218536199809948303e-04f,
+	7.833678139469280695e-04f,
+	9.404531768479146249e-04f,
+	1.089424209044921425e-03f,
+	1.230572163246295260e-03f,
+	1.360760328968521832e-03f,
+	1.481403816923236149e-03f,
+	1.590328718408866695e-03f,
+	1.689490975641610776e-03f,
+	1.776563631699757924e-03f,
+	1.853268298089821853e-03f,
+	1.916328794484908763e-03f,
+	1.967776983719276684e-03f,
+	2.003728864118613662e-03f,
+	2.027414074246970503e-03f,
+	2.034046996426489354e-03f,
+	2.029452613003435938e-03f,
+	2.007201473616313393e-03f,
+	1.973585807736127039e-03f,
+	1.926698145734787211e-03f,
+	1.862840512552727196e-03f,
+	1.791966049252097064e-03f,
+	1.704888718331066394e-03f,
+	1.605495570152393799e-03f,
+	1.496307054888335736e-03f,
+	1.376570660894356089e-03f,
+	1.243805838162378432e-03f,
+	1.102043087241082447e-03f,
+	9.526965123173604649e-04f,
+	7.956397935857579835e-04f,
+	6.302170064708588699e-04f,
+	4.590036745912726363e-04f,
+	2.839626536996175108e-04f,
+	1.063565540435180371e-04f,
+	-7.422721342128780998e-05f,
+	-2.565265450459263373e-04f,
+	-4.388598299075404698e-04f,
+	-6.189205476526566394e-04f,
+	-7.961262705400199390e-04f,
+	-9.696127345488953549e-04f,
+	-1.138939009930432615e-03f,
+	-1.302349023899550479e-03f,
+	-1.458405189075073598e-03f,
+	-1.605358435245399489e-03f,
+	-1.742775370943317088e-03f,
+	-1.869762595632652865e-03f,
+	-1.985911781570560801e-03f,
+	-2.089790029618312367e-03f,
+	-2.180641580541950540e-03f,
+	-2.256829742577346962e-03f,
+	-2.318593061356472289e-03f,
+	-2.364480874471166019e-03f,
+	-2.395746892241043015e-03f,
+	-2.409970671672834099e-03f,
+	-2.409764022345063303e-03f,
+	-2.390840568819557407e-03f,
+	-2.356807080481319351e-03f,
+	-2.305289945919096386e-03f,
+	-2.236268106940581847e-03f,
+	-2.153223892154313215e-03f,
+	-2.052897722082120367e-03f,
+	-1.937636794960137607e-03f,
+	-1.808464536013952920e-03f,
+	-1.664877036417756334e-03f,
+	-1.506825508998178940e-03f,
+	-1.337139508794419566e-03f,
+	-1.156149037591785132e-03f,
+	-9.643458635551162197e-04f,
+	-7.632041051623506900e-04f,
+	-5.549813412396642021e-04f,
+	-3.402863177271585760e-04f,
+	-1.199454662508615322e-04f,
+	1.047527713909197981e-04f,
+	3.315328852746103421e-04f,
+	5.590888320377315843e-04f,
+	7.861497581712608915e-04f,
+	1.011579321250659618e-03f,
+	1.233034218668646381e-03f,
+	1.448838372881181046e-03f,
+	1.657477565302965762e-03f,
+	1.858047535948573756e-03f,
+	2.048964152621419749e-03f,
+	2.228805001931073292e-03f,
+	2.395815485855593962e-03f,
+	2.548865608137266224e-03f,
+	2.686913803851371726e-03f,
+	2.808978744282293518e-03f,
+	2.913563115942288846e-03f,
+	2.999753592888572407e-03f,
+	3.066137817769513160e-03f,
+	3.112929601959538162e-03f,
+	3.138587929309369015e-03f,
+	3.144587734947453059e-03f,
+	3.127800872808529902e-03f,
+	3.090842521475294265e-03f,
+	3.031254684530182257e-03f,
+	2.950130137642501156e-03f,
+	2.848431349341861221e-03f,
+	2.725207073337886435e-03f,
+	2.581561765119441774e-03f,
+	2.418514296978438449e-03f,
+	2.235714166932401253e-03f,
+	2.034413339119782709e-03f,
+	1.816440168344832760e-03f,
+	1.582666163612144817e-03f,
+	1.333937563289675421e-03f,
+	1.072513911358660612e-03f,
+	7.996882306166352766e-04f,
+	5.168117546930846599e-04f,
+	2.254157578961755288e-04f,
+	-7.191911096914278356e-05f,
+	-3.734865286625007881e-04f,
+	-6.773978375037220190e-04f,
+	-9.819912492074400409e-04f,
+	-1.284812212140236344e-03f,
+	-1.583915987808354837e-03f,
+	-1.877310086261526657e-03f,
+	-2.163303212298719070e-03f,
+	-2.439256868102019846e-03f,
+	-2.703118072821014857e-03f,
+	-2.952812011592775756e-03f,
+	-3.186990430305648974e-03f,
+	-3.403448583095969402e-03f,
+	-3.600774474679839000e-03f,
+	-3.776664287098246541e-03f,
+	-3.930063349113377229e-03f,
+	-4.059269138968199693e-03f,
+	-4.163303442150813501e-03f,
+	-4.240667767208409697e-03f,
+	-4.290198398226796432e-03f,
+	-4.311801519120561296e-03f,
+	-4.303704130537259163e-03f,
+	-4.267255593503768880e-03f,
+	-4.200441736657622993e-03f,
+	-4.103800188232613853e-03f,
+	-3.977624227341148427e-03f,
+	-3.821526992511524792e-03f,
+	-3.636644080885834129e-03f,
+	-3.423706114571671046e-03f,
+	-3.183084683251925610e-03f,
+	-2.916004346589811790e-03f,
+	-2.624287659482761256e-03f,
+	-2.308892286140341345e-03f,
+	-1.971586284374568163e-03f,
+	-1.614570507234082495e-03f,
+	-1.239515476680194293e-03f,
+	-8.482357498048359763e-04f,
+	-4.432575136161458857e-04f,
+	-2.728441326953235998e-05f,
+	3.973098838377951475e-04f,
+	8.278420588809385023e-04f,
+	1.261419736641147555e-03f,
+	1.695193857955031675e-03f,
+	2.126431148416991612e-03f,
+	2.552325757567455201e-03f,
+	2.969788008274323182e-03f,
+	3.375620660472038789e-03f,
+	3.767028244296471463e-03f,
+	4.141291340021957708e-03f,
+	4.495534828194733962e-03f,
+	4.826614194737793503e-03f,
+	5.132193511136619313e-03f,
+	5.409365234160387441e-03f,
+	5.655949747744766672e-03f,
+	5.869159523866951216e-03f,
+	6.047185154377514305e-03f,
+	6.187824588347895331e-03f,
+	6.289637882263444425e-03f,
+	6.351219476975310772e-03f,
+	6.370304665503816362e-03f,
+	6.346938617610263164e-03f,
+	6.278930201678935979e-03f,
+	6.166706480716628060e-03f,
+	6.009724858160608689e-03f,
+	5.807607923347230493e-03f,
+	5.560689625506644480e-03f,
+	5.269670419878609915e-03f,
+	4.935033564167453334e-03f,
+	4.558142513860644410e-03f,
+	4.140469764319206804e-03f,
+	3.683361494916761233e-03f,
+	3.188964855010376163e-03f,
+	2.659948603021908536e-03f,
+	2.098461026712676158e-03f,
+	1.507315738560392705e-03f,
+	8.895949160130854324e-04f,
+	2.486946950876366331e-04f,
+	-4.121965304913834962e-04f,
+	-1.088974352881699270e-03f,
+	-1.777737783362205986e-03f,
+	-2.474316990615822720e-03f,
+	-3.174632150814740619e-03f,
+	-3.874076520042260725e-03f,
+	-4.568164821213745869e-03f,
+	-5.252055058334580487e-03f,
+	-5.921249306985668613e-03f,
+	-6.570861281337657921e-03f,
+	-7.196128567051874626e-03f,
+	-7.792017298800904199e-03f,
+	-8.354299385796432054e-03f,
+	-8.877633647755034732e-03f,
+	-9.357735352059573172e-03f,
+	-9.789625426339366304e-03f,
+	-1.016963596235228445e-02f,
+	-1.049289573851267844e-02f,
+	-1.075598125908316764e-02f,
+	-1.095459319402323703e-02f,
+	-1.108504246928433169e-02f,
+	-1.114452922935456509e-02f,
+	-1.112909293131714855e-02f,
+	-1.103655099631422817e-02f,
+	-1.086429932518619135e-02f,
+	-1.061006268500585235e-02f,
+	-1.027239402790344237e-02f,
+	-9.849776503209924441e-03f,
+	-9.341004940378035831e-03f,
+	-8.745352608082403514e-03f,
+	-8.062961844615131740e-03f,
+	-7.293619762467696069e-03f,
+	-6.438275107383132148e-03f,
+	-5.497680872496463547e-03f,
+	-4.473144237445787069e-03f,
+	-3.366458607657390242e-03f,
+	-2.180240041056900023e-03f,
+	-9.168787810336477898e-04f,
+	4.205698621717836511e-04f,
+	1.828577723471656565e-03f,
+	3.303232180313499071e-03f,
+	4.840587479935847502e-03f,
+	6.435939637580554221e-03f,
+	8.084571002498534831e-03f,
+	9.781222384967112882e-03f,
+	1.152052077613688330e-02f,
+	1.329653697203182425e-02f,
+	1.510349469504260189e-02f,
+	1.693496284189760850e-02f,
+	1.878473455524658567e-02f,
+	2.064636736430475183e-02f,
+	2.251288146233779500e-02f,
+	2.437761026182476767e-02f,
+	2.623365633702727170e-02f,
+	2.807435337228738823e-02f,
+	2.989231041273015047e-02f,
+	3.168126201183547874e-02f,
+	3.343401731637452023e-02f,
+	3.514383410526492751e-02f,
+	3.680445203059964226e-02f,
+	3.840857003346934140e-02f,
+	3.995076085637905977e-02f,
+	4.142446438302609113e-02f,
+	4.282400803576447146e-02f,
+	4.414372371084276242e-02f,
+	4.537855914424272080e-02f,
+	4.652329868323192008e-02f,
+	4.757354348593477444e-02f,
+	4.852512868410794461e-02f,
+	4.937401034984446879e-02f,
+	5.011689782341694627e-02f,
+	5.075076467716713863e-02f,
+	5.127291678055868884e-02f,
+	5.168127159348383931e-02f,
+	5.197411759880160576e-02f,
+	5.215017529716427236e-02f,
+	5.220884732697547020e-02f,
+	5.215017529716427236e-02f,
+	5.197411759880160576e-02f,
+	5.168127159348383931e-02f,
+	5.127291678055868884e-02f,
+	5.075076467716713863e-02f,
+	5.011689782341694627e-02f,
+	4.937401034984446879e-02f,
+	4.852512868410794461e-02f,
+	4.757354348593477444e-02f,
+	4.652329868323192008e-02f,
+	4.537855914424272080e-02f,
+	4.414372371084276242e-02f,
+	4.282400803576447146e-02f,
+	4.142446438302609113e-02f,
+	3.995076085637905977e-02f,
+	3.840857003346934140e-02f,
+	3.680445203059964226e-02f,
+	3.514383410526492751e-02f,
+	3.343401731637452023e-02f,
+	3.168126201183547874e-02f,
+	2.989231041273015047e-02f,
+	2.807435337228738823e-02f,
+	2.623365633702727170e-02f,
+	2.437761026182476767e-02f,
+	2.251288146233779500e-02f,
+	2.064636736430475183e-02f,
+	1.878473455524658567e-02f,
+	1.693496284189760850e-02f,
+	1.510349469504260189e-02f,
+	1.329653697203182425e-02f,
+	1.152052077613688330e-02f,
+	9.781222384967112882e-03f,
+	8.084571002498534831e-03f,
+	6.435939637580554221e-03f,
+	4.840587479935847502e-03f,
+	3.303232180313499071e-03f,
+	1.828577723471656565e-03f,
+	4.205698621717836511e-04f,
+	-9.168787810336477898e-04f,
+	-2.180240041056900023e-03f,
+	-3.366458607657390242e-03f,
+	-4.473144237445787069e-03f,
+	-5.497680872496463547e-03f,
+	-6.438275107383132148e-03f,
+	-7.293619762467696069e-03f,
+	-8.062961844615131740e-03f,
+	-8.745352608082403514e-03f,
+	-9.341004940378035831e-03f,
+	-9.849776503209924441e-03f,
+	-1.027239402790344237e-02f,
+	-1.061006268500585235e-02f,
+	-1.086429932518619135e-02f,
+	-1.103655099631422817e-02f,
+	-1.112909293131714855e-02f,
+	-1.114452922935456509e-02f,
+	-1.108504246928433169e-02f,
+	-1.095459319402323703e-02f,
+	-1.075598125908316764e-02f,
+	-1.049289573851267844e-02f,
+	-1.016963596235228445e-02f,
+	-9.789625426339366304e-03f,
+	-9.357735352059573172e-03f,
+	-8.877633647755034732e-03f,
+	-8.354299385796432054e-03f,
+	-7.792017298800904199e-03f,
+	-7.196128567051874626e-03f,
+	-6.570861281337657921e-03f,
+	-5.921249306985668613e-03f,
+	-5.252055058334580487e-03f,
+	-4.568164821213745869e-03f,
+	-3.874076520042260725e-03f,
+	-3.174632150814740619e-03f,
+	-2.474316990615822720e-03f,
+	-1.777737783362205986e-03f,
+	-1.088974352881699270e-03f,
+	-4.121965304913834962e-04f,
+	2.486946950876366331e-04f,
+	8.895949160130854324e-04f,
+	1.507315738560392705e-03f,
+	2.098461026712676158e-03f,
+	2.659948603021908536e-03f,
+	3.188964855010376163e-03f,
+	3.683361494916761233e-03f,
+	4.140469764319206804e-03f,
+	4.558142513860644410e-03f,
+	4.935033564167453334e-03f,
+	5.269670419878609915e-03f,
+	5.560689625506644480e-03f,
+	5.807607923347230493e-03f,
+	6.009724858160608689e-03f,
+	6.166706480716628060e-03f,
+	6.278930201678935979e-03f,
+	6.346938617610263164e-03f,
+	6.370304665503816362e-03f,
+	6.351219476975310772e-03f,
+	6.289637882263444425e-03f,
+	6.187824588347895331e-03f,
+	6.047185154377514305e-03f,
+	5.869159523866951216e-03f,
+	5.655949747744766672e-03f,
+	5.409365234160387441e-03f,
+	5.132193511136619313e-03f,
+	4.826614194737793503e-03f,
+	4.495534828194733962e-03f,
+	4.141291340021957708e-03f,
+	3.767028244296471463e-03f,
+	3.375620660472038789e-03f,
+	2.969788008274323182e-03f,
+	2.552325757567455201e-03f,
+	2.126431148416991612e-03f,
+	1.695193857955031675e-03f,
+	1.261419736641147555e-03f,
+	8.278420588809385023e-04f,
+	3.973098838377951475e-04f,
+	-2.728441326953235998e-05f,
+	-4.432575136161458857e-04f,
+	-8.482357498048359763e-04f,
+	-1.239515476680194293e-03f,
+	-1.614570507234082495e-03f,
+	-1.971586284374568163e-03f,
+	-2.308892286140341345e-03f,
+	-2.624287659482761256e-03f,
+	-2.916004346589811790e-03f,
+	-3.183084683251925610e-03f,
+	-3.423706114571671046e-03f,
+	-3.636644080885834129e-03f,
+	-3.821526992511524792e-03f,
+	-3.977624227341148427e-03f,
+	-4.103800188232613853e-03f,
+	-4.200441736657622993e-03f,
+	-4.267255593503768880e-03f,
+	-4.303704130537259163e-03f,
+	-4.311801519120561296e-03f,
+	-4.290198398226796432e-03f,
+	-4.240667767208409697e-03f,
+	-4.163303442150813501e-03f,
+	-4.059269138968199693e-03f,
+	-3.930063349113377229e-03f,
+	-3.776664287098246541e-03f,
+	-3.600774474679839000e-03f,
+	-3.403448583095969402e-03f,
+	-3.186990430305648974e-03f,
+	-2.952812011592775756e-03f,
+	-2.703118072821014857e-03f,
+	-2.439256868102019846e-03f,
+	-2.163303212298719070e-03f,
+	-1.877310086261526657e-03f,
+	-1.583915987808354837e-03f,
+	-1.284812212140236344e-03f,
+	-9.819912492074400409e-04f,
+	-6.773978375037220190e-04f,
+	-3.734865286625007881e-04f,
+	-7.191911096914278356e-05f,
+	2.254157578961755288e-04f,
+	5.168117546930846599e-04f,
+	7.996882306166352766e-04f,
+	1.072513911358660612e-03f,
+	1.333937563289675421e-03f,
+	1.582666163612144817e-03f,
+	1.816440168344832760e-03f,
+	2.034413339119782709e-03f,
+	2.235714166932401253e-03f,
+	2.418514296978438449e-03f,
+	2.581561765119441774e-03f,
+	2.725207073337886435e-03f,
+	2.848431349341861221e-03f,
+	2.950130137642501156e-03f,
+	3.031254684530182257e-03f,
+	3.090842521475294265e-03f,
+	3.127800872808529902e-03f,
+	3.144587734947453059e-03f,
+	3.138587929309369015e-03f,
+	3.112929601959538162e-03f,
+	3.066137817769513160e-03f,
+	2.999753592888572407e-03f,
+	2.913563115942288846e-03f,
+	2.808978744282293518e-03f,
+	2.686913803851371726e-03f,
+	2.548865608137266224e-03f,
+	2.395815485855593962e-03f,
+	2.228805001931073292e-03f,
+	2.048964152621419749e-03f,
+	1.858047535948573756e-03f,
+	1.657477565302965762e-03f,
+	1.448838372881181046e-03f,
+	1.233034218668646381e-03f,
+	1.011579321250659618e-03f,
+	7.861497581712608915e-04f,
+	5.590888320377315843e-04f,
+	3.315328852746103421e-04f,
+	1.047527713909197981e-04f,
+	-1.199454662508615322e-04f,
+	-3.402863177271585760e-04f,
+	-5.549813412396642021e-04f,
+	-7.632041051623506900e-04f,
+	-9.643458635551162197e-04f,
+	-1.156149037591785132e-03f,
+	-1.337139508794419566e-03f,
+	-1.506825508998178940e-03f,
+	-1.664877036417756334e-03f,
+	-1.808464536013952920e-03f,
+	-1.937636794960137607e-03f,
+	-2.052897722082120367e-03f,
+	-2.153223892154313215e-03f,
+	-2.236268106940581847e-03f,
+	-2.305289945919096386e-03f,
+	-2.356807080481319351e-03f,
+	-2.390840568819557407e-03f,
+	-2.409764022345063303e-03f,
+	-2.409970671672834099e-03f,
+	-2.395746892241043015e-03f,
+	-2.364480874471166019e-03f,
+	-2.318593061356472289e-03f,
+	-2.256829742577346962e-03f,
+	-2.180641580541950540e-03f,
+	-2.089790029618312367e-03f,
+	-1.985911781570560801e-03f,
+	-1.869762595632652865e-03f,
+	-1.742775370943317088e-03f,
+	-1.605358435245399489e-03f,
+	-1.458405189075073598e-03f,
+	-1.302349023899550479e-03f,
+	-1.138939009930432615e-03f,
+	-9.696127345488953549e-04f,
+	-7.961262705400199390e-04f,
+	-6.189205476526566394e-04f,
+	-4.388598299075404698e-04f,
+	-2.565265450459263373e-04f,
+	-7.422721342128780998e-05f,
+	1.063565540435180371e-04f,
+	2.839626536996175108e-04f,
+	4.590036745912726363e-04f,
+	6.302170064708588699e-04f,
+	7.956397935857579835e-04f,
+	9.526965123173604649e-04f,
+	1.102043087241082447e-03f,
+	1.243805838162378432e-03f,
+	1.376570660894356089e-03f,
+	1.496307054888335736e-03f,
+	1.605495570152393799e-03f,
+	1.704888718331066394e-03f,
+	1.791966049252097064e-03f,
+	1.862840512552727196e-03f,
+	1.926698145734787211e-03f,
+	1.973585807736127039e-03f,
+	2.007201473616313393e-03f,
+	2.029452613003435938e-03f,
+	2.034046996426489354e-03f,
+	2.027414074246970503e-03f,
+	2.003728864118613662e-03f,
+	1.967776983719276684e-03f,
+	1.916328794484908763e-03f,
+	1.853268298089821853e-03f,
+	1.776563631699757924e-03f,
+	1.689490975641610776e-03f,
+	1.590328718408866695e-03f,
+	1.481403816923236149e-03f,
+	1.360760328968521832e-03f,
+	1.230572163246295260e-03f,
+	1.089424209044921425e-03f,
+	9.404531768479146249e-04f,
+	7.833678139469280695e-04f,
+	6.218536199809948303e-04f,
+	4.551699060746775861e-04f,
+	2.857873195372625011e-04f,
+	1.111626718262373459e-04f,
+	-6.677406178178752556e-05f,
+	-2.493456346254276676e-04f,
+	-4.318143950642125005e-04f,
+	-6.136246006274017695e-04f,
+	-7.905846394091048650e-04f,
+	-9.665300050533379064e-04f,
+	-1.141005331022939802e-03f,
+	-1.316917886454150883e-03f,
+	-1.486141104669210433e-03f,
+	-1.647155815443303783e-03f,
+	-1.797273242898582814e-03f,
+	-1.949417435584684154e-03f,
+	-2.096913954321086727e-03f,
+	-2.232047902250976646e-03f,
+	-2.346136477694595220e-03f,
+	-2.478426427491166751e-03f,
+	-2.578657896338684957e-03f,
+	-2.677789887563414122e-03f,
+	-2.768994510294407740e-03f,
+	-2.844405185587222610e-03f,
+	-2.914713999951831606e-03f,
+	-2.970341994292376771e-03f,
+	-3.018670275854707340e-03f,
+	-3.053631305497389332e-03f,
+	-3.080405359676204654e-03f,
+	-3.094608710672835244e-03f,
+	-3.100379112034238119e-03f,
+	-3.094459880931395030e-03f,
+	-3.080199144963444505e-03f,
+	-3.055057205008311454e-03f,
+	-3.022083721865337531e-03f,
+	-2.979180881868471152e-03f,
+	-2.929173765819073714e-03f,
+	-2.870414276578328767e-03f,
+	-2.805594697222182562e-03f,
+	-2.733366088163403755e-03f,
+	-2.656450233282786622e-03f,
+	-2.573781872766172079e-03f,
+	-2.488277728817098796e-03f,
+	-2.399511185250983395e-03f,
+	-2.310817825992059205e-03f,
+	-2.222687438215988336e-03f,
+	-2.139677722379859474e-03f,
+	-2.064205661141766280e-03f,
+	-2.003351168661946825e-03f,
+	-1.963756492010986301e-03f,
+	-1.958317015202609354e-03f,
+	-2.002412022315385506e-03f,
+	-2.121955513533378170e-03f,
+	-2.351442108898825316e-03f,
+	-2.745022127282624284e-03f,
+	-3.379050597845852447e-03f,
+	-4.369545405522427123e-03f,
+	6.758761318511769325e-03f
+};
+
diff --git a/src/sync/TimeSyncFilter.h b/src/sync/TimeSyncFilter.h
new file mode 100644
index 0000000..1bbdedc
--- /dev/null
+++ b/src/sync/TimeSyncFilter.h
@@ -0,0 +1,52 @@
+/* Automatically generated file with GNU Octave */
+/* File name: "TimeSyncFilter.octave" */
+/* Filter taps in time-domain */
+
+#ifndef _TIMESYNCFILTER_H_
+#define _TIMESYNCFILTER_H_
+
+/* Filter bandwidths */
+#define HILB_FILT_BNDWIDTH_5            5200
+#define HILB_FILT_BNDWIDTH_10           10200
+
+/* Filter parameters for 24000 Hz sample rate */
+#define NUM_TAPS_HILB_FILT_5_24            41
+#define NUM_TAPS_HILB_FILT_10_24           41
+/* Low pass prototype for Hilbert-filter 5 kHz bandwidth */
+extern const float fHilLPProt5_24[NUM_TAPS_HILB_FILT_5_24];
+/* Low pass prototype for Hilbert-filter 10 kHz bandwidth */
+extern const float fHilLPProt10_24[NUM_TAPS_HILB_FILT_10_24];
+
+/* Filter parameters for 48000 Hz sample rate */
+#define NUM_TAPS_HILB_FILT_5_48            81
+#define NUM_TAPS_HILB_FILT_10_48           81
+/* Low pass prototype for Hilbert-filter 5 kHz bandwidth */
+extern const float fHilLPProt5_48[NUM_TAPS_HILB_FILT_5_48];
+/* Low pass prototype for Hilbert-filter 10 kHz bandwidth */
+extern const float fHilLPProt10_48[NUM_TAPS_HILB_FILT_10_48];
+
+/* Filter parameters for 96000 Hz sample rate */
+#define NUM_TAPS_HILB_FILT_5_96            161
+#define NUM_TAPS_HILB_FILT_10_96           161
+/* Low pass prototype for Hilbert-filter 5 kHz bandwidth */
+extern const float fHilLPProt5_96[NUM_TAPS_HILB_FILT_5_96];
+/* Low pass prototype for Hilbert-filter 10 kHz bandwidth */
+extern const float fHilLPProt10_96[NUM_TAPS_HILB_FILT_10_96];
+
+/* Filter parameters for 192000 Hz sample rate */
+#define NUM_TAPS_HILB_FILT_5_192            321
+#define NUM_TAPS_HILB_FILT_10_192           321
+/* Low pass prototype for Hilbert-filter 5 kHz bandwidth */
+extern const float fHilLPProt5_192[NUM_TAPS_HILB_FILT_5_192];
+/* Low pass prototype for Hilbert-filter 10 kHz bandwidth */
+extern const float fHilLPProt10_192[NUM_TAPS_HILB_FILT_10_192];
+
+/* Filter parameters for 384000 Hz sample rate */
+#define NUM_TAPS_HILB_FILT_5_384            641
+#define NUM_TAPS_HILB_FILT_10_384           641
+/* Low pass prototype for Hilbert-filter 5 kHz bandwidth */
+extern const float fHilLPProt5_384[NUM_TAPS_HILB_FILT_5_384];
+/* Low pass prototype for Hilbert-filter 10 kHz bandwidth */
+extern const float fHilLPProt10_384[NUM_TAPS_HILB_FILT_10_384];
+
+#endif	/* _TIMESYNCFILTER_H_ */
diff --git a/src/sync/TimeSyncFilter.octave b/src/sync/TimeSyncFilter.octave
new file mode 100644
index 0000000..505845e
--- /dev/null
+++ b/src/sync/TimeSyncFilter.octave
@@ -0,0 +1,176 @@
+%******************************************************************************\
+%* Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+%* Copyright (c) 2003
+%*
+%* Author:
+%*	Alexander Kurpiers, modified by David Flamand to support more sample rate
+%*
+%* Description:
+%* 	Hilbert Filter for timing acquisition
+%*  Runs at 48 kHz, can be downsampled to 48 kHz / 8 = 6 kHz
+%*
+%******************************************************************************
+%*
+%* This program is free software; you can redistribute it and/or modify it under
+%* the terms of the GNU General Public License as published by the Free Software
+%* Foundation; either version 2 of the License, or (at your option) any later 
+%* version.
+%*
+%* This program is distributed in the hope that it will be useful, but WITHOUT 
+%* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+%* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 
+%* details.
+%*
+%* You should have received a copy of the GNU General Public License along with
+%* this program; if not, write to the Free Software Foundation, Inc., 
+%* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+%*
+%******************************************************************************/
+
+function [b] = DesignFilter(fstart, fstop, ftrans, nhil, fs)
+    % Parks-McClellan optimal equiripple FIR filter design
+    B = fstop - fstart;
+    f = [0  B / 2  B / 2 + ftrans  fs / 2];
+    m = [2 2 0 0];
+    b = remez(nhil - 1, f * 2 / fs, m, [1 10]);
+endfunction
+
+
+% Hilbert filter characteristic frequencies
+% 5 kHz bandwidth
+global fstart5 = 800;
+global fstop5 = 5200;
+global ftrans5 = 800; % Size of transition region
+% 10 kHz bandwidth
+global fstart10 = 800;
+global fstop10 = 10200;
+global ftrans10 = 800; % Size of transition region
+
+
+function MakeFilter(fid_cpp, fid_h, multi)
+    global fstart5 fstop5 ftrans5;
+    global fstart10 fstop10 ftrans10;
+
+    fs = 48000 * multi;
+    ntaps = 80 * multi + 1;
+
+    % Length of hilbert filter
+    % 5 kHz bandwidth
+    nhil5 = ntaps;
+    % 10 kHz bandwidth
+    nhil10 = ntaps;
+
+    % Actual filter design
+    b5 = DesignFilter(fstart5, fstop5, ftrans5, nhil5, fs);
+    b10 = DesignFilter(fstart10, fstop10, ftrans10, nhil10, fs);
+
+    % Display the filter
+    PLOT = 0;
+    if (PLOT == 1)
+        close all;
+
+        % 5 kHz bandwidth filter
+        subplot(2, 1, 1)
+        f05 = (fstop5 + ftrans5) / 2;
+        t = linspace(0, (nhil5 - 1) / fs, nhil5);
+        hr = b5 .* cos(2 * pi * f05 * t);
+        hi = b5 .* sin(2 * pi * f05 * t);
+
+        % Complex hilbert filter
+        hbp = hr + hi * j;
+
+        [h1, f]= freqz(hbp, 1, 512, 'whole', fs);
+        plot(f - fs / 2, 20 * log10(abs([h1(257:512); h1(1:256)])));
+        axis([-fstart5 fstop5 + ftrans5 -90 10]);
+        grid;
+        % zoom on;
+        title('Hilbert-transformer 5 kHz bandwidth');
+        xlabel('Frequency [Hz]');
+        ylabel('Attenuation [dB]');
+
+        % 10 kHz bandwidth filter
+        subplot(2, 1, 2)
+        f010 = (fstop10 + ftrans10) / 2;
+        t = linspace(0, (nhil10 - 1) / fs, nhil10);
+        hr = b10 .* cos(2 * pi * f010 * t);
+        hi = b10 .* sin(2 * pi * f010 * t);
+
+        % Complex hilbert filter
+        hbp = hr + hi * j;
+
+        [h1, f]= freqz(hbp, 1, 512, 'whole', fs);
+        plot(f - fs / 2, 20 * log10(abs([h1(257:512); h1(1:256)])));
+        axis([-fstart10 fstop10 + ftrans5 -90 10]);
+        grid;
+        % zoom on;
+        title('Hilbert-transformer 10 kHz bandwidth');
+        xlabel('Frequency [Hz]');
+        ylabel('Attenuation [dB]');
+    end
+
+
+    % Export coefficients to file ****************************************
+
+    f = fs / 1000;
+
+    % Write header file
+    fprintf(fid_h, '/* Filter parameters for %i Hz sample rate */\n', fs);
+    fprintf(fid_h, '#define NUM_TAPS_HILB_FILT_5_%i            %i\n', f, nhil5);
+    fprintf(fid_h, '#define NUM_TAPS_HILB_FILT_10_%i           %i\n', f, nhil10);
+    fprintf(fid_h, '/* Low pass prototype for Hilbert-filter 5 kHz bandwidth */\n');
+    fprintf(fid_h, 'extern const float fHilLPProt5_%i[NUM_TAPS_HILB_FILT_5_%i];\n', f, f);
+    fprintf(fid_h, '/* Low pass prototype for Hilbert-filter 10 kHz bandwidth */\n');
+    fprintf(fid_h, 'extern const float fHilLPProt10_%i[NUM_TAPS_HILB_FILT_10_%i];\n', f, f);
+    fprintf(fid_h, '\n');
+
+    % Write filter taps
+    fprintf(fid_cpp, '/*********************************************************/\n');
+    fprintf(fid_cpp, '/* Filter taps for %-6i Hz sample rate                 */\n', fs);
+    fprintf(fid_cpp, '/* Low pass prototype for Hilbert-filter 5 kHz bandwidth */\n');
+    fprintf(fid_cpp, 'const float fHilLPProt5_%i[NUM_TAPS_HILB_FILT_5_%i] =\n', f, f);
+    fprintf(fid_cpp, '{\n');
+    fprintf(fid_cpp, '	%.18ef,\n', b5(1:end - 1));
+    fprintf(fid_cpp, '	%.18ef\n', b5(end));
+    fprintf(fid_cpp, '};\n');
+    fprintf(fid_cpp, '/* Low pass prototype for Hilbert-filter 10 kHz bandwidth */\n');
+    fprintf(fid_cpp, 'const float fHilLPProt10_%i[NUM_TAPS_HILB_FILT_10_%i] =\n', f, f);
+    fprintf(fid_cpp, '{\n');
+    fprintf(fid_cpp, '	%.18ef,\n', b10(1:end - 1));
+    fprintf(fid_cpp, '	%.18ef\n', b10(end));
+    fprintf(fid_cpp, '};\n');
+    fprintf(fid_cpp, '\n');
+endfunction
+
+
+fid_cpp = fopen('TimeSyncFilter.cpp', 'w');
+fprintf(fid_cpp, '/* Automatically generated file with GNU Octave */\n');
+fprintf(fid_cpp, '\n');
+fprintf(fid_cpp, '/* File name: "TimeSyncFilter.octave" */\n');
+fprintf(fid_cpp, '/* Filter taps in time-domain */\n');
+fprintf(fid_cpp, '\n');
+fprintf(fid_cpp, '#include "TimeSyncFilter.h"\n');
+fprintf(fid_cpp, '\n');
+
+fid_h = fopen('TimeSyncFilter.h', 'w');
+fprintf(fid_h, '/* Automatically generated file with GNU Octave */\n');
+fprintf(fid_h, '/* File name: "TimeSyncFilter.octave" */\n');
+fprintf(fid_h, '/* Filter taps in time-domain */\n');
+fprintf(fid_h, '\n');
+fprintf(fid_h, '#ifndef _TIMESYNCFILTER_H_\n');
+fprintf(fid_h, '#define _TIMESYNCFILTER_H_\n');
+fprintf(fid_h, '\n');
+fprintf(fid_h, '/* Filter bandwidths */\n');
+fprintf(fid_h, '#define HILB_FILT_BNDWIDTH_5            %i\n', fstop5 - fstart5 + ftrans5);
+fprintf(fid_h, '#define HILB_FILT_BNDWIDTH_10           %i\n', fstop10 - fstart10 + ftrans10);
+fprintf(fid_h, '\n');
+
+MakeFilter(fid_cpp, fid_h, 0.5); % 24000 kHz
+MakeFilter(fid_cpp, fid_h, 1);   % 48000 kHz
+MakeFilter(fid_cpp, fid_h, 2);   % 96000 kHz
+MakeFilter(fid_cpp, fid_h, 4);   % 192000 kHz
+MakeFilter(fid_cpp, fid_h, 8);   % 384000 kHz
+
+fprintf(fid_h, '#endif	/* _TIMESYNCFILTER_H_ */\n');
+
+fclose(fid_h);
+fclose(fid_cpp);
diff --git a/src/sync/TimeSyncTrack.cpp b/src/sync/TimeSyncTrack.cpp
new file mode 100644
index 0000000..57d98df
--- /dev/null
+++ b/src/sync/TimeSyncTrack.cpp
@@ -0,0 +1,759 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *	Time synchronization tracking using information of scattered pilots
+ *
+ *	Algorithm proposed by Baoguo Yang in "Timing Recovery for OFDM
+ *	Transmission", IEEE November 2000
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "TimeSyncTrack.h"
+
+
+/* Implementation *************************************************************/
+void CTimeSyncTrack::Process(CParameter& Parameters,
+		 CComplexVector& veccChanEst, int iNewTiCorr,
+		 _REAL& rLenPDS, _REAL& rOffsPDS)
+{
+	int			i, j;
+	int			iIntShiftVal;
+	int			iFirstPathDelay = 0;
+	CReal		rPeakBound;
+	CReal		rCurEnergy;
+	CReal		rWinEnergy;
+	CReal		rMaxWinEnergy;
+	_BOOLEAN	bDelayFound = FALSE;
+	_BOOLEAN	bPDSResultFound;
+
+	/* Rotate the averaged PDP to follow the time shifts -------------------- */
+	/* Update timing correction history (shift register) */
+	vecTiCorrHist.AddEnd(iNewTiCorr);
+
+	/* Calculate the actual shift of the timing correction. Since we do the
+	   timing correction at the sound card sample rate (48 kHz) and the
+	   estimated impulse response has a different sample rate (since the
+	   spectrum is only one little part of the sound card frequency range)
+	   we have to correct the timing correction by a certain bandwidth factor */
+	const CReal rActShiftTiCor = rFracPartTiCor -
+		(_REAL) vecTiCorrHist[0] * iNumCarrier / iDFTSize;
+
+	/* Integer part of shift */
+	const int iIntPartTiCorr = (int) Round(rActShiftTiCor);
+
+	/* Extract the fractional part since we can only correct integer timing
+	   shifts */
+	rFracPartTiCor = rActShiftTiCor - iIntPartTiCorr;
+
+	/* Shift the values in the vector storing the averaged impulse response. We
+	   have to consider two cases for shifting (left and right shift) */
+	if (rActShiftTiCor < 0)
+		iIntShiftVal = iIntPartTiCorr + iNumIntpFreqPil;
+	else
+		iIntShiftVal = iIntPartTiCorr;
+
+	/* OPH: copy latest impulse response into old impulse response store
+	   (for rdop calculation) */
+	veccOldImpulseResponse = veccPilots;
+
+	/* If new correction is out of range, do not apply rotation */
+	if ((iIntShiftVal > 0) && (iIntShiftVal < iNumIntpFreqPil))
+	{
+		/* Actual rotation of vector */
+		vecrAvPoDeSp.Merge(vecrAvPoDeSp(iIntShiftVal + 1, iNumIntpFreqPil),
+			vecrAvPoDeSp(1, iIntShiftVal));
+
+		/* OPH: rotate old impulse response vector */
+		veccOldImpulseResponse.Merge(veccOldImpulseResponse(iIntShiftVal + 1,
+			iNumIntpFreqPil), veccOldImpulseResponse(1, iIntShiftVal));
+	}
+
+
+	/* New estimate for impulse response ------------------------------------ */
+	/* Apply hamming window, Eq (15) */
+	veccPilots = veccChanEst * vecrHammingWindow;
+
+	/* Transform in time-domain to get an estimate for the delay power profile,
+	   Eq (15) */
+	veccPilots = Ifft(veccPilots, FftPlan);
+
+	/* Average result, Eq (16) (Should be a moving average function, for
+	   simplicity we have chosen an IIR filter here) */
+	IIR1(vecrAvPoDeSp, SqMag(veccPilots), rLamAvPDS);
+
+	/* Rotate the averaged result vector to put the earlier peaks
+	   (which can also detected in a certain amount) at the beginning of
+	   the vector */
+	vecrAvPoDeSpRot.Merge(vecrAvPoDeSp(iStPoRot, iNumIntpFreqPil),
+		vecrAvPoDeSp(1, iStPoRot - 1));
+
+
+	/* Different timing algorithms ------------------------------------------ */
+	switch (TypeTiSyncTrac)
+	{
+	case TSFIRSTPEAK:
+		/* Detect first peak algorithm proposed by Baoguo Yang */
+		/* Lower and higher bound */
+		rBoundHigher = Max(vecrAvPoDeSpRot) * rConst1;
+		rBoundLower = Min(vecrAvPoDeSpRot) * rConst2;
+
+		/* Calculate the peak bound, Eq (19) */
+		rPeakBound = Max(rBoundHigher, rBoundLower);
+
+		/* Get final estimate, Eq (18) */
+		for (i = 0; i < iNumIntpFreqPil - 1; i++)
+		{
+			/* We are only interested in the first peak */
+			if (bDelayFound == FALSE)
+			{
+				if ((vecrAvPoDeSpRot[i] > vecrAvPoDeSpRot[i + 1]) &&
+					(vecrAvPoDeSpRot[i] > rPeakBound))
+				{
+					/* The first peak was found, store index */
+					iFirstPathDelay = i;
+
+					/* Set the flag */
+					bDelayFound = TRUE;
+				}
+			}
+		}
+		break;
+
+	case TSENERGY:
+		/* Determin position of window with maximum energy in guard-interval.
+		   A window with the size of the guard-interval is moved over the entire
+		   profile and the energy inside this window is calculated. The window
+		   position which maximises this energy is taken as the new timing
+		   position */
+		rMaxWinEnergy = (CReal) 0.0;
+		for (i = 0; i < iNumIntpFreqPil - 1 - rGuardSizeFFT; i++)
+		{
+			rWinEnergy = (CReal) 0.0;
+
+			/* Energy IN the guard-interval */
+			for (j = 0; j < rGuardSizeFFT; j++)
+				rWinEnergy += vecrAvPoDeSpRot[i + j];
+
+			/* Get maximum */
+			if (rWinEnergy > rMaxWinEnergy)
+			{
+				rMaxWinEnergy = rWinEnergy;
+				iFirstPathDelay = i;
+			}
+		}
+
+		/* We always have a valid measurement, set flag */
+		bDelayFound = TRUE;
+		break;
+	}
+
+
+	/* Only apply timing correction if search was successful and tracking is
+	   activated */
+	if ((bDelayFound == TRUE) && (bTiSyncTracking == TRUE))
+	{
+		CReal rPropGain = 0.0; /* quiet compiler */
+		/* Consider the rotation introduced for earlier peaks in path delay.
+		   Since the "iStPoRot" is the position of the beginning of the block
+		   at the end for cutting out, "iNumIntpFreqPil" must be substracted.
+		   (Actually, a part of the following line should be look like this:
+		   "iStPoRot - 1 - iNumIntpFreqPil + 1" but the "- 1 + 1" compensate
+		   each other) */
+		iFirstPathDelay += iStPoRot - iNumIntpFreqPil - iTargetTimingPos - 1;
+
+
+		/* Correct timing offset -------------------------------------------- */
+		/* Final offset is target position in comparision to the estimated first
+		   path delay. Since we have a delay from the channel estimation, the
+		   previous correction is subtracted "- vecrNewMeasHist[0]". If the
+		   "real" correction arrives after the delay, this correction is
+		   compensated. The length of the history buffer (vecrNewMeasHist) must
+		   be equal to the delay of the channel estimation.
+		   The corrections must be quantized to the upsampled output sample
+		   rate ("* iDFTSize / iNumCarrier") */
+		const CReal rTiOffset = (CReal) -iFirstPathDelay *
+			iDFTSize / iNumCarrier - veciNewMeasHist[0];
+
+		/* Different controlling parameters for different types of tracking */
+		switch (TypeTiSyncTrac)
+		{
+		case TSFIRSTPEAK:
+			/* Adapt the linear control parameter to the region, where the peak
+			   was found. The region left of the desired timing position is
+			   critical, because we immediately get ISI if a peak appers here.
+			   Therefore we apply fast correction here. At the other positions,
+			   we smooth the controlling to improve the immunity against false
+			   peaks */
+			if (rTiOffset > 0)
+				rPropGain = CONT_PROP_BEFORE_GUARD_INT;
+			else
+				rPropGain = CONT_PROP_IN_GUARD_INT;
+			break;
+
+		case TSENERGY:
+			rPropGain = CONT_PROP_ENERGY_METHOD;
+			break;
+		}
+
+		/* In case of sample rate offset acquisition phase, use faster timing
+		   corrections */
+		if (bSamRaOffsAcqu == TRUE)
+			rPropGain *= 2;
+
+		/* Apply proportional control and fix result to sample grid */
+		const CReal rCurCorrValue = rTiOffset * rPropGain + rFracPartContr;
+		const int iContrTiOffs = (int) Fix(rCurCorrValue);
+
+		/* Calculate new fractional part of controlling */
+		rFracPartContr = rCurCorrValue - iContrTiOffs;
+
+		/* Manage correction history */
+		veciNewMeasHist.AddEnd(0);
+		for (i = 0; i < iSymDelay - 1; i++)
+			veciNewMeasHist[i] += iContrTiOffs;
+
+		/* Apply correction */
+		Parameters.iTimingOffsTrack = -iContrTiOffs;
+	}
+
+
+	/* Sample rate offset estimation ---------------------------------------- */
+	/* This sample rate offset estimation is based on the movement of the
+	   estimated PDS with time. The movement per symbol (or a number of symbols)
+	   is proportional to the sample rate offset. It has to be considered the
+	   PDS shiftings of the timing correction unit ("rActShiftTiCor" can be used
+	   for that). The procedere is to detect the maximum peak in the PDS and use
+	   this as a reference, assuming tha delay of this peak is not changing. The
+	   problem is when another peak get higher than this due to fading. In this
+	   case we must adjust the history to this new peak (the new reference) */
+	int		iMaxInd;
+	CReal	rMax;
+
+	/* Find index of maximum peak in PDS estimation. This is our reference
+	   for this estimation method */
+	Max(rMax, iMaxInd, vecrAvPoDeSpRot);
+
+	/* Integration of timing corrections
+	   FIXME: Check for overrun of "iIntegTiCorrections" variable! */
+	iIntegTiCorrections += (long int) iIntPartTiCorr;
+
+	/* We need to consider the timing corrections done by the timing unit. What
+	   we want to estimate is only the real movement of the detected maximum
+	   peak */
+	const int iCurRes = iIntegTiCorrections + iMaxInd;
+	veciSRTiCorrHist.AddEnd(iCurRes);
+
+	/* We assumed that the detected peak is always the same peak in the actual
+	   PDS. But due to fading the maximum can change to a different peak. In
+	   this case the estimation would be wrong. We try to detect the detection
+	   of a different peak by defining a maximum sample rate change. The sample
+	   rate offset is very likely to be very constant since usually crystal
+	   oscialltors are used. Thus, if a larger change of sample rate offset
+	   happens, we assume that the maximum peak has changed */
+	const int iNewDiff = veciSRTiCorrHist[iLenCorrectionHist - 2] - iCurRes;
+
+	/* If change is larger than 2, it is most likely that a new peak was chosen
+	   by the maximum function. Also, if the sign has changed of the difference
+	   (and it is not zero), we also say that a new peak was selected */
+	if ((abs(iNewDiff) > 2) ||
+		((Sign(iOldNonZeroDiff) != Sign(iNewDiff)) && (iNewDiff != 0)))
+	{
+		/* Correct the complete history to the new reference peak. Reference
+		   peak was already added, therefore do not use last element */
+		for (i = 0; i < iLenCorrectionHist - 1; i++)
+			veciSRTiCorrHist[i] -= iNewDiff;
+	}
+
+	/* Store old difference if it is not zero */
+	if (iNewDiff != 0)
+		iOldNonZeroDiff = iNewDiff;
+
+
+	/* Check, if we are in acquisition phase */
+	if (iResOffsetAcquCnt > 0)
+	{
+		/* Acquisition phase */
+		iResOffsetAcquCnt--;
+	}
+	else
+	{
+		/* Apply the result from acquisition only once */
+		if (bSamRaOffsAcqu == TRUE)
+		{
+			/* End of acquisition phase */
+			bSamRaOffsAcqu = FALSE;
+
+			/* Set sample rate offset to initial estimate. We consider the
+			   initialization phase of channel estimation by "iSymDelay" */
+			CReal rInitSamOffset = GetSamOffHz(iCurRes - veciSRTiCorrHist[
+				iLenCorrectionHist - (iResOffAcqCntMax - iSymDelay)],
+				iResOffAcqCntMax - iSymDelay - 1, Parameters.GetSigSampleRate());
+
+#ifndef USE_SAMOFFS_TRACK_FRE_PIL
+			/* Apply initial sample rate offset estimation */
+			Parameters.rResampleOffset -= rInitSamOffset;
+#endif
+
+			/* Reset estimation history (init with zeros) since the sample
+			   rate offset was changed */
+			veciSRTiCorrHist.Init(iLenCorrectionHist, 0);
+			iIntegTiCorrections = 0;
+		}
+		else
+		{
+			/* Tracking phase */
+			/* Get actual sample rate offset in Hertz */
+			const CReal rSamOffset = GetSamOffHz(iCurRes - veciSRTiCorrHist[0],
+				iLenCorrectionHist - 1, Parameters.GetSigSampleRate());
+
+#ifndef USE_SAMOFFS_TRACK_FRE_PIL
+			/* Apply result from sample rate offset estimation */
+			Parameters.rResampleOffset -= CONTR_SAMP_OFF_INT_FTI * rSamOffset;
+#endif
+		}
+	}
+
+
+	/* Delay spread length estimation --------------------------------------- */
+	/* Estimate the noise energy using the minimum statistic. We assume that
+	   the noise variance is equal on all samples of the impulse response.
+	   Therefore we subtract the variance on each sample. The total estimated
+	   signal energy is the total energy minus the noise energy */
+	/* Calculate total energy */
+	const CReal rTotEgy = Sum(vecrAvPoDeSpRot);
+
+	/* Sort the values of the PDS to get the smallest values */
+	CRealVector rSortAvPoDeSpRot(Sort(vecrAvPoDeSpRot));
+
+	/* Average the result of smallest values and overestimate result */
+	const CReal rSigmaNoise =
+		Sum(rSortAvPoDeSpRot(1, NUM_SAM_IR_FOR_MIN_STAT - 1)) /
+		NUM_SAM_IR_FOR_MIN_STAT * OVER_EST_FACT_MIN_STAT;
+
+	/* Calculate signal energy by subtracting the noise energy from total
+	   energy (energy cannot by negative -> bound at zero) */
+	const CReal rSigEnergyBound =
+		Max(rTotEgy - rSigmaNoise * iNumIntpFreqPil, (CReal) 0.0);
+
+	/* From left to the right -> search for end of PDS */
+	rEstPDSEnd = (CReal) (iNumIntpFreqPil - 1);
+	rCurEnergy = (CReal) 0.0;
+	bPDSResultFound = FALSE;
+	for (i = 0; i < iNumIntpFreqPil; i++)
+	{
+		if (bPDSResultFound == FALSE)
+		{
+			if (rCurEnergy > rSigEnergyBound)
+			{
+				/* Delay index */
+				rEstPDSEnd = (CReal) i;
+
+				bPDSResultFound = TRUE;
+			}
+
+			/* Accumulate signal energy, subtract noise on each sample */
+			rCurEnergy += vecrAvPoDeSpRot[i] - rSigmaNoise;
+		}
+	}
+
+	/* From right to the left -> search for beginning of PDS */
+	rEstPDSBegin = (CReal) 0.0;
+	rCurEnergy = (CReal) 0.0;
+	bPDSResultFound = FALSE;
+	for (i = iNumIntpFreqPil - 1; i >= 0; i--)
+	{
+		if (bPDSResultFound == FALSE)
+		{
+			if (rCurEnergy > rSigEnergyBound)
+			{
+				/* Delay index */
+				rEstPDSBegin = (CReal) i;
+
+				bPDSResultFound = TRUE;
+			}
+
+			/* Accumulate signal energy, subtract noise on each sample */
+			rCurEnergy += vecrAvPoDeSpRot[i] - rSigmaNoise;
+		}
+	}
+
+	/* If the signal energy is too low it can happen that the estimated
+	   beginning of the impulse response is before the end -> correct */
+	if (rEstPDSBegin > rEstPDSEnd)
+	{
+		/* Set beginning and end to their maximum (minimum) value */
+		rEstPDSBegin = (CReal) 0.0;
+		rEstPDSEnd = (CReal) (iNumIntpFreqPil - 1);
+	}
+
+	/* Correct estimates of begin and end of PDS by the rotation */
+	const CReal rPDSLenCorrection = iNumIntpFreqPil - iStPoRot + 1;
+	rEstPDSBegin -= rPDSLenCorrection;
+	rEstPDSEnd -= rPDSLenCorrection;
+
+
+	/* write PIR estimate into parameter struct for RSI output - use the function provided for plotting */
+	CVector<_REAL> vecrScale;
+	_REAL rLowerBound=0, rHigherBound=0, rStartGuard=0, rEndGuard=0, rPDSBegin=0, rPDSEnd=0;
+
+	//Parameters.Lock();
+	GetAvPoDeSp(Parameters.vecrPIR, vecrScale, rLowerBound, rHigherBound, rStartGuard, rEndGuard, rPDSBegin, rPDSEnd, Parameters.GetSigSampleRate());
+	Parameters.rPIRStart = vecrScale[0];
+	Parameters.rPIREnd = vecrScale[vecrScale.Size()-1];
+	//Parameters.Unlock();
+
+
+	/* Set return parameters */
+	rLenPDS = rEstPDSEnd - rEstPDSBegin;
+	rOffsPDS = rEstPDSBegin;
+}
+
+void CTimeSyncTrack::Init(CParameter& Parameters, int iNewSymbDelay)
+{
+	iNumCarrier = Parameters.CellMappingTable.iNumCarrier;
+	iScatPilFreqInt = Parameters.CellMappingTable.iScatPilFreqInt;
+	iNumIntpFreqPil = Parameters.CellMappingTable.iNumIntpFreqPil;
+	iDFTSize = Parameters.CellMappingTable.iFFTSizeN;
+
+	/* Timing correction history */
+	iSymDelay = iNewSymbDelay;
+	vecTiCorrHist.Init(iSymDelay, 0);
+
+	/* History for new measurements (corrections) */
+	veciNewMeasHist.Init(iSymDelay - 1, 0);
+
+	/* Init vector for received data at pilot positions */
+	veccPilots.Init(iNumIntpFreqPil);
+
+	/* Vector for averaged power delay spread estimation */
+	vecrAvPoDeSp.Init(iNumIntpFreqPil, (CReal) 0.0);
+
+	/* Lambda for IIR filter for averaging the PDS */
+	rLamAvPDS = IIR1Lam(TICONST_PDS_EST_TISYNC, (CReal) Parameters.GetSigSampleRate() /
+		Parameters.CellMappingTable.iSymbolBlockSize);
+
+	/* Vector for rotated result */
+	vecrAvPoDeSpRot.Init(iNumIntpFreqPil);
+
+	/* Length of guard-interval with respect to FFT-size! */
+	rGuardSizeFFT = (CReal) iNumCarrier *
+		Parameters.CellMappingTable.RatioTgTu.iEnum / Parameters.CellMappingTable.RatioTgTu.iDenom;
+
+	/* Get the hamming window taps. The window is to reduce the leakage effect
+	   of a DFT transformation */
+	vecrHammingWindow.Init(iNumIntpFreqPil);
+	vecrHammingWindow = Hamming(iNumIntpFreqPil);
+
+	/* Weights for peak bound calculation, in Eq. (19), special values for
+	   robustness mode D! */
+	if (Parameters.GetWaveMode() == RM_ROBUSTNESS_MODE_D)
+	{
+		rConst1 = pow((_REAL) 10.0, (_REAL) -TETA1_DIST_FROM_MAX_DB_RMD / 10);
+		rConst2 = pow((_REAL) 10.0, (_REAL) TETA2_DIST_FROM_MIN_DB_RMD / 10);
+	}
+	else
+	{
+		rConst1 = pow((_REAL) 10.0, (_REAL) -TETA1_DIST_FROM_MAX_DB / 10);
+		rConst2 = pow((_REAL) 10.0, (_REAL) TETA2_DIST_FROM_MIN_DB / 10);
+	}
+
+	/* Define start point for rotation of detection vector for acausal taps.
+	   Per definition is this point somewhere in the region after the
+	   actual guard-interval window */
+	if ((int) rGuardSizeFFT > iNumIntpFreqPil)
+		iStPoRot = iNumIntpFreqPil;
+	else
+	{
+		/* "+ 1" because of "Matlab indices" used in ".Merge()" function */
+		iStPoRot = (int) (rGuardSizeFFT +
+			Ceil((iNumIntpFreqPil - rGuardSizeFFT) / 2) + 1);
+	}
+
+	/* Init fractional part of timing correction to zero and fractional part
+	   of controlling */
+	rFracPartTiCor = (CReal) 0.0;
+	rFracPartContr = (CReal) 0.0;
+
+	/* Inits for the time synchronization tracking type */
+	SetTiSyncTracType(TypeTiSyncTrac);
+
+	/* Init begin and end of PDS estimation with zero and the length of guard-
+	   interval respectively */
+	rEstPDSBegin = (CReal) 0.0;
+	rEstPDSEnd = rGuardSizeFFT;
+
+	/* Init plans for FFT (faster processing of Fft and Ifft commands) */
+	FftPlan.Init(iNumIntpFreqPil);
+
+
+	/* Inits for sample rate offset estimation ------------------------------ */
+	/* Calculate number of symbols for a given time span as defined for the
+	   length of the sample rate offset estimation history size */
+	iLenCorrectionHist = (int) ((_REAL) Parameters.GetSigSampleRate() *
+		HIST_LEN_SAM_OFF_EST_TI_CORR / Parameters.CellMappingTable.iSymbolBlockSize);
+
+	/* Init count for acquisition */
+	iResOffAcqCntMax = (int) ((_REAL) Parameters.GetSigSampleRate() *
+		SAM_OFF_EST_TI_CORR_ACQ_LEN / Parameters.CellMappingTable.iSymbolBlockSize);
+
+	/* Init sample rate offset estimation acquisition count */
+	iResOffsetAcquCnt = iResOffAcqCntMax;
+
+	veciSRTiCorrHist.Init(iLenCorrectionHist, 0); /* Init with zeros */
+	iIntegTiCorrections = 0;
+
+	/* Symbol block size converted in domain of estimated PDS */
+	rSymBloSiIRDomain =
+		(CReal) Parameters.CellMappingTable.iSymbolBlockSize * iNumCarrier / iDFTSize;
+
+	/* Init variable for storing the old difference of maximum position */
+	iOldNonZeroDiff = 0;
+
+	/* (O.Haffenden) Vector for power delay spread estimation for previous
+	   symbol (used for RSCI rdop calculation) */
+	veccOldImpulseResponse.Init(iNumIntpFreqPil, (CReal) 0.0);
+	vecrRdelThresholds.Init(3);
+	vecrRdelThresholds[0] = (CReal) 90.0;
+	vecrRdelThresholds[1] = (CReal) 95.0;
+	vecrRdelThresholds[2] = (CReal) 99.0;
+	vecrRdelIntervals.Init(3);
+}
+
+CReal CTimeSyncTrack::GetSamOffHz(int iDiff, int iLen, int iSampleRate)
+{
+	/* Calculate actual sample rate offset in Hertz */
+	const CReal rCurSampOffsNorm = (CReal) iDiff / iLen / rSymBloSiIRDomain;
+
+	return (CReal) iSampleRate * ((CReal) 1.0 - (CReal) 1.0 / ((CReal) 1.0 + rCurSampOffsNorm));
+}
+
+void CTimeSyncTrack::SetTiSyncTracType(ETypeTiSyncTrac eNewTy)
+{
+	TypeTiSyncTrac = eNewTy;
+
+	switch (TypeTiSyncTrac)
+	{
+	case TSFIRSTPEAK:
+		/* Define target position for first path. Should be close to zero but
+		   not exactely zero because even small estimation errors would lead to
+		   ISI. The target timing position must be at least 2 samples away from
+		   the guard-interval border */
+		iTargetTimingPos = (int) (rGuardSizeFFT / TARGET_TI_POS_FRAC_GUARD_INT);
+		if (iTargetTimingPos < 2)
+			iTargetTimingPos = 2;
+		break;
+
+	case TSENERGY:
+		/* No target timing position needed */
+		iTargetTimingPos = 0;
+		break;
+	}
+}
+
+void CTimeSyncTrack::GetAvPoDeSp(CVector<_REAL>& vecrData,
+								 CVector<_REAL>& vecrScale,
+								_REAL& rLowerBound, _REAL& rHigherBound,
+								_REAL& rStartGuard, _REAL& rEndGuard,
+								_REAL& rPDSBegin, _REAL& rPDSEnd, int iSampleRate)
+{
+	int		i;
+	int		iHalfSpec;
+	_REAL	rScaleIncr;
+	_REAL	rScaleAbs;
+
+	/* Init output vectors */
+	vecrData.Init(iNumIntpFreqPil, (_REAL) 0.0);
+	vecrScale.Init(iNumIntpFreqPil, (_REAL) 0.0);
+	rHigherBound = (_REAL) 0.0;
+	rLowerBound = (_REAL) 0.0;
+	rStartGuard = (_REAL) 0.0;
+	rEndGuard = (_REAL) 0.0;
+	rPDSBegin = (_REAL) 0.0;
+	rPDSEnd = (_REAL) 0.0;
+
+	/* Do copying of data only if vector is of non-zero length which means that
+	   the module was already initialized */
+	if (iNumIntpFreqPil != 0)
+	{
+		/* With this setting we only define the position of the guard-interval
+		   in the plot. With this setting we position it centered */
+		iHalfSpec = (int) ((iNumIntpFreqPil - rGuardSizeFFT) / 2);
+
+		/* Init scale (in "ms") */
+		rScaleIncr = (_REAL) iDFTSize /
+			(iSampleRate * iNumIntpFreqPil) * 1000 / iScatPilFreqInt;
+
+		/* Let the target timing position be the "0" time */
+		rScaleAbs = -(iHalfSpec + iTargetTimingPos) * rScaleIncr;
+
+		/* Copy first part of data in output vector */
+		for (i = 0; i < iHalfSpec; i++)
+		{
+			const _REAL rCurPDSVal =
+				vecrAvPoDeSp[iNumIntpFreqPil - iHalfSpec + i];
+
+			if (rCurPDSVal > 0)
+				vecrData[i] = (_REAL) 10.0 * log10(rCurPDSVal);
+			else
+				vecrData[i] = RET_VAL_LOG_0;
+
+			/* Scale */
+			vecrScale[i] = rScaleAbs;
+			rScaleAbs += rScaleIncr;
+		}
+
+		/* Save scale point because this is the start point of guard-interval */
+		rStartGuard = rScaleAbs;
+
+		/* Copy second part of data in output vector */
+		for (i = iHalfSpec; i < iNumIntpFreqPil; i++)
+		{
+			const _REAL rCurPDSVal = vecrAvPoDeSp[i - iHalfSpec];
+
+			if (rCurPDSVal > 0)
+				vecrData[i] = (_REAL) 10.0 * log10(rCurPDSVal);
+			else
+				vecrData[i] = RET_VAL_LOG_0;
+
+			/* Scale */
+			vecrScale[i] = rScaleAbs;
+			rScaleAbs += rScaleIncr;
+		}
+
+		/* Return bounds */
+		switch (TypeTiSyncTrac)
+		{
+		case TSFIRSTPEAK:
+			if (rBoundHigher > 0)
+				rHigherBound = (_REAL) 10.0 * log10(rBoundHigher);
+			else
+				rHigherBound = RET_VAL_LOG_0;
+
+			if (rBoundLower > 0)
+				rLowerBound = (_REAL) 10.0 * log10(rBoundLower);
+			else
+				rLowerBound = RET_VAL_LOG_0;
+			break;
+
+		case TSENERGY:
+			/* No bounds needed for energy type, set both values to "defined
+			   infinity value", so it does not show up in the plot */
+			rHigherBound = RET_VAL_LOG_0;
+			rLowerBound = RET_VAL_LOG_0;
+			break;
+		}
+
+		/* End point of guard interval */
+		rEndGuard = rScaleIncr * (rGuardSizeFFT - iTargetTimingPos);
+
+		/* Estmiated begin and end of estimated PDS */
+		rPDSBegin = rScaleIncr * (rEstPDSBegin - iTargetTimingPos);
+		rPDSEnd = rScaleIncr * (rEstPDSEnd - iTargetTimingPos);
+	}
+}
+
+/* OPH: Calculate the delay according to the rdel tag of RSCI */
+void CTimeSyncTrack::CalculateRdel(CParameter& Parameters)
+{
+	/* Define the intervals in ascending order of threshold percentage */
+	CReal rTotEgy = Sum(vecrAvPoDeSpRot);
+
+	CReal rIntervalAccum= (CReal) 0.0; 
+	const int ciNumDelayIntervals = vecrRdelThresholds.GetSize();
+	CRealVector vecrIntervalStart, vecrIntervalEnd;
+	vecrRdelIntervals.Init(ciNumDelayIntervals);
+	vecrIntervalStart.Init(ciNumDelayIntervals);
+	vecrIntervalEnd.Init(ciNumDelayIntervals);
+
+	int i = 0;
+	int j;
+
+	for (j = ciNumDelayIntervals - 1; j >= 0; j--)
+	{
+		CReal rIntervalThresh = rTotEgy *
+			((CReal) 1.0 - (vecrRdelThresholds[j] / (CReal) 100.0)) *
+			(CReal) 0.5;
+
+		for (; rIntervalAccum < rIntervalThresh && i < iNumIntpFreqPil; i++)
+		{
+			rIntervalAccum += vecrAvPoDeSpRot[i];
+		}
+		vecrIntervalStart[j] = i;
+	}
+
+	i = iNumIntpFreqPil - 1;
+	rIntervalAccum = (CReal) 0.0;
+
+	for (j = ciNumDelayIntervals - 1; j >= 0; j--)
+	{
+		_REAL rIntervalThresh = rTotEgy *
+			((CReal) 1.0 - (vecrRdelThresholds[j] / (CReal) 100.0)) *
+			(CReal) 0.5;
+
+		for (; rIntervalAccum < rIntervalThresh && i >= 0; i--)
+		{
+			rIntervalAccum += vecrAvPoDeSpRot[i];
+		}
+		vecrIntervalEnd[j] = i;
+	}
+
+	for (j = 0; j < ciNumDelayIntervals; j++)
+	{
+		CReal rInterval =
+			((_REAL) (vecrIntervalEnd[j] - vecrIntervalStart[j])) *
+			Parameters.CellMappingTable.iFFTSizeN / (Parameters.GetSigSampleRate() *
+			Parameters.CellMappingTable.iNumIntpFreqPil * Parameters.CellMappingTable.iScatPilFreqInt) * 1000;
+
+		/* Clip the delay interval values for display purposes */
+		if (rInterval < (CReal) -9.9)
+			rInterval = (CReal) -9.9;
+
+		if (rInterval > (CReal) 9.9)
+			rInterval = (CReal) 9.9;
+
+		vecrRdelIntervals[j] = rInterval;
+	}
+
+	Parameters.vecrRdelThresholds = vecrRdelThresholds;
+	Parameters.vecrRdelIntervals = vecrRdelIntervals;
+}
+
+void CTimeSyncTrack::CalculateRdop(CParameter& Parameters)
+{
+	/* Initialise accumulators for sum of squares and sum of squared
+	   differences */
+	CReal rSumSqDiff = (CReal) 0.0;
+	CReal rSumSqChan = (CReal) 0.0;
+
+	/* Now do the calculation */
+	for (int i = 0; i < veccPilots.GetSize(); i++)
+	{
+		rSumSqDiff += SqMag(veccPilots[i] - veccOldImpulseResponse[i]);
+		rSumSqChan += SqMag(veccPilots[i]);
+	}
+
+	CReal rTs = (_REAL) Parameters.CellMappingTable.iSymbolBlockSize / Parameters.GetSigSampleRate();
+
+	Parameters.rRdop = Sqrt(rSumSqDiff / rSumSqChan) / (crPi * rTs);
+}
diff --git a/src/sync/TimeSyncTrack.h b/src/sync/TimeSyncTrack.h
new file mode 100644
index 0000000..91a185e
--- /dev/null
+++ b/src/sync/TimeSyncTrack.h
@@ -0,0 +1,167 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *	See TimeSyncTrack.cpp
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later 
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT 
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#if !defined(TIMESYNCTRACK_H__3B0BA6346234634554344_BBE7A0D31912__INCLUDED_)
+#define TIMESYNCTRACK_H__3B0BA6346234634554344_BBE7A0D31912__INCLUDED_
+
+#include "../GlobalDefinitions.h"
+#include "../Parameter.h"
+#include "../util/Vector.h"
+#include "../matlib/Matlib.h"
+
+
+/* Definitions ****************************************************************/
+/* Define target position for first path in guard-interval. The number defines
+   the fraction of the guard-interval */
+#define TARGET_TI_POS_FRAC_GUARD_INT		9
+
+/* Weights for bound calculation. First parameter is for peak distance and 
+   second for distance from minimum value */
+#define TETA1_DIST_FROM_MAX_DB				20
+#define TETA2_DIST_FROM_MIN_DB				23
+#define TETA1_DIST_FROM_MAX_DB_RMD			20 /* Robustness mode D */
+#define TETA2_DIST_FROM_MIN_DB_RMD			15 /* Robustness mode D */
+
+/* Control parameters */
+#define CONT_PROP_IN_GUARD_INT				((_REAL) 0.06)
+#define CONT_PROP_BEFORE_GUARD_INT			((_REAL) 0.08)
+#define CONT_PROP_ENERGY_METHOD				((_REAL) 0.02)
+
+/* Time constant for IIR averaging of PDS estimation */
+#define TICONST_PDS_EST_TISYNC				((CReal) 0.25) /* sec */
+
+/* Minimum statistic used for estimation of the noise variance where the samples
+   with the lowest energy are taken as an estimate for the noise. Since the
+   actual energy is most certainly higher than the minimum, we need to
+   overestimate the result. Specify the number of samples for minimum search
+   and the overestimation factor */
+#define NUM_SAM_IR_FOR_MIN_STAT				10
+#define OVER_EST_FACT_MIN_STAT				((CReal) 4.0)
+
+/* Parameter of controlling the closed loop for sample rate offset */
+#define CONTR_SAMP_OFF_INT_FTI				((_REAL) 0.001)
+
+/* Length of history for sample rate offset estimation using time corrections
+   in seconds */
+#define HIST_LEN_SAM_OFF_EST_TI_CORR		((CReal) 30.0) /* sec */
+
+/* Length of history used for sample rate offset acquisition estimate */
+#define SAM_OFF_EST_TI_CORR_ACQ_LEN			((CReal) 4.0) /* sec */
+
+
+/* Classes ********************************************************************/
+class CTimeSyncTrack
+{
+public:
+	CTimeSyncTrack() : bTiSyncTracking(FALSE), 
+		bSamRaOffsAcqu(TRUE), TypeTiSyncTrac(TSENERGY) {}
+	virtual ~CTimeSyncTrack() {}
+
+	enum ETypeTiSyncTrac {TSENERGY, TSFIRSTPEAK};
+
+	void Init(CParameter& Parameter, int iNewSymbDelay);
+
+	void Process(CParameter& Parameter, CComplexVector& veccChanEst,
+				 int iNewTiCorr, _REAL& rLenPDS, _REAL& rOffsPDS);
+
+	void GetAvPoDeSp(CVector<_REAL>& vecrData, CVector<_REAL>& vecrScale, 
+					 _REAL& rLowerBound, _REAL& rHigherBound,
+					 _REAL& rStartGuard, _REAL& rEndGuard, _REAL& rPDSBegin,
+					 _REAL& rPDSEnd, int iSampleRate);
+
+	void StartTracking() {bTiSyncTracking = TRUE;}
+	void StopTracking() {bTiSyncTracking = FALSE;}
+
+	 /* SetInitFlag() is needed for this function. Is done in channel estimation
+	    module */
+	void StartSaRaOffAcq() {bSamRaOffsAcqu = TRUE;}
+
+	void SetTiSyncTracType(ETypeTiSyncTrac eNewTy);
+	ETypeTiSyncTrac GetTiSyncTracType() {return TypeTiSyncTrac;}
+ 
+	/* OPH: calculation of delay and doppler using RSCI method */
+	void CalculateRdel(CParameter& Parameter);
+	CRealVector& GetRdelThresholds() {return vecrRdelThresholds;}
+	void CalculateRdop(CParameter& Parameter);
+
+
+protected:
+	CComplexVector			veccPilots;
+	int						iNumIntpFreqPil;
+	CFftPlans				FftPlan;
+	int						iScatPilFreqInt;
+	int						iNumCarrier;
+	CRealVector				vecrAvPoDeSp;
+	CReal					rLamAvPDS;
+
+	CRealVector				vecrHammingWindow;
+	CReal					rConst1;
+	CReal					rConst2;
+	int						iStPoRot;
+	CRealVector				vecrAvPoDeSpRot;
+	int						iSymDelay;
+	CShiftRegister<int>		vecTiCorrHist;
+	CShiftRegister<int>		veciNewMeasHist;
+	
+	CReal					rFracPartTiCor;
+	int						iTargetTimingPos;
+
+	_BOOLEAN				bTiSyncTracking;
+	_BOOLEAN				bSamRaOffsAcqu;
+
+	int						iDFTSize;
+
+	CReal					rBoundLower;
+	CReal					rBoundHigher;
+	CReal					rGuardSizeFFT;
+
+	CReal					rEstPDSEnd; /* Estimated end of PSD */
+	CReal					rEstPDSBegin; /* Estimated beginning of PSD */
+
+	CReal					rFracPartContr;
+
+	ETypeTiSyncTrac			TypeTiSyncTrac;
+
+	CShiftRegister<int>		veciSRTiCorrHist;
+	int						iLenCorrectionHist;
+	long int				iIntegTiCorrections;
+	CReal					rSymBloSiIRDomain;
+	int						iResOffsetAcquCnt;
+	int						iResOffAcqCntMax;
+	int						iOldNonZeroDiff;
+
+	CReal GetSamOffHz(int iDiff, int iLen, int iSampleRate);
+
+	/* O. Haffenden variables for rdop and rdel calculation */
+	CComplexVector			veccOldImpulseResponse;
+	CRealVector				vecrRdelThresholds;
+	CRealVector				vecrRdelIntervals;
+};
+
+
+#endif // !defined(TIMESYNCTRACK_H__3B0BA6346234634554344_BBE7A0D31912__INCLUDED_)
diff --git a/src/tables/TableAMSS.h b/src/tables/TableAMSS.h
new file mode 100644
index 0000000..c0c8294
--- /dev/null
+++ b/src/tables/TableAMSS.h
@@ -0,0 +1,52 @@
+/******************************************************************************\
+ * BBC Research & Development
+ * Copyright (c) 2005
+ *
+ * Author(s):
+ *	Andrew Murphy
+ *
+ * Description:
+ *	Tables for AMSS
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#if !defined(__TABLE_AMSS_H__3B0_CA63_4344_BGDEB2B_23E7912__INCLUDED_)
+#define __TABLE_AMSS_H__3B0_CA63_4344_BGDEB2B_23E7912__INCLUDED_
+
+#include <string>
+#include "../GlobalDefinitions.h"
+
+
+/* Definitions ****************************************************************/
+#define LEN_TABLE_AMSS_CARRIER_MODE		8
+
+const string strTableAMSSCarrierMode[LEN_TABLE_AMSS_CARRIER_MODE] =
+{
+    "No Carrier Control",	// 0 0 0
+    "reserved",				// 0 0 1
+    "AMC Mode 1 (-3dB)",	// 0 1 0
+    "AMC Mode 2 (-6dB)",	// 0 1 1
+    "DAM Mode 1 (+3dB)",	// 1 0 0
+    "DAM Mode 2 (+6dB)",	// 1 0 1
+    "reserved",				// 1 1 0
+    "reserved"				// 1 1 1
+};
+
+
+#endif // !defined(__TABLE_AMSS_H__3B0_CA63_4344_BGDEB2B_23E7912__INCLUDED_)
diff --git a/src/tables/TableCarMap.cpp b/src/tables/TableCarMap.cpp
new file mode 100644
index 0000000..a0a1e24
--- /dev/null
+++ b/src/tables/TableCarMap.cpp
@@ -0,0 +1,381 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *	Tables for carrier mapping
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "TableCarMap.h"
+
+/* FAC positions. The two numbers are {symbol no, carrier no} */
+const int iTableFACRobModA[NUM_FAC_CELLS][2] = {
+    {2, 26}, {2, 46}, {2, 66}, {2, 86},
+    {3, 10}, {3, 30}, {3, 50}, {3, 70}, {3, 90},
+    {4, 14}, {4, 22}, {4, 34}, {4, 62}, {4, 74}, {4, 94},
+    {5, 26}, {5, 38}, {5, 58}, {5, 66}, {5, 78},
+    {6, 22}, {6, 30}, {6, 42}, {6, 62}, {6, 70}, {6, 82},
+    {7, 26}, {7, 34}, {7, 46}, {7, 66}, {7, 74}, {7, 86},
+    {8, 10}, {8, 30}, {8, 38}, {8, 50}, {8, 58}, {8, 70}, {8, 78}, {8, 90},
+    {9, 14}, {9, 22}, {9, 34}, {9, 42}, {9, 62}, {9, 74}, {9, 82}, {9, 94},
+    {10, 26}, {10, 38}, {10, 46}, {10, 66}, {10, 86},
+    {11, 10}, {11, 30}, {11, 50}, {11, 70}, {11, 90},
+    {12, 14}, {12, 34}, {12, 74}, {12, 94},
+    {13, 38}, {13, 58}, {13, 78}
+};
+
+const int iTableFACRobModB[NUM_FAC_CELLS][2] = {
+    {2, 13}, {2, 25}, {2, 43}, {2, 55}, {2, 67},
+    {3, 15}, {3, 27}, {3, 45}, {3, 57}, {3, 69},
+    {4, 17}, {4, 29}, {4, 47}, {4, 59}, {4, 71},
+    {5, 19}, {5, 31}, {5, 49}, {5, 61}, {5, 73},
+    {6, 9}, {6, 21}, {6, 33}, {6, 51}, {6, 63}, {6, 75},
+    {7, 11}, {7, 23}, {7, 35}, {7, 53}, {7, 65}, {7, 77},
+    {8, 13}, {8, 25}, {8, 37}, {8, 55}, {8, 67}, {8, 79},
+    {9, 15}, {9, 27}, {9, 39}, {9, 57}, {9, 69}, {9, 81},
+    {10, 17}, {10, 29}, {10, 41}, {10, 59}, {10, 71}, {10, 83},
+    {11, 19}, {11, 31}, {11, 43}, {11, 61}, {11, 73},
+    {12, 21}, {12, 33}, {12, 45}, {12, 63}, {12, 75},
+    {13, 23}, {13, 35}, {13, 47}, {13, 65}, {13, 77},
+};
+
+const int iTableFACRobModC[NUM_FAC_CELLS][2] = {
+    {3, 9}, {3, 21}, {3, 45}, {3, 57},
+    {4, 23}, {4, 35}, {4, 47},
+    {5, 13}, {5, 25}, {5, 37}, {5, 49},
+    {6, 15}, {6, 27}, {6, 39}, {6, 51},
+    {7, 5}, {7, 17}, {7, 29}, {7, 41}, {7, 53},
+    {8, 7}, {8, 19}, {8, 31}, {8, 43}, {8, 55},
+    {9, 9}, {9, 21}, {9, 45}, {9, 57},
+    {10, 23}, {10, 35}, {10, 47},
+    {11, 13}, {11, 25}, {11, 37}, {11, 49},
+    {12, 15}, {12, 27}, {12, 39}, {12, 51},
+    {13, 5}, {13, 17}, {13, 29}, {13, 41}, {13, 53},
+    {14, 7}, {14, 19}, {14, 31}, {14, 43}, {14, 55},
+    {15, 9}, {15, 21}, {15, 45}, {15, 57},
+    {16, 23}, {16, 35}, {16, 47},
+    {17, 13}, {17, 25}, {17, 37}, {17, 49},
+    {18, 15}, {18, 27}, {18, 39}, {18, 51}
+};
+
+const int iTableFACRobModD[NUM_FAC_CELLS][2] = {
+    {3, 9}, {3, 18}, {3, 27},
+    {4, 10}, {4, 19},
+    {5, 11}, {5, 20}, {5, 29},
+    {6, 12}, {6, 30},
+    {7, 13}, {7, 22}, {7, 31},
+    {8, 5}, {8, 14}, {8, 23}, {8, 32},
+    {9, 6}, {9, 15}, {9, 24}, {9, 33},
+    {10, 16}, {10, 25}, {10, 34},
+    {11, 8}, {11, 17}, {11, 26}, {11, 35},
+    {12, 9}, {12, 18}, {12, 27}, {12, 36},
+    {13, 10}, {13, 19}, {13, 37},
+    {14, 11}, {14, 20}, {14, 29},
+    {15, 12}, {15, 30},
+    {16, 13}, {16, 22}, {16, 31},
+    {17, 5}, {17, 14}, {17, 23}, {17, 32},
+    {18, 6}, {18, 15}, {18, 24}, {18, 33},
+    {19, 16}, {19, 25}, {19, 34},
+    {20, 8}, {20, 17}, {20, 26}, {20, 35},
+    {21, 9}, {21, 18}, {21, 27}, {21, 36},
+    {22, 10}, {22, 19}, {22, 37}
+};
+
+
+/* Frequency pilots ***********************************************************/
+#define NUM_FREQ_PILOTS			3
+const int iTableFreqPilRobModA[NUM_FREQ_PILOTS][2] = {
+    {18, 205},
+    {54, 836},
+    {72, 215}
+};
+
+const int iTableFreqPilRobModB[NUM_FREQ_PILOTS][2] = {
+    {16, 331},
+    {48, 651},
+    {64, 555}
+};
+
+const int iTableFreqPilRobModC[NUM_FREQ_PILOTS][2] = {
+    {11, 214},
+    {33, 392},
+    {44, 242}
+};
+
+const int iTableFreqPilRobModD[NUM_FREQ_PILOTS][2] = {
+    {7,	788},
+    {21, 1014},
+    {28, 332}
+};
+
+
+/* Time pilots ****************************************************************/
+/* The two numbers are: {carrier no, phase} (Phases are normalized to 1024) */
+#define RMA_NUM_TIME_PIL	21
+const int iTableTimePilRobModA[RMA_NUM_TIME_PIL][2] = {
+    {17, 973},
+    {18, 205},
+    {19, 717},
+    {21, 264},
+    {28, 357},
+    {29, 357},
+    {32, 952},
+    {33, 440},
+    {39, 856},
+    {40, 88},
+    {41, 88},
+    {53, 68},
+    {54, 836},
+    {55, 836},
+    {56, 836},
+    {60, 1008},
+    {61, 1008},
+    {63, 752},
+    {71, 215},
+    {72, 215},
+    {73, 727}
+};
+
+#define RMB_NUM_TIME_PIL	19
+const int iTableTimePilRobModB[RMB_NUM_TIME_PIL][2] = {
+    {14, 304},
+    {16, 331},
+    {18, 108},
+    {20, 620},
+    {24, 192},
+    {26, 704},
+    {32, 44},
+    {36, 432},
+    {42, 588},
+    {44, 844},
+    {48, 651},
+    {49, 651},
+    {50, 651},
+    {54, 460},
+    {56, 460},
+    {62, 944},
+    {64, 555},
+    {66, 940},
+    {68, 428}
+};
+
+#define RMC_NUM_TIME_PIL	19
+const int iTableTimePilRobModC[RMC_NUM_TIME_PIL][2] = {
+    {8, 722},
+    {10, 466},
+    {11, 214},
+    {12, 214},
+    {14, 479},
+    {16, 516},
+    {18, 260},
+    {22, 577},
+    {24, 662},
+    {28, 3},
+    {30, 771},
+    {32, 392},
+    {33, 392},
+    {36, 37},
+    {38, 37},
+    {42, 474},
+    {44, 242},
+    {45, 242},
+    {46, 754}
+};
+
+#define RMD_NUM_TIME_PIL	21
+const int iTableTimePilRobModD[RMD_NUM_TIME_PIL][2] = {
+    {5, 636},
+    {6, 124},
+    {7, 788},
+    {8, 788},
+    {9, 200},
+    {11, 688},
+    {12, 152},
+    {14, 920},
+    {15, 920},
+    {17, 644},
+    {18, 388},
+    {20, 652},
+    {21, 1014},
+    {23, 176},
+    {24, 176},
+    {26, 752},
+    {27, 496},
+    {28, 332},
+    {29, 432},
+    {30, 964},
+    {32, 452}
+};
+
+
+/* Scattered pilots ***********************************************************/
+/* Definitions for the positions of scattered pilots */
+#define RMA_SCAT_PIL_FREQ_INT	4
+#define RMA_SCAT_PIL_TIME_INT	5
+
+#define RMB_SCAT_PIL_FREQ_INT	2
+#define RMB_SCAT_PIL_TIME_INT	3
+
+#define RMC_SCAT_PIL_FREQ_INT	2
+#define RMC_SCAT_PIL_TIME_INT	2
+
+#define RMD_SCAT_PIL_FREQ_INT	1
+#define RMD_SCAT_PIL_TIME_INT	3
+
+/* Phase definitions of scattered pilots ------------------------------------ */
+const int iTableScatPilConstRobModA[3] = {4, 5, 2};
+
+const int iTableScatPilConstRobModB[3] = {2, 3, 1};
+
+const int iTableScatPilConstRobModC[3] = {2, 2, 1};
+
+const int iTableScatPilConstRobModD[3] = {1, 3, 1};
+
+#define SIZE_ROW_WZ_ROB_MOD_A	5
+#define SIZE_COL_WZ_ROB_MOD_A	3
+const int iScatPilWRobModA[SIZE_ROW_WZ_ROB_MOD_A][SIZE_COL_WZ_ROB_MOD_A] = {
+    {228, 341, 455},
+    {455, 569, 683},
+    {683, 796, 910},
+    {910,   0, 114},
+    {114, 228, 341}
+};
+const int iScatPilZRobModA[SIZE_ROW_WZ_ROB_MOD_A][SIZE_COL_WZ_ROB_MOD_A] = {
+    {0,    81, 248},
+    {18,  106, 106},
+    {122, 116,  31},
+    {129, 129,  39},
+    {33,   32, 111}
+};
+const int iScatPilQRobModA = 36;
+
+#define SIZE_ROW_WZ_ROB_MOD_B	3
+#define SIZE_COL_WZ_ROB_MOD_B	5
+const int iScatPilWRobModB[SIZE_ROW_WZ_ROB_MOD_B][SIZE_COL_WZ_ROB_MOD_B] = {
+    {512,   0, 512,   0, 512},
+    {0,   512,   0, 512,   0},
+    {512,   0, 512,   0, 512}
+};
+const int iScatPilZRobModB[SIZE_ROW_WZ_ROB_MOD_B][SIZE_COL_WZ_ROB_MOD_B] = {
+    {0,    57, 164,  64,  12},
+    {168, 255, 161, 106, 118},
+    {25,  232, 132, 233,  38}
+};
+const int iScatPilQRobModB = 12;
+
+#define SIZE_ROW_WZ_ROB_MOD_C	2
+#define SIZE_COL_WZ_ROB_MOD_C	10
+const int iScatPilWRobModC[SIZE_ROW_WZ_ROB_MOD_C][SIZE_COL_WZ_ROB_MOD_C] = {
+    {465, 372, 279, 186,  93,   0, 931, 838, 745, 652},
+    {931, 838, 745, 652, 559, 465, 372, 279, 186,  93}
+};
+const int iScatPilZRobModC[SIZE_ROW_WZ_ROB_MOD_C][SIZE_COL_WZ_ROB_MOD_C] = {
+    {0,    76, 29,  76,   9, 190, 161, 248,  33, 108},
+    {179, 178, 83, 253, 127, 105, 101, 198, 250, 145}
+};
+const int iScatPilQRobModC = 12;
+
+#define SIZE_ROW_WZ_ROB_MOD_D	3
+#define SIZE_COL_WZ_ROB_MOD_D	8
+const int iScatPilWRobModD[SIZE_ROW_WZ_ROB_MOD_D][SIZE_COL_WZ_ROB_MOD_D] = {
+    {366, 439, 512, 585, 658, 731, 805, 878},
+    {731, 805, 878, 951,   0,  73, 146, 219},
+    {73,  146, 219, 293, 366, 439, 512, 585}
+};
+const int iScatPilZRobModD[SIZE_ROW_WZ_ROB_MOD_D][SIZE_COL_WZ_ROB_MOD_D] = {
+    {0,   240,  17,  60, 220,  38, 151, 101},
+    {110,   7,  78,  82, 175, 150, 106,  25},
+    {165,   7, 252, 124, 253, 177, 197, 142}
+};
+const int iScatPilQRobModD = 14;
+
+/* Gain definitions of scattered pilots ------------------------------------- */
+#define NUM_BOOSTED_SCAT_PILOTS		4
+const int iScatPilGainRobModA[6][NUM_BOOSTED_SCAT_PILOTS] = {
+    {2, 6, 98, 102},
+    {2, 6, 110, 114},
+    {-102, -98, 98, 102},
+    {-114, -110, 110, 114},
+    {-98, -94, 310, 314},
+    {-110, -106, 346, 350}
+};
+
+const int iScatPilGainRobModB[6][NUM_BOOSTED_SCAT_PILOTS] = {
+    {1, 3, 89, 91},
+    {1, 3, 101, 103},
+    {-91, -89, 89, 91},
+    {-103, -101, 101, 103},
+    {-87, -85, 277, 279},
+    {-99, -97, 309, 311}
+};
+
+const int iScatPilGainRobModC[6][NUM_BOOSTED_SCAT_PILOTS] = {
+    {0, 0, 0, 0},
+    {0, 0, 0, 0},
+    {0, 0, 0, 0},
+    {-69, -67, 67, 69},
+    {0, 0, 0, 0},
+    {-67, -65, 211, 213}
+};
+
+const int iScatPilGainRobModD[6][NUM_BOOSTED_SCAT_PILOTS] = {
+    {0, 0, 0, 0},
+    {0, 0, 0, 0},
+    {0, 0, 0, 0},
+    {-44, -43, 43, 44},
+    {0, 0, 0, 0},
+    {-43, -42, 134, 135}
+};
+
+
+/* Dummy cells for the MSC ****************************************************/
+/* Already normalized */
+const _COMPLEX cDummyCells64QAM[2] = {
+    _COMPLEX(0.1543033499f,  0.1543033499f),
+    _COMPLEX(0.1543033499f, -0.1543033499f)
+};
+
+const _COMPLEX cDummyCells16QAM[2] = {
+    _COMPLEX(0.3162277660f,  0.3162277660f),
+    _COMPLEX(0.3162277660f, -0.3162277660f)
+};
+
+
+/* Spectrum occupancy, carrier numbers for each mode **************************/
+const int iTableCarrierKmin[6][4] = {
+    {2, 1, 0, 0},
+    {2, 1, 0, 0},
+    {-102, -91, 0, 0},
+    {-114, -103, -69, -44},
+    {-98, -87, 0, 0},
+    {-110, -99, -67, -43}
+};
+
+const int iTableCarrierKmax[6][4] = {
+    {102, 91, 0, 0},
+    {114, 103, 0, 0},
+    {102, 91, 0, 0},
+    {114, 103, 69, 44},
+    {314, 279, 0, 0},
+    {350, 311, 213, 135}
+};
diff --git a/src/tables/TableCarMap.h b/src/tables/TableCarMap.h
new file mode 100644
index 0000000..20ea0de
--- /dev/null
+++ b/src/tables/TableCarMap.h
@@ -0,0 +1,141 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *	Tables for carrier mapping
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#if !defined(TABLE_CAR_MAP_H__3B0_CA63_4344_BB2B_23E7912__INCLUDED_)
+#define TABLE_CAR_MAP_H__3B0_CA63_4344_BB2B_23E7912__INCLUDED_
+
+#include "../GlobalDefinitions.h"
+
+
+/* Definitions ****************************************************************/
+/* FAC ************************************************************************/
+#define NUM_FAC_CELLS			65
+
+/* FAC positions. The two numbers are {symbol no, carrier no} */
+extern const int iTableFACRobModA[NUM_FAC_CELLS][2];
+
+extern const int iTableFACRobModB[NUM_FAC_CELLS][2];
+
+extern const int iTableFACRobModC[NUM_FAC_CELLS][2];
+
+extern const int iTableFACRobModD[NUM_FAC_CELLS][2];
+
+/* Frequency pilots ***********************************************************/
+#define NUM_FREQ_PILOTS			3
+extern const int iTableFreqPilRobModA[NUM_FREQ_PILOTS][2];
+
+extern const int iTableFreqPilRobModB[NUM_FREQ_PILOTS][2];
+
+extern const int iTableFreqPilRobModC[NUM_FREQ_PILOTS][2];
+
+extern const int iTableFreqPilRobModD[NUM_FREQ_PILOTS][2];
+
+/* Time pilots ****************************************************************/
+/* The two numbers are: {carrier no, phase} (Phases are normalized to 1024) */
+#define RMA_NUM_TIME_PIL	21
+extern const int iTableTimePilRobModA[RMA_NUM_TIME_PIL][2];
+
+#define RMB_NUM_TIME_PIL	19
+extern const int iTableTimePilRobModB[RMB_NUM_TIME_PIL][2];
+
+#define RMC_NUM_TIME_PIL	19
+extern const int iTableTimePilRobModC[RMC_NUM_TIME_PIL][2];
+
+#define RMD_NUM_TIME_PIL	21
+extern const int iTableTimePilRobModD[RMD_NUM_TIME_PIL][2];
+
+/* Scattered pilots ***********************************************************/
+/* Definitions for the positions of scattered pilots */
+#define RMA_SCAT_PIL_FREQ_INT	4
+#define RMA_SCAT_PIL_TIME_INT	5
+
+#define RMB_SCAT_PIL_FREQ_INT	2
+#define RMB_SCAT_PIL_TIME_INT	3
+
+#define RMC_SCAT_PIL_FREQ_INT	2
+#define RMC_SCAT_PIL_TIME_INT	2
+
+#define RMD_SCAT_PIL_FREQ_INT	1
+#define RMD_SCAT_PIL_TIME_INT	3
+
+/* Phase definitions of scattered pilots ------------------------------------ */
+extern const int iTableScatPilConstRobModA[3];
+
+extern const int iTableScatPilConstRobModB[3];
+
+extern const int iTableScatPilConstRobModC[3];
+
+extern const int iTableScatPilConstRobModD[3];
+
+#define SIZE_ROW_WZ_ROB_MOD_A	5
+#define SIZE_COL_WZ_ROB_MOD_A	3
+extern const int iScatPilWRobModA[SIZE_ROW_WZ_ROB_MOD_A][SIZE_COL_WZ_ROB_MOD_A];
+extern const int iScatPilZRobModA[SIZE_ROW_WZ_ROB_MOD_A][SIZE_COL_WZ_ROB_MOD_A];
+extern const int iScatPilQRobModA;
+
+#define SIZE_ROW_WZ_ROB_MOD_B	3
+#define SIZE_COL_WZ_ROB_MOD_B	5
+extern const int iScatPilWRobModB[SIZE_ROW_WZ_ROB_MOD_B][SIZE_COL_WZ_ROB_MOD_B];
+extern const int iScatPilZRobModB[SIZE_ROW_WZ_ROB_MOD_B][SIZE_COL_WZ_ROB_MOD_B];
+extern const int iScatPilQRobModB;
+
+#define SIZE_ROW_WZ_ROB_MOD_C	2
+#define SIZE_COL_WZ_ROB_MOD_C	10
+extern const int iScatPilWRobModC[SIZE_ROW_WZ_ROB_MOD_C][SIZE_COL_WZ_ROB_MOD_C];
+extern const int iScatPilZRobModC[SIZE_ROW_WZ_ROB_MOD_C][SIZE_COL_WZ_ROB_MOD_C];
+extern const int iScatPilQRobModC;
+
+#define SIZE_ROW_WZ_ROB_MOD_D	3
+#define SIZE_COL_WZ_ROB_MOD_D	8
+extern const int iScatPilWRobModD[SIZE_ROW_WZ_ROB_MOD_D][SIZE_COL_WZ_ROB_MOD_D];
+extern const int iScatPilZRobModD[SIZE_ROW_WZ_ROB_MOD_D][SIZE_COL_WZ_ROB_MOD_D];
+extern const int iScatPilQRobModD;
+
+/* Gain definitions of scattered pilots ------------------------------------- */
+#define NUM_BOOSTED_SCAT_PILOTS		4
+extern const int iScatPilGainRobModA[6][NUM_BOOSTED_SCAT_PILOTS];
+
+extern const int iScatPilGainRobModB[6][NUM_BOOSTED_SCAT_PILOTS];
+
+extern const int iScatPilGainRobModC[6][NUM_BOOSTED_SCAT_PILOTS];
+
+extern const int iScatPilGainRobModD[6][NUM_BOOSTED_SCAT_PILOTS];
+
+/* Dummy cells for the MSC ****************************************************/
+/* Already normalized */
+extern const _COMPLEX cDummyCells64QAM[2];
+
+extern const _COMPLEX cDummyCells16QAM[2];
+
+
+/* Spectrum occupancy, carrier numbers for each mode **************************/
+extern const int iTableCarrierKmin[6][4];
+
+extern const int iTableCarrierKmax[6][4];
+
+#endif // !defined(TABLE_CAR_MAP_H__3B0_CA63_4344_BB2B_23E7912__INCLUDED_)
diff --git a/src/tables/TableDRMGlobal.h b/src/tables/TableDRMGlobal.h
new file mode 100644
index 0000000..0a85e56
--- /dev/null
+++ b/src/tables/TableDRMGlobal.h
@@ -0,0 +1,104 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *	DRM global definitions
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#if !defined(TABLE_DRM_GLOB_H__3B0_CA63_4344_BB2B_23E7912__INCLUDED_)
+#define TABLE_DRM_GLOB_H__3B0_CA63_4344_BB2B_23E7912__INCLUDED_
+
+
+/* Definitions ****************************************************************/
+/* We define a "virtual" intermedia frequency for the DC carrier in the range
+   of the FFT-size. This IF is independent of the "real" IF defined by the
+   frequency estimation acquisition unit. Here, we are constrained to certain
+   numbers to get continuous signals like they are defined in the DRM-standard,
+   i.e. the frequency pilots which have to be continuous. Our IF must be a
+   multiple of 1500 Hz and must also be chosen so that the largest mode (20 kHz)
+   must fit into the range of the FFT-size. Therefore 6000 Hz was chosen */
+#define VIRTUAL_INTERMED_FREQ			6000	// Hz
+
+/* Default sample rate MUST be set to a safe value of 48000,
+   for testing purpose it must be a multiple of 750 */
+#define DEFAULT_SOUNDCRD_SAMPLE_RATE	48000	// Hz
+
+/* DRM parameters */
+#define NUM_FRAMES_IN_SUPERFRAME		3
+
+#define RMA_FFT_SIZE_N					1152	// RMB: Robustness Mode A
+#define RMA_NUM_SYM_PER_FRAME			15
+#define RMA_ENUM_TG_TU					1
+#define RMA_DENOM_TG_TU					9
+
+#define RMB_FFT_SIZE_N					1024	// RMA: Robustness Mode B
+#define RMB_NUM_SYM_PER_FRAME			15
+#define RMB_ENUM_TG_TU					1
+#define RMB_DENOM_TG_TU					4
+
+#define RMC_FFT_SIZE_N					704		// RMC: Robustness Mode C
+#define RMC_NUM_SYM_PER_FRAME			20
+#define RMC_ENUM_TG_TU					4
+#define RMC_DENOM_TG_TU					11
+
+#define RMD_FFT_SIZE_N					448		// RMD: Robustness Mode D
+#define RMD_NUM_SYM_PER_FRAME			24
+#define RMD_ENUM_TG_TU					11
+#define RMD_DENOM_TG_TU					14
+
+#define MAX_NUM_STREAMS					4
+#define MAX_NUM_SERVICES				4
+
+#define NUM_ROBUSTNESS_MODES			4
+
+#define ADJ_FOR_SRATE(value, srate)		(value * srate / 48000) /* Reminder: 48000 is the right value, do not edit! (don't replace it by DEFAULT_SOUNDCRD_SAMPLE_RATE) */
+
+
+/* Service ID has 24 bits, define a number which cannot be an ID and fits into
+   the 32 bits of the length of the variable (e.g.: 1 << 25) */
+#define SERV_ID_NOT_USED				(1 << 25)
+
+/* Define a stream ID which is not valid to show that this service is not
+   attached to a stream */
+#define STREAM_ID_NOT_USED				(MAX_NUM_STREAMS + 1)
+
+
+/* Audio stream definitions ------------------------------------------------- */
+/* The text message (when present) shall occupy the last four bytes of the
+   lower protected part of each logical frame carrying an audio stream
+   (6.5.1) */
+#define NUM_BYTES_TEXT_MESS_IN_AUD_STR	4
+
+/* Transform length: the transform length is 960 to ensure that one
+   audio frame corresponds to 80 ms or 40 ms in time. This is required
+   to harmonize CELP and AAC frame lengths and thus to allow the
+   combination of an integer number of audio frames to build an audio
+   super frame of 400 ms duration */
+#define AUD_DEC_TRANSFROM_LENGTH		960
+
+/* Number of DRM frames per minute */
+#define NUM_DRM_FRAMES_PER_MIN			150
+
+
+#endif // !defined(TABLE_DRM_GLOB_H__3B0_CA63_4344_BB2B_23E7912__INCLUDED_)
diff --git a/src/tables/TableFAC.cpp b/src/tables/TableFAC.cpp
new file mode 100644
index 0000000..d41560d
--- /dev/null
+++ b/src/tables/TableFAC.cpp
@@ -0,0 +1,990 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *	Tables for FAC
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "TableFAC.h"
+
+/* Definitions ****************************************************************/
+/* ETSI ES201980V2.1.1: page 115, 7.5.3: ...FAC shall use 4-QAM mapping. A
+   fixed code rate shall be applied...R_all=0.6...
+   6 tailbits are used for the encoder to get in zero state ->
+   65 [number of cells] * 2 [4-QAM] * 0.6 [code-rate] - 6 [tailbits] = 72 */
+#define NUM_FAC_BITS_PER_BLOCK			72
+
+/* iTableNumOfServices[a][b]
+   a: Number of audio services
+   b: Number of data services
+   (6.3.4) */
+const int iTableNumOfServices[5][5] = {
+    /* -> Data */
+    {-1,  1,  2,  3, 15},
+    { 4,  5,  6,  7, -1},
+    { 8,  9, 10, -1, -1},
+    {12, 13, -1, -1, -1},
+    { 0, -1, -1, -1, -1}
+};
+
+/* Language code */
+#define LEN_TABLE_LANGUAGE_CODE			16
+
+const string strTableLanguageCode[LEN_TABLE_LANGUAGE_CODE] = {
+    "No language specified",
+    "Arabic",
+    "Bengali",
+    "Chinese (Mandarin)",
+    "Dutch",
+    "English",
+    "French",
+    "German",
+    "Hindi",
+    "Japanese",
+    "Javanese",
+    "Korean",
+    "Portuguese",
+    "Russian",
+    "Spanish",
+    "Other language"
+};
+
+/* Programme Type codes */
+#define LEN_TABLE_PROG_TYPE_CODE_TOT	32
+#define LEN_TABLE_PROG_TYPE_CODE		30
+
+const string strTableProgTypCod[LEN_TABLE_PROG_TYPE_CODE_TOT] = {
+    "No programme type",
+    "News",
+    "Current Affairs",
+    "Information",
+    "Sport",
+    "Education",
+    "Drama",
+    "Culture",
+    "Science",
+    "Varied",
+    "Pop Music",
+    "Rock Music",
+    "Easy Listening Music",
+    "Light Classical",
+    "Serious Classical",
+    "Other Music",
+    "Weather/meteorology",
+    "Finance/Business",
+    "Children's programmes",
+    "Social Affairs",
+    "Religion",
+    "Phone In",
+    "Travel",
+    "Leisure",
+    "Jazz Music",
+    "Country Music",
+    "National Music",
+    "Oldies Music",
+    "Folk Music",
+    "Documentary",
+    "Not used",
+    "Not used"
+};
+
+
+/* Country code table according to ISO 3166 */
+
+const struct elCountry TableCountryCode[LEN_TABLE_COUNTRY_CODE] = {
+    {"af", "Afghanistan"},
+    {"ax", "Aland Islands"},
+    {"al", "Albania"},
+    {"dz", "Algeria"},
+    {"as", "American Samoa"},
+    {"ad", "Andorra"},
+    {"ao", "Angola"},
+    {"ai", "Anguilla"},
+    {"aq", "Antarctica"},
+    {"ag", "Antigua and barbuda"},
+    {"ar", "Argentina"},
+    {"am", "Armenia"},
+    {"aw", "Aruba"},
+    {"au", "Australia"},
+    {"at", "Austria"},
+    {"az", "Azerbaijan"},
+    {"bs", "Bahamas"},
+    {"bh", "Bahrain"},
+    {"bd", "Bangladesh"},
+    {"bb", "Barbados"},
+    {"by", "Belarus"},
+    {"be", "Belgium"},
+    {"bz", "Belize"},
+    {"bj", "Benin"},
+    {"bm", "Bermuda"},
+    {"bt", "Bhutan"},
+    {"bo", "Bolivia"},
+    {"ba", "Bosnia and Herzegovina"},
+    {"bw", "Botswana"},
+    {"bv", "Bouvet Island"},
+    {"br", "Brazil"},
+    {"io", "British Indian Ocean Ter."},
+    {"bn", "Brunei Darussalam"},
+    {"bg", "Bulgaria"},
+    {"bf", "Burkina Faso"},
+    {"bi", "Burundi"},
+    {"kh", "Cambodia"},
+    {"cm", "Cameroon"},
+    {"ca", "Canada"},
+    {"cv", "Cape Verde"},
+    {"ky", "Cayman Islands"},
+    {"cf", "Central African Republic"},
+    {"td", "Chad"},
+    {"cl", "Chile"},
+    {"cn", "China"},
+    {"cx", "Christmas Island"},
+    {"cc", "Cocos (Keeling) Islands"},
+    {"co", "Colombia"},
+    {"km", "Comoros"},
+    {"cg", "Congo Democratic Rep."},
+    {"cd", "Congo"},
+    {"ck", "Cook Islands"},
+    {"cr", "Costa Rica"},
+    {"ci", "C�te d'Ivoire"},
+    {"hr", "Croatia"},
+    {"cu", "Cuba"},
+    {"cy", "Cyprus"},
+    {"cz", "Czech Republic"},
+    {"dk", "Denmark"},
+    {"dj", "Djibouti"},
+    {"dm", "Dominica"},
+    {"do", "Dominican Republic"},
+    {"ec", "Ecuador"},
+    {"eg", "Egypt"},
+    {"sv", "El Salvador"},
+    {"gq", "Equatorial Guinea"},
+    {"er", "Eritrea"},
+    {"ee", "Estonia"},
+    {"et", "Ethiopia"},
+    {"fk", "Falkland Islands"},
+    {"fo", "Faroe Islands"},
+    {"fj", "Fiji"},
+    {"fi", "Finland"},
+    {"fr", "France"},
+    {"gf", "French Guiana"},
+    {"pf", "French Polynesia"},
+    {"tf", "French Southern Ter."},
+    {"ga", "Gabon"},
+    {"gm", "Gambia"},
+    {"ge", "Georgia"},
+    {"de", "Germany"},
+    {"gh", "Ghana"},
+    {"gi", "Gibraltar"},
+    {"gr", "Greece"},
+    {"gl", "Greenland"},
+    {"gd", "Grenada"},
+    {"gp", "Guadeloupe"},
+    {"gu", "Guam"},
+    {"gt", "Guatemala"},
+    {"gg", "Guernsey"},
+    {"gn", "Guinea"},
+    {"gw", "Guinea-Bissau"},
+    {"gy", "Guyana"},
+    {"ht", "Haiti"},
+    {"hm", "Heard Is. Mcdonald Is."},
+    {"va", "Vatican City State"},
+    {"hn", "Honduras"},
+    {"hk", "Hong Kong"},
+    {"hu", "Hungary"},
+    {"is", "Iceland"},
+    {"in", "India"},
+    {"id", "Indonesia"},
+    {"ir", "Iran"},
+    {"iq", "Iraq"},
+    {"im", "Isle of Man"},
+    {"ie", "Ireland"},
+    {"il", "Israel"},
+    {"it", "Italy"},
+    {"jm", "Jamaica"},
+    {"jp", "Japan"},
+    {"je", "Jersey"},
+    {"jo", "Jordan"},
+    {"kz", "Kazakhstan"},
+    {"ke", "Kenya"},
+    {"ki", "Kiribati"},
+    {"kp", "Korea Democratic Rep."},
+    {"kr", "Korea, Republic of"},
+    {"kw", "Kuwait"},
+    {"kg", "Kyrgyzstan"},
+    {"la", "Lao People's Democratic Rep."},
+    {"lv", "Latvia"},
+    {"lb", "Lebanon"},
+    {"ls", "Lesotho"},
+    {"lr", "Liberia"},
+    {"ly", "Libyan Arab Jamahiriya"},
+    {"li", "Liechtenstein"},
+    {"lt", "Lithuania"},
+    {"lu", "Luxembourg"},
+    {"mo", "Macao"},
+    {"mk", "Macedonia"},
+    {"mg", "Madagascar"},
+    {"mw", "Malawi"},
+    {"my", "Malaysia"},
+    {"mv", "Maldives"},
+    {"ml", "Mali"},
+    {"mt", "Malta"},
+    {"mh", "Marshall Islands"},
+    {"mq", "Martinique"},
+    {"mr", "Mauritania"},
+    {"mu", "Mauritius"},
+    {"yt", "Mayotte"},
+    {"mx", "Mexico"},
+    {"fm", "Micronesia"},
+    {"md", "Moldova"},
+    {"mc", "Monaco"},
+    {"mn", "Mongolia"},
+    {"me", "Montenegro"},
+    {"ms", "Montserrat"},
+    {"ma", "Morocco"},
+    {"mz", "Mozambique"},
+    {"mm", "Myanmar"},
+    {"na", "Namibia"},
+    {"nr", "Nauru"},
+    {"np", "Nepal"},
+    {"nl", "Netherlands"},
+    {"an", "Netherlands Antilles"},
+    {"nc", "New Caledonia"},
+    {"nz", "New Zealand"},
+    {"ni", "Nicaragua"},
+    {"ne", "Niger"},
+    {"ng", "Nigeria"},
+    {"nu", "Niue"},
+    {"nf", "Norfolk Island"},
+    {"mp", "Northern Mariana Is."},
+    {"no", "Norway"},
+    {"om", "Oman"},
+    {"pk", "Pakistan"},
+    {"pw", "Palau"},
+    {"ps", "Palestinian Territory"},
+    {"pa", "Panama"},
+    {"pg", "Papua New Guinea"},
+    {"py", "Paraguay"},
+    {"pe", "Peru"},
+    {"ph", "Philippines"},
+    {"pn", "Pitcairn"},
+    {"pl", "Poland"},
+    {"pt", "Portugal"},
+    {"pr", "Puerto Rico"},
+    {"qa", "Qatar"},
+    {"re", "R�union"},
+    {"ro", "Romania"},
+    {"ru", "Russian Federation"},
+    {"rw", "Rwanda"},
+    {"sh", "Saint Helena"},
+    {"kn", "Saint Kitts and Nevis"},
+    {"lc", "Saint Lucia"},
+    {"pm", "Saint Pierre and Miquelon"},
+    {"vc", "Saint Vincent and the Grenadines"},
+    {"ws", "Samoa"},
+    {"sm", "San Marino"},
+    {"st", "Sao Tome and Principe"},
+    {"sa", "Saudi arabia"},
+    {"sn", "Senegal"},
+    {"rs", "Serbia"},
+    {"sc", "Seychelles"},
+    {"sl", "Sierra Leone"},
+    {"sg", "Singapore"},
+    {"sk", "Slovakia"},
+    {"si", "Slovenia"},
+    {"sb", "Solomon Islands"},
+    {"so", "Somalia"},
+    {"za", "South Africa"},
+    {"gs", "South Georgia South Sandwich Is."},
+    {"es", "Spain"},
+    {"lk", "Sri Lanka"},
+    {"sd", "Sudan"},
+    {"sr", "Suriname"},
+    {"sj", "Svalbard and Jan Mayen"},
+    {"sz", "Swaziland"},
+    {"se", "Sweden"},
+    {"ch", "Switzerland"},
+    {"sy", "Syrian Arab Republic"},
+    {"tw", "Taiwan"},
+    {"tj", "Tajikistan"},
+    {"tz", "Tanzania"},
+    {"th", "Thailand"},
+    {"tl", "Timor-Leste"},
+    {"tg", "Togo"},
+    {"tk", "Tokelau"},
+    {"to", "Tonga"},
+    {"tt", "Trinidad and Tobago"},
+    {"tn", "Tunisia"},
+    {"tr", "Turkey"},
+    {"tm", "Turkmenistan"},
+    {"tc", "Turks and Caicos Islands"},
+    {"tv", "Tuvalu"},
+    {"ug", "Uganda"},
+    {"ua", "Ukraine"},
+    {"ae", "United Arab Emirates"},
+    {"gb", "United Kingdom"},
+    {"us", "United States"},
+    {"um", "United States Is."},
+    {"uy", "Uruguay"},
+    {"uz", "Uzbekistan"},
+    {"vu", "Vanuatu"},
+    {"ve", "Venezuela"},
+    {"vn", "Vietnam"},
+    {"vg", "Virgin Islands, British"},
+    {"vi", "Virgin Islands, U.S."},
+    {"wf", "Wallis and Futuna"},
+    {"eh", "Western Sahara"},
+    {"ye", "Yemen"},
+    {"zm", "Zambia"},
+    {"zw", "Zimbabwe"}
+};
+
+/* Get country name from ISO 3166 A2 */
+
+string GetISOCountryName(const string strA2)
+{
+    for (int i = 0; i < LEN_TABLE_COUNTRY_CODE; i++)
+    {
+        if (!strA2.compare(TableCountryCode[i].strcode))
+            return TableCountryCode[i].strDesc;
+    }
+
+    return "";
+}
+
+
+/* Language code table according to ISO 639-2 */
+/* All Alpha 3 codes: "bibliographic" (B code) and "terminological" (T code) */
+
+const struct elLanguage TableISOLanguageCode[LEN_TABLE_ISO_LANGUAGE_CODE] = {
+    {"aar", "Afar"},
+    {"abk", "Abkhazian"},
+    {"ace", "Achinese"},
+    {"ach", "Acoli"},
+    {"ada", "Adangme"},
+    {"ady", "Adyghe; Adygei"},
+    {"afa", "Afro-Asiatic (Other)"},
+    {"afh", "Afrihili"},
+    {"afr", "Afrikaans"},
+    {"ain", "Ainu"},
+    {"aka", "Akan"},
+    {"akk", "Akkadian"},
+    {"alb", "Albanian"},
+    {"sqi", "Albanian"},
+    {"ale", "Aleut"},
+    {"alg", "Algonquian languages"},
+    {"alt", "Southern Altai"},
+    {"amh", "Amharic"},
+    {"ang", "English, Old (ca.450-1100)"},
+    {"anp", "Angika"},
+    {"apa", "Apache languages"},
+    {"ara", "Arabic"},
+    {"arc", "Aramaic"},
+    {"arg", "Aragonese"},
+    {"arm", "Armenian"},
+    {"hye", "Armenian"},
+    {"arn", "Araucanian"},
+    {"arp", "Arapaho"},
+    {"art", "Artificial (Other)"},
+    {"arw", "Arawak"},
+    {"asm", "Assamese"},
+    {"ast", "Asturian; Bable"},
+    {"ath", "Athapascan languages"},
+    {"aus", "Australian languages"},
+    {"ava", "Avaric"},
+    {"ave", "Avestan"},
+    {"awa", "Awadhi"},
+    {"aym", "Aymara"},
+    {"aze", "Azerbaijani"},
+    {"bad", "Banda"},
+    {"bai", "Bamileke languages"},
+    {"bak", "Bashkir"},
+    {"bal", "Baluchi"},
+    {"bam", "Bambara"},
+    {"ban", "Balinese"},
+    {"baq", "Basque"},
+    {"eus", "Basque"},
+    {"bas", "Basa"},
+    {"bat", "Baltic (Other)"},
+    {"bej", "Beja"},
+    {"bel", "Belarusian"},
+    {"bem", "Bemba"},
+    {"ben", "Bengali"},
+    {"ber", "Berber (Other)"},
+    {"bho", "Bhojpuri"},
+    {"bih", "Bihari"},
+    {"bik", "Bikol"},
+    {"bin", "Bini"},
+    {"bis", "Bislama"},
+    {"bla", "Siksika"},
+    {"bnt", "Bantu (Other)"},
+    {"bos", "Bosnian"},
+    {"bra", "Braj"},
+    {"bre", "Breton"},
+    {"btk", "Batak (Indonesia)"},
+    {"bua", "Buriat"},
+    {"bug", "Buginese"},
+    {"bul", "Bulgarian"},
+    {"bur", "Burmese"},
+    {"mya", "Burmese"},
+    {"byn", "Blin; Bilin"},
+    {"cad", "Caddo"},
+    {"cai", "Central American Indian (Other)"},
+    {"car", "Carib"},
+    {"cat", "Catalan; Valencian"},
+    {"cau", "Caucasian (Other)"},
+    {"ceb", "Cebuano"},
+    {"cel", "Celtic (Other)"},
+    {"cha", "Chamorro"},
+    {"chb", "Chibcha"},
+    {"che", "Chechen"},
+    {"chg", "Chagatai"},
+    {"chi", "Chinese"},
+    {"zho", "Chinese"},
+    {"chk", "Chuukese"},
+    {"chm", "Mari"},
+    {"chn", "Chinook jargon"},
+    {"cho", "Choctaw"},
+    {"chp", "Chipewyan"},
+    {"chr", "Cherokee"},
+    {"chu", "Church Slavic - Slavonic..."},
+    {"chv", "Chuvash"},
+    {"chy", "Cheyenne"},
+    {"cmc", "Chamic languages"},
+    {"cop", "Coptic"},
+    {"cor", "Cornish"},
+    {"cos", "Corsican"},
+    {"cpe", "Creoles and pidgins, English based"},
+    {"cpf", "Creoles and pidgins, French-based"},
+    {"cpp", "Creoles and pidgins, Portuguese-based"},
+    {"cre", "Cree"},
+    {"crh", "Crimean Tatar; Crimean Turkish"},
+    {"crp", "Creoles and pidgins (Other)"},
+    {"csb", "Kashubian"},
+    {"cus", "Cushitic (Other)"},
+    {"cze", "Czech"},
+    {"ces", "Czech"},
+    {"dak", "Dakota"},
+    {"dan", "Danish"},
+    {"dar", "Dargwa"},
+    {"day", "Dayak"},
+    {"del", "Delaware"},
+    {"den", "Slave (Athapascan)"},
+    {"dgr", "Dogrib"},
+    {"din", "Dinka"},
+    {"div", "Divehi; Dhivehi; Maldivian"},
+    {"doi", "Dogri"},
+    {"dra", "Dravidian (Other)"},
+    {"dsb", "Lower Sorbian"},
+    {"dua", "Duala"},
+    {"dum", "Dutch, Middle (ca.1050-1350)"},
+    {"dut", "Dutch; Flemish"},
+    {"nld", "Dutch; Flemish"},
+    {"dyu", "Dyula"},
+    {"dzo", "Dzongkha"},
+    {"efi", "Efik"},
+    {"egy", "Egyptian (Ancient)"},
+    {"eka", "Ekajuk"},
+    {"elx", "Elamite"},
+    {"eng", "English"},
+    {"enm", "English, Middle (1100-1500)"},
+    {"epo", "Esperanto"},
+    {"est", "Estonian"},
+    {"ewe", "Ewe"},
+    {"ewo", "Ewondo"},
+    {"fan", "Fang"},
+    {"fao", "Faroese"},
+    {"fat", "Fanti"},
+    {"fij", "Fijian"},
+    {"fil", "Filipino; Pilipino"},
+    {"fin", "Finnish"},
+    {"fiu", "Finno-Ugrian (Other)"},
+    {"fon", "Fon"},
+    {"fre", "French"},
+    {"fra", "French"},
+    {"frm", "French, Middle (ca.1400-1600)"},
+    {"fro", "French, Old (842-ca.1400)"},
+    {"frr", "Northern Frisian"},
+    {"frs", "Eastern Frisian"},
+    {"fry", "Western Frisian"},
+    {"ful", "Fulah"},
+    {"fur", "Friulian"},
+    {"gaa", "Ga"},
+    {"gay", "Gayo"},
+    {"gba", "Gbaya"},
+    {"gem", "Germanic (Other)"},
+    {"geo", "Georgian"},
+    {"kat", "Georgian"},
+    {"ger", "German"},
+    {"deu", "German"},
+    {"gez", "Geez"},
+    {"gil", "Gilbertese"},
+    {"gla", "Gaelic; Scottish Gaelic"},
+    {"gle", "Irish"},
+    {"glg", "Galician"},
+    {"glv", "Manx"},
+    {"gmh", "German, Middle High (ca.1050-1500)"},
+    {"goh", "German, Old High (ca.750-1050)"},
+    {"gon", "Gondi"},
+    {"gor", "Gorontalo"},
+    {"got", "Gothic"},
+    {"grb", "Grebo"},
+    {"grc", "Greek, Ancient (to 1453)"},
+    {"gre", "Greek, Modern (1453-)"},
+    {"ell", "Greek, Modern (1453-)"},
+    {"grn", "Guarani"},
+    {"gsw", "Alemani; Swiss German"},
+    {"guj", "Gujarati"},
+    {"gwi", "Gwich�in"},
+    {"hai", "Haida"},
+    {"hat", "Haitian; Haitian Creole"},
+    {"hau", "Hausa"},
+    {"haw", "Hawaiian"},
+    {"heb", "Hebrew"},
+    {"her", "Herero"},
+    {"hil", "Hiligaynon"},
+    {"him", "Himachali"},
+    {"hin", "Hindi"},
+    {"hit", "Hittite"},
+    {"hmn", "Hmong"},
+    {"hmo", "Hiri Motu"},
+    {"hsb", "Upper Sorbian"},
+    {"hun", "Hungarian"},
+    {"hup", "Hupa"},
+    {"iba", "Iban"},
+    {"ibo", "Igbo"},
+    {"ice", "Icelandic"},
+    {"isl", "Icelandic"},
+    {"ido", "Ido"},
+    {"iii", "Sichuan Yi"},
+    {"ijo", "Ijo"},
+    {"iku", "Inuktitut"},
+    {"ile", "Interlingue"},
+    {"ilo", "Iloko"},
+    {"ina", "Interlingua"},
+    {"inc", "Indic (Other)"},
+    {"ind", "Indonesian"},
+    {"ine", "Indo-European (Other)"},
+    {"inh", "Ingush"},
+    {"ipk", "Inupiaq"},
+    {"ira", "Iranian (Other)"},
+    {"iro", "Iroquoian languages"},
+    {"ita", "Italian"},
+    {"jav", "Javanese"},
+    {"jbo", "Lojban"},
+    {"jpn", "Japanese"},
+    {"jpr", "Judeo-Persian"},
+    {"jrb", "Judeo-Arabic"},
+    {"kaa", "Kara-Kalpak"},
+    {"kab", "Kabyle"},
+    {"kac", "Kachin"},
+    {"kal", "Kalaallisut; Greenlandic"},
+    {"kam", "Kamba"},
+    {"kan", "Kannada"},
+    {"kar", "Karen"},
+    {"kas", "Kashmiri"},
+    {"kau", "Kanuri"},
+    {"kaw", "Kawi"},
+    {"kaz", "Kazakh"},
+    {"kbd", "Kabardian"},
+    {"kha", "Khasi"},
+    {"khi", "Khoisan (Other)"},
+    {"khm", "Khmer"},
+    {"kho", "Khotanese"},
+    {"kik", "Kikuyu; Gikuyu"},
+    {"kin", "Kinyarwanda"},
+    {"kir", "Kirghiz"},
+    {"kmb", "Kimbundu"},
+    {"kok", "Konkani"},
+    {"kom", "Komi"},
+    {"kon", "Kongo"},
+    {"kor", "Korean"},
+    {"kos", "Kosraean"},
+    {"kpe", "Kpelle"},
+    {"krc", "Karachay-Balkar"},
+    {"krl", "Karelian"},
+    {"kro", "Kru"},
+    {"kru", "Kurukh"},
+    {"kua", "Kuanyama; Kwanyama"},
+    {"kum", "Kumyk"},
+    {"kur", "Kurdish"},
+    {"kut", "Kutenai"},
+    {"lad", "Ladino"},
+    {"lah", "Lahnda"},
+    {"lam", "Lamba"},
+    {"lao", "Lao"},
+    {"lat", "Latin"},
+    {"lav", "Latvian"},
+    {"lez", "Lezghian"},
+    {"lim", "Limburgan; Limburger; Limburgish"},
+    {"lin", "Lingala"},
+    {"lit", "Lithuanian"},
+    {"lol", "Mongo"},
+    {"loz", "Lozi"},
+    {"ltz", "Luxembourgish; Letzeburgesch"},
+    {"lua", "Luba-Lulua"},
+    {"lub", "Luba-Katanga"},
+    {"lug", "Ganda"},
+    {"lui", "Luiseno"},
+    {"lun", "Lunda"},
+    {"luo", "Luo (Kenya and Tanzania)"},
+    {"lus", "lushai"},
+    {"mac", "Macedonian"},
+    {"mkd", "Macedonian"},
+    {"mad", "Madurese"},
+    {"mag", "Magahi"},
+    {"mah", "Marshallese"},
+    {"mai", "Maithili"},
+    {"mak", "Makasar"},
+    {"mal", "Malayalam"},
+    {"man", "Mandingo"},
+    {"mao", "Maori"},
+    {"mri", "Maori"},
+    {"map", "Austronesian (Other)"},
+    {"mar", "Marathi"},
+    {"mas", "Masai"},
+    {"may", "Malay"},
+    {"msa", "Malay"},
+    {"mdf", "Moksha"},
+    {"mdr", "Mandar"},
+    {"men", "Mende"},
+    {"mga", "Irish, Middle (900-1200)"},
+    {"mic", "Mi'kmaq; Micmac"},
+    {"min", "Minangkabau"},
+    {"mis", "Miscellaneous languages"},
+    {"mkh", "Mon-Khmer (Other)"},
+    {"mlg", "Malagasy"},
+    {"mlt", "Maltese"},
+    {"mnc", "Manchu"},
+    {"mni", "Manipuri"},
+    {"mno", "Manobo languages"},
+    {"moh", "Mohawk"},
+    {"mol", "Moldavian"},
+    {"mon", "Mongolian"},
+    {"mos", "Mossi"},
+    {"mul", "Multiple languages"},
+    {"mun", "Munda languages"},
+    {"mus", "Creek"},
+    {"mwl", "Mirandese"},
+    {"mwr", "Marwari"},
+    {"myn", "Mayan languages"},
+    {"myv", "Erzya"},
+    {"nah", "Nahuatl"},
+    {"nai", "North American Indian"},
+    {"nap", "Neapolitan"},
+    {"nau", "Nauru"},
+    {"nav", "Navajo; Navaho"},
+    {"nbl", "Ndebele, South; South Ndebele"},
+    {"nde", "Ndebele, North; North Ndebele"},
+    {"ndo", "Ndonga"},
+    {"nds", "Low German; Low Saxon..."},
+    {"nep", "Nepali"},
+    {"new", "Nepal Bhasa; Newari"},
+    {"nia", "Nias"},
+    {"nic", "Niger-Kordofanian (Other)"},
+    {"niu", "Niuean"},
+    {"nno", "Norwegian Nynorsk"},
+    {"nob", "Norwegian Bokm�l"},
+    {"nog", "Nogai"},
+    {"non", "Norse, Old"},
+    {"nor", "Norwegian"},
+    {"nqo", "N'ko"},
+    {"nso", "Northern Sotho; Pedi; Sepedi"},
+    {"nub", "Nubian languages"},
+    {"nwc", "Classical Newari; Classical Nepal Bhasa"},
+    {"nya", "Chichewa; Chewa; Nyanja"},
+    {"nym", "Nyamwezi"},
+    {"nyn", "Nyankole"},
+    {"nyo", "Nyoro"},
+    {"nzi", "Nzima"},
+    {"oci", "Occitan (post 1500); Proven�al"},
+    {"oji", "Ojibwa"},
+    {"ori", "Oriya"},
+    {"orm", "Oromo"},
+    {"osa", "Osage"},
+    {"oss", "Ossetian; Ossetic"},
+    {"ota", "Turkish, Ottoman (1500-1928)"},
+    {"oto", "Otomian languages"},
+    {"paa", "Papuan (Other)"},
+    {"pag", "Pangasinan"},
+    {"pal", "Pahlavi"},
+    {"pam", "Pampanga"},
+    {"pan", "Panjabi; Punjabi"},
+    {"pap", "Papiamento"},
+    {"pau", "Palauan"},
+    {"peo", "Persian, Old (ca.600-400 B.C.)"},
+    {"per", "Persian"},
+    {"fas", "Persian"},
+    {"phi", "Philippine (Other)"},
+    {"phn", "Phoenician"},
+    {"pli", "Pali"},
+    {"pol", "Polish"},
+    {"pon", "Pohnpeian"},
+    {"por", "Portuguese"},
+    {"pra", "Prakrit languages"},
+    {"pro", "Proven�al, Old (to 1500)"},
+    {"pus", "Pushto"},
+    {"que", "Quechua"},
+    {"raj", "Rajasthani"},
+    {"rap", "Rapanui"},
+    {"rar", "Rarotongan"},
+    {"roa", "Romance (Other)"},
+    {"roh", "Raeto-Romance"},
+    {"rom", "Romany"},
+    {"rum", "Romanian"},
+    {"ron", "Romanian"},
+    {"run", "Rundi"},
+    {"rup", "Aromanian; Arumanian; Macedo-Romanian"},
+    {"rus", "Russian"},
+    {"sad", "Sandawe"},
+    {"sag", "Sango"},
+    {"sah", "Yakut"},
+    {"sai", "South American Indian (Other)"},
+    {"sal", "Salishan languages"},
+    {"sam", "Samaritan Aramaic"},
+    {"san", "Sanskrit"},
+    {"sas", "Sasak"},
+    {"sat", "Santali"},
+    {"scc", "Serbian"},
+    {"srp", "Serbian"},
+    {"scn", "Sicilian"},
+    {"sco", "Scots"},
+    {"scr", "Croatian"},
+    {"hrv", "Croatian"},
+    {"sel", "Selkup"},
+    {"sem", "Semitic (Other)"},
+    {"sga", "Irish, Old (to 900)"},
+    {"sgn", "Sign Languages"},
+    {"shn", "Shan"},
+    {"sid", "Sidamo"},
+    {"sin", "Sinhala; Sinhalese"},
+    {"sio", "Siouan languages"},
+    {"sit", "Sino-Tibetan (Other)"},
+    {"sla", "Slavic (Other)"},
+    {"slo", "Slovak"},
+    {"slk", "Slovak"},
+    {"slv", "Slovenian"},
+    {"sma", "Southern Sami"},
+    {"sme", "Northern Sami"},
+    {"smi", "Sami languages (Other)"},
+    {"smj", "Lule Sami"},
+    {"smn", "Inari Sami"},
+    {"smo", "Samoan"},
+    {"sms", "Skolt Sami"},
+    {"sna", "Shona"},
+    {"snd", "Sindhi"},
+    {"snk", "Soninke"},
+    {"sog", "Sogdian"},
+    {"som", "Somali"},
+    {"son", "Songhai"},
+    {"sot", "Sotho, Southern"},
+    {"spa", "Spanish; Castilian"},
+    {"srd", "Sardinian"},
+    {"srn", "Sranan Togo"},
+    {"srr", "Serer"},
+    {"ssa", "Nilo-Saharan (Other)"},
+    {"ssw", "Swati"},
+    {"suk", "Sukuma"},
+    {"sun", "Sundanese"},
+    {"sus", "Susu"},
+    {"sux", "Sumerian"},
+    {"swa", "Swahili"},
+    {"swe", "Swedish"},
+    {"syr", "Syriac"},
+    {"tah", "Tahitian"},
+    {"tai", "Tai (Other)"},
+    {"tam", "Tamil"},
+    {"tat", "Tatar"},
+    {"tel", "Telugu"},
+    {"tem", "Timne"},
+    {"ter", "Tereno"},
+    {"tet", "Tetum"},
+    {"tgk", "Tajik"},
+    {"tgl", "Tagalog"},
+    {"tha", "Thai"},
+    {"tib", "Tibetan"},
+    {"bod", "Tibetan"},
+    {"tig", "Tigre"},
+    {"tir", "Tigrinya"},
+    {"tiv", "Tiv"},
+    {"tkl", "Tokelau"},
+    {"tlh", "Klingon; tlhIngan-Hol"},
+    {"tli", "Tlingit"},
+    {"tmh", "Tamashek"},
+    {"tog", "Tonga (Nyasa)"},
+    {"ton", "Tonga (Tonga Islands)"},
+    {"tpi", "Tok Pisin"},
+    {"tsi", "Tsimshian"},
+    {"tsn", "Tswana"},
+    {"tso", "Tsonga"},
+    {"tuk", "Turkmen"},
+    {"tum", "Tumbuka"},
+    {"tup", "Tupi languages"},
+    {"tur", "Turkish"},
+    {"tut", "Altaic (Other)"},
+    {"tvl", "Tuvalu"},
+    {"twi", "Twi"},
+    {"tyv", "Tuvinian"},
+    {"udm", "Udmurt"},
+    {"uga", "Ugaritic"},
+    {"uig", "Uighur; Uyghur"},
+    {"ukr", "Ukrainian"},
+    {"umb", "Umbundu"},
+    {"und", "Undetermined"},
+    {"urd", "Urdu"},
+    {"uzb", "Uzbek"},
+    {"vai", "Vai"},
+    {"ven", "Venda"},
+    {"vie", "Vietnamese"},
+    {"vol", "Volap�k"},
+    {"vot", "Votic"},
+    {"wak", "Wakashan languages"},
+    {"wal", "Walamo"},
+    {"war", "Waray"},
+    {"was", "Washo"},
+    {"wel", "Welsh"},
+    {"cym", "Welsh"},
+    {"wen", "Sorbian languages"},
+    {"wln", "Walloon"},
+    {"wol", "Wolof"},
+    {"xal", "Kalmyk; Oirat"},
+    {"xho", "Xhosa"},
+    {"yao", "Yao"},
+    {"yap", "Yapese"},
+    {"yid", "Yiddish"},
+    {"yor", "Yoruba"},
+    {"ypk", "Yupik languages"},
+    {"zap", "Zapotec"},
+    {"zen", "Zenaga"},
+    {"zha", "Zhuang; Chuang"},
+    {"znd", "Zande"},
+    {"zul", "Zulu"},
+    {"zun", "Zuni"},
+    {"zxx", "No linguistic content"},
+    {"zza", "Zaza; Dimili; Dimli; Kirdki..."}
+};
+
+/* Get language name from ISO */
+
+string GetISOLanguageName(const string strA3)
+{
+    for (int i = 0; i < LEN_TABLE_ISO_LANGUAGE_CODE; i++)
+    {
+        if (!strA3.compare(TableISOLanguageCode[i].strISOCode))
+            return TableISOLanguageCode[i].strDesc;
+    }
+
+    return "";
+}
+
+
+/* CIRAF zones */
+
+const string strTableCIRAFzones[LEN_TABLE_CIRAF_ZONES] = {
+    "", /* 0 undefined */
+    "Alaska", /* 1 */
+    "west Canada", /* 2 */
+    "central Canada - west", /* 3 */
+    "central Canada - east, Baffin Island", /* 4 */
+    "Greenland", /* 5 */
+    "west USA", /* 6 */
+    "central USA", /* 7 */
+    "east USA", /* 8 */
+    "east Canada", /* 9 */
+    "Belize, Guatemala, Mexico", /* 10 */
+    "Caribbean, central America",  /* 11 */
+    "northwestern south America", /* 12 */
+    "northeast Brazil", /* 13 */
+    "southwestern south America", /* 14 */
+    "southeast Brazil",  /* 15 */
+    "south Argentina, south Chile, Falkland Islands", /* 16 */
+    "Iceland", /* 17 */
+    "Scandinavia", /* 18 */
+    "west Russia northwest", /* 19 */
+    "west Russia north", /* 20 */
+    "central Russia northwest", /* 21 */
+    "central Russia north", /* 22 */
+    "central Russia east", /* 23 */
+    "east Russia northwest", /* 24 */
+    "east Russia north", /* 25 */
+    "east Russia northeast", /* 26 */
+    "northwest Europe", /* 27 */
+    "central east south Europe", /* 28 */
+    "Baltics and west Russia", /* 29 */
+    "central Asia, west Russia southeast", /* 30 */
+    "central Russia southwest, east Kazakhstan, east Kyrgyzstan", /* 31 */
+    "central Russia south, west Mongolia", /* 32 */
+    "central Russia southeast, east Mongolia", /* 33 */
+    "east Russia southwest: Sakhalin, Sikhote Alin", /* 34 */
+    "east Russia east: Kamchatka", /* 35 */
+    "Azores, Canary Island, Madeira", /* 36 */
+    "southwest Europe, northwest Africa", /* 37 */
+    "Egypt, Libya", /* 38 */
+    "Middle East", /* 39 */
+    "Afghanistan, Iran", /* 40 */
+    "Bangladesh, Bhutan, India, Nepal, Pakistan", /* 41 */
+    "west China", /* 42 */
+    "central China", /* 43 */
+    "east China, Macao, Hong Kong, North Korea, South Korea, Taiwan", /* 44 */
+    "Japan", /* 45 */
+    "west Africa", /* 46 */
+    "west Sudan", /* 47 */
+    "Horn of Africa", /* 48 */
+    "Kampuchea, Laos, Myanmar, Vietnam", /* 49 */
+    "Philippines", /* 50 */
+    "Malaysia, Papua New Guinea, west Indonesia", /* 51 */
+    "Angola, Burundi, Congo, Gabon, Zaire", /* 52 */
+    "Madagascar, Malawi, Mozambique, Seychelles, Zambia, Zimbabwe", /* 53 */
+    "Malaysia, Singapore, west Indonesia", /* 54 */
+    "northeast Australia", /* 55 */
+    "Caledonia, Fiji/Vanuatu", /* 56 */
+    "Botswana, Lesotho, Namibia, Swaziland, South African Republic", /* 57 */
+    "west Australia", /* 58 */
+    "southeast Australia", /* 59 */
+    "New Zealand", /* 60 */
+    "Hawaii", /* 61 */
+    "Phoenix Islands, Samoa", /* 62 */
+    "Cook Islands, Polynesia", /* 63 */
+    "Guam/Palau, Saipan", /* 64 */
+    "Kiribati, Marshall", /* 65 */
+    "central Atlantic - south: Ascension, St. Helena", /* 66 */
+    "Antarctica", /* 67 */
+    "southwest Indian Ocean: Kerguelen", /* 68 */
+    "Antarctica", /* 69 */
+    "Antarctica", /* 70 */
+    "Antarctica", /* 71 */
+    "Antarctica", /* 72 */
+    "Antarctica", /* 73 */
+    "South Pole", /* 74 */
+    "North Pole", /* 75 */
+    "northeast Pacific", /* 76 */
+    "central Pacific - northeast", /* 77 */
+    "central Pacific - southeast", /* 78 */
+    "central Indian Ocean", /* 79 */
+    "northern Atlantic", /* 80 */
+    "central Atlantic", /* 81 */
+    "northwest Pacific", /* 82 */
+    "south Pacific", /* 83 */
+    "south Atlantic", /* 84 */
+    "southeast Indian Ocean" /* 85 */
+};
diff --git a/src/tables/TableFAC.h b/src/tables/TableFAC.h
new file mode 100644
index 0000000..b768614
--- /dev/null
+++ b/src/tables/TableFAC.h
@@ -0,0 +1,101 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *	Tables for FAC
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#if !defined(TABLE_FAC_H__3B0_CA63_4344_BGDEB2B_23E7912__INCLUDED_)
+#define TABLE_FAC_H__3B0_CA63_4344_BGDEB2B_23E7912__INCLUDED_
+
+#include <string>
+#include "../GlobalDefinitions.h"
+
+/* Definitions ****************************************************************/
+/* ETSI ES201980V2.1.1: page 115, 7.5.3: ...FAC shall use 4-QAM mapping. A
+   fixed code rate shall be applied...R_all=0.6...
+   6 tailbits are used for the encoder to get in zero state ->
+   65 [number of cells] * 2 [4-QAM] * 0.6 [code-rate] - 6 [tailbits] = 72 */
+#define NUM_FAC_BITS_PER_BLOCK_DRM30	72
+#define NUM_FAC_BITS_PER_BLOCK_DRMPLUS 120
+
+/* iTableNumOfServices[a][b]
+   a: Number of audio services
+   b: Number of data services
+   (6.3.4) */
+extern const int iTableNumOfServices[5][5];
+
+/* Language code */
+#define LEN_TABLE_LANGUAGE_CODE			16
+
+extern const string strTableLanguageCode[LEN_TABLE_LANGUAGE_CODE];
+
+/* Programme Type codes */
+#define LEN_TABLE_PROG_TYPE_CODE_TOT	32
+#define LEN_TABLE_PROG_TYPE_CODE		30
+
+extern const string strTableProgTypCod[LEN_TABLE_PROG_TYPE_CODE_TOT];
+
+/* Country code table according to ISO 3166 */
+
+#define LEN_TABLE_COUNTRY_CODE			244
+
+#define LEN_COUNTRY_CODE				2
+#define MAX_LEN_DESC_COUNTRY_CODE		44
+
+struct elCountry {
+    char	strcode [LEN_COUNTRY_CODE+1];
+    char	strDesc [MAX_LEN_DESC_COUNTRY_CODE+1];
+};
+
+extern const struct elCountry TableCountryCode[LEN_TABLE_COUNTRY_CODE];
+
+/* Get country name from ISO 3166 A2 */
+
+string GetISOCountryName(const string strA2);
+
+/* Language code table according to ISO/IEC 639-2 */
+
+#define LEN_TABLE_ISO_LANGUAGE_CODE			505
+
+#define LEN_ISO_LANGUAGE_CODE				3
+#define MAX_LEN_DESC_ISO_LANGUAGE_CODE		44
+
+struct elLanguage {
+    char	strISOCode [LEN_ISO_LANGUAGE_CODE+1];
+    char	strDesc [MAX_LEN_DESC_ISO_LANGUAGE_CODE+1];
+};
+
+extern const struct elLanguage TableISOLanguageCode[LEN_TABLE_ISO_LANGUAGE_CODE];
+
+/* Get language name from ISO 3166 */
+
+string GetISOLanguageName(const string strA3);
+
+/* CIRAF zones */
+#define LEN_TABLE_CIRAF_ZONES			86
+
+extern const string strTableCIRAFzones[LEN_TABLE_CIRAF_ZONES];
+
+#endif // !defined(TABLE_FAC_H__3B0_CA63_4344_BGDEB2B_23E7912__INCLUDED_)
diff --git a/src/tables/TableMLC.h b/src/tables/TableMLC.h
new file mode 100644
index 0000000..aa03d38
--- /dev/null
+++ b/src/tables/TableMLC.h
@@ -0,0 +1,511 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *	Tables for MLC
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#if !defined(_TABLE_MLC_H__3B0_CA63_4344_BB2B_23E7912__INCLUDED_)
+#define _TABLE_MLC_H__3B0_CA63_4344_BB2B_23E7912__INCLUDED_
+
+#include "../GlobalDefinitions.h"
+
+
+/* Definitions ****************************************************************/
+/* Default number of iterations at application startup */
+#define MC_NUM_ITERATIONS				1
+
+/* Generator polynomials used for channel coding (octal form, defined by
+   a leading "0"!). We must bit-reverse the octal-forms given in the standard
+   since we shift bits from right to the left! */
+/* In this implementation we shift bits from right to left, therefore the order
+   of the code-words are: [..., b_(0, i), b_(1, i), b(2, i), b(3, i), ...] */
+#define MC_NUM_OUTPUT_BITS_PER_STEP		4	/* MC: Multi-level Coder */
+const _BYTE byGeneratorMatrix[MC_NUM_OUTPUT_BITS_PER_STEP] = {
+    0155,	/* (133) x_{0, i} */
+    0117,	/* (171) x_{1, i} */
+    0123,	/* (145) x_{2, i} */
+    0155	/* (133) x_{3, i} */
+};
+
+#define MC_CONSTRAINT_LENGTH			7
+
+/* Since we have a periodical structure in the trellis it
+   is enough to build one step. 2^(MC_CONSTRAINT_LENGTH - 1) states have
+   to be considered. ("- 1": since one bit is the transition to the next
+   state) */
+#define MC_NUM_STATES					(1 << (MC_CONSTRAINT_LENGTH - 1))
+#define MC_NUM_OUTPUT_COMBINATIONS		(1 << MC_NUM_OUTPUT_BITS_PER_STEP)
+
+/* Maximum number of levels (Its in case of HMmix) */
+#define MC_MAX_NUM_LEVELS				6
+
+
+/* Puncturing --------------------------------------------------------------- */
+/* Only these types of patterns are used in DRM */
+#define PP_TYPE_0000					0 /* not used, dummy */
+#define PP_TYPE_1111					1
+#define PP_TYPE_0111					2
+#define PP_TYPE_0011					3
+#define PP_TYPE_0001					4
+#define PP_TYPE_0101					5
+
+/* {a, b, c ...}: a = Number of groups, b = Number of "1"s, c = Patterns */
+const uint32_t iPuncturingPatterns[13][10] = {
+    /*
+    B0: 1
+    B1: 1
+    B2: 1
+    B3: 1
+    */
+    {1, 4,
+        PP_TYPE_1111,
+        PP_TYPE_0000,
+        PP_TYPE_0000,
+        PP_TYPE_0000,
+        PP_TYPE_0000,
+        PP_TYPE_0000,
+        PP_TYPE_0000,
+        PP_TYPE_0000},
+
+    /*
+    B0: 1 1 1
+    B1: 1 1 1
+    B2: 1 1 1
+    B3: 1 0 0
+    */
+    {3, 10,
+     PP_TYPE_1111,
+     PP_TYPE_0111,
+     PP_TYPE_0111,
+     PP_TYPE_0000,
+     PP_TYPE_0000,
+     PP_TYPE_0000,
+     PP_TYPE_0000,
+     PP_TYPE_0000},
+
+    /*
+    B0: 1
+    B1: 1
+    B2: 1
+    B3: 0
+    */
+    {1, 3,
+     PP_TYPE_0111,
+     PP_TYPE_0000,
+     PP_TYPE_0000,
+     PP_TYPE_0000,
+     PP_TYPE_0000,
+     PP_TYPE_0000,
+     PP_TYPE_0000,
+     PP_TYPE_0000},
+
+    /*
+    B0: 1 1 1 1
+    B1: 1 1 1 1
+    B2: 1 1 1 0
+    B3: 0 0 0 0
+    */
+    {4, 11,
+     PP_TYPE_0111,
+     PP_TYPE_0111,
+     PP_TYPE_0111,
+     PP_TYPE_0011,
+     PP_TYPE_0000,
+     PP_TYPE_0000,
+     PP_TYPE_0000,
+     PP_TYPE_0000},
+
+    /*
+    B0: 1
+    B1: 1
+    B2: 0
+    B3: 0
+    */
+    {1, 2,
+     PP_TYPE_0011,
+     PP_TYPE_0000,
+     PP_TYPE_0000,
+     PP_TYPE_0000,
+     PP_TYPE_0000,
+     PP_TYPE_0000,
+     PP_TYPE_0000,
+     PP_TYPE_0000},
+
+    /*
+    B0: 1 1 1 1
+    B1: 1 0 1 0
+    B2: 0 1 0 0
+    B3: 0 0 0 0
+    */
+    {4, 7,
+     PP_TYPE_0011,
+     PP_TYPE_0101,
+     PP_TYPE_0011,
+     PP_TYPE_0001,
+     PP_TYPE_0000,
+     PP_TYPE_0000,
+     PP_TYPE_0000,
+     PP_TYPE_0000},
+
+    /*
+    B0: 1 1 1
+    B1: 1 0 1
+    B2: 0 0 0
+    B3: 0 0 0
+    */
+    {3, 5,
+     PP_TYPE_0011,
+     PP_TYPE_0001,
+     PP_TYPE_0011,
+     PP_TYPE_0000,
+     PP_TYPE_0000,
+     PP_TYPE_0000,
+     PP_TYPE_0000,
+     PP_TYPE_0000},
+
+    /*
+    B0: 1 1
+    B1: 1 0
+    B2: 0 0
+    B3: 0 0
+    */
+    {2, 3,
+     PP_TYPE_0011,
+     PP_TYPE_0001,
+     PP_TYPE_0000,
+     PP_TYPE_0000,
+     PP_TYPE_0000,
+     PP_TYPE_0000,
+     PP_TYPE_0000,
+     PP_TYPE_0000},
+
+    /*
+    B0: 1 1 1 1 1 1 1 1
+    B1: 1 0 0 1 0 0 1 0
+    B2: 0 0 0 0 0 0 0 0
+    B3: 0 0 0 0 0 0 0 0
+    */
+    {8, 11,
+     PP_TYPE_0011,
+     PP_TYPE_0001,
+     PP_TYPE_0001,
+     PP_TYPE_0011,
+     PP_TYPE_0001,
+     PP_TYPE_0001,
+     PP_TYPE_0011,
+     PP_TYPE_0001},
+
+    /*
+    B0: 1 1 1
+    B1: 1 0 0
+    B2: 0 0 0
+    B3: 0 0 0
+    */
+    {3, 4,
+     PP_TYPE_0011,
+     PP_TYPE_0001,
+     PP_TYPE_0001,
+     PP_TYPE_0000,
+     PP_TYPE_0000,
+     PP_TYPE_0000,
+     PP_TYPE_0000,
+     PP_TYPE_0000},
+
+    /*
+    B0: 1 1 1 1
+    B1: 1 0 0 0
+    B2: 0 0 0 0
+    B3: 0 0 0 0
+    */
+    {4, 5,
+     PP_TYPE_0011,
+     PP_TYPE_0001,
+     PP_TYPE_0001,
+     PP_TYPE_0001,
+     PP_TYPE_0000,
+     PP_TYPE_0000,
+     PP_TYPE_0000,
+     PP_TYPE_0000},
+
+    /*
+    B0: 1 1 1 1 1 1 1
+    B1: 1 0 0 0 0 0 0
+    B2: 0 0 0 0 0 0 0
+    B3: 0 0 0 0 0 0 0
+    */
+    {7, 8,
+     PP_TYPE_0011,
+     PP_TYPE_0001,
+     PP_TYPE_0001,
+     PP_TYPE_0001,
+     PP_TYPE_0001,
+     PP_TYPE_0001,
+     PP_TYPE_0001,
+     PP_TYPE_0000},
+
+    /*
+    B0: 1 1 1 1 1 1 1 1
+    B1: 1 0 0 0 0 0 0 0
+    B2: 0 0 0 0 0 0 0 0
+    B3: 0 0 0 0 0 0 0 0
+    */
+    {8, 9,
+     PP_TYPE_0011,
+     PP_TYPE_0001,
+     PP_TYPE_0001,
+     PP_TYPE_0001,
+     PP_TYPE_0001,
+     PP_TYPE_0001,
+     PP_TYPE_0001,
+     PP_TYPE_0001}
+};
+
+/* Puncturing patterns for tailbits */
+#define LENGTH_TAIL_BIT_PAT				6
+const uint32_t iPunctPatTailbits[12][LENGTH_TAIL_BIT_PAT] = {
+    /*
+    B0: 1 1 1 1 1 1
+    B1: 1 1 1 1 1 1
+    B2: 0 0 0 0 0 0
+    B3: 0 0 0 0 0 0
+    */
+    {PP_TYPE_0011,
+        PP_TYPE_0011,
+        PP_TYPE_0011,
+        PP_TYPE_0011,
+        PP_TYPE_0011,
+        PP_TYPE_0011},
+
+    /*
+    B0: 1 1 1 1 1 1
+    B1: 1 1 1 1 1 1
+    B2: 1 0 0 0 0 0
+    B3: 0 0 0 0 0 0
+    */
+    {PP_TYPE_0111,
+     PP_TYPE_0011,
+     PP_TYPE_0011,
+     PP_TYPE_0011,
+     PP_TYPE_0011,
+     PP_TYPE_0011},
+
+    /*
+    B0: 1 1 1 1 1 1
+    B1: 1 1 1 1 1 1
+    B2: 1 0 0 1 0 0
+    B3: 0 0 0 0 0 0
+    */
+    {PP_TYPE_0111,
+     PP_TYPE_0011,
+     PP_TYPE_0011,
+     PP_TYPE_0111,
+     PP_TYPE_0011,
+     PP_TYPE_0011},
+
+    /*
+    B0: 1 1 1 1 1 1
+    B1: 1 1 1 1 1 1
+    B2: 1 1 0 1 0 0
+    B3: 0 0 0 0 0 0
+    */
+    {PP_TYPE_0111,
+     PP_TYPE_0111,
+     PP_TYPE_0011,
+     PP_TYPE_0111,
+     PP_TYPE_0011,
+     PP_TYPE_0011},
+
+    /*
+    B0: 1 1 1 1 1 1
+    B1: 1 1 1 1 1 1
+    B2: 1 1 0 1 1 0
+    B3: 0 0 0 0 0 0
+    */
+    {PP_TYPE_0111,
+     PP_TYPE_0111,
+     PP_TYPE_0011,
+     PP_TYPE_0111,
+     PP_TYPE_0111,
+     PP_TYPE_0011},
+
+    /*
+    B0: 1 1 1 1 1 1
+    B1: 1 1 1 1 1 1
+    B2: 1 1 1 1 1 0
+    B3: 0 0 0 0 0 0
+    */
+    {PP_TYPE_0111,
+     PP_TYPE_0111,
+     PP_TYPE_0111,
+     PP_TYPE_0111,
+     PP_TYPE_0111,
+     PP_TYPE_0011},
+
+    /*
+    B0: 1 1 1 1 1 1
+    B1: 1 1 1 1 1 1
+    B2: 1 1 1 1 1 1
+    B3: 0 0 0 0 0 0
+    */
+    {PP_TYPE_0111,
+     PP_TYPE_0111,
+     PP_TYPE_0111,
+     PP_TYPE_0111,
+     PP_TYPE_0111,
+     PP_TYPE_0111},
+
+    /*
+    B0: 1 1 1 1 1 1
+    B1: 1 1 1 1 1 1
+    B2: 1 1 1 1 1 1
+    B3: 1 0 0 0 0 0
+    */
+    {PP_TYPE_1111,
+     PP_TYPE_0111,
+     PP_TYPE_0111,
+     PP_TYPE_0111,
+     PP_TYPE_0111,
+     PP_TYPE_0111},
+
+    /*
+    B0: 1 1 1 1 1 1
+    B1: 1 1 1 1 1 1
+    B2: 1 1 1 1 1 1
+    B3: 1 0 0 1 0 0
+    */
+    {PP_TYPE_1111,
+     PP_TYPE_0111,
+     PP_TYPE_0111,
+     PP_TYPE_1111,
+     PP_TYPE_0111,
+     PP_TYPE_0111},
+
+    /*
+    B0: 1 1 1 1 1 1
+    B1: 1 1 1 1 1 1
+    B2: 1 1 1 1 1 1
+    B3: 1 1 0 1 0 0
+    */
+    {PP_TYPE_1111,
+     PP_TYPE_1111,
+     PP_TYPE_0111,
+     PP_TYPE_1111,
+     PP_TYPE_0111,
+     PP_TYPE_0111},
+
+    /*
+    B0: 1 1 1 1 1 1
+    B1: 1 1 1 1 1 1
+    B2: 1 1 1 1 1 1
+    B3: 1 1 0 1 0 1
+    */
+    {PP_TYPE_1111,
+     PP_TYPE_1111,
+     PP_TYPE_0111,
+     PP_TYPE_1111,
+     PP_TYPE_0111,
+     PP_TYPE_1111},
+
+    /*
+    B0: 1 1 1 1 1 1
+    B1: 1 1 1 1 1 1
+    B2: 1 1 1 1 1 1
+    B3: 1 1 1 1 0 1
+    */
+    {PP_TYPE_1111,
+     PP_TYPE_1111,
+     PP_TYPE_1111,
+     PP_TYPE_1111,
+     PP_TYPE_0111,
+     PP_TYPE_1111},
+};
+
+
+/* Code rate combinations --------------------------------------------------- */
+/* row-index: protection level */
+/* {a, b, c}: a = R_0, b = R_1, c = RY_Icm */
+const int iCodRateCombMSC16SM[2][3] = {
+    {2, 7, 3},
+    {4, 9, 4}
+};
+
+/* {a, b, c, d}: a = R_0, b = R_1, c = R_2, d = RY_Icm */
+const int iCodRateCombMSC64SM[4][4] = {
+    {0,  4,  9,  4},
+    {2,  7, 10, 15},
+    {4,  9, 11,  8},
+    {7, 10, 12, 45}
+};
+
+/* {a, b, c, d}: a = R_0, b = R_1, c = R_2, d = RY_Icm */
+const int iCodRateCombMSC64HMsym[4][4] = {
+    {4, 1,  6, 10},
+    {5, 3,  8, 11},
+    {6, 5, 11, 56},
+    {7, 7, 12,  9}
+};
+
+/* {a, b, c, d, e, f, g}: a = R_0Re, b = R_0Im, c = R_1Re, d = R_1Im,
+   e = R_2Re, f = R_2Im, g = RY_Icm */
+const int iCodRateCombMSC64HMmix[4][7] = {
+    {4, 0, 1,  4,  6,  9,  20},
+    {5, 2, 3,  7,  8, 10, 165},
+    {6, 4, 5,  9, 11, 11,  56},
+    {7, 7, 7, 10, 12, 12,  45}
+};
+
+/* {a, b}: a = R_0, b = R_1 */
+const int iCodRateCombSDC16SM[2] = {
+    2, 7
+};
+
+/* {a}: a = R_0 */
+const int iCodRateCombSDC4SM = {
+    4
+};
+
+/* {a}: a = R_0 */
+const int iCodRateCombFDC4SM = {
+    6
+};
+
+
+/* Interleaver sequence ----------------------------------------------------- */
+/* The different coding modes in DRM use bit-interleavers in certain paths. We
+   define the following vectors to store the position and type of the
+   interleaver as described in the DRM-standard
+
+   Interleaver modules have to be initialized in the way:
+   [0]: t_0 = 13;
+   [1]: t_0 = 21;
+   "-1": no interleaver in this level */
+const int iInterlSequ4SM[MC_MAX_NUM_LEVELS] =     { 1, -1, -1, -1, -1, -1};
+const int iInterlSequ16SM[MC_MAX_NUM_LEVELS] =    { 0,  1, -1, -1, -1, -1};
+const int iInterlSequ64SM[MC_MAX_NUM_LEVELS] =    {-1,  0,  1, -1, -1, -1};
+const int iInterlSequ64HMsym[MC_MAX_NUM_LEVELS] = {-1,  0,  1, -1, -1, -1};
+const int iInterlSequ64HMmix[MC_MAX_NUM_LEVELS] = {-1, -1,  0,  0,  1,  1};
+
+
+#endif // !defined(_TABLE_MLC_H__3B0_CA63_4344_BB2B_23E7912__INCLUDED_)
diff --git a/src/tables/TableQAMMapping.h b/src/tables/TableQAMMapping.h
new file mode 100644
index 0000000..37790c8
--- /dev/null
+++ b/src/tables/TableQAMMapping.h
@@ -0,0 +1,316 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *	Tables for QAM mapping (Mapping is already normalized)
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#if !defined(QAM_MAPPING_H__3B0_CA63_4344_BB2B_23E7912__INCLUDED_)
+#define QAM_MAPPING_H__3B0_CA63_4344_BB2B_23E7912__INCLUDED_
+
+#include "../matlib/Matlib.h"
+#include "../GlobalDefinitions.h"
+
+
+/* Definitions ****************************************************************/
+/* Input bits are collected in bytes separately for imaginary and real part.
+   The order is: [i_0, i_1, i_2] and [q_0, q_1, q_2] -> {i, q}
+   All entries are normalized according to the DRM-standard */
+const _REAL rTableQAM64SM[8][2] = {
+    { 1.0801234497f,  1.0801234497f},
+    {-0.1543033499f, -0.1543033499f},
+    { 0.4629100498f,  0.4629100498f},
+    {-0.7715167498f, -0.7715167498f},
+    { 0.7715167498f,  0.7715167498f},
+    {-0.4629100498f, -0.4629100498f},
+    { 0.1543033499f,  0.1543033499f},
+    {-1.0801234497f, -1.0801234497f}
+};
+
+const _REAL rTableQAM64HMsym[8][2] = {
+    { 1.0801234497f,  1.0801234497f},
+    { 0.4629100498f,  0.4629100498f},
+    { 0.7715167498f,  0.7715167498f},
+    { 0.1543033499f,  0.1543033499f},
+    {-0.1543033499f, -0.1543033499f},
+    {-0.7715167498f, -0.7715167498f},
+    {-0.4629100498f, -0.4629100498f},
+    {-1.0801234497f, -1.0801234497f}
+};
+
+const _REAL rTableQAM64HMmix[8][2] = {
+    { 1.0801234497f,  1.0801234497f},
+    { 0.4629100498f, -0.1543033499f},
+    { 0.7715167498f,  0.4629100498f},
+    { 0.1543033499f, -0.7715167498f},
+    {-0.1543033499f,  0.7715167498f},
+    {-0.7715167498f, -0.4629100498f},
+    {-0.4629100498f,  0.1543033499f},
+    {-1.0801234497f, -1.0801234497f}
+};
+
+const _REAL rTableQAM16[4][2] = {
+    { 0.9486832980f,  0.9486832980f},
+    {-0.3162277660f, -0.3162277660f},
+    { 0.3162277660f,  0.3162277660f},
+    {-0.9486832980f, -0.9486832980f}
+};
+
+const _REAL rTableQAM4[2][2] = {
+    { 0.7071067811f,  0.7071067811f},
+    {-0.7071067811f, -0.7071067811f}
+};
+
+
+/* Global functions ***********************************************************/
+/*
+	----------------------------------------------------------------------------
+	Implementation of distance to nearest constellation point (symbol) for all
+	QAM types
+*/
+inline CComplex MinDist4QAM(const CComplex cI)
+{
+    /* Return vector pointing to nearest signal point of this constellation.
+       2 possible constellation points for real and imaginary axis */
+    return CComplex(
+               /* Real axis minimum distance */
+               Min(Abs(rTableQAM4[0][0] - Real(cI)), Abs(rTableQAM4[1][0] - Real(cI))),
+               /* Imaginary axis minimum distance */
+               Min(Abs(rTableQAM4[0][1] - Imag(cI)), Abs(rTableQAM4[1][1] - Imag(cI))));
+}
+
+inline CComplex MinDist16QAM(const CComplex cI)
+{
+    /* Return vector pointing to nearest signal point of this constellation.
+       4 possible constellation points for real and imaginary axis */
+    return CComplex(
+               /* Real axis minimum distance */
+               Min(Abs(rTableQAM16[0][0] - Real(cI)), Abs(rTableQAM16[1][0] - Real(cI)),
+                   Abs(rTableQAM16[2][0] - Real(cI)), Abs(rTableQAM16[3][0] - Real(cI))),
+               /* Imaginary axis minimum distance */
+               Min(Abs(rTableQAM16[0][1] - Imag(cI)), Abs(rTableQAM16[1][1] - Imag(cI)),
+                   Abs(rTableQAM16[2][1] - Imag(cI)), Abs(rTableQAM16[3][1] - Imag(cI))));
+}
+
+inline CComplex MinDist64QAM(const CComplex cI)
+{
+    /* Return vector pointing to nearest signal point of this constellation.
+       8 possible constellation points for real and imaginary axis */
+    return CComplex(
+               /* Real axis minimum distance */
+               Min(Abs(rTableQAM64SM[0][0] - Real(cI)), Abs(rTableQAM64SM[1][0] - Real(cI)),
+                   Abs(rTableQAM64SM[2][0] - Real(cI)), Abs(rTableQAM64SM[3][0] - Real(cI)),
+                   Abs(rTableQAM64SM[4][0] - Real(cI)), Abs(rTableQAM64SM[5][0] - Real(cI)),
+                   Abs(rTableQAM64SM[6][0] - Real(cI)), Abs(rTableQAM64SM[7][0] - Real(cI))),
+               /* Imaginary axis minimum distance */
+               Min(Abs(rTableQAM64SM[0][1] - Imag(cI)), Abs(rTableQAM64SM[1][1] - Imag(cI)),
+                   Abs(rTableQAM64SM[2][1] - Imag(cI)), Abs(rTableQAM64SM[3][1] - Imag(cI)),
+                   Abs(rTableQAM64SM[4][1] - Imag(cI)), Abs(rTableQAM64SM[5][1] - Imag(cI)),
+                   Abs(rTableQAM64SM[6][1] - Imag(cI)), Abs(rTableQAM64SM[7][1] - Imag(cI))));
+}
+
+
+/*
+	----------------------------------------------------------------------------
+	Implementation of hard decision for all QAM types
+*/
+inline CComplex Dec4QAM(const CComplex cI)
+{
+    CReal rDecRe, rDecIm;
+
+    /* Real */
+    if (Abs(rTableQAM4[0][0] - Real(cI)) < Abs(rTableQAM4[1][0] - Real(cI)))
+        rDecRe = rTableQAM4[0][0];
+    else
+        rDecRe = rTableQAM4[1][0];
+
+    /* Imaginary */
+    if (Abs(rTableQAM4[0][1] - Imag(cI)) < Abs(rTableQAM4[1][1] - Imag(cI)))
+        rDecIm = rTableQAM4[0][1];
+    else
+        rDecIm = rTableQAM4[1][1];
+
+    return CComplex(rDecRe, rDecIm);
+}
+
+inline CComplex Dec16QAM(const CComplex cI)
+{
+    CReal rCurDist;
+
+    /* Real */
+    CReal rMinDist = Abs(rTableQAM16[0][0] - Real(cI));
+    CReal rDecRe = rTableQAM16[0][0];
+
+    rCurDist = Abs(rTableQAM16[1][0] - Real(cI));
+    if (rCurDist < rMinDist)
+    {
+        rMinDist = rCurDist;
+        rDecRe = rTableQAM16[1][0];
+    }
+
+    rCurDist = Abs(rTableQAM16[2][0] - Real(cI));
+    if (rCurDist < rMinDist)
+    {
+        rMinDist = rCurDist;
+        rDecRe = rTableQAM16[2][0];
+    }
+
+    rCurDist = Abs(rTableQAM16[3][0] - Real(cI));
+    if (rCurDist < rMinDist)
+        rDecRe = rTableQAM16[3][0];
+
+    /* Imaginary */
+    rMinDist = Abs(rTableQAM16[0][1] - Imag(cI));
+    CReal rDecIm = rTableQAM16[0][1];
+
+    rCurDist = Abs(rTableQAM16[1][1] - Imag(cI));
+    if (rCurDist < rMinDist)
+    {
+        rMinDist = rCurDist;
+        rDecIm = rTableQAM16[1][1];
+    }
+
+    rCurDist = Abs(rTableQAM16[2][1] - Imag(cI));
+    if (rCurDist < rMinDist)
+    {
+        rMinDist = rCurDist;
+        rDecIm = rTableQAM16[2][1];
+    }
+
+    rCurDist = Abs(rTableQAM16[3][1] - Imag(cI));
+    if (rCurDist < rMinDist)
+        rDecIm = rTableQAM16[3][1];
+
+    return CComplex(rDecRe, rDecIm);
+}
+
+inline CComplex Dec64QAM(const CComplex cI)
+{
+    CReal rCurDist;
+
+    /* Real */
+    CReal rMinDist = Abs(rTableQAM64SM[0][0] - Real(cI));
+    CReal rDecRe = rTableQAM64SM[0][0];
+
+    rCurDist = Abs(rTableQAM64SM[1][0] - Real(cI));
+    if (rCurDist < rMinDist)
+    {
+        rMinDist = rCurDist;
+        rDecRe = rTableQAM64SM[1][0];
+    }
+
+    rCurDist = Abs(rTableQAM64SM[2][0] - Real(cI));
+    if (rCurDist < rMinDist)
+    {
+        rMinDist = rCurDist;
+        rDecRe = rTableQAM64SM[2][0];
+    }
+
+    rCurDist = Abs(rTableQAM64SM[3][0] - Real(cI));
+    if (rCurDist < rMinDist)
+    {
+        rMinDist = rCurDist;
+        rDecRe = rTableQAM64SM[3][0];
+    }
+
+    rCurDist = Abs(rTableQAM64SM[4][0] - Real(cI));
+    if (rCurDist < rMinDist)
+    {
+        rMinDist = rCurDist;
+        rDecRe = rTableQAM64SM[4][0];
+    }
+
+    rCurDist = Abs(rTableQAM64SM[5][0] - Real(cI));
+    if (rCurDist < rMinDist)
+    {
+        rMinDist = rCurDist;
+        rDecRe = rTableQAM64SM[5][0];
+    }
+
+    rCurDist = Abs(rTableQAM64SM[6][0] - Real(cI));
+    if (rCurDist < rMinDist)
+    {
+        rMinDist = rCurDist;
+        rDecRe = rTableQAM64SM[6][0];
+    }
+
+    rCurDist = Abs(rTableQAM64SM[7][0] - Real(cI));
+    if (rCurDist < rMinDist)
+        rDecRe = rTableQAM64SM[7][0];
+
+    /* Imaginary */
+    rMinDist = Abs(rTableQAM64SM[0][1] - Imag(cI));
+    CReal rDecIm = rTableQAM64SM[0][1];
+
+    rCurDist = Abs(rTableQAM64SM[1][1] - Imag(cI));
+    if (rCurDist < rMinDist)
+    {
+        rMinDist = rCurDist;
+        rDecIm = rTableQAM64SM[1][1];
+    }
+
+    rCurDist = Abs(rTableQAM64SM[2][1] - Imag(cI));
+    if (rCurDist < rMinDist)
+    {
+        rMinDist = rCurDist;
+        rDecIm = rTableQAM64SM[2][1];
+    }
+
+    rCurDist = Abs(rTableQAM64SM[3][1] - Imag(cI));
+    if (rCurDist < rMinDist)
+    {
+        rMinDist = rCurDist;
+        rDecIm = rTableQAM64SM[3][1];
+    }
+
+    rCurDist = Abs(rTableQAM64SM[4][1] - Imag(cI));
+    if (rCurDist < rMinDist)
+    {
+        rMinDist = rCurDist;
+        rDecIm = rTableQAM64SM[4][1];
+    }
+
+    rCurDist = Abs(rTableQAM64SM[5][1] - Imag(cI));
+    if (rCurDist < rMinDist)
+    {
+        rMinDist = rCurDist;
+        rDecIm = rTableQAM64SM[5][1];
+    }
+
+    rCurDist = Abs(rTableQAM64SM[6][1] - Imag(cI));
+    if (rCurDist < rMinDist)
+    {
+        rMinDist = rCurDist;
+        rDecIm = rTableQAM64SM[6][1];
+    }
+
+    rCurDist = Abs(rTableQAM64SM[7][1] - Imag(cI));
+    if (rCurDist < rMinDist)
+        rDecIm = rTableQAM64SM[7][1];
+
+    return CComplex(rDecRe, rDecIm);
+}
+
+
+#endif // !defined(QAM_MAPPING_H__3B0_CA63_4344_BB2B_23E7912__INCLUDED_)
diff --git a/src/tables/TableStations.cpp b/src/tables/TableStations.cpp
new file mode 100644
index 0000000..7a695fd
--- /dev/null
+++ b/src/tables/TableStations.cpp
@@ -0,0 +1,1239 @@
+/******************************************************************************\
+ * British Broadcasting Corporation
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Julian Cable
+ *
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "TableStations.h"
+
+using namespace std;
+
+static struct { const char *code; const char *lang; } eibi_langs[] = {
+	{ "-TS", "Time Signal Station" },
+	{ "A", "Arabic" },
+	{ "AB", "Abkhaz" },
+	{ "AC", "Aceh" },
+	{ "ACH", "Achang" },
+	{ "AD", "Adygea" },
+	{ "ADI", "Adi" },
+	{ "AF", "Afrikaans" },
+	{ "AFA", "Afar" },
+	{ "AFG", "Pashto and Dari" },
+	{ "AH", "Amharic" },
+	{ "AK", "Akha" },
+	{ "AL", "Albanian" },
+	{ "ALG", "Algerian" },
+	{ "AM", "Amoy" },
+	{ "Ang", "Angelus programme of Vaticane Radio" },
+	{ "AR", "Armenian" },
+	{ "ARO", "Aromanian" },
+	{ "ARU", "Arunachal" },
+	{ "ASS", "Assamese" },
+	{ "ASY", "Assyrian" },
+	{ "ATS", "Atsi" },
+	{ "Aud", "Papal Audience" },
+	{ "AV", "Avar" },
+	{ "AW", "Awadhi" },
+	{ "AY", "Aymara" },
+	{ "AZ", "Azeri" },
+	{ "B", "Brazilian" },
+	{ "BAD", "Badaga" },
+	{ "BAG", "Bagri" },
+	{ "BAJ", "Bajau" },
+	{ "BAK", "Baku" },
+	{ "BAL", "Balinese" },
+	{ "BAN", "Banjar" },
+	{ "BAO", "Baoule" },
+	{ "BAR", "Bari" },
+	{ "BAS", "Bashkir" },
+	{ "BAY", "Bayash Romani" },
+	{ "BB", "Braj Bhasa" },
+	{ "BC", "Baluchi" },
+	{ "BE", "Bengali" },
+	{ "BEM", "Bemba" },
+	{ "BH", "Bhili" },
+	{ "BHN", "Bahnar" },
+	{ "BI", "Bile" },
+	{ "BID", "Bidayuh" },
+	{ "BIS", "Bisaya" },
+	{ "BJ", "Bhojpuri" },
+	{ "BK", "Balkarian" },
+	{ "BLK", "Balkan Romani" },
+	{ "BLT", "Balti" },
+	{ "BM", "Bambara" },
+	{ "BNA", "Borana Oromo" },
+	{ "BNG", "Bangala" },
+	{ "BNJ", "Banjari" },
+	{ "BOR", "Boro" },
+	{ "BOS", "Bosnian" },
+	{ "BR", "Burmese" },
+	{ "BRA", "Brahui" },
+	{ "BRI", "Brij" },
+	{ "Bru", "Bru" },
+	{ "BSL", "Bislama" },
+	{ "BT", "Black Tai" },
+	{ "BTK", "Batak-Toba" },
+	{ "BU", "Bulgarian" },
+	{ "BUG", "Bugis" },
+	{ "BUK", "Bukharian" },
+	{ "BUN", "Bundeli" },
+	{ "BUR", "Buryat" },
+	{ "BY", "Byelorussian" },
+	{ "C", "Chinese" },
+	{ "CA", "Cantonese" },
+	{ "CC", "Chaochow" },
+	{ "CD", "Chowdary" },
+	{ "CEB", "Cebuano" },
+	{ "CH", "Chin" },
+	{ "C-A", "Chin-Asho" },
+	{ "C-D", "Chin-Daai" },
+	{ "CHE", "Chechen" },
+	{ "CHG", "Chattisgarhi" },
+	{ "CHI", "Chitrali" },
+	{ "C-K", "Chin-Khumi" },
+	{ "C-O", "Chin-Thado" },
+	{ "CHR", "Chrau" },
+	{ "CHT", "Chatrali" },
+	{ "CHU", "Chuwabu" },
+	{ "C-T", "Chin-Tidim" },
+	{ "C-Z", "Chin-Zomin" },
+	{ "CI", "Circassic" },
+	{ "CKM", "Chakma" },
+	{ "CKW", "Chokwe" },
+	{ "COF", "Cofan" },
+	{ "COK", "Cook Islands Maori" },
+	{ "CR", "Creole" },
+	{ "CRU", "Chru" },
+	{ "CT", "Catalan" },
+	{ "CV", "Chuvash" },
+	{ "CW", "Chewa" },
+	{ "CZ", "Czech" },
+	{ "D", "German" },
+	{ "D-P", "Lower German" },
+	{ "DA", "Danish" },
+	{ "DAO", "Dao" },
+	{ "DD", "Dhodiya" },
+	{ "DEG", "Degar" },
+	{ "DH", "Dhivehi" },
+	{ "DI", "Dinka" },
+	{ "DIA", "Dial Arabic" },
+	{ "DN", "Damara-Nama service in Namibia" },
+	{ "DO", "Dogri-Kangri" },
+	{ "DR", "Dari" },
+	{ "DU", "Dusun" },
+	{ "DUN", "Dungan" },
+	{ "DY", "Dyula" },
+	{ "DZ", "Dzonkha" },
+	{ "E", "English" },
+	{ "EC", "Eastern Cham" },
+	{ "EDI", "English, German, Italian" },
+	{ "E-C", "Col.English" },
+	{ "EGY", "Egyptian Arabic" },
+	{ "E-L", "English Learning Programme" },
+	{ "EO", "Esperanto" },
+	{ "ES", "Estonian" },
+	{ "Ewe", "Ewe" },
+	{ "F", "French" },
+	{ "FA", "Faroese" },
+	{ "FI", "Finnish" },
+	{ "FJ", "Fijian" },
+	{ "FON", "Fon" },
+	{ "FP", "Filipino" },
+	{ "FS", "Farsi" },
+	{ "FT", "Fiote" },
+	{ "FU", "Fulani" },
+	{ "FUJ", "FutaJalon" },
+	{ "GA", "Garhwali" },
+	{ "GD", "Greenlandic" },
+	{ "GE", "Georgian" },
+	{ "GJ", "Gujari" },
+	{ "GL", "Galicic" },
+	{ "GM", "Gamit" },
+	{ "GO", "Gorontalo" },
+	{ "GON", "Gondi" },
+	{ "GR", "Greek" },
+	{ "GU", "Gujarati" },
+	{ "GUA", "Guaraní" },
+	{ "GUR", "Gurage" },
+	{ "HA", "Haussa" },
+	{ "HAD", "Hadiya" },
+	{ "HB", "Hebrew" },
+	{ "HD", "Hindko" },
+	{ "HI", "Hindi" },
+	{ "HK", "Hakka" },
+	{ "HM", "Hmong" },
+	{ "HMA", "Hmar" },
+	{ "HMB", "Hmong-Blue" },
+	{ "HMW", "Hmong-White" },
+	{ "HN", "Hani" },
+	{ "HO", "Ho" },
+	{ "HR", "Croatian" },
+	{ "Hre", "Hre" },
+	{ "HU", "Hungarian" },
+	{ "HUA", "Huarani" },
+	{ "HZ", "Hazaragi" },
+	{ "I", "Italian" },
+	{ "IB", "Iban" },
+	{ "Ibo", "Ibo" },
+	{ "IG", "Igbo" },
+	{ "ILC", "Ilocano" },
+	{ "ILG", "Ilonggo" },
+	{ "IN", "Indonesian" },
+	{ "INU", "Inuktikut" },
+	{ "IRQ", "Iraqi" },
+	{ "IS", "Icelandic" },
+	{ "J", "Japanese" },
+	{ "Jeh", "Jeh" },
+	{ "JG", "Jingpho" },
+	{ "JL", "Joula" },
+	{ "JOR", "Jordanian" },
+	{ "JR", "Jarai" },
+	{ "JU", "Juba" },
+	{ "JV", "Javanese" },
+	{ "K", "Korean" },
+	{ "KA", "Karen" },
+	{ "K-P", "Karen-Pao" },
+	{ "K-S", "Karen-Sgaw" },
+	{ "K-W", "Karen-Pwo" },
+	{ "KAD", "Kadazan" },
+	{ "KAL", "Kalderash Romani" },
+	{ "KAB", "Kabardino" },
+	{ "KAM", "Kambaata" },
+	{ "KAN", "Kannada" },
+	{ "KAO", "Kaonde" },
+	{ "KAR", "Karelian" },
+	{ "KAT", "Katu" },
+	{ "KAY", "Kayan" },
+	{ "KB", "Kabyle" },
+	{ "KBO", "Kok Borok" },
+	{ "KC", "Kachin" },
+	{ "KG", "Kyrgyz" },
+	{ "KH", "Khmer" },
+	{ "KHA", "Kham" },
+	{ "KHM", "Khmu" },
+	{ "KIM", "Kimwani" },
+	{ "KiR", "KiRundi" },
+	{ "KK", "KiKongo" },
+	{ "KMB", "Kimbundu" },
+	{ "KNK", "KinyaRwanda-KiRundi" },
+	{ "KNU", "Kanuri" },
+	{ "KO", "Kosovar Albanian" },
+	{ "KOH", "Koho" },
+	{ "KOM", "Komering" },
+	{ "KON", "Konkani" },
+	{ "KOY", "Koya" },
+	{ "KPK", "Karakalpak" },
+	{ "KRB", "Karbi" },
+	{ "KRI", "Krio" },
+	{ "KRW", "KinyaRwanda" },
+	{ "KS", "Kashmiri" },
+	{ "KU", "Kurdish" },
+	{ "KuA", "Kurdish and Arabic" },
+	{ "KuF", "Kurdish and Farsi" },
+	{ "KUI", "Kui" },
+	{ "KUL", "Kulina" },
+	{ "K/k", "Kirmanji Kurdish" },
+	{ "K/s", "Sorani Kurdish" },
+	{ "KUK", "Kuki" },
+	{ "KUM", "Kumaoni" },
+	{ "KUN", "Kunama" },
+	{ "KUR", "Kurukh" },
+	{ "KUT", "Kutchi" },
+	{ "KWA", "Kwanyama" },
+	{ "KYK", "Kayan" },
+	{ "KZ", "Kazakh" },
+	{ "L", "Latin" },
+	{ "LA", "Ladino" },
+	{ "LAH", "Lahu" },
+	{ "LAM", "Lampung" },
+	{ "LAO", "Lao" },
+	{ "LaS", "Ladino and Spanish" },
+	{ "LB", "Lun Bawang" },
+	{ "LBO", "Limboo" },
+	{ "LEP", "Lepcha" },
+	{ "LHO", "Lhotshampa" },
+	{ "LIM", "Limba" },
+	{ "LIN", "Lingala" },
+	{ "LIS", "Lisu" },
+	{ "LND", "Lunda Ndembo" },
+	{ "LO", "Lomwe" },
+	{ "LOZ", "Lozi" },
+	{ "LT", "Lithuanian" },
+	{ "LTO", "Oriental Liturgy of Vaticane Radio" },
+	{ "LU", "Lunda" },
+	{ "LUC", "Luchazi" },
+	{ "LUN", "Lunyaneka" },
+	{ "LUR", "Luri" },
+	{ "LUV", "Luvale" },
+	{ "LV", "Latvian" },
+	{ "M", "Mandarin" },
+	{ "MA", "Maltese" },
+	{ "MAD", "Madurese" },
+	{ "MAG", "Maghi" },
+	{ "MAI", "Maithili" },
+	{ "MAK", "Makonde" },
+	{ "MAL", "Malayalam" },
+	{ "MAM", "Mamay" },
+	{ "MAN", "Manchu" },
+	{ "MAO", "Maori" },
+	{ "MAR", "Marathi" },
+	{ "MAS", "Masaai" },
+	{ "MC", "Macedonian" },
+	{ "MCH", "Mavchi" },
+	{ "MEI", "Meithei" },
+	{ "MEN", "Mende" },
+	{ "MEW", "Mewari" },
+	{ "MIE", "Mien" },
+	{ "MKB", "Minangkabau" },
+	{ "MKS", "Makasar" },
+	{ "MKU", "Makua" },
+	{ "ML", "Malay" },
+	{ "MLK", "Malinke" },
+	{ "MNO", "Mnong" },
+	{ "MO", "Mongolian" },
+	{ "MOc", "Chinese" },
+	{ "Mon", "Mon" },
+	{ "MOO", "Moore" },
+	{ "MOR", "Moro" },
+	{ "MR", "Maronite" },
+	{ "MRC", "Moroccan" },
+	{ "MRI", "Mari" },
+	{ "MRU", "Maru" },
+	{ "MSY", "Malagasy" },
+	{ "MUG", "Mugrabian" },
+	{ "MUN", "Mundari" },
+	{ "MUO", "Muong" },
+	{ "MUR", "Murut" },
+	{ "MW", "Marwari" },
+	{ "MZ", "Mizo" },
+	{ "NAG", "Naga-Makware" },
+	{ "NDA", "Ndau" },
+	{ "NDE", "Ndebele" },
+	{ "NE", "Nepali" },
+	{ "NG", "Nagpuri" },
+	{ "NGA", "Ngangela" },
+	{ "NI", "Ni" },
+	{ "NIC", "Nicobari" },
+	{ "NIU", "Niuean" },
+	{ "NL", "Dutch" },
+	{ "NO", "Norwegian" },
+	{ "NP", "Nupe" },
+	{ "NU", "Nuer" },
+	{ "NUN", "Nung" },
+	{ "NW", "Newari" },
+	{ "NY", "Nyanja" },
+	{ "OG", "Ogan" },
+	{ "OH", "Otjiherero service in Namibia" },
+	{ "OO", "Oromo" },
+	{ "OR", "Oriya" },
+	{ "OS", "Ossetic" },
+	{ "OW", "Oshiwambo service in Angola and Namibia" },
+	{ "P", "Portuguese" },
+	{ "PAL", "Palaung - Pale" },
+	{ "PED", "Pedi" },
+	{ "PF", "Pashto and Farsi" },
+	{ "PJ", "Punjabi" },
+	{ "PO", "Polish" },
+	{ "POT", "Pothwari" },
+	{ "PS", "Pashto" },
+	{ "PU", "Pulaar" },
+	{ "Q", "Quechua" },
+	{ "QQ", "Qashqai" },
+	{ "R", "Russian" },
+	{ "RAD", "Rade" },
+	{ "REN", "Rengao" },
+	{ "RH", "Rahanwein" },
+	{ "RO", "Romanian" },
+	{ "ROG", "Roglai" },
+	{ "ROM", "Romanes" },
+	{ "Ros", "Rosary session of Vaticane Radio" },
+	{ "RWG", "Rawang" },
+	{ "S", "Spanish" },
+	{ "SAD", "Sadari" },
+	{ "SAH", "Saho" },
+	{ "SAM", "Samayiki" },
+	{ "SAN", "Sango" },
+	{ "SAS", "Sasak" },
+	{ "SC", "Serbo-Croat" },
+	{ "SCA", "Scandinavian languages" },
+	{ "SD", "Sindhi" },
+	{ "SED", "Sedang" },
+	{ "SEF", "Sefardi" },
+	{ "SEN", "Sena" },
+	{ "SGA", "Shangaan" },
+	{ "SGK", "Sgaw Karan" },
+	{ "SGM", "Sara Gambai" },
+	{ "SGO", "Songo" },
+	{ "SHA", "Shan" },
+	{ "SHk", "Shan-Khamti" },
+	{ "SHC", "Sharchogpa" },
+	{ "SHE", "Sheena" },
+	{ "SHO", "Shona" },
+	{ "SHP", "Sherpa" },
+	{ "SHU", "Shuwa" },
+	{ "SI", "Sinhalese" },
+	{ "SID", "Sidamo" },
+	{ "SIK", "Sikkimese" },
+	{ "SIR", "Siraiki" },
+	{ "SK", "Slovak" },
+	{ "SLM", "Solomon Islands Pidgin" },
+	{ "SM", "Samoan" },
+	{ "SNK", "Sanskrit" },
+	{ "SNT", "Santhali" },
+	{ "SO", "Somali" },
+	{ "SON", "Songhai" },
+	{ "SOT", "SeSotho" },
+	{ "SOU", "Sous" },
+	{ "SR", "Serbian" },
+	{ "SRA", "Soura" },
+	{ "STI", "Stieng" },
+	{ "SUD", "Sudanese" },
+	{ "SUN", "Sundanese" },
+	{ "SUS", "Sousou" },
+	{ "SV", "Slovenian" },
+	{ "SWA", "Swahili" },
+	{ "SWE", "Swedish" },
+	{ "SWT", "Swatow" },
+	{ "SWZ", "SiSwati" },
+	{ "SYL", "Syrian-Lebanese Arabic" },
+	{ "T", "Thai" },
+	{ "TAG", "Tagalog" },
+	{ "TAH", "Tachelhit" },
+	{ "TAM", "Tamil" },
+	{ "TB", "Tibetan" },
+	{ "TEL", "Telugu" },
+	{ "TEM", "Temme" },
+	{ "TFT", "Tarifit" },
+	{ "TGR", "Tigre" },
+	{ "THA", "Tharu Buksa" },
+	{ "TIG", "Tigrinya" },
+	{ "TJ", "Tajik" },
+	{ "TK", "Turkmen" },
+	{ "TL", "Tai-Lu" },
+	{ "TM", "Tamazight" },
+	{ "TMJ", "Tamajeq" },
+	{ "TN", "Tai-Nua" },
+	{ "TNG", "Tonga" },
+	{ "TO", "Tongan" },
+	{ "TOK", "Tokelau" },
+	{ "TOR", "Torajanese" },
+	{ "TP", "Tok Pisin" },
+	{ "TS", "Tswana" },
+	{ "TSA", "Tsangla" },
+	{ "TSH", "Tshwa" },
+	{ "TT", "Tatar" },
+	{ "TTB", "Tatar-Bashkir" },
+	{ "TU", "Turkish" },
+	{ "TUL", "Tulu" },
+	{ "TUM", "Tumbuka" },
+	{ "TUN", "Tunisian" },
+	{ "TUR", "Turki" },
+	{ "TV", "Tuva" },
+	{ "TW", "Taiwanese" },
+	{ "Twi", "Twi" },
+	{ "TZ", "Tamazight" },
+	{ "UD", "Udmurt" },
+	{ "UI", "Uighur" },
+	{ "UK", "Ukrainian" },
+	{ "UM", "Umbundu" },
+	{ "UR", "Urdu" },
+	{ "UZ", "Uzbek" },
+	{ "V", "Vasco" },
+	{ "Ves", "Vespers" },
+	{ "Vn", "Vernacular = local languages" },
+	{ "VN", "Vietnamese" },
+	{ "VV", "Vasavi" },
+	{ "VX", "Vlax Romani" },
+	{ "W", "Wolof" },
+	{ "Wa", "Wa" },
+	{ "WE", "Wenzhou" },
+	{ "WT", "White Tai" },
+	{ "WU", "Wu" },
+	{ "XH", "Xhosa" },
+	{ "YAO", "Yao" },
+	{ "Yi", "Yi" },
+	{ "YI", "Yiddish" },
+	{ "YK", "Yakutian" },
+	{ "YO", "Yoruba" },
+	{ "YOL", "Yolngu" },
+	{ "YZ", "Yezidish" },
+	{ "Z", "Zulu" },
+	{ "ZA", "Zarma" },
+	{ "ZD", "Zande" },
+	{ "ZG", "Zaghawa" },
+	{ "ZH", "Zhuang" },
+	{ 0, 0}
+	};
+
+static struct { const char *code; const char *country; } itu_r_countries[] = {
+	{ "ABW", "Aruba" },
+	{ "ADM", "Andaman & Nicobar Island" },
+	{ "AFG", "Afghanistan" },
+	{ "AFS", "South Africa" },
+	{ "AGL", "Angola" },
+	{ "AIA", "Anguilla" },
+	{ "ALB", "Albania" },
+	{ "ALG", "Algeria" },
+	{ "ALS", "Alaska" },
+	{ "AMS", "Saint Paul & Amsterdam Is." },
+	{ "AND", "Andorra" },
+	{ "ANO", "Annobon I." },
+	{ "ARG", "Argentina" },
+	{ "ARM", "Armenia" },
+	{ "ARS", "Saudi Arabia" },
+	{ "ASC", "Ascension I." },
+	{ "ATA", "Antarctica" },
+	{ "ATG", "Antigua" },
+	{ "ATN", "Netherlands Leeward Antilles" },
+	{ "ATW", "Netherlands Windward Antilles" },
+	{ "AUS", "Australia" },
+	{ "AUT", "Austria" },
+	{ "AVE", "Aves I." },
+	{ "AZE", "Azerbaijan" },
+	{ "AZR", "Azores" },
+	{ "B", "Brasil" },
+	{ "BAH", "Bahamas" },
+	{ "BAL", "Balleny Is." },
+	{ "BAN", "Banaba" },
+	{ "BDI", "Burundi" },
+	{ "BEL", "Belgium" },
+	{ "BEN", "Benin" },
+	{ "BER", "Bermuda" },
+	{ "BFA", "Burkina Faso" },
+	{ "BGD", "Bangla Desh" },
+	{ "BHR", "Bahrain" },
+	{ "BIH", "Bosnia-Hertsegovina" },
+	{ "BIO", "Chagos Is." },
+	{ "BLR", "Belarus" },
+	{ "BLZ", "Belize" },
+	{ "BOL", "Bolivia" },
+	{ "BOT", "Botswana" },
+	{ "BOV", "Bouvet I." },
+	{ "BRB", "Barbados" },
+	{ "BRM", "Burma" },
+	{ "BRU", "Brunei" },
+	{ "BTN", "Bhutan" },
+	{ "BUL", "Bulgaria" },
+	{ "CAB", "Cabinda" },
+	{ "CAF", "Central African Republic" },
+	{ "CAN", "Canada" },
+	{ "CBG", "Cambodia" },
+	{ "CEU", "Ceuta" },
+	{ "CGO", "Republic of Congo" },
+	{ "CHL", "Chile" },
+	{ "CHN", "China" },
+	{ "CHR", "Chrstmas I." },
+	{ "CKH", "Cook Is." },
+	{ "CKN", "North Cook Is." },
+	{ "CLM", "Colombia" },
+	{ "CLN", "Sri Lanka" },
+	{ "CLP", "Clipperton" },
+	{ "CME", "Cameroon" },
+	{ "CNR", "Canary Is." },
+	{ "COM", "Comores" },
+	{ "CPV", "Cape Verde Is." },
+	{ "CRO", "Crozet I." },
+	{ "CTI", "Ivory Coast" },
+	{ "CTR", "Costa Rica" },
+	{ "CUB", "Cuba" },
+	{ "CVA", "Vatican State" },
+	{ "CYM", "Cayman Is." },
+	{ "CYP", "Gyprus" },
+	{ "CZE", "Czech Republic" },
+	{ "D", "Germany" },
+	{ "DAI", "Daito Is." },
+	{ "DES", "Desventurados Is." },
+	{ "DJI", "Djibouti" },
+	{ "DMA", "Dominica" },
+	{ "DNK", "Denmarlc" },
+	{ "DOM", "Dominican Republic" },
+	{ "DRC",  "Democratic Republic of Congo" },
+	{ "E", "Spain" },
+	{ "EGY", "Egypt" },
+	{ "EQA", "Ecuador" },
+	{ "ERI", "Eritrea" },
+	{ "EST", "Estonia" },
+	{ "ETH", "Ethiopia" },
+	{ "EUR", "Iles Europe & Bassas da India" },
+	{ "F", "France" },
+	{ "FAR", "Faroe Is." },
+	{ "FIN", "Finland" },
+	{ "FJI", "Fiji Is." },
+	{ "FLK", "Falkland Is." },
+	{ "FSM", "Federated States of Micronesia" },
+	{ "G", "Great Britain and Northern Ireland" },
+	{ "GAB", "Gabon" },
+	{ "GDL", "Guadeloupe" },
+	{ "GEO", "Georgia" },
+	{ "GHA", "Ghana" },
+	{ "GIB", "Gibraltar" },
+	{ "GMB", "Gambia" },
+	{ "GNB", "Guinea-Bissau" },
+	{ "GNE", "Equatorial Guinea" },
+	{ "GPG", "Galapagos Is." },
+	{ "GRC", "Greece" },
+	{ "GRD", "Grenada" },
+	{ "GRL", "Greenland" },
+	{ "GTB", "Guantanamo Bay" },
+	{ "GTM", "Guatemala" },
+	{ "GUF", "French Guyana" },
+	{ "GUI", "Guinea" },
+	{ "GUM", "Guam" },
+	{ "GUY", "Guyana" },
+	{ "HKG", "Hong Kong, part of China" },
+	{ "HMD", "Heard & McDonaid Is." },
+	{ "HND", "Honduras" },
+	{ "HNG", "Hungary" },
+	{ "HOL", "Netherlands" },
+	{ "HRV", "Croatia" },
+	{ "HTI", "Haiti" },
+	{ "HWA", "Hawaii Is." },
+	{ "HWL", "Howland & Baker Is." },
+	{ "I", "Italy" },
+	{ "ICO", "Cocos I." },
+	{ "IND", "India" },
+	{ "INS", "Indonesia" },
+	{ "IRL", "Ireland" },
+	{ "IRN", "Iran" },
+	{ "IRQ", "Iraq" },
+	{ "ISL", "Iceland" },
+	{ "ISR", "Israel" },
+	{ "IWA", "Ogasawara" },
+	{ "J", "Japan" },
+	{ "JAF", "Jarvis" },
+	{ "JDN", "Juan de Nova Island" },
+	{ "JMC", "Jamaica" },
+	{ "JMY", "Jan Mayen" },
+	{ "JON", "Johnston Atoll" },
+	{ "JOR", "Jordan" },
+	{ "JUF", "Juan Femandez I." },
+	{ "KAL", "Kaliningrad" },
+	{ "KAZ", "Kazakstan" },
+	{ "KEN", "Kenya" },
+	{ "KER", "Kerguelen" },
+	{ "KGZ", "Kyrgyzstan" },
+	{ "KIR", "Kiribati" },
+	{ "KOR", "Korea, South" },
+	{ "KRE", "Korea, North" },
+	{ "KWT", "Kuwait" },
+	{ "LAO", "Laos" },
+	{ "LBN", "Lebanon" },
+	{ "LBR", "Liberia" },
+	{ "LBY", "Libya" },
+	{ "LCA", "Saint Lucia" },
+	{ "LIE", "Liechtenstein" },
+	{ "LSO", "Lesotho" },
+	{ "LTU", "Lithuania" },
+	{ "LUX", "Luxembourg" },
+	{ "LVA", "Latvia" },
+	{ "MAC", "Macao" },
+	{ "MAU", "Mauritius" },
+	{ "MCO", "Monaco" },
+	{ "MDA", "Moldova" },
+	{ "MDG", "Madagascar" },
+	{ "MDR", "Madeira" },
+	{ "MEL", "Melilla" },
+	{ "MEX", "Mexico" },
+	{ "MKD", "Macedonia" },
+	{ "MLA", "Malaysia" },
+	{ "MLD", "Maldives" },
+	{ "MLI", "Mali" },
+	{ "MLT", "Malta" },
+	{ "MNE", "Montenegro" },
+	{ "MNG", "Mongolia" },
+	{ "MOZ", "Mozambique" },
+	{ "MRA", "Northern Mariana Islands" },
+	{ "MRC", "Morocco" },
+	{ "MRL", "Marshail Is." },
+	{ "MRN", "Marion & Prince Edward Is." },
+	{ "MRQ", "Marquesas Is." },
+	{ "MRT", "Martinique" },
+	{ "MSR", "Montserrat" },
+	{ "MTN", "Mauritania" },
+	{ "MWI", "Malawi" },
+	{ "MYT", "Mayotte" },
+	{ "NCG", "Nicaragua" },
+	{ "NCL", "New Caledonia" },
+	{ "NFK", "Norfolk I." },
+	{ "NGR", "Niger" },
+	{ "NIG", "Nigeria" },
+	{ "NIU", "Niue" },
+	{ "NMB", "Namibia" },
+	{ "NOR", "Norway" },
+	{ "NPL", "Nepal" },
+	{ "NRU", "Nauru" },
+	{ "NZL", "New Zealand" },
+	{ "OCE", "Society Is." },
+	{ "OMA", "Oman" },
+	{ "PAK", "Pakistan" },
+	{ "PAL", "Palau" },
+	{ "PAQ", "Easter Island" },
+	{ "PHL", "Philippines" },
+	{ "PHX", "Phoenix Is." },
+	{ "PLM", "Palmyra" },
+	{ "PNG", "Papua New Guinea" },
+	{ "PNR", "Panama Republic" },
+	{ "POL", "Poland" },
+	{ "POR", "Portugal" },
+	{ "PRG", "Paraguay" },
+	{ "PRU", "Peru" },
+	{ "PRV", "Okino-Tori-Shima" },
+	{ "PTC", "Pitcairn" },
+	{ "PTR", "Puerto Rico" },
+	{ "QAT", "Qatar" },
+	{ "REU", "Reunion" },
+	{ "ROU", "Roumania" },
+	{ "RRW", "Rwanda" },
+	{ "RUS", "Russian Federation" },
+	{ "S", "Sweden" },
+	{ "SAP", "San Andres & Providencia" },
+	{ "SCN", "Saint Kitts - Nevis" },
+	{ "SCO", "Scott I." },
+	{ "SDN", "Sudan" },
+	{ "SEN", "Senegal" },
+	{ "SEY", "Seychelles" },
+	{ "SGA", "South Georgia Is." },
+	{ "SHN", "Saint Helena I." },
+	{ "SLM", "Solomon Is." },
+	{ "SLV", "El Salvador" },
+	{ "SMA", "Samoa" },
+	{ "SMO", "Samoa" },
+	{ "SMR", "San Marino" },
+	{ "SNG", "Singapore" },
+	{ "SOK", "South Orkney Is." },
+	{ "SOM", "Somalia" },
+	{ "SPM", "Saint Pierre & Miquelon" },
+	{ "SPO", "Sao Paulo I." },
+	{ "SPR", "Spratly Is." },
+	{ "SRB", "Serbia" },
+	{ "SRL", "Sierra Leone" },
+	{ "SSI", "South Sandwich Is." },
+	{ "STB", "Saint Barthelemy" },
+	{ "STP", "Sao Tome & Principe" },
+	{ "SUI", "Switzerland" },
+	{ "SUR", "Suriname" },
+	{ "SVB", "Svalbard" },
+	{ "SVK", "Slovakia" },
+	{ "SVN", "Slovenia" },
+	{ "SWZ", "Swaziland" },
+	{ "SYR", "Syria" },
+	{ "TCD", "Tchad" },
+	{ "TCI", "Turks & Caicos Is." },
+	{ "TGO", "Togo" },
+	{ "THA", "Thaiiand" },
+	{ "TJK", "Tadjikistan" },
+	{ "TKL", "Tokelau I." },
+	{ "TKM", "Turkmenistan" },
+	{ "TON", "Tonga" },
+	{ "TRC", "Tristan da Cunha" },
+	{ "TRD", "Trinidad & Tobago" },
+	{ "TRI", "Trindade & Martim Vaz Is.," },
+	{ "TUA", "Tuamotu Archipelago" },
+	{ "TUN", "Tunisia" },
+	{ "TUR", "Turkey" },
+	{ "TUV", "Tuvalu" },
+	{ "TWN", "Taiwan" },
+	{ "TZA", "Tanzania" },
+	{ "UAE", "United Arab Emirates" },
+	{ "UGA", "Uganda" },
+	{ "UKR", "Ukraine" },
+	{ "URG", "Uruguay" },
+	{ "USA", "United States of America" },
+	{ "UZB", "Uzbekistan" },
+	{ "VCT", "Saint Vincent" },
+	{ "VEN", "Venezuela" },
+	{ "VIR", "American Virgin Is." },
+	{ "VRG", "British Virgin Is." },
+	{ "VTN", "Vietnam" },
+	{ "VUT", "Vanuatu" },
+	{ "WAK", "Wake I." },
+	{ "WAL", "Waliis & Futuna Is." },
+	{ "YEM", "Yemen" },
+	{ "ZMB", "Zambia" },
+	{ "ZWE", "Zimbabwe" },
+	{ 0, 0}
+	};
+
+static struct { const char *code; const char *target; } eibi_targets[] = {
+	{ "Af", "Africa" },
+	{ "Am", "America" },
+	{ "As", "Asia" },
+	{ "Car", "Caribbean" },
+	{ "Cau", "Caucasus" },
+	{ "CIS", "Commonwealth of Independent States" },
+	{ "CNA", "Central North America" },
+	{ "ENA", "Eastern North America" },
+	{ "Eu", "Europe" },
+	{ "FE", "Far East" },
+	{ "LAm", "Latin America" },
+	{ "ME", "Middle East" },
+	{ "NAO", "North Atlantic Ocean" },
+	{ "Oc", "Oceania" },
+	{ "SAO", "South Atlantic Ocean" },
+	{ "SEA", "South East Asia" },
+	{ "SEE", "South East Europe" },
+	{ "Sib", "Siberia" },
+	{ "WNA", "Western North America" },
+	{ 0, 0}
+	};
+
+	/*
+	 *  One-letter or two-letter codes for different transmitter sites within one country.
+	 *  No such code is used if there is only one transmitter site in that country.
+	 *          
+	 *  The code is used plainly if the transmitter is located within the home country of the station.
+	 *  Otherwise, it is preceeded by "/ABC"
+	 *  where ABC is the ITU code of the host country of the transmitter site.
+	 *  Example:
+	 *    A BBC broadcast, relayed by the transmitters in Samara, Russia, would be designated as "/RUS-s".
+	 *  In many cases, a station has a "major" transmitter site which is normally not designated.
+	 *  Should this station use a different transmitter site in certain cases, they are marked.
+	 *  No transmitter-site code is used when the transmitter site is not known.
+	 */
+static struct { const char *country; const char *mark; const char * bc; const char *site;} eibi_stations[] = {
+	{ "AFS", "", "", "Meyerton 26S35-28E08" },
+	{ "AGL", "", "", "Mulenvos 08S53-13E20" },
+	{ "AIA", "", "", "The Valley 18N13-63W01" },
+	{ "ALB", "", "CRI", "Cerrik 40N59'47-19E59'58 (1x100kW = 2x50kW)" },
+	{ "ALB", "", "R Tirana", "Shijiak 41N19'535-19E33'086 (1x100kW = 2x50kW)" },
+	{ "ALB", "", "MW", "Durres/Fllake 41N22'11-19E30'17 (500 kW)" },
+	{ "ALG", "", "", "Bouchaoui or Ouled Fayet" },
+	{ "ALS", "", "", "Anchor Point 59N45-151W44" },
+	{ "ARG", "", "", "General Pacheco 34S36-58W22" },
+	{ "ARM", "", "", "Gavar (formerly Kamo) 40N25-45E11" },
+	{ "ARS", "", "", "Riyadh 24N30-46E23" },
+	{ "ARS", "j", "", "Jeddah 21N32-39E10" },
+	{ "ASC", "", "", "Ascension Island, 07S54-14W23" },
+	{ "ATA", "", "", "Base Esperanza 63S24-56W59" },
+	{ "ATG", "", "", "St.John's 17N06-61W48 (2 x 250kW)" },
+	{ "ATN", "", "", "Bonaire 12N12-68W18" },
+	{ "AUS", "", "", "Shepparton 36S20-145E25" },
+	{ "AUS", "a", "", "Alice Springs 23S49-133E51" },
+	{ "AUS", "b", "", "Brandon 19S31-147E20" },
+	{ "AUS", "d", "", "Darwin NT 12S25-136E37" },
+	{ "AUS", "h", "", "Humpty Doo NT 12S34-131E05" },
+	{ "AUS", "ka", "", "Katherine NT 14S24-132E11" },
+	{ "AUS", "ku", "", "Kununurra WA 15S48-128E41" },
+	{ "AUS", "t", "", "Tennant Creek NT 19S40-134E16" },
+	{ "AUT", "", "", "Moosbrunn 48N00-16E28" },
+	{ "AZE", "", "", "Gäncä 40N37-46E20" },
+	{ "BEL", "", "", "Wavre(Waver) 50N44-04E34" },
+	{ "BEN", "", "", "Parakou 09N20-02E38" },
+	{ "BGD", "", "", "Dhaka 23N43-90E26" },
+	{ "BHR", "", "", "Abu Hayan 26N02-50E37" },
+	{ "BIH", "", "", "Bijeljina 44N42-19E10" },
+	{ "BIO", "", "", "Diego Garcia 07S03-72E04" },
+	{ "BLR", "", "", "Minsk-Sasnovy 53N56-27E34" },
+	{ "BLR", "b", "", "Brest 52N20-23E35 (5kW)" },
+	{ "BLR", "g", "", "Hrodna/Grodno 53N40-23E50(5 kW)" },
+	{ "BLR", "m", "", "Mahiliou/Mogilev (Orsha) 53N37-30E20 (5 kW)" },
+	{ "BOT", "", "VoA", "Mopeng Hill 21S57-27E39" },
+	{ "BTN", "", "", "Thimphu 27N28-89E39" },
+	{ "BUL", "", "", "Plovdiv-Padarsko 42N10-24E42  (2x500kW, 3x250kW)" },
+	{ "BUL", "s", "", "Sofia-Kostinbrod 42N49-23E13  (2x100kW, 2x50kW)" },
+	{ "BUL", "v", "", "Varna 43N03-27E40" },
+	{ "BUL", "#", "747", "Petrich 41N42-23E18  (500kW)" },
+	{ "BUL", "#", "1224", "Vidin 43N49-22E40  (500kW)" },
+	{ "CAN", "", "", "Sackville 45N53-64W19" },
+	{ "CAN", "c", "", "Calgary AB" },
+	{ "CAN", "j", "", "St John's NL 47N34-52W48" },
+	{ "CAN", "o", "", "Ottawa ON 40N18-75W45" },
+	{ "CAN", "t", "", "Toronto (Aurora) ON 44N00-79W30" },
+	{ "CAN", "v", "", "Vancouver BC 49N11-123W04" },
+	{ "CBG", "", "", "Phnom Penh 11N34-104E51" },
+	{ "CHL", "", "", "Santiago 33S27-70W41" },
+	{ "CHN", "a", "", "Baoji 34N30-107E10 (5x100kW)" },
+	{ "CHN", "b", "", "Beijing 39N57-116E27" },
+	{ "CHN", "B", "", "Beijing 39N55-116E25 (12x100kW, 9x50kW)" },
+	{ "CHN", "d", "", "Dongfang (Hainan) 18N54-108E39 (150kW)" },
+	{ "CHN", "e", "", "Gejiu (Yunnan) 23N21-103E08" },
+	{ "CHN", "g", "", "Gannan (Hezuo) 35N06-102E54" },
+	{ "CHN", "h", "", "Hohhot (Nei Menggu) 41N12-111E30" },
+	{ "CHN", "j", "", "Jinhua 28N07-119E39" },
+	{ "CHN", "k", "", "Kunming (Yunnan) 25N10-102E50" },
+	{ "CHN", "ka", "", "Kashi (Kashgar) (Xinjiang) 39N30-76E00" },
+	{ "CHN", "L", "", "Lingshi (Shanxi) 36N52-111E40 (6x100kW)" },
+	{ "CHN", "n", "", "Nanning (Guangxi) 22N47-108E11" },
+	{ "CHN", "q", "", "Ge'ermu (Qinghai) 36N24-94E59 (100kW)" },
+	{ "CHN", "qq", "", "Qiqihar 47N02-124E03 (500kW)" },
+	{ "CHN", "s", "", "Shijiazhuang (Hebei) 38N04-114E28 (5x50kW)" },
+	{ "CHN", "t", "", "Tibet (Lhasa) 29N30-90E59" },
+	{ "CHN", "u", "", "Urumqi (Xinjiang) 43N35-87E30 (6x500kW)" },
+	{ "CHN", "x", "", "Xian (Shaanxi) 34N12-108E54" },
+	{ "CHN", "#", "603", "Guangdong" },
+	{ "CHN", "#", "684", "Dongfang" },
+	{ "CHN", "#", "1296", "Kunming" },
+	{ "CHN", "#", "", "Fuzhou:26N06-119E24" },
+	{ "CHN", "#", "", "Lhasa:29N30-90E59" },
+	{ "CHN", "#", "", "Nanchang:28N38-115E56" },
+	{ "CHN", "#", "", "Nanjing:32N02-118E44" },
+	{ "CHN", "#", "", "Nanning:32N02-108E11" },
+	{ "CHN", "#", "", "Qinghai: Xining 36N38-101E36" },
+	{ "CLN", "", "DW", "Trincomalee 08N44-81E10 (SW 3 x 250kW, MW 400kW)" },
+	{ "CLN", "#", "", "R.Japan/SLBC" },
+	{ "CLN", "#", "", "RL/VoA" },
+	{ "CTR", "", "Gene Scott", "Cahuita 09N45-82W54" },
+	{ "REE", "", "", "Caiari de Porocí 10N00-83W30" },
+	{ "CUB", "", "", "La Habana (Quivicán) 22N50-82W17" },
+	{ "CVA", "", "", "Santa Maria di Galeria 42N03-12E19" },
+	{ "CVA", "v", "", "Citta del Vaticano 41N54-12E27" },
+	{ "CYP", "", "", "Zygi (Limassol) 34N43-33E19" },
+	{ "CYP", "y", "", "Yeni Iskele 35N13-33E55" },
+	{ "CZE", "", "", "Litomysl 49N48-16E10" },
+	{ "D", "", "", "unknown German station TBD" },
+	{ "D", "b", "", "Biblis 49N41-08E29" },
+	{ "D", "be", "", "Berlin 52N30-13E20" },
+	{ "D", "d", "", "Dillberg 49N19-11E23" },
+	{ "D", "e", "", "Erlangen 49N35-11E00" },
+	{ "D", "h", "", "Holzkirchen 47N52-11E44" },
+	{ "D", "ha", "", "Hannover 52N23-09E42" },
+	{ "D", "i", "", "Ismaning 48N15-11E45" },
+	{ "D", "j", "", "Juelich 50N57-06E22 (100kW)" },
+	{ "D", "L", "", "Lampertheim 49N36-08E33" },
+	{ "D", "n", "", "Nauen 52N38-12E54 ( 4 x 500kW)" },
+	{ "D", "nu", "", "Nuernberg 49N27-11E05" },
+	{ "D", "w", "", "Wertachtal 48N05-10E41  (13 x 500kW)" },
+	{ "DJI", "", "", "Djibouti 11N30-43E00" },
+	{ "DNK", "", "", "Karup 56N18-09E10" },
+	{ "E", "", "", "Noblejas 39N57-03W26" },
+	{ "EGY", "", "", "unknown Egypt" },
+	{ "EGY", "a", "", "Abis 31N10-30E05" },
+	{ "EGY", "z", "", "Abu Zaabal 30N16-31E22" },
+	{ "EQA", "", "", "Quito or Sucua or Loja or Macas" },
+	{ "ETH", "", "R.Ethiopia", "Geja Jewe 08N47-38E38" },
+	{ "F", "", "", "Issoudun 46N57-01E59" },
+	{ "F", "r", "", "Rennes 48N06-01W41" },
+	{ "FIN", "", "YLE", "Pori 61N28-21E35" },
+	{ "FIN", "#", "Scand.Weekend R.", "" },
+	{ "G", "", "", "unknown UK" },
+	{ "G", "r", "", "Rampisham 50N48-02W38" },
+	{ "G", "s", "", "Skelton 54N44-02W54" },
+	{ "G", "w", "", "Woofferton 52N19-02W43" },
+	{ "G", "cp", "", "London-Crystal Palace" },
+	{ "G", "cr", "", "London-Croydon" },
+	{ "G", "", "648", "Orfordness" },
+	{ "G", "", "1296", "Orfordness" },
+	{ "G", "", "198", "Droitwich" },
+	{ "GAB", "", "", "Moyabi 01S40-13E31" },
+	{ "GEO", "", "", "Dusheti 42N03-44E41" },
+	{ "GNE", "", "", "Bata 01N48-09E46" },
+	{ "GRC", "", "", "Avlis (38N23-23E36)" },
+	{ "GRC", "o", "", "Rhodes ?" },
+	{ "GUF", "", "", "Montsinery 04N54-52W36" },
+	{ "GUM", "", "AWR", "Agat, 13N20-144E39" },
+	{ "GUM", "", "KTWR", "Agana 13N17-144E40" },
+	{ "GUM", "", "AFRTS", "Barrigada 13N34-144E50" },
+	{ "GUY", "", "", "Sparendaam 06N49-58W10" },
+	{ "HNG", "", "", "Jaszbereny 47N35-19E52" },
+	{ "HOL", "", "", "Flevo 52N21-05E27" },
+	{ "HRV", "", "", "Deanovec 45N41-16E27" },
+	{ "HWA", "", "", "Naalehu 19N02-155W40" },
+	{ "HWA", "", "AFRTS", "Pearl Harbour 21N25-158W09" },
+	{ "I", "", "RAI, VoM", "Roma (Prato Smeraldo) 41N48-12E31" },
+	{ "IRRS", "", "", "unknown. Formerly Milano 45N27-09E11" },
+	{ "IND", "", "", "unknown India" },
+	{ "IND", "a", "", "Aligarh 28N00-78E06" },
+	{ "IND", "b", "", "Bengaluru-Doddaballapur (Bangalore) 13N14-77E13" },
+	{ "IND", "c", "", "Chennai(ex Madras) 13N08-80E07" },
+	{ "IND", "d", "", "Delhi (Kingsway) 26N45-77E12" },
+	{ "IND", "g", "", "Gorakhpur 23N52-83E28" },
+	{ "IND", "k", "", "Delhi(Khampur) 28N43-77E38" },
+	{ "IND", "m", "", "Mumbai (ex Bombay) 19N11-72E49" },
+	{ "IND", "p", "", "Panaji (ex Goa) 15N28-73E51" },
+	{ "IND", "w", "", "Guwahati 26N11-91E50" },
+	{ "IND", "#", "594", "Kolkata(Calcutta)-Chinsurah" },
+	{ "IND", "#", "1134", "Kolkata(Calcutta)-Chinsurah" },
+	{ "IND", "#", "", "702-Jalandhar" },
+	{ "IND", "#", "", "1053-Tuticorin" },
+	{ "IND", "#", "", "1071-Rajkot" },
+	{ "IND", "#", "", "Regional Stations" },
+	{ "IND", "#", "", "Aizawl(10kW)" },
+	{ "IND", "#", "", "Bhopal(50kW)" },
+	{ "IND", "#", "", "Chennai(50kW)" },
+	{ "IND", "#", "", "Delhi(Kingsway)(50kW)" },
+	{ "IND", "#", "", "Gangtok(10kW)" },
+	{ "IND", "#", "", "Guwahati(50kW)" },
+	{ "IND", "#", "", "Hyderabad(50kW)" },
+	{ "IND", "#", "", "Imphal(50kW)" },
+	{ "IND", "#", "", "Itanagar(50kW)" },
+	{ "IND", "#", "", "Jaipur(50kW)" },
+	{ "IND", "#", "", "Jammu(50kW)" },
+	{ "IND", "#", "", "Jeypore(50kW)" },
+	{ "IND", "#", "", "Kohima(50kW)" },
+	{ "IND", "#", "", "Kolkata(Calcutta)(50kW)" },
+	{ "IND", "#", "", "Kurseong(50kW)" },
+	{ "IND", "#", "", "Leh(10kW)" },
+	{ "IND", "#", "", "Lucknow(50kW)" },
+	{ "IND", "#", "", "Mumbai(50kW)" },
+	{ "IND", "#", "", "Port Blair-Brookshabad(5kW)" },
+	{ "IND", "#", "", "Ranchi(50kW)" },
+	{ "IND", "#", "", "Shillong(50kW)" },
+	{ "IND", "#", "", "Shimla(50kW)" },
+	{ "IND", "#", "", "Srinagar(50kW)" },
+	{ "IND", "#", "", "Thiruvananthapuram(Trivendrum)(50kW)" },
+	{ "INS", "", "", "Jakarta (Cimanggis) 06S12-106E51" },
+	{ "IRN", "", "", "unknown Iran" },
+	{ "IRN", "a", "", "Ahwaz 31N20-48E40" },
+	{ "IRN", "k", "", "Kamalabad 35N46-51E27" },
+	{ "IRN", "m", "", "Mashhad 36N15-59E33" },
+	{ "IRN", "s", "", "Sirjan 29N27-55E41" },
+	{ "IRN", "z", "", "Zahedan 29N28-60E53" },
+	{ "ISL", "", "", "Reykjavík 64N05-21W50" },
+	{ "ISR", "", "", "Yavne 31N52-34E45" },
+	{ "J", "", "", "Yamata 36N10-139E50" },
+	{ "JOR", "", "", "Al Karanah 31N44-36E26" },
+	{ "KAZ", "", "", "Almaty (Alma Ata, Dmitrievka) 43N17-77E00" },
+	{ "KAZ", "k", "", "Karaturuk 43N39-77E56" },
+	{ "KGZ", "", "", "Bishkek 42N54-74E37" },
+	{ "KOR", "", "", "Kimjae 35N50-126E50" },
+	{ "KOR", "h", "", "Hwasung 37N13-126E47" },
+	{ "KRE", "", "", "Kanggye or Pyongyang or Kujang" },
+	{ "KRE", "k", "", "Kanggye 40N58-126E36" },
+	{ "KRE", "p", "", "Pyongyang 39N05-125E23" },
+	{ "KRE", "u", "", "Kujang 40N05-125E05" },
+	{ "KWT", "", "", "Sulaibiyah 29N10-47E45" },
+	{ "LAO", "", "", "Vientiane 17N58-102E33" },
+	{ "LBY", "", "", "Tripoli" },
+	{ "LTU", "", "", "Sitkunai 55N02-23E49 http" },
+	{ "LUX", "", "", "Junglinster 49N43-06E15" },
+	{ "LVA", "", "", "Ulbroka 56N56-24E17" },
+	{ "MCO", "", "", "Mont Angel/Fontbonne 43N44-07E26" },
+	{ "MDA", "", "", "Maiac near Grigoriopol 47N14-29E24" },
+	{ "MDG", "", "", "Talata Volonondry 18S43-47E37" },
+	{ "MLA", "", "", "unknown MLA" },
+	{ "MLA", "ka", "", "Kajang 03N01-101E46" },
+	{ "MLA", "kk", "", "Kota Kinabalu 06N12-116E14" },
+	{ "MLA", "ku", "", "Kuching 01N33-110E20" },
+	{ "MLA", "s", "", "Sibu 02N18-111E49" },
+	{ "MLI", "", "", "Bamako 12N39-08W01" },
+	{ "MNG", "", "", "Ulaanbaatar 47N55-107E00" },
+	{ "MRA", "", "RFA/RL/VoA", "Tinian 15N03-145E36" },
+	{ "MRA", "s", "", "Saipan (Agingan Point) 15N07-145E42" },
+	{ "KFBS", "", "Marpi", "Saipan 15N16-145E48" },
+	{ "MRC", "", "VoA/RL/RFE", "Briech 35N34-05W58" },
+	{ "MRC", "t", "RTM", "Tanger 35N48-05W55" },
+	{ "MRC", "n", "Medi-1", "Nador 35N03-02W55" },
+	{ "NOR", "", "", "unknown Norway" },
+	{ "NOR", "k", "", "Kvitsoy 59N04-05E27" },
+	{ "NOR", "s", "", "Sveio 59N37-05E19" },
+	{ "NZL", "", "", "Rangitaiki 38S50-176E25" },
+	{ "OMA", "", "BBC", "A'Seela 21N57-59E27" },
+	{ "OMA", "t", "Radio Oman", "Thumrait 17N38-53E56" },
+	{ "OMA", "s", "", "Seeb 23N40-58E10" },
+	{ "PAK", "", "", "Islamabad 33N27-73E12" },
+	{ "PAK", "p", "", "Peshawar 34N00-71E30 (10kW)" },
+	{ "PAK", "q", "", "Quetta 30N15-67E00 (10kW)" },
+	{ "PAK", "r", "", "Rawalpindi 33N30-73E00 (10kW)" },
+	{ "PAL", "", "", "Medorn 07N22-134E28" },
+	{ "PHL", "", "RL/Voa", "Tinang 15N21-120E37" },
+	{ "PHL", "i", "", "Iba 15N20-119E58" },
+	{ "PHL", "x", "", "Tinang-2(portable) 15N21-120E38 (50kW)" },
+	{ "PHL", "#", "1143", "Poro 16N26-120E17" },
+	{ "FEBC", "", "", "Bocaue 14N48-120E55" },
+	{ "FEBC", "i", "", "Iba 15N22-119E57" },
+	{ "FEBC", "#", "RVA, R Vaticana", "Palauig, Zembales 15N28-119E50" },
+	{ "FEBC", "#", "", "DUR2 9581 14N41-120E59" },
+	{ "POL", "", "", "Warszawa 52N04-20E52" },
+	{ "POR", "", "DW", "Sines 37N57-08W45 (3 x 250kW)" },
+	{ "RdP", "", "", "Sao Gabriel(Lisboa) 38N45-08W40" },
+	{ "PTR", "", "", "Roosevelt Roads 18N23-67W11" },
+	{ "ROU", "", "", "Tiganesti 44N42-26E06" },
+	{ "ROU", "t", "", "Tiganesti 44N42-26E06" },
+	{ "ROU", "g", "", "Galbeni 46N44-26E50" },
+	{ "ROU", "s", "", "Saftica 50kW" },
+	{ "RUS", "", "", "unknown Russia" },
+	{ "RUS", "a", "", "Armavir/Tblisskaya/Krasnodar 45N00-40E49" },
+	{ "RUS", "ar", "", "Arkhangelsk 64N30-40E30" },
+	{ "RUS", "b", "", "Blagoveshchensk (Amur) 50N16-127E30" },
+	{ "RUS", "c", "", "Chita (Atamanovka) (S Siberia) 51N50-113E43" },
+	{ "RUS", "e", "", "Ekaterinburg (S Ural) 56N55-60E36" },
+	{ "RUS", "i", "", "Irkutsk (Angarsk) (S Siberia) 52N18-104E18" },
+	{ "RUS", "k", "", "Kaliningrad-Bolshakovo 54N54-21E43" },
+	{ "RUS", "ka", "", "Komsomolsk-na-Amur (Far East) 50N39-136E55" },
+	{ "RUS", "kh", "", "Khabarovsk (Far East) 48N33-135E15" },
+	{ "RUS", "kr", "", "Krasnoyarsk 56N01-92E54" },
+	{ "RUS", "ku", "", "Kurovskaya-Avsyunino (near Moscow) 55N34-39E09" },
+	{ "RUS", "m", "", "Moscow/Moskva 55N45-37E18" },
+	{ "RUS", "ma", "", "Magadan" },
+	{ "RUS", "mu", "", "Murmansk 68N58-32E46" },
+	{ "RUS", "n", "", "Novosibirsk (Oyash) 55N31-83E45" },
+	{ "RUS", "n", "DW", "Novosibirsk City 55N04-82E58" },
+	{ "RUS", "p", "", "Petropavlovsk-Kamchatskij (Yelizovo) 52N59-158E39" },
+	{ "RUS", "s", "", "Samara (Zhygulevsk) 53N17-50E15" },
+	{ "RUS", "se", "", "Serpukhov [actually Noginsk but Noginsk closed with start of A03] 54N54-37E25" },
+	{ "RUS", "sp", "", "St.Petersburg (Popovka/Krasnyj Bor) 59N39-30E42" },
+	{ "RUS", "t", "", "Taldom - Severnyj (near Moscow) 56N44-37E38" },
+	{ "RUS", "u", "", "Ulan-Ude" },
+	{ "RUS", "v", "", "Vladivostok (Razdolnoye) 43N32-131E57" },
+	{ "RUS", "ya", "", "Yakutsk/Tulagino 62N01-129E48" },
+	{ "RUS", "ys", "", "Yuzhno-Sakhalinsk (Vestochka) 46N55-142E54" },
+	{ "RRW", "", "", "Kigali 01S53-30E07 (4 x 250kW)" },
+	{ "S", "", "", "Hoerby 55N49-13E44" },
+	{ "SEY", "", "", "Mahe 04S36-55E28" },
+	{ "SLV", "", "", "S Salvador or Sonsonate" },
+	{ "SNG", "", "", "Kranji 01N25-103E44" },
+	{ "SRB", "s", "", "Stubline 44N34-20E09" },
+	{ "SRL", "", "SLBS", "Goderich 08N30-13W14" },
+	{ "STP", "", "", "Pinheira 00N18-06E46" },
+	{ "SVK", "", "", "Rimavska Sobota 48N23-20E00" },
+	{ "SWZ", "", "", "Manzini 26S34-31E59" },
+	{ "SYR", "", "", "Adra 33N27-36E30" },
+	{ "TCD", "", "", "N'Djamena-Gredia 12N08-15E03" },
+	{ "THA", "", "RL/R.THA/VoA", "Udon Thani 17N25-102E48" },
+	{ "THA", "b", "", "Bangkok / Prathum Thani(1575, 4830, 6070, 7115) 13N47-100E30" },
+	{ "THA", "", "BBC", "Nakhon Sawan 15N49-100E04" },
+	{ "TJK", "", "", "Yangi Yul (Dushanbe) 38N29-68E48" },
+	{ "TJK", "y", "", "Yangi Yul (Dushanbe) 38N29-68E48" },
+	{ "TJK", "o", "", "Orzu 37N32-68E42" },
+	{ "TUN", "", "", "Sfax 34N48-10E53" },
+	{ "TUR", "", "", "Emirler 39N29-32E51" },
+	{ "TUR", "c", "", "Cakirlar 39N58-32E40" },
+	{ "TWN", "", "", "Huwei 23N43-120E25" },
+	{ "TWN", "h", "", "Huwei 23N43-120E25" },
+	{ "TWN", "k", "", "Kouhu 23N35-120E10" },
+	{ "TWN", "m", "", "Minhsiung 23N29-120E27" },
+	{ "TWN", "n", "", "Tainan 23N11-120E38" },
+	{ "TWN", "p", "", "Paochung 23N43-120E18" },
+	{ "TWN", "s", "", "Tanshui 25N13-121E29" },
+	{ "TWN", "t", "", "Taipei (Pali) 25N05-121E27" },
+	{ "UAE", "", "", "Dhabbiya 24N11-54E14" },
+	{ "UAE", "m", "", "Makta 24N21-54E34" },
+	{ "UAE", "", "UAE R Dubai", "Dubai 25N14-55E16" },
+	{ "UKR", "", "", "Kiev/Brovary 50N31-30E46" },
+	{ "UKR", "k", "", "Kiev/Brovary 50N31-30E46" },
+	{ "UKR", "L", "", "Lviv (Krasne) (Russian name Lvov) 49N51-24E40" },
+	{ "UKR", "m", "", "Mykolaiv (Kopani) (Russian name Nikolayev) 46N49-32E14" },
+	{ "UKR", "x", "", "Kharkiv (Taranivka) (Russian name Kharkov) 49N38-36E07" },
+	{ "UKR", "z", "", "Zaporizhzhya" },
+	{ "UKR", "", "657", "Chernivtsi" },
+	{ "UKR", "", "936", "Krasne" },
+	{ "USA", "", "", "unknown USA" },
+	{ "USA", "c", "", "Cypress Creek, SC 32N41-81W08" },
+	{ "USA", "d", "", "Delano, CA 35N45-119W10" },
+	{ "USA", "g", "", "Greenville, NC 35N35-77W22" },
+	{ "USA", "k", "", "Key Saddlebunch, FL 24N34-81W45" },
+	{ "USA", "o", "", "Okeechobee, FL 27N28-80W56" },
+	{ "USA", "w", "", "via WWCR, Nashville" },
+	{ "USA", "", "KAIJ", "Dallas, TX 33N13-96W52" },
+	{ "USA", "", "KJES", "Vado, NM 32N08-106W35" },
+	{ "USA", "", "KTBN", "Salt Lake City, UT 40N39-112W03" },
+	{ "USA", "", "KVOH", "Los Angeles (Rancho Simi), CA 34N15-118W38" },
+	{ "USA", "", "WBCQ", "Monticello, ME 46N20-67W50" },
+	{ "USA", "", "WBOH", "Newport, NC 34N47-76W56" },
+	{ "USA", "", "WEWN", "Birmingham (Vandiver), AL 33N30-86W28" },
+	{ "USA", "", "WGTG", "McGaysville, GA 34N58-84W22" },
+	{ "USA", "", "WHRA", "Greenbush, ME 45N08-68W34" },
+	{ "USA", "", "WHRI", "Cypress Creek, SC 32N41-81W08" },
+	{ "USA", "", "WINB", "Red Lion (York), PA 39N54-76W35" },
+	{ "USA", "", "WJIE", "Millerstown, KY 37N26-86W02" },
+	{ "USA", "", "WMLK", "Bethel, PA 40N29-76W17" },
+	{ "USA", "", "WRMI", "Miami (Hialeah Gardens), FL 25N54-80W22" },
+	{ "USA", "", "WRNO", "New Orleans, LA 29N50-90W07" },
+	{ "USA", "", "WTJC", "Newport, NC 34N47-76W53" },
+	{ "USA", "", "WYFR", "Okeechobee, FL 27N28-80W56" },
+	{ "USA", "", "WWBS", "Macon, GA 32N50-83W38" },
+	{ "USA", "", "WWCR", "Nashville, TN 36N13-86W54" },
+	{ "USA", "", "WWRB", "Manchester / Morrison, TN 35N29-86W02" },
+	{ "UZB", "", "", "Tashkent 41N13-69E09" },
+	{ "VTN", "", "", "Sontay 21N12-105E22" },
+	{ "VTN", "d", "", "Daclac 12N41-108E31" },
+	{ "VTN", "h", "", "Hanoi-Metri 20N59-105E52" },
+	{ "VTN", "x", "", "Xuan Mai 20N43-105E33" },
+	{ "YEM", "a", "", "Al Hiswah/Aden 12N50-45E02" },
+	{ "YEM", "s", "", "Sanaa 15N22-44E11" },
+	{ 0, 0, 0, 0}
+	};
+
+CStationData::CStationData()
+{
+	int i;
+	for(i=0; eibi_langs[i].code; i++)
+	{
+		l[eibi_langs[i].code] = eibi_langs[i].lang;
+	}
+
+	for(i=0; itu_r_countries[i].code; i++)
+	{
+		c[itu_r_countries[i].code] = itu_r_countries[i].country;
+	}
+
+	for(i=0; eibi_targets[i].code; i++)
+	{
+		string code = eibi_targets[i].code;
+		string v = eibi_targets[i].target;
+		string C = "C"; string c = "Central ";
+		string N = "N"; string n = "North ";
+		string S = "S"; string s = "South ";
+		string E = "E"; string e = "East ";
+		string W = "W"; string w = "West ";
+		t[code] = v;
+		t[C+code] = c+v;
+		t[N+code] = n+v;
+		t[S+code] = s+v;
+		t[E+code] = e+v;
+		t[W+code] = w+v;
+	}
+	for(i=0; eibi_stations[i].country; i++)
+	{
+		s[eibi_stations[i].country][eibi_stations[i].mark] = eibi_stations[i].site;
+	}
+}
+
+string
+CStationData::eibi_language(const std::string& code)
+{
+	map<string,string>::const_iterator i = l.find(code);
+	if(i == l.end())
+		return "";
+	return i->second;
+}
+
+string
+CStationData::itu_r_country(const std::string& code)
+{
+	map<string,string>::const_iterator i = c.find(code);
+	if(i == c.end())
+		return "";
+	return i->second;
+}
+
+string
+CStationData::eibi_target(const std::string& code)
+{
+	map<string,string>::const_iterator i = t.find(code);
+	if(i == t.end())
+		return "";
+	return i->second;
+}
+
+string
+CStationData::eibi_station(const std::string& country, const std::string& stn)
+{
+	map<string, map<string,string> >::const_iterator site = s.find(country);
+	if(site == s.end())
+		return "";
+	map<string,string>::const_iterator tx = site->second.find(stn);
+	if(tx == site->second.end())
+		return "";
+	return tx->second;
+}
diff --git a/src/tables/TableStations.h b/src/tables/TableStations.h
new file mode 100644
index 0000000..ed4d42e
--- /dev/null
+++ b/src/tables/TableStations.h
@@ -0,0 +1,50 @@
+/******************************************************************************\
+ * British Broadcasting Corporation
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Julian Cable
+ *
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#ifndef _TABLE_STATIONS_H
+#define _TABLE_STATIONS_H
+
+#include <string>
+#include <map>
+
+class CStationData
+{
+public:
+	CStationData();
+
+	std::string eibi_language(const std::string& code);
+	std::string itu_r_country(const std::string& code);
+	std::string eibi_target(const std::string& code);
+	std::string eibi_station(const std::string& country, const std::string& stn);
+
+private:
+	std::map<std::string,std::string> l;
+	std::map<std::string,std::string> c;
+	std::map<std::string,std::string> t;
+	std::map<std::string, std::map<std::string,std::string> > s;
+};
+
+#endif
diff --git a/src/util-QT/EPG.cpp b/src/util-QT/EPG.cpp
new file mode 100644
index 0000000..df71238
--- /dev/null
+++ b/src/util-QT/EPG.cpp
@@ -0,0 +1,1629 @@
+/******************************************************************************\
+ * British Broadcasting Corporation
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Julian Cable
+ *
+ * Description:
+ *	ETSI DAB/DRM Electronic Programme Guide class
+ *
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "EPG.h"
+#include "../util-QT/Util.h"
+#include <QFileInfo>
+#include <QFile>
+#include <QDir>
+#include <QTextStream>
+#include <QRegExp>
+#include <iostream>
+#include <cstdlib>
+#include <sys/stat.h>
+#ifdef _WIN32
+# include <windows.h>
+#endif
+
+const
+EPG::gl
+EPG::genre_list[] = {
+    {"1", "Audio-Video"},
+    {"1.0", "Proprietary"},
+    {"1.1", "PlayRecording"},
+    {"1.1.1", "Pure entertainment"},
+    {"1.1.2", "Informative entertainment"},
+    {"1.10", "Mute"},
+    {"1.11", "VolumeUp"},
+    {"1.12", "VolumeDown"},
+    {"1.13", "Loop/Repeat"},
+    {"1.14", "Shuffle"},
+    {"1.15", "SkipToStart"},
+    {"1.16", "SkipToEnd"},
+    {"1.17", "CopyCD"},
+    {"1.2", "PlayStream"},
+    {"1.2.1", "Government"},
+    {"1.2.2", "Pure information"},
+    {"1.2.3", "Infotainment"},
+    {"1.2.4", "Advice"},
+    {"1.3", "Record"},
+    {"1.3.1", "School Programmes"},
+    {"1.3.1.1", "Primary"},
+    {"1.3.1.2", "Secondary"},
+    {"1.3.1.3", "Tertiary"},
+    {"1.3.2", "Lifelong/further education"},
+    {"1.4", "Preview"},
+    {"1.5", "Pause"},
+    {"1.6", "FastForward"},
+    {"1.6.1", "Gambling"},
+    {"1.6.2", "Home Shopping"},
+    {"1.7", "Rewind"},
+    {"1.7.1", "Fund Raising"},
+    {"1.7.2", "Social Action"},
+    {"1.8", "SkipForward"},
+    {"1.8.1", "General enrichment"},
+    {"1.8.2", "Inspirational enrichment"},
+    {"1.9", "SkipBackward"},
+    {"1.9.1", "Very Easy"},
+    {"1.9.2", "Easy"},
+    {"1.9.3", "Medium"},
+    {"1.9.4", "Difficult"},
+    {"1.9.5", "Very Difficult"},
+    {"10", "For more information"},
+    {"11", "Programme review information"},
+    {"12", "Recap"},
+    {"13", "The making of"},
+    {"14", "Support"},
+    {"15", "Segmentation"},
+    {"16", "Derived"},
+    {"17", "TVA RMPI document"},
+    {"18", "Content Package"},
+    {"2", "Video "},
+    {"2.0", "Proprietary"},
+    {"2.1", "Zoom"},
+    {"2.1.1 ", "Bulletin"},
+    {"2.1.2", "Magazine"},
+    {"2.1.2.1", "Presenter led magazine"},
+    {"2.1.2.2", "Clip led magazine"},
+    {"2.1.3", "Event"},
+    {"2.1.3.1", "Commented event"},
+    {"2.1.3.2", "Uncommented event"},
+    {"2.1.4", "Documentary"},
+    {"2.1.5", "Discussion/Interview/Debate/Talkshow"},
+    {"2.1.6", "Lecture/Speech/Presentation"},
+    {"2.1.7", "Textual (incl. relayed teletext)"},
+    {"2.1.8", "Phone-in"},
+    {"2.1.9", "DJ with discs"},
+    {"2.2", "SlowMotion"},
+    {"2.2.1", "Fictional portrayal of life"},
+    {"2.2.2", "Readings"},
+    {"2.2.3", "Dramatic documentary"},
+    {"2.3", "CCOn"},
+    {"2.3.1", "Anime"},
+    {"2.3.2", "Computer"},
+    {"2.3.3", "Cartoon"},
+    {"2.3.4", "Puppetry"},
+    {"2.3.4.1", "Real time puppetry"},
+    {"2.3.4.2", "Physical model animation"},
+    {"2.4", "StepForward"},
+    {"2.4.1", "Hosted show"},
+    {"2.4.1.1", "Simple game show"},
+    {"2.4.1.2", "Big game show"},
+    {"2.4.2", "Panel-show"},
+    {"2.4.2.1", "Simple game show"},
+    {"2.4.2.2", "Big game show"},
+    {"2.4.3", "Non-hosted show"},
+    {"2.4.4", "Standup comedian(s)"},
+    {"2.4.5", "Reality Show"},
+    {"2.4.5.1", "Observational show"},
+    {"2.4.5.2", "Controlled show"},
+    {"2.5", "StepBackward"},
+    {"2.5.1", "Solo performance"},
+    {"2.5.2", "Small ensemble performance"},
+    {"2.5.3", "Large ensemble performance"},
+    {"2.5.4", "Mixed"},
+    {"2.6", "void"},
+    {"2.7", "INTERACTIVE"},
+    {"2.7.1", "LOCAL INTERACTIVITY"},
+    {"2.7.1.1", "Static informational"},
+    {"2.7.1.10", "Elimination and timer"},
+    {"2.7.1.11", "Categories"},
+    {"2.7.1.12", "Level based quiz/game"},
+    {"2.7.1.13", "Following a sequence"},
+    {"2.7.1.14", "Local multi player"},
+    {"2.7.1.15", "Multi stream audio-video"},
+    {"2.7.1.16", "Enhanced advertisement"},
+    {"2.7.1.17", "Logic based games"},
+    {"2.7.1.18", "Word games"},
+    {"2.7.1.19", "Positional games"},
+    {"2.7.1.2", "Dynamic informational"},
+    {"2.7.1.20", "Board games"},
+    {"2.7.1.21", "Text based gaming"},
+    {"2.7.1.22", "Dynamic 2D/3D graphics"},
+    {"2.7.1.3", "Viewing chats"},
+    {"2.7.1.4", "Quiz - Basic multiple choice"},
+    {"2.7.1.5", "Quiz - Text or number entry answers"},
+    {"2.7.1.6", "Re-ordering"},
+    {"2.7.1.7", "Positional"},
+    {"2.7.1.8", "Sync quiz"},
+    {"2.7.1.9", "Timer quiz"},
+    {"2.7.2", "INTERMITTENT RESPONSE"},
+    {"2.7.2.1", "Single impulse vote"},
+    {"2.7.2.10", "Multi player TS networked services/games"},
+    {"2.7.2.11", "Interactive advertisement"},
+    {"2.7.2.2", "Impulse vote from choices"},
+    {"2.7.2.3", "Impulse Yes/No vote"},
+    {"2.7.2.4", "Impulse vote with a value"},
+    {"2.7.2.5", "Submit answers/form"},
+    {"2.7.2.6", "SMS using mobile"},
+    {"2.7.2.7", "SMS using TV remote"},
+    {"2.7.2.8", "Impulse gambling"},
+    {"2.7.2.9", "Impulse transaction"},
+    {"2.7.3", "ALWAYS ON CONNECTION"},
+    {"2.7.3.1", "Chat Forum"},
+    {"2.7.3.10", "Impulse transaction"},
+    {"2.7.3.11", "Non-linear audio-video"},
+    {"2.7.3.2", "Chat Forum via web"},
+    {"2.7.3.3", "Threaded mail discussions"},
+    {"2.7.3.4", "Point to point"},
+    {"2.7.3.5", "3rd party point to point"},
+    {"2.7.3.6", "Voice chat using mic capability"},
+    {"2.7.3.7", "Dual player networked services/games"},
+    {"2.7.3.8", "Multi player RT networked services/games"},
+    {"2.7.3.9", "Gambling services"},
+    {"3", "Data"},
+    {"3.0", "Proprietary"},
+    {"3.1", "NON-FICTION/INFORMATION"},
+    {"3.1.1", "News"},
+    {"3.1.1.1", "Daily news"},
+    {"3.1.1.2", "Special news/edition"},
+    {"3.1.1.3", "Special News Report"},
+    {"3.1.1.4", "News Commentary"},
+    {"3.1.1.5", "News Periodical/General"},
+    {"3.1.1.6", "National politics/National assembly"},
+    {"3.1.1.7", "Business News"},
+    {"3.1.1.8", "International News"},
+    {"3.1.1.9", "Sports News"},
+    {"3.1.1.10", "Cultural News"},
+    {"3.1.1.10.1", "Arts News"},
+    {"3.1.1.10.2", "Entertainment News"},
+    {"3.1.1.10.3", "Film News"},
+    {"3.1.1.10.4", "Music News"},
+    {"3.1.1.10.5", "Radio in the News"},
+    {"3.1.1.10.6", "TV in the News"},
+    {"3.1.1.11", "Regional News"},
+    {"3.1.1.12", "Traffic Information"},
+    {"3.1.1.13", "Weather forecasts"},
+    {"3.1.1.14", "Service information"},
+    {"3.1.1.15", "Public affairs"},
+    {"3.1.1.16", "Current affairs"},
+    {"3.1.1.17", "Consumer affairs"},
+    {"3.1.2", "Religion/Philosophies"},
+    {"3.1.2.1", "Religion"},
+    {"3.1.2.1.1", "Buddhism"},
+    {"3.1.2.1.2", "Hinduism"},
+    {"3.1.2.1.3", "Christianity"},
+    {"3.1.2.1.4", "Islam"},
+    {"3.1.2.1.5", "Judaism"},
+    {"3.1.2.1.8", "Shintoism"},
+    {"3.1.2.1.9", "Baha'i"},
+    {"3.1.2.1.10", "Confucianism"},
+    {"3.1.2.1.11", "Jainism"},
+    {"3.1.2.1.12", "Sikhism"},
+    {"3.1.2.1.13", "Taoism"},
+    {"3.1.2.1.14", "Vodun (Voodoo)"},
+    {"3.1.2.1.15", "Asatru (Nordic Paganism)"},
+    {"3.1.2.1.16", "Drudism"},
+    {"3.1.2.1.17", "Goddess worship"},
+    {"3.1.2.1.18", "Wicca"},
+    {"3.1.2.1.19", "Witchcraft"},
+    {"3.1.2.1.20", "Caodaism"},
+    {"3.1.2.1.21", "Damanhur Community"},
+    {"3.1.2.1.22", "Druse (Mowahhidoon)"},
+    {"3.1.2.1.23", "Eckankar"},
+    {"3.1.2.1.24", "Gnosticism"},
+    {"3.1.2.1.25", "Rroma (Gypsies)"},
+    {"3.1.2.1.26", "Hare Krishna and ISKCON"},
+    {"3.1.2.1.27", "Lukumi (Santeria)"},
+    {"3.1.2.1.28", "Macumba"},
+    {"3.1.2.1.29", "Native American spirituality"},
+    {"3.1.2.1.30", "New Age"},
+    {"3.1.2.1.31", "Osho"},
+    {"3.1.2.1.32", "Satanism"},
+    {"3.1.2.1.33", "Scientology"},
+    {"3.1.2.1.34", "Thelema"},
+    {"3.1.2.1.35", "Unitarian-Universalism"},
+    {"3.1.2.1.36", "The Creativity Movement"},
+    {"3.1.2.1.37", "Zoroastrianism"},
+    {"3.1.2.1.38", "Quakerism"},
+    {"3.1.2.1.39", "Rastafarianism"},
+    {"3.1.2.2", "Non-religious philosophies"},
+    {"3.1.2.2.1", "Communism"},
+    {"3.1.2.2.2", "Humanism"},
+    {"3.1.2.2.5", "Libertarianism"},
+    {"3.1.2.2.7", "Deism"},
+    {"3.1.2.2.8", "Falun Gong and Falun Dafa"},
+    {"3.1.2.2.9", "Objectivism"},
+    {"3.1.2.2.10", "Universism"},
+    {"3.1.2.2.11", "Atheism"},
+    {"3.1.2.2.12", "Agnosticism"},
+    {"3.1.3", "General non-fiction"},
+    {"3.1.3.1", "Political"},
+    {"3.1.3.1.1", "Capitalism"},
+    {"3.1.3.1.2", "Fascism"},
+    {"3.1.3.1.3", "Republicanism"},
+    {"3.1.3.1.4", "Socialism"},
+    {"3.1.3.2", "Social"},
+    {"3.1.3.3", "Economic"},
+    {"3.1.3.4", "Legal"},
+    {"3.1.3.5", "Finance"},
+    {"3.1.3.6", "Education"},
+    {"3.1.3.6.1", "Pre-School"},
+    {"3.1.3.6.2", "Primary Education"},
+    {"3.1.3.6.3", "Secondary Education"},
+    {"3.1.3.6.4", "Colleges and Universities"},
+    {"3.1.3.6.5", "Adult education"},
+    {"3.1.3.6.6", "Non-formal education"},
+    {"3.1.3.6.7", "Homework"},
+    {"3.1.3.6.8", "Reading groups"},
+    {"3.1.3.6.9", "Distance learning"},
+    {"3.1.3.6.10", "Religious schools"},
+    {"3.1.3.6.11", "Student organisations"},
+    {"3.1.3.6.12", "Testing in Education"},
+    {"3.1.3.6.13", "Theory and methods of Education"},
+    {"3.1.3.6.14", "Interdisciplinary studies"},
+    {"3.1.3.7", "International affairs"},
+    {"3.1.3.8", "Military/Defence"},
+    {"3.1.3.9", "Industry/Manufacturing"},
+    {"3.1.3.10", "Agriculture"},
+    {"3.1.3.11", "Construction"},
+    {"3.1.4", "Arts"},
+    {"3.1.4.1", "Music"},
+    {"3.1.4.2", "Dance"},
+    {"3.1.4.3", "Theatre"},
+    {"3.1.4.4", "Opera"},
+    {"3.1.4.5", "Cinema"},
+    {"3.1.4.6", "Poetry"},
+    {"3.1.4.8", "Plastic arts"},
+    {"3.1.4.9", "Fine arts"},
+    {"3.1.4.10", "Experimental arts"},
+    {"3.1.4.11", "Architecture"},
+    {"3.1.4.12", "Showbiz"},
+    {"3.1.5", "Humanities"},
+    {"3.1.5.1", "Literature"},
+    {"3.1.5.2", "Languages"},
+    {"3.1.5.3", "History"},
+    {"3.1.5.4", "Culture/Tradition/Anthropology/Ethnic studies"},
+    {"3.1.5.5", "War/Conflict"},
+    {"3.1.5.6", "Philosophy"},
+    {"3.1.5.7", "Political Science"},
+    {"3.1.6", "Sciences"},
+    {"3.1.6.1", "Applied sciences"},
+    {"3.1.6.2", "Nature"},
+    {"3.1.6.2.1", "Biology"},
+    {"3.1.6.2.2", "Geology"},
+    {"3.1.6.2.3", "Botany"},
+    {"3.1.6.2.4", "Zoology"},
+    {"3.1.6.3", "Animals/Wildlife"},
+    {"3.1.6.4", "Environment"},
+    {"3.1.6.5", "Space"},
+    {"3.1.6.6", "Physical sciences"},
+    {"3.1.6.6.1", "Physics"},
+    {"3.1.6.6.2", "Chemistry"},
+    {"3.1.6.6.3", "Mechanics"},
+    {"3.1.6.6.4", "Engineering"},
+    {"3.1.6.7", "Medicine"},
+    {"3.1.6.7.1", "Alternative Medicine"},
+    {"3.1.6.8", "Technology"},
+    {"3.1.6.9", "Physiology"},
+    {"3.1.6.10", "Psychology"},
+    {"3.1.6.11", "Social"},
+    {"3.1.6.12", "Spiritual"},
+    {"3.1.6.13", "Mathematics"},
+    {"3.1.6.14", "Archaeology"},
+    {"3.1.6.15", "Statistics"},
+    {"3.1.6.16", "Liberal Arts and Science"},
+    {"3.1.7", "Human interest"},
+    {"3.1.7.1", "Reality"},
+    {"3.1.7.2", "Society/Show business/Gossip"},
+    {"3.1.7.3", "Biography/Notable personalities"},
+    {"3.1.7.4", "Personal problems"},
+    {"3.1.7.5", "Investigative journalism"},
+    {"3.1.7.6", "Museums"},
+    {"3.1.7.7", "Religious buildings"},
+    {"3.1.7.8", "Personal stories"},
+    {"3.1.7.9", "Family life"},
+    {"3.1.7.10", "libraries"},
+    {"3.1.8", "Transport and Communications"},
+    {"3.1.8.1", "Air"},
+    {"3.1.8.2", "Land"},
+    {"3.1.8.3", "Sea"},
+    {"3.1.8.4", "Space"},
+    {"3.1.9", "Events"},
+    {"3.1.9.1", "Anniversary"},
+    {"3.1.9.2", "Fairs"},
+    {"3.1.9.3", "Tradeshows"},
+    {"3.1.9.4", "Musicals"},
+    {"3.1.9.5", "Exhibition"},
+    {"3.1.9.6", "Royal Events"},
+    {"3.1.9.7", "State Events"},
+    {"3.1.9.8", "International Events"},
+    {"3.1.9.9", "National Events"},
+    {"3.1.9.10", "Local/Regional Events"},
+    {"3.1.9.11", "Seasonal Events"},
+    {"3.1.9.12", "Sporting Events"},
+    {"3.1.9.13", "Festivals"},
+    {"3.1.9.14", "Concerts"},
+    {"3.1.9.15", "Funeral/Memorial"},
+    {"3.1.10", "Media"},
+    {"3.1.10.1", "Advertising"},
+    {"3.1.10.2", "Print media"},
+    {"3.1.10.3", "Television"},
+    {"3.1.10.4", "Radio"},
+    {"3.1.10.5", "New media"},
+    {"3.1.10.6", "Marketing"},
+    {"3.1.11", "Listings"},
+    {"3.2", "Sports"},
+    {"3.2.1", "Athletics"},
+    {"3.2.1.1", "Field"},
+    {"3.2.1.2", "Track"},
+    {"3.2.1.3", "Combined athletics"},
+    {"3.2.1.4", "Running"},
+    {"3.2.1.5", "Cross-country"},
+    {"3.2.1.6", "Triathlon"},
+    {"3.2.2", "Cycling/Bicycle"},
+    {"3.2.2.1", "Mountainbike"},
+    {"3.2.2.2", "Bicross"},
+    {"3.2.2.3", "Indoor cycling"},
+    {"3.2.2.4", "Road cycling"},
+    {"3.2.3", "Team sports"},
+    {"3.2.3.1", "Football (American)"},
+    {"3.2.3.2", "Football (Australian)"},
+    {"3.2.3.3", "Football (Gaelic)"},
+    {"3.2.3.4", "Football (Indoor)"},
+    {"3.2.3.5", "Beach soccer"},
+    {"3.2.3.6", "Bandy"},
+    {"3.2.3.7", "Baseball"},
+    {"3.2.3.8", "Basketball"},
+    {"3.2.3.9", "Cricket"},
+    {"3.2.3.10", "Croquet"},
+    {"3.2.3.11", "Faustball"},
+    {"3.2.3.12", "Football (Soccer)"},
+    {"3.2.3.13", "Handball"},
+    {"3.2.3.14", "Hockey"},
+    {"3.2.3.15", "Korfball"},
+    {"3.2.3.16", "Lacrosse"},
+    {"3.2.3.17", "Netball"},
+    {"3.2.3.18", "Roller skating"},
+    {"3.2.3.19", "Rugby"},
+    {"3.2.3.19.1", "Rugby union"},
+    {"3.2.3.19.2", "Rugby league"},
+    {"3.2.3.20", "Softball"},
+    {"3.2.3.21", "Volleyball"},
+    {"3.2.3.22", "Beach volley"},
+    {"3.2.3.23", "Hurling"},
+    {"3.2.3.24", "Frisbee"},
+    {"3.2.3.25", "Kabadi"},
+    {"3.2.3.26", "Camogie"},
+    {"3.2.3.27", "Shinty"},
+    {"3.2.3.28", "Street Soccer"},
+    {"3.2.4", "Racket sports"},
+    {"3.2.4.1", "Badminton"},
+    {"3.2.4.2", "Racketball"},
+    {"3.2.4.3", "Short tennis"},
+    {"3.2.4.4", "Soft tennis"},
+    {"3.2.4.5", "Squash"},
+    {"3.2.4.6", "Table tennis"},
+    {"3.2.4.7", "Tennis"},
+    {"3.2.5", "Martial Arts"},
+    {"3.2.5.1", "Aikido"},
+    {"3.2.5.2", "Jai-alai"},
+    {"3.2.5.3", "Judo"},
+    {"3.2.5.4", "Ju-jitsu"},
+    {"3.2.5.5", "Karate"},
+    {"3.2.5.6", "Sumo/Fighting games"},
+    {"3.2.5.7", "Sambo"},
+    {"3.2.5.8", "Taekwondo"},
+    {"3.2.6", "Water sports"},
+    {"3.2.6.1", "Bodyboarding"},
+    {"3.2.6.2", "Yatching"},
+    {"3.2.6.3", "Canoeing"},
+    {"3.2.6.4", "Diving"},
+    {"3.2.6.5", "Fishing"},
+    {"3.2.6.6", "Polo"},
+    {"3.2.6.7", "Rowing"},
+    {"3.2.6.8", "Sailing"},
+    {"3.2.6.9", "Sub-aquatics"},
+    {"3.2.6.10", "Surfing"},
+    {"3.2.6.11", "Swimming"},
+    {"3.2.6.12", "Water polo"},
+    {"3.2.6.13", "Water skiing"},
+    {"3.2.6.14", "Windsurfing"},
+    {"3.2.7", "Winter sports"},
+    {"3.2.7.1", "Bobsleigh/Tobogganing"},
+    {"3.2.7.2", "Curling"},
+    {"3.2.7.3", "Ice-hockey"},
+    {"3.2.7.4", "Ice-skating"},
+    {"3.2.7.5", "Luge"},
+    {"3.2.7.6", "Skating"},
+    {"3.2.7.7", "Skibob"},
+    {"3.2.7.8", "Skiing"},
+    {"3.2.7.9", "Sleddog"},
+    {"3.2.7.10", "Snowboarding"},
+    {"3.2.7.11", "Alpine skiing"},
+    {"3.2.7.12", "Freestyle skiing "},
+    {"3.2.7.13", "Inline skating"},
+    {"3.2.7.14", "Nordic skiing"},
+    {"3.2.7.15", "Ski jumping"},
+    {"3.2.7.16", "Speed skating"},
+    {"3.2.7.17", "Figure skating"},
+    {"3.2.7.18", "Ice-dance"},
+    {"3.2.7.19", "Marathon"},
+    {"3.2.7.20", "Short-track"},
+    {"3.2.7.21", "Biathlon"},
+    {"3.2.8", "Motor sports"},
+    {"3.2.8.1", "Auto racing"},
+    {"3.2.8.2", "Motor boating"},
+    {"3.2.8.3", "Motor cycling"},
+    {"3.2.8.4", "Formula 1"},
+    {"3.2.8.5", "Indy car"},
+    {"3.2.8.6", "Karting"},
+    {"3.2.8.7", "Rally"},
+    {"3.2.8.8", "Trucking"},
+    {"3.2.8.9", "Tractor pulling"},
+    {"3.2.8.10", "Stock car"},
+    {"3.2.8.11", "Hill Climb"},
+    {"3.2.8.12", "Trials"},
+    {"3.2.9", "'Social' sports"},
+    {"3.2.9.1", "Billiards"},
+    {"3.2.9.2", "Boules"},
+    {"3.2.9.3", "Bowling"},
+    {"3.2.9.5", "Dance sport"},
+    {"3.2.9.6", "Darts"},
+    {"3.2.9.7", "Pool"},
+    {"3.2.9.8", "Snooker"},
+    {"3.2.9.9", "Tug-of-war"},
+    {"3.2.9.10", "Balle pelote"},
+    {"3.2.9.11", "Basque pelote"},
+    {"3.2.9.12", "Trickshot"},
+    {"3.2.10", "Gymnastics"},
+    {"3.2.10.1", "Asymmetric bars"},
+    {"3.2.10.2", "Beam"},
+    {"3.2.10.3", "Horse"},
+    {"3.2.10.4", "Mat"},
+    {"3.2.10.5", "Parallel bars"},
+    {"3.2.10.6", "Rings"},
+    {"3.2.10.7", "Trampoline"},
+    {"3.2.11", "Equestrian"},
+    {"3.2.11.1", "Cart"},
+    {"3.2.11.2", "Dressage"},
+    {"3.2.11.3", "Horse racing"},
+    {"3.2.11.4", "Polo"},
+    {"3.2.11.5", "Jumping"},
+    {"3.2.11.6", "Crossing"},
+    {"3.2.11.7", "Trotting"},
+    {"3.2.12", "Adventure sports"},
+    {"3.2.12.1", "Archery"},
+    {"3.2.12.2", "Extreme sports"},
+    {"3.2.12.3", "Mountaineering"},
+    {"3.2.12.4", "Climbing"},
+    {"3.2.12.5", "Orienteering"},
+    {"3.2.12.6", "Shooting"},
+    {"3.2.12.7", "Sport acrobatics"},
+    {"3.2.12.8", "Rafting"},
+    {"3.2.12.9", "Caving"},
+    {"3.2.12.10", "Skateboarding"},
+    {"3.2.12.11", "Treking"},
+    {"3.2.13", "Strength-based sports"},
+    {"3.2.13.1", "Body-building"},
+    {"3.2.13.2", "Boxing"},
+    {"3.2.13.3", "Combative sports"},
+    {"3.2.13.4", "Power-lifting"},
+    {"3.2.13.5", "Weight-lifting"},
+    {"3.2.13.6", "Wrestling"},
+    {"3.2.14", "Air sports"},
+    {"3.2.14.1", "Ballooning"},
+    {"3.2.14.2", "Hang gliding"},
+    {"3.2.14.3", "Sky diving"},
+    {"3.2.14.4", "Delta-plane"},
+    {"3.2.14.5", "Parachuting"},
+    {"3.2.14.6", "Kiting"},
+    {"3.2.14.7", "Aeronautics"},
+    {"3.2.14.8", "Gliding"},
+    {"3.2.14.9", "Flying"},
+    {"3.2.14.10", "Aerobatics"},
+    {"3.2.15", "Golf"},
+    {"3.2.16", "Fencing"},
+    {"3.2.17", "Dog racing"},
+    {"3.2.18", "Casting"},
+    {"3.2.19", "Maccabi"},
+    {"3.2.20", "Modern Pentathlon"},
+    {"3.2.21", "Sombo"},
+    {"3.2.22", "Mind Games"},
+    {"3.2.22.1", "Bridge"},
+    {"3.2.22.2", "Chess"},
+    {"3.2.22.3", "Poker"},
+    {"3.2.23", "Traditional Games"},
+    {"3.2.24", "Disabled Sport"},
+    {"3.2.24.1", "Physically Challenged"},
+    {"3.2.24.2", "Mentally Challenged"},
+    {"3.4", "FICTION/DRAMA"},
+    {"3.4.1", "General light drama"},
+    {"3.4.2", "Soap"},
+    {"3.4.2.1", "Soap opera"},
+    {"3.4.2.2", "Soap special"},
+    {"3.4.2.3", "Soap talk"},
+    {"3.4.3", "Romance"},
+    {"3.4.4", "Legal Melodrama"},
+    {"3.4.5", "Medical melodrama"},
+    {"3.4.6", "Action"},
+    {"3.4.6.1", "Adventure"},
+    {"3.4.6.2", "Disaster"},
+    {"3.4.6.3", "Mystery"},
+    {"3.4.6.4", "Detective/Police"},
+    {"3.4.6.5", "Historical/Epic"},
+    {"3.4.6.6", "Horror"},
+    {"3.4.6.7", "Science fiction"},
+    {"3.4.6.8", "War"},
+    {"3.4.6.9", "Western"},
+    {"3.4.6.10", "Thriller"},
+    {"3.4.6.11", "Sports"},
+    {"3.4.6.12", "Martial arts"},
+    {"3.4.6.13", "Epic"},
+    {"3.4.7", "Fantasy/Fairy tale"},
+    {"3.4.8", "Erotica"},
+    {"3.4.9", "Docudrama"},
+    {"3.4.10", "Musical"},
+    {"3.4.13", "Classical drama"},
+    {"3.4.14", "Period drama"},
+    {"3.4.15", "Contemporary drama"},
+    {"3.4.16", "Religious drama"},
+    {"3.4.17", "Poems/Stories"},
+    {"3.4.18", "Biography"},
+    {"3.4.19", "Psychological drama"},
+    {"3.4.20", "Political Drama"},
+    {"3.5", "AMUSEMENT/ENTERTAINMENT"},
+    {"3.5.2", "Quiz/Contest"},
+    {"3.5.2.1", "Quiz"},
+    {"3.5.2.2", "Contest"},
+    {"3.5.3", "Variety/Talent"},
+    {"3.5.3.1", "Cabaret"},
+    {"3.5.3.2", "Talent"},
+    {"3.5.4", "Surprise"},
+    {"3.5.5", "Reality"},
+    {"3.5.7", "Comedy"},
+    {"3.5.7.1", "Broken comedy"},
+    {"3.5.7.2", "Romantic comedy"},
+    {"3.5.7.3", "Sitcom"},
+    {"3.5.7.4", "Satire"},
+    {"3.5.7.5", "Candid Camera"},
+    {"3.5.7.6", "Humour"},
+    {"3.5.7.7", "Spoof"},
+    {"3.5.10", "Magic/Hypnotism"},
+    {"3.5.11", "Circus"},
+    {"3.5.12", "Dating"},
+    {"3.5.13", "Bullfighting"},
+    {"3.5.14", "Rodeo"},
+    {"3.5.16", "Chat"},
+    {"3.6", "Music"},
+    {"3.6.1", "Classical music"},
+    {"3.6.1.1", "Early"},
+    {"3.6.1.2", "Classical"},
+    {"3.6.1.3", "Romantic"},
+    {"3.6.1.4", "Contemporary"},
+    {"3.6.1.5", "Light classical"},
+    {"3.6.1.6", "Middle Ages"},
+    {"3.6.1.7", "Renaissance"},
+    {"3.6.1.8", "Baroque"},
+    {"3.6.1.9", "Opera"},
+    {"3.6.1.10", "Solo instruments"},
+    {"3.6.1.11", "Chamber"},
+    {"3.6.1.12", "Symphonic"},
+    {"3.6.1.13", "Vocal"},
+    {"3.6.1.14", "Choral"},
+    {"3.6.1.15", "Song"},
+    {"3.6.1.16", "Orchestral"},
+    {"3.6.1.17", "Organ"},
+    {"3.6.1.18", "String Quartet"},
+    {"3.6.1.19", "Experimental/Avant Garde"},
+    {"3.6.2", "Jazz"},
+    {"3.6.2.1", "New Orleans/Early jazz"},
+    {"3.6.2.2", "Big band/Swing/Dixie"},
+    {"3.6.2.3", "Blues/Soul jazz"},
+    {"3.6.2.4", "Bop/Hard bop/Bebop/Postbop"},
+    {"3.6.2.5", "Traditional/Smooth jazz"},
+    {"3.6.2.6", "Cool jazz"},
+    {"3.6.2.7", "Modern/Avant-garde/Free jazz"},
+    {"3.6.2.8", "Latin and World jazz"},
+    {"3.6.2.9", "Pop jazz/Jazz funk"},
+    {"3.6.2.10", "Acid jazz/Fusion"},
+    {"3.6.3", "Background music"},
+    {"3.6.3.1", "Middle-of-the-road"},
+    {"3.6.3.2", "Easy listening"},
+    {"3.6.3.3", "Ambient"},
+    {"3.6.3.4", "Mood music"},
+    {"3.6.3.5", "Oldies"},
+    {"3.6.3.6", "Love songs"},
+    {"3.6.3.7", "Dance hall"},
+    {"3.6.3.8", "Soundtrack"},
+    {"3.6.3.9", "Trailer"},
+    {"3.6.3.10", "Showtunes"},
+    {"3.6.3.11", "TV"},
+    {"3.6.3.12", "Cabaret"},
+    {"3.6.3.13", "Instrumental"},
+    {"3.6.3.14", "Sound clip"},
+    {"3.6.3.15", "Retro"},
+    {"3.6.4", "Pop-rock"},
+    {"3.6.4.1", "Pop"},
+    {"3.6.4.2", "Chanson/Ballad"},
+    {"3.6.4.3", "Traditional rock and roll"},
+    {"3.6.4.5", "Classic/Dance/Pop-rock"},
+    {"3.6.4.6", "Folk"},
+    {"3.6.4.8", "New Age"},
+    {"3.6.4.11", "Seasonal/Holiday"},
+    {"3.6.4.12", "Japanese pop-rock"},
+    {"3.6.4.13", "Karaoke/Singing contests"},
+    {"3.6.4.14", "Rock"},
+    {"3.6.4.14.1", "AOR / Slow Rock / Soft Rock"},
+    {"3.6.4.14.2", "Metal"},
+    {"3.6.4.14.3", "Glam Rock"},
+    {"3.6.4.14.4", "Punk Rock"},
+    {"3.6.4.14.5", "Prog / Symphonic Rock"},
+    {"3.6.4.14.6", "Alternative / Indie"},
+    {"3.6.4.14.7", "Experimental / Avant Garde"},
+    {"3.6.4.14.8", "Art Rock"},
+    {"3.6.4.14.9", "Folk Rock"},
+    {"3.6.4.14.10", "Nu Punk"},
+    {"3.6.4.14.11", "Grunge"},
+    {"3.6.4.14.12", "Garage Punk/Psychedelia"},
+    {"3.6.4.14.13", "Heavy Rock"},
+    {"3.6.4.15", "New Wave"},
+    {"3.6.4.16", "Easy listening / Exotica"},
+    {"3.6.4.17", "Singer/Songwriter"},
+    {"3.6.5", "Blues/Rhythm and Blues/Soul/Gospel"},
+    {"3.6.5.1", "Blues"},
+    {"3.6.5.2", "R and B"},
+    {"3.6..5.2.1", "Hip Hop Soul"},
+    {"3.6..5.2.2", "Neo Soul"},
+    {"3.6..5.2.3", "New Jack Swing"},
+    {"3.6.5.3", "Soul"},
+    {"3.6.5.4", "Gospel"},
+    {"3.6.5.5", "Rhythm and Blues"},
+    {"3.6.5.6", "Funk"},
+    {"3.6.5.6.1", "Afro Funk"},
+    {"3.6.5.6.2", "Rare Groove"},
+    {"3.6.6", "Country and Western"},
+    {"3.6.7", "Rap/Hip Hop/Reggae"},
+    {"3.6.7.1", "Rap/Christian rap"},
+    {"3.6.7.1.1", "Gangsta Rap"},
+    {"3.6.7.2", "Hip Hop/Trip-Hop"},
+    {"3.6.7.2.1", "Dirty South Hip Hop"},
+    {"3.6.7.2.2", "East Coast Hip Hop"},
+    {"3.6.7.2.4", "UK Hip Hop"},
+    {"3.6.7.2.5", "West Coast Hip Hop"},
+    {"3.6.7.3", "Reggae"},
+    {"3.6.7.3.1", "Dancehall"},
+    {"3.6.7.3.2", "Dub"},
+    {"3.6.7.3.3", "Lovers Rock"},
+    {"3.6.7.3.4", "Raggamuffin"},
+    {"3.6.7.3.5", "Rocksteady"},
+    {"3.6.7.3.6", "Ska"},
+    {"3.6.8", "Electronic/Club/Urban/Dance"},
+    {"3.6.8.1", "Acid/Punk/Acid Punk"},
+    {"3.6.8.2", "Disco"},
+    {"3.6.8.3", "Techno/Euro-Techno/Techno-Industrial/Industrial"},
+    {"3.6.8.4", "House/Techno House"},
+    {"3.6.8.4.1", "Progressive House"},
+    {"3.6.8.5", "Rave"},
+    {"3.6.8.6", "Jungle/Tribal"},
+    {"3.6.8.7", "Trance"},
+    {"3.6.8.11", "Drum and Bass"},
+    {"3.6.8.14", "Dance/Dance-pop"},
+    {"3.6.8.15", "Garage (1990s)"},
+    {"3.6.8.16", "UK Garage"},
+    {"3.6.8.16.1", "2 Step"},
+    {"3.6.8.16.2", "4/4 Vocal Garage"},
+    {"3.6.8.16.3", "8 Bar"},
+    {"3.6.8.16.4", "Dubstep"},
+    {"3.6.8.16.5", "Eski-Beat"},
+    {"3.6.8.16.6", "Grime"},
+    {"3.6.8.16.7", "Soulful House and Garage"},
+    {"3.6.8.16.8", "Speed Garage"},
+    {"3.6.8.16.9", "Sublow"},
+    {"3.6.8.17", "Breakbeat"},
+    {"3.6.8.18", "Broken Beat"},
+    {"3.6.8.22", "Ambient Dance"},
+    {"3.6.8.23", "Alternative Dance"},
+    {"3.6.9", "World/Traditional/Ethnic/Folk music"},
+    {"3.6.9.1", "Africa"},
+    {"3.6.9.2", "Asia"},
+    {"3.6.9.3", "Australia/Oceania"},
+    {"3.6.9.4", "Caribbean"},
+    {"3.6.9.4.1", "Calypso"},
+    {"3.6.9.4.2", "SOCA"},
+    {"3.6.9.5", "Europe"},
+    {"3.6.9.6", "Latin America"},
+    {"3.6.9.7", "Middle East"},
+    {"3.6.9.8", "North America"},
+    {"3.6.9.9", "Fusion"},
+    {"3.6.9.10", "Modern"},
+    {"3.6.10", "Hit-Chart/Song Requests"},
+    {"3.6.11", "Children's songs"},
+    {"3.6.12", "Event music"},
+    {"3.6.12.1", "Wedding music"},
+    {"3.6.12.2", "Sports music"},
+    {"3.6.12.3", "Ceremonial/Chants"},
+    {"3.6.13", "Spoken"},
+    {"3.6.14", "Dance"},
+    {"3.6.14.1", "Ballet"},
+    {"3.6.14.2", "Tap"},
+    {"3.6.14.3", "Modern"},
+    {"3.6.14.4", "Classical"},
+    {"3.6.14.5", "Ballroom"},
+    {"3.6.15", "Religious music"},
+    {"3.6.16", "Era"},
+    {"3.6.16.1", "Medieval (before 1400)"},
+    {"3.6.16.2", "Renaissance (1400-1600)"},
+    {"3.6.16.3", "Baroque (1600-1760)"},
+    {"3.6.16.4", "Classical (1730-1820)"},
+    {"3.6.16.5", "Romantic (1815-1910"},
+    {"3.6.16.6", "20th Century"},
+    {"3.6.16.6.1", "1910s"},
+    {"3.6.16.6.2", "1920s"},
+    {"3.6.16.6.3", "1930s"},
+    {"3.6.16.6.4", "1940s"},
+    {"3.6.16.6.5", "1950s"},
+    {"3.6.16.6.6", "1960s"},
+    {"3.6.16.6.7", "1970s"},
+    {"3.6.16.6.8", "1980s"},
+    {"3.6.16.6.9", "1990s"},
+    {"3.6.16.7", "21st Century"},
+    {"3.6.16.7.1", "2000s"},
+    {"3.6.16.7.2", "2010s"},
+    {"3.6.16.7.3", "2020s"},
+    {"3.6.16.7.4", "2030s"},
+    {"3.6.16.7.5", "2040s"},
+    {"3.6.16.7.6", "2050s"},
+    {"3.6.16.7.7", "2060s"},
+    {"3.6.16.7.8", "2070s"},
+    {"3.6.16.7.9", "2080s"},
+    {"3.6.16.7.10", "2090s"},
+    {"3.7", "INTERACTIVE GAMES"},
+    {"3.7.1", "CONTENT GAMES CATEGORIES"},
+    {"3.7.1.1", "Action"},
+    {"3.7.1.2", "Adventure"},
+    {"3.7.1.3", "Fighting"},
+    {"3.7.1.4", "Online"},
+    {"3.7.1.5", "Platform"},
+    {"3.7.1.6", "Puzzle"},
+    {"3.7.1.7", "RPG/ MUDs"},
+    {"3.7.1.8", "Racing"},
+    {"3.7.1.9", "Simulation"},
+    {"3.7.1.10", "Sports"},
+    {"3.7.1.11", "Strategy"},
+    {"3.7.1.12", "Wrestling"},
+    {"3.7.1.13", "Classic/Retro"},
+    {"3.7.2", "STYLE"},
+    {"3.7.2.1", "Logic based"},
+    {"3.7.2.2", "Word games"},
+    {"3.7.2.3", "Positional"},
+    {"3.7.2.4", "Board games"},
+    {"3.7.2.5", "Text environments"},
+    {"3.7.2.6", "Dynamic 2D/3D graphics"},
+    {"3.7.2.7", "Non-linear video"},
+    {"3.8", "LEISURE/HOBBY/LIFESTYLE"},
+    {"3.8.1", "General Consumer Advice"},
+    {"3.8.1.1", "Road safety"},
+    {"3.8.1.2", "Consumer advice"},
+    {"3.8.1.3", "Employment Advice"},
+    {"3.8.1.4", "Self-help"},
+    {"3.8.2", "Computing/Technology"},
+    {"3.8.2.1", "Technology/Computing"},
+    {"3.8.2.2", "Computer Games"},
+    {"3.8.3", "Cookery, Food, Drink"},
+    {"3.8.3.1", "Cookery"},
+    {"3.8.3.2", "Food and Drink"},
+    {"3.8.4", "Homes/Interior/Gardening"},
+    {"3.8.4.1", "Do-it-yourself"},
+    {"3.8.4.2", "Home Improvement"},
+    {"3.8.4.3", "Gardening"},
+    {"3.8.4.4", "Property Buying and Selling"},
+    {"3.8.5", "Hobbies"},
+    {"3.8.5.1", "Fishing"},
+    {"3.8.5.2", "Pets"},
+    {"3.8.5.3", "Craft/Handicraft"},
+    {"3.8.5.4", "Art"},
+    {"3.8.5.5", "Music"},
+    {"3.8.5.6", "Board Games"},
+    {"3.8.5.7", "Card Cames"},
+    {"3.8.5.8", "Gaming"},
+    {"3.8.5.9", "Shopping"},
+    {"3.8.5.10", "Collectibles/Antiques"},
+    {"3.8.5.11", "Jewellery"},
+    {"3.8.5.12", "Aviation"},
+    {"3.8.5.13", "Trains"},
+    {"3.8.5.14", "Boating"},
+    {"3.8.5.15", "Ornithology"},
+    {"3.8.6", "Cars and Motoring"},
+    {"3.8.6.1", "Car"},
+    {"3.8.6.2", "Motorcycle"},
+    {"3.8.7", "Personal/Lifestyle/Family"},
+    {"3.8.7.1", "Fitness / Keep-fit"},
+    {"3.8.7.2", "Personal health"},
+    {"3.8.7.3", "Fashion"},
+    {"3.8.7.4", "House Keeping"},
+    {"3.8.7.5", "Parenting"},
+    {"3.8.7.6", "Beauty"},
+    {"3.8.9", "Travel/Tourism"},
+    {"3.8.9.1", "Holidays"},
+    {"3.8.9.2", "Adventure/Expeditions"},
+    {"3.8.9.3", "Outdoor pursuits"},
+    {"3.9", "Adult"},
+    {"4", "Commerce"},
+    {"4.0", "Proprietary"},
+    {"4.1", "Buy"},
+    {"4.11", "LANGUAGE OF TARGET AUDIENCE"},
+    {"4.2", "AddToWishList"},
+    {"4.2.1", "Children"},
+    {"4.2.1.0", "specific single age"},
+    {"4.2.1.1", "age 4-7"},
+    {"4.2.1.2", "age 8-13"},
+    {"4.2.1.3", "age 14-15"},
+    {"4.2.1.4", "age 0-3"},
+    {"4.2.2", "Adults"},
+    {"4.2.2.1", "age 16-17"},
+    {"4.2.2.2", "age 18-24"},
+    {"4.2.2.3", "age 25-34"},
+    {"4.2.2.4", "age 35-44"},
+    {"4.2.2.5", "age 45-54"},
+    {"4.2.2.6", "age 55-64"},
+    {"4.2.2.7", "age 65+"},
+    {"4.2.2.8", "specific single age"},
+    {"4.2.3", "Adults"},
+    {"4.2.3.1", "Age 25-34"},
+    {"4.2.3.2", "Age 35-44"},
+    {"4.2.3.3", "Age 45-54"},
+    {"4.2.3.4", "Age 55-64"},
+    {"4.2.3.5", "Age 65+"},
+    {"4.2.3.6", "Specific single age"},
+    {"4.2.4", "All ages"},
+    {"4.3", "AddToCart"},
+    {"4.3.1", "Ethnic"},
+    {"4.3.1.1", "Immigrant groups"},
+    {"4.3.1.2", "Indigineous"},
+    {"4.3.2", "Religious"},
+    {"4.4", "OCCUPATIONAL GROUPS"},
+    {"4.4.1", "AB"},
+    {"4.4.1.1", "A"},
+    {"4.4.1.2", "B"},
+    {"4.4.2", "C1C2"},
+    {"4.4.2.1", "C1"},
+    {"4.4.2.2", "C2"},
+    {"4.4.3", "DE"},
+    {"4.4.3.1", "D"},
+    {"4.4.3.2", "E"},
+    {"4.5", "OTHER SPECIAL INTEREST/OCCUPATIONAL GROUPS"},
+    {"4.6", "GENDER"},
+    {"4.6.1", "Primarily for males"},
+    {"4.6.2", "Primarily for females"},
+    {"4.6.3", "For males and females"},
+    {"4.7", "GEOGRAPHICAL"},
+    {"4.7.1", "Universal"},
+    {"4.7.2", "Continental"},
+    {"4.7.3", "National"},
+    {"4.7.4", "Regional"},
+    {"4.7.5", "Local"},
+    {"4.7.6", "Multinational"},
+    {"4.8", "EDUCATION STANDARD"},
+    {"4.8.1", "Primary"},
+    {"4.8.2", "Secondary"},
+    {"4.8.3", "Tertiary"},
+    {"4.8.4", "Post Graduate/Life Long Learning"},
+    {"4.9", "LIFESTYLE STAGES"},
+    {"4.9.1", "Single"},
+    {"4.9.2", "Couple"},
+    {"4.9.3", "Family with Children 0-3"},
+    {"4.9.4", "Family with Children 4-7"},
+    {"4.9.5", "Family with Children 8-15"},
+    {"4.9.6", "Family with Children 16+"},
+    {"4.9.7", "Empty Nester"},
+    {"4.9.8", "Retired"},
+    {"5", "Educational notes"},
+    {"5.1", "Studio"},
+    {"5.1.1", "Live"},
+    {"5.1.2", "As live"},
+    {"5.1.3", "Edited"},
+    {"5.10", "Online Distribution"},
+    {"5.10.1", "Made on location"},
+    {"5.10.1.1", "Live"},
+    {"5.10.1.2", "As Live"},
+    {"5.10.1.3", "Edited"},
+    {"5.10.2", "Made in studio"},
+    {"5.10.2.1", "Live"},
+    {"5.10.2.2", "As Live"},
+    {"5.10.2.3", "Edited"},
+    {"5.10.3", "Made on consumer equipment"},
+    {"5.10.3.1", "Live"},
+    {"5.10.3.2", "As Live"},
+    {"5.10.3.3", "Edited"},
+    {"5.11", "Offline Distribution"},
+    {"5.2", "Made on Location"},
+    {"5.2.1", "Live"},
+    {"5.2.2", "As live"},
+    {"5.2.3", "Edited"},
+    {"5.3", "Cinema industry originated"},
+    {"5.4", "Made on film (but not originating from the cinema industry)"},
+    {"5.5", "Home video"},
+    {"5.6", "Multimedia format (I.e. text/computer, etc.)"},
+    {"5.7", "Cinema"},
+    {"5.7.1", "Made on location"},
+    {"5.7.2", "Made in studio"},
+    {"5.7.3", "Made by the consumer"},
+    {"5.8", "TV"},
+    {"5.8.1", "Made on location"},
+    {"5.8.1.1", "Live"},
+    {"5.8.1.2", "As Live"},
+    {"5.8.1.3", "Edited"},
+    {"5.8.2", "Made in studio"},
+    {"5.8.2.1", "Live"},
+    {"5.8.2.2", "As Live"},
+    {"5.8.2.3", "Edited"},
+    {"5.8.3", "Made by the consumer"},
+    {"5.9", "Radio"},
+    {"5.9.1", "Made on location"},
+    {"5.9.1.1", "Live"},
+    {"5.9.1.2", "As Live"},
+    {"5.9.1.3", "Edited"},
+    {"5.9.2", "Made in studio"},
+    {"5.9.2.1", "Live"},
+    {"5.9.2.2", "As Live"},
+    {"5.9.2.3", "Edited"},
+    {"5.9.3", "Made on consumer equipment (home audio)"},
+    {"5.9.3.1", "Live"},
+    {"5.9.3.2", "As Live"},
+    {"5.9.3.3", "Edited"},
+    {"6", "Recommendation"},
+    {"6.0", "ALERT NOT REQUIRED"},
+    {"6.0.1",
+     "No content that requires alerting in any of the categories below"},
+    {"6.1", "SEX"},
+    {"6.1.1", "No sex descriptors"},
+    {"6.1.2", "Obscured or implied sexual activity"},
+    {"6.1.3", "Frank portrayal of sex and sexuality"},
+    {"6.1.4", "Scenes of explicit sexual behaviour suitable for adults only"},
+    {"6.1.4.1",
+     "One scene of explicit sexual behaviour suitable for adults only"},
+    {"6.1.4.2",
+     "Occasional scenes of explicit sexual behaviour suitable for adults only"},
+    {"6.1.4.3",
+     "Frequent scenes of explicit sexual behaviour suitable for adults only"},
+    {"6.1.5", "Sexual Violence"},
+    {"6.1.5.1", "One scene of sexual violence"},
+    {"6.1.5.2", "Occasional scenes of sexual violence"},
+    {"6.1.5.3", "Frequent scenes of sexual Violence"},
+    {"6.1.6", "Verbal sexual References"},
+    {"6.1.6.1", "One verbal sexual reference"},
+    {"6.1.6.2", "Occasional verbal sexual references"},
+    {"6.1.6.3", "Frequent verbal sexual references"},
+    {"6.10", "STROBING"},
+    {"6.10.1", "No strobing"},
+    {"6.10.2",
+     "Strobing that could impact on those suffering from Photosensitive epilepsy"},
+    {"6.10.2.1",
+     "One scene of strobing that could impact on those suffering from photosensitive epilepsy"},
+    {"6.10.2.2",
+     "Occasional strobing that could impact on those suffering from photosensitive epilepsy"},
+    {"6.10.2.3",
+     "Frequent strobing that could impact on those suffering from photosensitive epilepsy"},
+    {"6.2", "NUDITY"},
+    {"6.2.1", "No nudity descriptors"},
+    {"6.2.2", "Partial nudity"},
+    {"6.2.2.1", "One scene of partial nudity"},
+    {"6.2.2.2", "Occasional scenes of partial nudity"},
+    {"6.2.2.3", "Frequent scenes of partial nudity"},
+    {"6.2.3", "Full frontal nudity"},
+    {"6.2.3.1", "One scene of full frontal nudity"},
+    {"6.2.3.2", "Occasional scenes of full frontal nudity"},
+    {"6.2.3.3", "Frequent scenes of full frontal nudity"},
+    {"6.3", "VIOLENCE - HUMAN BEINGS"},
+    {"6.3.1", "No violence descriptors human beings"},
+    {"6.3.2", "Deliberate infliction of pain to human beings"},
+    {"6.3.2.1", "One Scene of deliberate infliction of pain to human beings"},
+    {"6.3.2.2", "Occasional deliberate infliction of pain to human beings"},
+    {"6.3.2.3", "Frequent deliberate infliction of pain to human beings"},
+    {"6.3.3",
+     "Infliction of strong psychological or physical pain to human beings"},
+    {"6.3.3.1",
+     "One scene of infliction of strong psychological or physical pain to human beings"},
+    {"6.3.3.2",
+     "Occasional scenes of infliction of strong psychological or physical pain to human beings"},
+    {"6.3.3.3",
+     "Frequent scenes of infliction of strong psychological or physical pain to human beings"},
+    {"6.3.4", "Deliberate killing of human beings"},
+    {"6.3.4.1", "One scene of deliberate killing of human beings"},
+    {"6.3.4.2", "Occasional deliberate killing of human beings"},
+    {"6.3.4.3", "Frequent deliberate killing of human beings"},
+    {"6.4", "VIOLENCE - ANIMALS"},
+    {"6.4.1", "No violence descriptors animals"},
+    {"6.4.2", "Deliberate infliction of pain to animals"},
+    {"6.4.2.1", "One scene of deliberate infliction of pain to animals"},
+    {"6.4.2.2", "Occasional deliberate infliction of pain to animals"},
+    {"6.4.2.3", "Frequent deliberate infliction of pain to animals"},
+    {"6.4.3", "Deliberate killing of animals"},
+    {"6.4.3.1", "One scene of deliberate killing of animals"},
+    {"6.4.3.2", "Occasional deliberate killing of animals"},
+    {"6.5", "VIOLENCE - FANTASY CHARACTERS"},
+    {"6.5.1", "No violence descriptors"},
+    {"6.5.2",
+     "Deliberate infliction of pain to fantasy characters (including animation)"},
+    {"6.5.2.1",
+     "One scene of deliberate infliction of pain to fantasy characters (including animation)"},
+    {"6.5.2.2",
+     "Occasional deliberate infliction of pain to fantasy characters (including animation)"},
+    {"6.5.2.3",
+     "Frequent deliberate infliction of pain to fantasy characters (including animation)"},
+    {"6.5.3",
+     "Deliberate killing of fantasy characters (including animation)"},
+    {"6.5.3.1",
+     "One scene of deliberate killing of fantasy characters (including animation)"},
+    {"6.5.3.2",
+     "Occasional deliberate killing of fantasy characters (including animation)"},
+    {"6.5.3.3",
+     "Frequent deliberate killing of fantasy characters (including animation)"},
+    {"6.6", "LANGUAGE"},
+    {"6.6.1", "No language descriptors"},
+    {"6.6.10",
+     "Occasional use of offensive language (racist, homophobic, sexist)"},
+    {"6.6.11",
+     "Frequent use of offensive language (racist, homophobic, sexist)"},
+    {"6.6.12", "One use of offensive language (racist, homophobic, sexist)"},
+    {"6.6.2", "Occasional use of mild swear words and profanities"},
+    {"6.6.3", "Frequent use of mild swear words and profanities"},
+    {"6.6.4", "Occasional use of very strong language"},
+    {"6.6.5", "Frequent use of very strong language"},
+    {"6.6.6", "One use of very strong language"},
+    {"6.6.7", "Occasional use of strong language"},
+    {"6.6.8", "Frequent use of strong language"},
+    {"6.6.9", "One use of strong language"},
+    {"6.7", "DISTURBING SCENES"},
+    {"6.7.1", "No disturbing scenes descriptors"},
+    {"6.7.2",
+     "Factual material that may cause distress, including verbal descriptions of traumatic events and the telling of sensitive human interest stories."},
+    {"6.7.3",
+     "Mild scenes of blood and gore (including medical procedures, injuries from accidents, terrorists attack, murder, disaster, war)"},
+    {"6.7.3.1", "One mild scene of blood and gore"},
+    {"6.7.3.2", "Occasional mild scenes of blood and gore"},
+    {"6.7.3.3", "Frequent mild scenes of blood and gore"},
+    {"6.7.4", "Severe scenes of blood and gore (as 6.7.3 above)"},
+    {"6.7.4.1", "One severe scene of blood and gore"},
+    {"6.7.4.2",
+     "Occasional severe scenes of blood and gore (as 6.7.3 above)"},
+    {"6.7.4.3", "Frequent severe scenes of blood and gore (as 6.7.3 above)"},
+    {"6.7.5", "Scenes with extreme horror effects"},
+    {"6.7.5.1", "One scene with extreme horror effects"},
+    {"6.7.5.2", "Occasional scenes with extreme horror effects"},
+    {"6.7.5.3", "Frequent scenes with extreme horror effects"},
+    {"6.8", "DISCRIMINATION"},
+    {"6.8.1", "No discrimination descriptors"},
+    {"6.8.2",
+     "Deliberate discrimination or the portrayal of deliberate discrimination"},
+    {"6.9", "ILLEGAL DRUGS"},
+    {"6.9.1", "No illegal drugs descriptors"},
+    {"6.9.2", "Portrayal of illegal drug use"},
+    {"6.9.2.1", "One scene of illegal drug use"},
+    {"6.9.2.2", "Occasional portrayal of illegal drug use"},
+    {"6.9.2.3", "Frequent portrayal of illegal drug use"},
+    {"6.9.3", "Portrayal of illegal drug use with instructive detail"},
+    {"6.9.3.1", "One scene of illegal drug use with instructive detail"},
+    {"6.9.3.2",
+     "Occasional portrayal of illegal drug use with instructive detail"},
+    {"6.9.3.3",
+     "Frequent portrayal of illegal drug use with instructive detail"},
+    {"7", "GroupRecommendation"},
+    {"7.0", "Proprietary"},
+    {"7.1", "Linear"},
+    {"7.1.1", "Audio only"},
+    {"7.1.2", "Video only"},
+    {"7.1.3", "Audio and video"},
+    {"7.1.4", "Multimedia"},
+    {"7.1.4.1", "Text"},
+    {"7.1.4.2", "Graphics"},
+    {"7.1.4.3", "Application"},
+    {"7.1.5", "Data"},
+    {"7.2", "Non Linear"},
+    {"7.2.1", "Audio only"},
+    {"7.2.2", "Video only"},
+    {"7.2.3", "Audio and video"},
+    {"7.2.4", "Multimedia"},
+    {"7.2.4.1", "Text"},
+    {"7.2.4.2", "Graphics"},
+    {"7.2.4.3", "Application"},
+    {"7.2.5", "Data"},
+    {"7.3", "AUDIO VIDEO ENHANCEMENTS"},
+    {"7.3.1", "Linear with non-sync"},
+    {"7.3.10", "Linear broadcast with online insertions"},
+    {"7.3.11", "Other"},
+    {"7.3.2", "Linear with sync"},
+    {"7.3.3", "Multi stream audio"},
+    {"7.3.4", "Multi stream video"},
+    {"7.3.5", "Non-linear one stream av show"},
+    {"7.3.6", "Non-linear multi stream"},
+    {"7.3.7", "Hybrid NVOD"},
+    {"7.3.8", "Mix and match"},
+    {"7.3.9", "Parallel 'layer controlled' audio or video support"},
+    {"8", "Commercial advert"},
+    {"8.0", "Proprietary"},
+    {"8.1", "Alternative"},
+    {"8.10", "Confrontational"},
+    {"8.11", "Contemporary"},
+    {"8.12", "Crazy"},
+    {"8.13", "Cutting edge"},
+    {"8.14", "Eclectic"},
+    {"8.15", "Edifying"},
+    {"8.16", "Exciting"},
+    {"8.17", "Fast-moving"},
+    {"8.18", "Frantic"},
+    {"8.19", "Fun"},
+    {"8.2", "Analytical"},
+    {"8.20", "Gripping"},
+    {"8.21", "Gritty"},
+    {"8.22", "Gutsy"},
+    {"8.23", "Happy"},
+    {"8.24", "Heart-rending"},
+    {"8.25", "Heart-warming"},
+    {"8.26", "Hot"},
+    {"8.27", "Humorous"},
+    {"8.28", "Innovative"},
+    {"8.29", "Insightful"},
+    {"8.3", "Astonishing"},
+    {"8.30", "Inspirational"},
+    {"8.31", "Intriguing"},
+    {"8.32", "Irreverent"},
+    {"8.33", "Laid back"},
+    {"8.34", "Outrageous"},
+    {"8.35", "Peaceful"},
+    {"8.36", "Powerful"},
+    {"8.37", "Practical"},
+    {"8.38", "Rollercoaster"},
+    {"8.39", "Romantic"},
+    {"8.4", "Ambitious"},
+    {"8.40", "Rousing"},
+    {"8.41", "Sad"},
+    {"8.42", "Satirical"},
+    {"8.43", "Serious"},
+    {"8.44", "Sexy"},
+    {"8.45", "Shocking"},
+    {"8.46", "Silly"},
+    {"8.47", "Spooky"},
+    {"8.48", "Stunning"},
+    {"8.49", "Stylish"},
+    {"8.5", "Black"},
+    {"8.50", "Terrifying"},
+    {"8.51", "Thriller"},
+    {"8.52", "Violent"},
+    {"8.53", "Wacky"},
+    {"8.6", "Breathtaking"},
+    {"8.7", "Chilling"},
+    {"8.8", "Coarse"},
+    {"8.9", "Compelling"},
+    {"9", "Direct product purchase"},
+    {0, 0},
+};
+
+EPG::EPG(CParameter& NParameters, const string& savePath):
+    Parameters(NParameters)
+{
+    for (int i = 0; true; i++)
+    {
+        if (genre_list[i].genre == 0)
+            break;
+        genres[genre_list[i].genre] = genre_list[i].desc;
+    }
+    dir = QString::fromUtf8((savePath+"/EPG").c_str());
+    CreateDirectories(dir);
+    servicesFilename = dir + "services.xml";
+    loadChannels (servicesFilename);
+    saveChannels (servicesFilename);
+}
+
+EPG& EPG::operator=(const EPG& e)
+{
+    progs = e.progs;
+    genres = e.genres;
+    servicesFilename = e.servicesFilename;
+    Parameters = e.Parameters;
+    return *this;
+}
+
+void
+EPG::addChannel (const string& label, uint32_t sid)
+{
+    Parameters.ServiceInformation[sid].label.insert(label);
+    Parameters.ServiceInformation[sid].id = sid;
+}
+
+void
+EPG::parseDoc (const QDomDocument & doc)
+{
+    QDomNodeList programmes = doc.elementsByTagName ("programme");
+    if(programmes.count()==0)
+		return;
+    QDomNode l1 = programmes.item (0);
+    while (!l1.isNull ())
+    {
+        if (l1.nodeName () == "programme")
+        {
+            CProg p;
+            QDomNode l2 = l1.firstChild ();
+            p.shortId =
+                l1.toElement ().attribute ("shortId", "0").toInt ();
+            while (!l2.isNull ())
+            {
+                if (l2.isElement ())
+                {
+                    QDomElement e = l2.toElement ();
+                    if (e.tagName () == "location")
+                    {
+                        QDomNode l3 = e.firstChild ();
+                        while (!l3.isNull ())
+                        {
+                            if (l3.isElement ())
+                            {
+                                QDomElement e = l3.toElement ();
+                                if (e.tagName () == "time")
+                                {
+                                    p.actualTime = parseTime(e.attribute ("actualTime", ""));
+                                    p.actualDuration = parseDuration(e.attribute ("actualDuration", ""));
+                                    p.time = parseTime(e.attribute ("time", ""));
+                                    p.duration = parseDuration(e.attribute ("duration", ""));
+                                }
+                            }
+                            l3 = l3.nextSibling ();
+                        }
+                    }
+                    if ((e.tagName () == "mediumName") && (p.name == ""))
+                        p.name = e.text ();
+                    if (e.tagName () == "longName")
+                        p.name = e.text ();
+                    if (e.tagName () == "mediaDescription")
+                    {
+                        QDomNode l3 = e.firstChild ();
+                        while (!l3.isNull ())
+                        {
+                            if (l3.isElement ())
+                            {
+                                QDomElement e = l3.toElement ();
+                                if (e.tagName () == "shortDescription")
+                                {
+                                    p.description = e.text ();
+                                }
+                            }
+                            l3 = l3.nextSibling ();
+                        }
+                    }
+                    if (e.tagName () == "genre")
+                    {
+                        QString genre = e.attribute ("href", "");
+                        int i = genre.lastIndexOf(':');
+                        if (i != -1)
+                            genre = genre.mid (i + 1);
+                        QString type = e.attribute ("type", "main");
+                        if (type == "main")
+                            p.mainGenre.push_back (genres[genre]);
+                        else if (type == "secondary")
+                            p.secondaryGenre.push_back (genres[genre]);
+                        else if (type == "other")
+                            p.otherGenre.push_back (genres[genre]);
+                    }
+                }
+                l2 = l2.nextSibling ();
+            }
+            time_t start;
+            if (p.actualTime!=0)
+                start = p.actualTime;
+            else
+                start = p.time;
+            QMap<time_t,CProg>::ConstIterator existing = progs.find(start);
+            if (existing != progs.end())
+            {
+                p.augment(existing.value());
+            }
+            progs[start] = p;
+        }
+        l1 = l1.nextSibling ();
+    }
+}
+
+void EPG::CProg::augment(const CProg& p)
+{
+    if (p.time!=0)
+        time = p.time;
+    if (p.actualTime!=0)
+        actualTime = p.actualTime;
+    if (p.duration>0)
+        duration = p.duration;
+    if (p.actualDuration>0)
+        actualDuration = p.actualDuration;
+    if (crid=="")
+        crid = p.crid;
+    if (name=="")
+        name = p.name;
+    if (description=="")
+        description = p.description;
+    if (shortId==0 && p.shortId!=0)
+        shortId = p.shortId;
+    // assume genres not in both files
+    size_t i;
+    for (i=0; i<p.mainGenre.size(); i++)
+        mainGenre.push_back(p.mainGenre[i]);
+    for (i=0; i<p.secondaryGenre.size(); i++)
+        secondaryGenre.push_back(p.secondaryGenre[i]);
+    for (i=0; i<p.otherGenre.size(); i++)
+        otherGenre.push_back(p.otherGenre[i]);
+}
+
+/*
+<service>
+<serviceID id="e1.ce15.c221.0" />
+<shortName>Radio 1</shortName>
+<mediumName>BBC Radio 1</mediumName>
+</service>
+*/
+
+void
+EPG::saveChannels (const QString & fileName)
+{
+    QFile f (fileName);
+    if (!f.open (QIODevice::WriteOnly))
+    {
+        return;
+    }
+    QDomDocument doc ("serviceInformation");
+    QDomElement root = doc.createElement ("serviceInformation");
+    doc.appendChild (root);
+    QDomElement ensemble = doc.createElement ("ensemble");
+    root.appendChild (ensemble);
+    for (map < uint32_t, CServiceInformation >::const_iterator i = Parameters.ServiceInformation.begin();
+            i != Parameters.ServiceInformation.end(); i++)
+    {
+        const CServiceInformation& si = i->second;
+        QDomElement service = doc.createElement ("service");
+        QDomElement serviceID = doc.createElement ("serviceID");
+        serviceID.setAttribute ("id", QString::number (ulong (si.id), 16));
+        service.appendChild (serviceID);
+        for (set<string>::const_iterator j = si.label.begin(); j != si.label.end(); j++)
+        {
+            QDomElement shortName = doc.createElement ("shortName");
+            QDomText text = doc.createTextNode (QString().fromUtf8(j->c_str()));
+            shortName.appendChild (text);
+            service.appendChild (shortName);
+        }
+        ensemble.appendChild (service);
+    }
+    QTextStream stream (&f);
+    stream << doc.toString ();
+    f.close ();
+
+}
+
+void
+EPG::loadChannels (const QString & fileName)
+{
+    QDomDocument domTree;
+    QFile f (fileName);
+    if (!f.open (QIODevice::ReadOnly))
+    {
+        addChannel ("BBC & DW", 0xE1C248);
+        return;
+    }
+    if (!domTree.setContent (&f))
+    {
+        f.close ();
+        return;
+    }
+    f.close ();
+    QDomNodeList ensembles = domTree.elementsByTagName ("ensemble");
+    QDomNode n = ensembles.item (0).firstChild ();
+    while (!n.isNull ())
+    {
+        if (n.nodeName () == "service")
+        {
+            QDomNode e = n.firstChild ();
+            string name;
+            QString sid;
+            while (!e.isNull ())
+            {
+                if (e.isElement ())
+                {
+                    QDomElement s = e.toElement ();
+                    if (s.tagName () == "shortName")
+                        name = s.text().toUtf8().constData();
+                    if (s.tagName () == "serviceID")
+                        sid = s.attribute ("id", "0");
+                }
+                e = e.nextSibling ();
+            }
+            if (name != "")
+            {
+                addChannel (name, sid.toUInt (NULL, 16));
+            }
+        }
+        n = n.nextSibling ();
+    }
+}
+
+time_t EPG::parseTime(const QString & time)
+{
+    if (time=="")
+        return 0; // invalid
+    QRegExp q("[-T:+Z]");
+    QStringList sl = time.split(q);
+#ifdef _WIN32
+    SYSTEMTIME st;
+    st.wYear = 1970;
+    st.wMonth = 1;
+    st.wDay = 1;
+    st.wDayOfWeek = 0;
+    st.wHour = 0;
+    st.wMinute = 0;
+    st.wSecond = 0;
+    st.wMilliseconds = 0;
+    FILETIME zero;
+    SystemTimeToFileTime(&st, &zero);
+    ULARGE_INTEGER unix_zero;
+    unix_zero.LowPart = zero.dwLowDateTime;
+    unix_zero.HighPart = zero.dwHighDateTime;
+    // its  116444736000000000
+    st.wYear = sl[0].toUInt();
+    st.wMonth = sl[1].toUInt();
+    st.wDay = sl[2].toUInt();
+    st.wDayOfWeek = 0;
+    st.wHour = sl[3].toUInt();
+    st.wMinute = sl[4].toUInt();
+    st.wSecond = sl[5].toUInt();
+    st.wMilliseconds = 0;
+    FILETIME to;
+    SystemTimeToFileTime(&st, &to);
+    ULARGE_INTEGER ft;
+    ft.LowPart = to.dwLowDateTime;
+    ft.HighPart = to.dwHighDateTime;
+    time_t t = time_t((ft.QuadPart - unix_zero.QuadPart)/10000000L);
+
+    if (sl.count()==8)
+    {
+        int hh = sl[6].toInt();
+        int mm = sl[7].toInt();
+        time_t offset = 60*(60*hh+mm);
+        if (time[19]=='+') // + offset means UTC is earlier
+            t -= offset;
+        else
+            t += offset;
+    }
+#else
+    tm bdt;
+    bdt.tm_year = sl[0].toUInt()-1900;
+    bdt.tm_mon = sl[1].toUInt()-1;
+    bdt.tm_mday = sl[2].toUInt();
+    bdt.tm_hour = sl[3].toUInt();
+    bdt.tm_min = sl[4].toUInt();
+    bdt.tm_sec = sl[5].toUInt();
+    string se;
+    char *e = getenv("TZ");
+    if (e)
+        se = e;
+    putenv(const_cast<char*>("TZ=UTC"));
+    tzset();
+    time_t t = mktime(&bdt);
+    if (e)
+        setenv("TZ", se.c_str(), 1);
+    else
+        unsetenv("TZ");
+    // time zone offset
+    if (sl.count()==8)
+    {
+        int hh = sl[6].toInt();
+        int mm = sl[7].toInt();
+        int secs = 60*(60*hh+mm);
+        if (time[19]=='+') // + offset means UTC is earlier
+            t -= secs;
+        else
+            t += secs;
+    }
+#endif
+    return t;
+}
+
+int EPG::parseDuration (const QString& duration)
+{
+    if(duration.length()==0)
+        return 0;
+    if (duration[0]=='P')
+    {
+        int /*yy=0,mo=0,dd=0,*/hh=0,mi=0,ss=0;
+        int d=0;
+        bool date=true;
+        for (size_t i=1; i<(size_t)duration.length(); i++)
+        {
+            switch (duration[int(i)].unicode())
+            {
+            case 'T':
+                d = 0;
+                date=false;
+                break;
+            case '0':
+                d = d*10;
+                break;
+            case '1':
+                d = d*10+1;
+                break;
+            case '2':
+                d = d*10+2;
+                break;
+            case '3':
+                d = d*10+3;
+                break;
+            case '4':
+                d = d*10+4;
+                break;
+            case '5':
+                d = d*10+5;
+                break;
+            case '6':
+                d = d*10+6;
+                break;
+            case '7':
+                d = d*10+7;
+                break;
+            case '8':
+                d = d*10+8;
+                break;
+            case '9':
+                d = d*10+9;
+                break;
+            case 'Y':
+//                yy=d;
+                d=0;
+                break;
+            case 'M':
+                if (!date)
+                    mi = d;
+//                else
+//                    mo = d;
+                d = 0;
+                break;
+            case 'D':
+//                dd=d;
+                d=0;
+                break;
+            case 'H':
+                hh=d;
+                d=0;
+                break;
+            case 'S':
+                ss=d;
+                d=0;
+            }
+        }
+        // assume date part is empty
+        return 60*(60*hh+mi)+ss;
+    }
+    else
+        return 0;
+}
+
diff --git a/src/util-QT/EPG.h b/src/util-QT/EPG.h
new file mode 100644
index 0000000..04afa92
--- /dev/null
+++ b/src/util-QT/EPG.h
@@ -0,0 +1,82 @@
+/******************************************************************************\
+ * British Broadcasting Corporation
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Julian Cable
+ *
+ * Description:
+ *	ETSI DAB/DRM Electronic Programme Guide utilities
+ *
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include <QDomDocument>
+#include <QMap>
+#include <QString>
+#include <QDateTime>
+#include "../GlobalDefinitions.h"
+#include "../Parameter.h"
+#include "../datadecoding/DABMOT.h"
+#include "epgdec.h"
+
+class EPG
+{
+  public:
+    EPG (CParameter&, const string&);
+    virtual ~ EPG ()
+    {
+	saveChannels (servicesFilename);
+    }
+	/* assignment operator to help MSVC8 */
+	EPG& operator=(const EPG&);
+
+    void loadChannels (const QString & fileName);
+    void saveChannels (const QString & fileName);
+    void addChannel (const string& label, uint32_t sid);
+    void parseDoc (const QDomDocument &);
+
+    class CProg
+    {
+      public:
+
+	  CProg(): time(0), actualTime(0), duration(0), actualDuration(0),
+                name(""), description(""),
+			  crid(""), shortId(0), mainGenre(), secondaryGenre(), otherGenre()
+		{}
+        void augment(const CProg&);
+
+		time_t time, actualTime;
+		int duration, actualDuration;
+		QString name, description;
+		QString crid;
+		uint32_t shortId;
+		vector<QString> mainGenre, secondaryGenre, otherGenre;
+    };
+
+    QMap < time_t, CProg > progs;
+    QMap < QString, QString > genres;
+    QString dir, servicesFilename;
+    CParameter& Parameters;
+    QMap < QString, time_t > filesLoaded;
+private:
+    static const struct gl { const char *genre; const char* desc; } genre_list[];
+    time_t parseTime(const QString & time);
+    int parseDuration (const QString & duration);
+};
diff --git a/src/util-QT/PacketSocketQT.cpp b/src/util-QT/PacketSocketQT.cpp
new file mode 100644
index 0000000..97ef8fc
--- /dev/null
+++ b/src/util-QT/PacketSocketQT.cpp
@@ -0,0 +1,358 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright(c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer, Julian Cable, Oliver Haffenden
+ *
+ * Description:
+ *
+ * This is an implementation of the CPacketSocket interface that wraps up a QT socket.
+ *
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or(at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "PacketSocketQT.h"
+#include <QStringList>
+#include <QTimer>
+#include <QUdpSocket>
+#include <QTcpSocket>
+#include <iostream>
+#include <sstream>
+
+#include <errno.h>
+#ifndef _WIN32
+# include <netinet/in.h>
+# include <arpa/inet.h>
+#endif
+
+#ifdef _WIN32
+/* Always include winsock2.h before windows.h */
+# include <winsock2.h>
+# include <ws2tcpip.h>
+# include <windows.h>
+#endif
+
+/* Some defines needed for compatibility when using Linux */
+#ifndef _WIN32
+typedef int SOCKET;
+# define SOCKET_ERROR				(-1)
+# define INVALID_SOCKET				(-1)
+#endif
+
+CPacketSocketQT::CPacketSocketQT():
+    pPacketSink(NULL), HostAddrOut(), iHostPortOut(-1),
+    writeBuf(),udp(true),
+    udpSocket(NULL), tcpSocket(NULL)
+{
+}
+
+CPacketSocketQT::~CPacketSocketQT()
+{
+}
+
+// Set the sink which will receive the packets
+void
+CPacketSocketQT::SetPacketSink(CPacketSink * pSink)
+{
+    pPacketSink = pSink;
+}
+
+// Stop sending packets to the sink
+void
+CPacketSocketQT::ResetPacketSink(void)
+{
+    pPacketSink = NULL;
+}
+
+// Send packet to the socket
+void
+CPacketSocketQT::SendPacket(const vector < _BYTE > &vecbydata, uint32_t addr, uint16_t port)
+{
+    /*int bytes_written;*/
+    (void)addr; (void)port;
+    if(udpSocket != NULL)
+        /*bytes_written =*/ udpSocket->writeDatagram((char*)&vecbydata[0], vecbydata.size(), HostAddrOut, iHostPortOut);
+    else if(tcpSocket != NULL)
+       /*bytes_written =*/ tcpSocket->write((char*)&vecbydata[0], vecbydata.size());
+}
+
+QStringList
+CPacketSocketQT::parseDest(const string & strNewAddr)
+{
+    return QString(strNewAddr.c_str()).split(":", QString::KeepEmptyParts);
+}
+
+_BOOLEAN
+CPacketSocketQT::SetDestination(const string & strNewAddr)
+{
+    /* syntax
+       1:  <port>                send to port on localhost
+       2:  <ip>:<port>           send to port on host or port on m/c group
+       3:  <ip>:<ip>:<port>      send to port on m/c group via interface
+       prefix with "t" for tcp
+     */
+    int ttl = 127;
+    _BOOLEAN bAddressOK = TRUE;
+    QHostAddress AddrInterface;
+    QStringList parts = parseDest(strNewAddr);
+    QString first = parts[0].toLower();
+    if(first.startsWith("t"))
+    {
+        udp = false;
+        parts[0] = first.right(1);
+        //qDebug("tcp: %s", first);
+    }
+
+    switch(parts.count())
+    {
+    case 1: // Just a port - send to ourselves
+        bAddressOK = HostAddrOut.setAddress("127.0.0.1");
+        iHostPortOut = parts[0].toUInt();
+        break;
+    case 2: // host and port, unicast
+        bAddressOK = HostAddrOut.setAddress(parts[0]);
+        iHostPortOut = parts[1].toUInt();
+        break;
+    case 3: // interface, host and port, usually multicast udp
+        AddrInterface.setAddress(parts[0]);
+        bAddressOK = HostAddrOut.setAddress(parts[1]);
+        iHostPortOut = parts[2].toUInt();
+        break;
+    default:
+        bAddressOK = FALSE;
+    }
+    if(udp)
+    {
+        if(udpSocket == NULL)
+            udpSocket = new QUdpSocket();
+# if QT_VERSION < 0x040800
+        const SOCKET s = udpSocket->socketDescriptor();
+        if(setsockopt(s, IPPROTO_IP, IP_TTL, (char*)&ttl, sizeof(ttl))==SOCKET_ERROR)
+            bAddressOK = FALSE;
+        uint32_t mc_if = htonl(AddrInterface.toIPv4Address());
+        if(mc_if != 0)
+        {
+            if(setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF,
+                          (char *) &mc_if, sizeof(mc_if)) == SOCKET_ERROR)
+                bAddressOK = FALSE;
+        }
+# else
+        udpSocket->setSocketOption(QAbstractSocket::MulticastTtlOption, ttl);
+        if(AddrInterface != QHostAddress(QHostAddress::Any))
+             udpSocket->setMulticastInterface(GetInterface(AddrInterface));
+# endif
+    }
+    else
+    {
+        if(tcpSocket == NULL)
+            tcpSocket = new QTcpSocket();
+        tcpSocket->connectToHost(HostAddrOut, iHostPortOut);
+        bAddressOK = tcpSocket->waitForConnected(5000);
+    }
+    return bAddressOK;
+}
+
+_BOOLEAN
+CPacketSocketQT::GetDestination(string & str)
+{
+    stringstream s;
+    s << HostAddrOut.toString().toLatin1().constData() << ":" << iHostPortOut;
+    str = s.str();
+    return TRUE;
+}
+
+
+_BOOLEAN
+CPacketSocketQT::SetOrigin(const string & strNewAddr)
+{
+    /* syntax (unwanted fields can be empty, e.g. <source ip>::<group ip>:<port>
+       1:  <port>
+       2:  <group ip>:<port>
+       3:  <interface ip>:<group ip>:<port>
+       4:  <source ip>:<interface ip>:<group ip>:<port>
+       5: - for TCP - no need to separately set origin
+     */
+
+    if(strNewAddr == "-")
+    {
+        udp = false;
+        if(tcpSocket == NULL)
+            tcpSocket = new QTcpSocket();
+        return TRUE;
+    }
+
+    if(udpSocket == NULL)
+        udpSocket = new QUdpSocket();
+
+    int iPort=-1;
+    QHostAddress AddrGroup, AddrInterface, AddrSource;
+    QStringList parts = parseDest(strNewAddr);
+    bool ok=true;
+    switch(parts.count())
+    {
+    case 1:
+        iPort = parts[0].toUInt(&ok);
+        break;
+    case 2:
+        iPort = parts[1].toUInt(&ok);
+        ok &= AddrGroup.setAddress(parts[0]);
+        break;
+    case 3:
+        iPort = parts[2].toUInt(&ok);
+        if(parts[0].length() > 0)
+            ok &= AddrInterface.setAddress(parts[0]);
+        if(parts[1].length() > 0)
+            ok &= AddrGroup.setAddress(parts[1]);
+        break;
+    case 4:
+        iPort = parts[3].toUInt(&ok);
+        if(parts[0].length() > 0)
+            ok &= AddrSource.setAddress(parts[0]);
+        if(parts[1].length() > 0)
+            ok &= AddrInterface.setAddress(parts[1]);
+        if(parts[2].length() > 0)
+            ok &= AddrGroup.setAddress(parts[2]);
+        break;
+    default:
+        ok = false;
+    }
+
+    if(ok)
+    {
+        return doSetSource(AddrGroup, AddrInterface, iPort, AddrSource);
+    }
+    return FALSE;
+}
+
+_BOOLEAN CPacketSocketQT::doSetSource(QHostAddress AddrGroup, QHostAddress AddrInterface, int iPort, QHostAddress AddrSource)
+{
+    if(udp)
+    {
+        if(AddrSource == QHostAddress(QHostAddress::Any))
+            sourceAddr = 0;
+        else
+            sourceAddr = AddrSource.toIPv4Address();
+        /* Multicast ? */
+        uint32_t gp = AddrGroup.toIPv4Address();
+        if(gp == 0)
+        {
+            /* Initialize the listening socket. */
+            udpSocket->bind(AddrInterface, iPort);
+        }
+        else if((gp & 0xe0000000) == 0xe0000000)	/* multicast! */
+        {
+            bool ok = udpSocket->bind(iPort, QUdpSocket::ShareAddress);
+            if(ok == false)
+            {
+                throw CGenErr("Can't bind to port to receive packets");
+            }
+#if QT_VERSION < 0x040800
+            struct ip_mreq mreq;
+            mreq.imr_multiaddr.s_addr = htonl(AddrGroup.toIPv4Address());
+            mreq.imr_interface.s_addr = htonl(AddrInterface.toIPv4Address());
+            int n = setsockopt(udpSocket->socketDescriptor(), IPPROTO_IP, IP_ADD_MEMBERSHIP,(char *) &mreq,	sizeof(mreq));
+            if(n == SOCKET_ERROR)
+                ok = false;
+#else
+            if(AddrInterface == QHostAddress(QHostAddress::Any))
+                ok = udpSocket->joinMulticastGroup(AddrGroup);
+            else
+                ok = udpSocket->joinMulticastGroup(AddrGroup, GetInterface(AddrInterface));
+#endif
+            if(!ok)
+            {
+                qDebug("Can't join multicast group");
+                //throw CGenErr(string());
+            }
+        }
+        else /* one address specified, but not multicast - listen on a specific interface */
+        {
+            /* Initialize the listening socket. */
+            udpSocket->bind(AddrGroup, iPort);
+        }
+    }
+    return TRUE;
+}
+
+QNetworkInterface
+CPacketSocketQT::GetInterface(QHostAddress AddrInterface)
+{
+    QList<QNetworkInterface> l = QNetworkInterface::allInterfaces () ;
+    for(int i=0; i<l.size(); i++) {
+        QList<QHostAddress> h = l[i].allAddresses();
+        QString s;
+        for(int j=0; j<h.size(); j++) {
+            s += h[j].toString() + " ";
+            if(h[j].toIPv4Address() == AddrInterface.toIPv4Address()) {
+                return l[j];
+            }
+        }
+    }
+    return QNetworkInterface::allInterfaces().first();
+}
+
+void
+CPacketSocketQT::poll()
+{
+    if(udp)
+        pollDatagram();
+    else
+        pollStream();
+}
+
+void
+CPacketSocketQT::pollStream()
+{
+    vector < _BYTE > vecbydata(MAX_SIZE_BYTES_NETW_BUF);
+    /* Read block from network interface */
+    int iNumBytesRead = tcpSocket->read((char *) &vecbydata[0], MAX_SIZE_BYTES_NETW_BUF);
+    if(iNumBytesRead > 0)
+    {
+        /* Decode the incoming packet */
+        if(pPacketSink != NULL)
+        {
+            vecbydata.resize(iNumBytesRead);
+            QHostAddress peer = tcpSocket->peerAddress();
+            uint32_t addr = peer.toIPv4Address();
+            int port = tcpSocket->peerPort();
+            if(sourceAddr == 0 || sourceAddr == addr) // optionally filter on source address
+                pPacketSink->SendPacket(vecbydata, addr, port);
+        }
+    }
+}
+
+void
+CPacketSocketQT::pollDatagram()
+{
+    vector < _BYTE > vecbydata(MAX_SIZE_BYTES_NETW_BUF);
+    while (udpSocket->hasPendingDatagrams()) {
+        vecbydata.resize(udpSocket->pendingDatagramSize());
+        QHostAddress sender;
+        quint16 senderPort;
+
+        udpSocket->readDatagram((char*)&vecbydata[0], vecbydata.size(), &sender, &senderPort);
+
+        uint32_t addr = sender.toIPv4Address();
+        if(sourceAddr == 0)
+            pPacketSink->SendPacket(vecbydata, addr, senderPort);
+        else if(sourceAddr == addr) // optionally filter on source address
+            pPacketSink->SendPacket(vecbydata, addr, senderPort);
+    }
+}
diff --git a/src/util-QT/PacketSocketQT.h b/src/util-QT/PacketSocketQT.h
new file mode 100644
index 0000000..957acb6
--- /dev/null
+++ b/src/util-QT/PacketSocketQT.h
@@ -0,0 +1,90 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer, Oliver Haffenden
+ *
+ * Description:
+ *	Implementation of CPacketSocket interface that wraps up a QSocket. See PacketSocketQT.cpp.
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#ifndef PACKET_SOCKET_QT_H_INCLUDED
+#define PACKET_SOCKET_QT_H_INCLUDED
+
+#include "../GlobalDefinitions.h"
+#include "../util/Vector.h"
+#include "../util/Buffer.h"
+
+#include <QUdpSocket>
+#include <QTcpSocket>
+#include <QHostAddress>
+#include <QNetworkInterface>
+#include <QNetworkAddressEntry>
+#include <qdatetime.h>
+
+/* Maximum number of bytes received from the network interface. Maximum data
+   rate of DRM is approx. 80 kbps. One MDI packet must be sent each DRM frame
+   which is every 400 ms -> 0.4 * 80000 / 8 = 4000 bytes. Allocating more than
+   double of this size should be ok for all possible cases */
+#define MAX_SIZE_BYTES_NETW_BUF		10000
+
+#include "../MDI/PacketInOut.h"
+
+class CPacketSocketQT :
+	public CPacketSocket
+{
+public:
+	CPacketSocketQT();
+	virtual ~CPacketSocketQT();
+	// Set the sink which will receive the packets
+	virtual void SetPacketSink(CPacketSink *pSink);
+	// Stop sending packets to the sink
+	virtual void ResetPacketSink(void);
+
+	// Send packet to the socket
+	void SendPacket(const vector<_BYTE>& vecbydata, uint32_t addr=0, uint16_t port=0);
+
+	virtual _BOOLEAN SetDestination(const string& str);
+	virtual _BOOLEAN SetOrigin(const string& str);
+
+	virtual _BOOLEAN GetDestination(string& str);
+
+	void poll();
+
+private:
+	void pollStream();
+	void pollDatagram();
+
+	QStringList parseDest(const string & strNewAddr);
+	_BOOLEAN doSetSource(QHostAddress, QHostAddress, int, QHostAddress);
+	QNetworkInterface GetInterface(QHostAddress AddrInterface);
+	CPacketSink *pPacketSink;
+
+	uint32_t	sourceAddr;
+	QHostAddress	HostAddrOut;
+	int		iHostPortOut;
+	vector<_BYTE>	writeBuf;
+	bool udp;
+
+	QUdpSocket* udpSocket;
+	QTcpSocket* tcpSocket;
+};
+#endif
diff --git a/src/util-QT/Rig.cpp b/src/util-QT/Rig.cpp
new file mode 100644
index 0000000..1f8b4e9
--- /dev/null
+++ b/src/util-QT/Rig.cpp
@@ -0,0 +1,118 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "Rig.h"
+
+
+void CRig::SetFrequencyCallback(void* sfCallbackParam, int iNewFreqkHz)
+{
+    ((CRig*)sfCallbackParam)->SetFrequency(iNewFreqkHz);
+}
+
+CRig::CRig(CSettings* pSettings, CParameter* pParameters) :
+    pSettings(pSettings), pParameters(pParameters), subscribers(0)
+{
+#ifdef HAVE_LIBHAMLIB
+    connect(&timer, SIGNAL(timeout()), this, SLOT(onTimer()));
+    Hamlib.LoadSettings(*pSettings);
+#endif
+}
+
+CRig::~CRig()
+{
+#ifdef HAVE_LIBHAMLIB
+    Hamlib.SaveSettings(*pSettings);
+#endif
+}
+
+void CRig::subscribe()
+{
+#ifdef HAVE_LIBHAMLIB
+    if(Hamlib.GetHamlibModelID()==RIG_MODEL_NONE)
+    {
+        cerr << "can't subscribe - no rig set! " << subscribers << endl;
+        return;
+    }
+#endif
+    subscribers++;
+    if(subscribers>0)
+	{
+#ifdef HAVE_LIBHAMLIB
+        timer.start(1000);
+#endif
+	}
+}
+
+void CRig::unsubscribe()
+{
+#ifdef HAVE_LIBHAMLIB
+    if(Hamlib.GetHamlibModelID()==RIG_MODEL_NONE)
+    {
+        cerr << "can't unsubscribe - no rig set! " << subscribers << endl;
+        return;
+    }
+#endif
+    if(subscribers>0)
+    {
+        subscribers--;
+        cerr << "unsubscribe " << subscribers << endl;
+    }
+    if(subscribers<=0)
+    {
+#ifdef HAVE_LIBHAMLIB
+        timer.stop();
+        emit sigstr(-1000.0);
+#endif
+    }
+}
+
+void CRig::onTimer()
+{
+#ifdef HAVE_LIBHAMLIB
+    _REAL r;
+    if (Hamlib.GetSMeter(r) == CHamlib::SS_VALID)
+    {
+        pParameters->Lock();
+        r += pParameters->rSigStrengthCorrection;
+        pParameters->SigStrstat.addSample(r);
+        pParameters->Unlock();
+        emit sigstr(r);
+    }
+    else
+        emit sigstr(-1000.0);
+#endif
+}
+
+void CRig::SetFrequency(int f)
+{
+#ifdef HAVE_LIBHAMLIB
+    Hamlib.SetFrequency(f);
+#else
+    (void)f;
+#endif
+}
diff --git a/src/util-QT/Rig.h b/src/util-QT/Rig.h
new file mode 100644
index 0000000..801d1d4
--- /dev/null
+++ b/src/util-QT/Rig.h
@@ -0,0 +1,77 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer, Andrea Russo
+ *
+ * Description:
+ *
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#ifndef __RIG_H
+#define __RIG_H
+
+#include "../Parameter.h"
+#include "../util/Settings.h"
+#ifdef HAVE_LIBHAMLIB
+# include "../util/Hamlib.h"
+#endif
+#include <QObject>
+#include <QTimer>
+
+class CRig : public QObject
+{
+	Q_OBJECT
+public:
+	static void SetFrequencyCallback(void* sfCallbackParam, int iNewFreqkHz);
+	CRig(CSettings* pSettings, CParameter* pParameters);
+	~CRig();
+	void SetFrequency(int);
+#ifdef HAVE_LIBHAMLIB
+	void GetRigList(map<rig_model_t,CHamlib::SDrRigCaps>& r) { Hamlib.GetRigList(r); }
+	rig_model_t GetHamlibModelID() { return Hamlib.GetHamlibModelID(); }
+	void SetHamlibModelID(rig_model_t r) { Hamlib.SetHamlibModelID(r); }
+	void SetEnableModRigSettings(_BOOLEAN b) { Hamlib.SetEnableModRigSettings(b); }
+	void GetPortList(map<string,string>& ports) { Hamlib.GetPortList(ports); }
+	string GetComPort() { return Hamlib.GetComPort(); }
+	void SetComPort(const string& s) { Hamlib.SetComPort(s); }
+	_BOOLEAN GetEnableModRigSettings() { return Hamlib.GetEnableModRigSettings(); }
+	CHamlib::ESMeterState GetSMeter(_REAL& r) { return Hamlib.GetSMeter(r); }
+	CHamlib* GetRig() { return &Hamlib; }
+
+protected:
+	CHamlib Hamlib;
+	QTimer timer;
+#endif
+protected:
+	CSettings* pSettings;
+	CParameter* pParameters;
+	int subscribers;
+
+signals:
+    void sigstr(double);
+public slots:
+	void subscribe();
+	void unsubscribe();
+	void onTimer();
+};
+
+#endif
diff --git a/src/util-QT/Util.cpp b/src/util-QT/Util.cpp
new file mode 100644
index 0000000..2f06468
--- /dev/null
+++ b/src/util-QT/Util.cpp
@@ -0,0 +1,549 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	
+ *
+ * Description:
+ *
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "Util.h"
+#include "../DrmTransceiver.h"
+#include "../datadecoding/DataDecoder.h"
+#include <QRegExp>
+#include <QDate>
+#include <QUrl>
+#include <QDir>
+#include <QFileInfo>
+#include <QCoreApplication>
+#include <QStringList>
+#ifdef QT_GUI_LIB
+# include <QHeaderView>
+#endif
+
+/* Ensure that the given filename is secure */
+QString VerifyFilename(QString filename)
+{
+    filename.replace(QRegExp("/"), "_"); /* replace unix-like path separator with '_' */
+#ifdef _WIN32
+    filename.replace(QRegExp("\\\\"), "_"); /* replace windows path separator with '_' */
+    filename.replace(QRegExp(":"), "_"); /* replace ':' with '_' */
+#endif
+    return filename;
+}
+
+/* Ensure that the given html path is secure */
+QString VerifyHtmlPath(QString path)
+{
+    if (path == "..")
+        return "_";
+#ifdef _WIN32
+    path.replace(QRegExp("\\\\"), "_"); /* replace windows path separator with '_' */
+    path.replace(QRegExp(":"), "_"); /* replace ':' with '_' */
+#endif
+    path.replace(QRegExp("^\\.\\./"), "_/"); /* replace '../' at the beginning with '_/' */
+    path.replace(QRegExp("/\\.\\.$"), "/_"); /* replace '/..' at the end with '/_' */
+    path.replace(QRegExp("/\\.\\./"), "/_/"); /* replace '/../' with '/_/' */
+    return path;
+}
+
+/* Accept both absolute and relative url, but only return the path component.
+   Invalid characters in path are percent-encoded (e.g. space = %20) */
+QString UrlEncodePath(QString url)
+{
+    /* Get path component */
+    QString path(QUrl(url, QUrl::TolerantMode).path());
+    /* Prepend with '/' if none present */
+    if (path.size() == 0 || path.at(0) != QChar('/'))
+        path.insert(0, QChar('/'));
+    /* Replace multiple '/' by single '/' */
+    path.replace(QRegExp("/{1,}"), "/");
+    /* Replace all occurrence of '/./' with '/' */
+    while (path.indexOf("/./") != -1)
+        path.replace(QRegExp("/\\./"), "/");
+    /* The Actual percent encoding */
+    path = QString(QUrl(path, QUrl::TolerantMode).toEncoded(
+        QUrl::RemoveScheme | QUrl::RemoveAuthority |
+        QUrl::RemoveQuery | QUrl::RemoveFragment));
+    return path;
+}
+
+/* Determine if the given url is a directory */
+bool IsUrlDirectory(QString url)
+{
+    return url.endsWith(QChar('/'));
+}
+
+/* Convert all www. or http:// or email to real
+   clickable link, for use with QLabel and such.
+   Code by David Flamand */
+QString& Linkify(QString& text, QString linkColor)
+{
+    int i, j, posWWW=-2, posHTTP=-2, posMAIL=-2, posBegin, posEnd, size;
+    if (!linkColor.isEmpty())
+        linkColor = " style=\"color: " + linkColor + ";\"";
+    size = text.size();
+    for (i = 0; i < size;)
+    {
+        if (posWWW != -1 && posWWW < i)
+            posWWW  = text.indexOf("www.", i, Qt::CaseInsensitive);
+        if (posHTTP != -1 && posHTTP < i)
+            posHTTP = text.indexOf("http://", i, Qt::CaseInsensitive);
+        if (posMAIL != -1 && posMAIL < i)
+            posMAIL = text.indexOf(QRegExp("\\b[0-9a-z._-]+@[0-9a-z.-]+\\.[a-z]{2,4}\\b", Qt::CaseInsensitive), i);
+        if (posMAIL>=0 && (posMAIL<=posWWW || posWWW<0) && (posMAIL<posHTTP || posHTTP<0))
+            posBegin = posMAIL;
+        else if (posWWW>=0 && (posWWW<posHTTP || posHTTP<0))
+            posBegin = posWWW;
+        else
+            posBegin = posHTTP;
+        if (posBegin >= 0)
+        {
+            posEnd = size;
+            for (j = posBegin; j < size; j++)
+            {
+                int chr = text[j].unicode();
+                if (!((chr=='@' && posBegin==posMAIL) ||
+                      chr=='.' || chr=='/' ||
+                      chr=='~' || chr=='-' ||
+                      chr=='_' || chr==':' ||
+                     (chr>='a' && chr<='z') ||
+                     (chr>='A' && chr<='Z') ||
+                     (chr>='0' && chr<='9')))
+                {
+                    posEnd = j;
+                    break;
+                }
+            }
+            const int rawLinkSize = posEnd-posBegin;
+            QStringRef rawLink(&text, posBegin, rawLinkSize);
+            QString newLink;
+            if (posBegin == posMAIL)
+                newLink = "<a href=\"mailto:%1\"" + linkColor + ">%1</a>";
+            else if (posBegin == posWWW)
+                newLink = "<a href=\"http://%1\"" + linkColor + ">%1</a>";
+            else /* posBegin == posHTTP */
+                newLink = "<a href=\"%1\"" + linkColor + ">%1</a>";
+            newLink = newLink.arg(rawLink.toString());
+            const int newLinkSize = newLink.size();
+            text.replace(posBegin, rawLinkSize, newLink);
+            const int diff = newLinkSize - rawLinkSize;
+            i = posEnd + diff;
+            size += diff;
+            if (posWWW >= 0)
+                posWWW += diff;
+            if (posHTTP >= 0)
+                posHTTP += diff;
+            if (posMAIL >= 0)
+                posMAIL += diff;
+        }
+        else
+            break;
+    }
+    return text;
+}
+
+void CreateDirectories(const QString& strFilename)
+{
+    /*
+        This function is for creating a complete directory structure to a given
+    	file name. If there is a pathname like this:
+    	/html/files/images/myimage.gif
+    	this function create all the folders into MOTCache:
+    	/html
+    	/html/files
+    	/html/files/images
+    	QFileInfo only creates a file if the pathname is valid. If not all folders
+    	are created, QFileInfo will not save the file. There was no QT function
+    	or a hint the QT mailing list found in which does the job of this function.
+    */
+    for (int i = 0;; i++)
+    {
+#ifdef _WIN32
+        int i1 = strFilename.indexOf(QChar('/'), i);
+        int i2 = strFilename.indexOf(QChar('\\'), i);
+        i = (i1 >= 0 && ((i1 < i2) || (i2<0))) ? i1 : i2;
+#else
+        i = strFilename.indexOf(QChar('/'), i);
+#endif
+        if (i < 0)
+            break;
+        const QString strDirName = strFilename.left(i);
+        if (!strDirName.isEmpty() && !QFileInfo(strDirName).exists())
+            QDir().mkdir(strDirName);
+    }
+}
+
+void RestartTransceiver(CDRMTransceiver *DRMTransceiver)
+{
+    if (DRMTransceiver != NULL)
+    {
+        QMutex sleep;
+        CParameter& Parameters = *DRMTransceiver->GetParameters();
+        DRMTransceiver->Restart();
+        while (Parameters.eRunState == CParameter::RESTART)
+        {
+            QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
+            sleep.lock(); /* TODO find a better way to sleep on Qt */
+            sleep.tryLock(10); /* 10 ms */
+            sleep.unlock();
+        }
+    }
+}
+
+QString GetCodecString(const CService& service)
+{
+    QString strReturn;
+
+    /* First check if it is audio or data service */
+    if (service.eAudDataFlag == CService::SF_AUDIO)
+    {
+        /* Audio service */
+        const CAudioParam::EAudSamRat eSamRate = service.AudioParam.eAudioSamplRate;
+
+        /* Audio coding */
+        switch (service.AudioParam.eAudioCoding)
+        {
+        case CAudioParam::AC_NONE:
+            break;
+
+        case CAudioParam::AC_AAC:
+            /* Only 12 and 24 kHz sample rates are supported for AAC encoding */
+            if (eSamRate == CAudioParam::AS_12KHZ)
+                strReturn = "aac";
+            else
+                strReturn = "AAC";
+            break;
+
+        case CAudioParam::AC_CELP:
+            /* Only 8 and 16 kHz sample rates are supported for CELP encoding */
+            if (eSamRate == CAudioParam::AS_8_KHZ)
+                strReturn = "celp";
+            else
+                strReturn = "CELP";
+            break;
+
+        case CAudioParam::AC_HVXC:
+            strReturn = "HVXC";
+            break;
+
+        case CAudioParam::AC_OPUS:
+            strReturn = "OPUS ";
+            /* Opus Audio sub codec */
+            switch (service.AudioParam.eOPUSSubCod)
+            {
+                case CAudioParam::OS_SILK:
+                    strReturn += "SILK ";
+                    break;
+                case CAudioParam::OS_HYBRID:
+                    strReturn += "HYBRID ";
+                    break;
+                case CAudioParam::OS_CELT:
+                    strReturn += "CELT ";
+                    break;
+            }
+            /* Opus Audio bandwidth */
+            switch (service.AudioParam.eOPUSBandwidth)
+            {
+                case CAudioParam::OB_NB:
+                    strReturn += "NB";
+                    break;
+                case CAudioParam::OB_MB:
+                    strReturn += "MB";
+                    break;
+                case CAudioParam::OB_WB:
+                    strReturn += "WB";
+                    break;
+                case CAudioParam::OB_SWB:
+                    strReturn += "SWB";
+                    break;
+                case CAudioParam::OB_FB:
+                    strReturn += "FB";
+                    break;
+            }
+            break;
+
+        case CAudioParam::AC_xHE_AAC:
+            strReturn = "xHE AAC ";
+        }
+
+        /* SBR */
+        if (service.AudioParam.eSBRFlag == CAudioParam::SB_USED)
+        {
+            strReturn += "+";
+        }
+    }
+    else
+    {
+        /* Data service */
+        strReturn = "Data:";
+    }
+
+    return strReturn;
+}
+
+QString GetTypeString(const CService& service)
+{
+    QString strReturn;
+
+    /* First check if it is audio or data service */
+    if (service.eAudDataFlag == CService::SF_AUDIO)
+    {
+        /* Audio service */
+        switch (service.AudioParam.eAudioCoding)
+        {
+        case CAudioParam::AC_NONE:
+            break;
+
+        case CAudioParam::AC_OPUS:
+            /* Opus channels configuration */
+            switch (service.AudioParam.eOPUSChan)
+            {
+            case CAudioParam::OC_MONO:
+            strReturn = "MONO";
+            break;
+
+            case CAudioParam::OC_STEREO:
+            strReturn = "STEREO";
+            break;
+            }
+            break;
+
+        default:
+            /* Mono-Stereo */
+            switch (service.AudioParam.eAudioMode)
+            {
+            case CAudioParam::AM_MONO:
+                strReturn = "Mono";
+                break;
+
+            case CAudioParam::AM_P_STEREO:
+                strReturn = "P-Stereo";
+                break;
+
+            case CAudioParam::AM_STEREO:
+                strReturn = "Stereo";
+                break;
+            }
+        }
+    }
+    else
+    {
+        strReturn = GetDataTypeString(service);
+    }
+    return strReturn;
+}
+
+QString GetDataTypeString(const CService& service)
+{
+    QString strReturn;
+    /* Data service */
+    if (service.DataParam.ePacketModInd == CDataParam::PM_PACKET_MODE)
+    {
+        if (service.DataParam.eAppDomain == CDataParam::AD_DAB_SPEC_APP)
+        {
+            switch (service.DataParam.iUserAppIdent)
+            {
+            case 1:
+                strReturn = QObject::tr("Dynamic labels");
+                break;
+
+            case DAB_AT_MOTSLIDESHOW:
+                strReturn = QObject::tr("MOT Slideshow");
+                break;
+
+            case DAB_AT_BROADCASTWEBSITE:
+                strReturn = QObject::tr("MOT WebSite");
+                break;
+
+            case DAB_AT_TPEG:
+                strReturn = QObject::tr("TPEG");
+                break;
+
+            case DAB_AT_DGPS:
+                strReturn = QObject::tr("DGPS");
+                break;
+
+            case DAB_AT_TMC:
+                strReturn = QObject::tr("TMC");
+                break;
+
+            case DAB_AT_EPG:
+                strReturn = QObject::tr("EPG - Electronic Programme Guide");
+                break;
+
+            case DAB_AT_JAVA:
+                strReturn = QObject::tr("Java");
+                break;
+
+            case DAB_AT_JOURNALINE: /* Journaline */
+                strReturn = QObject::tr("Journaline");
+                break;
+            }
+        }
+        else
+            strReturn = QObject::tr("Unknown Service");
+    }
+    else
+        strReturn = QObject::tr("Unknown Service");
+
+    return strReturn;
+}
+
+QString getAMScheduleUrl()
+{
+    QDate d = QDate::currentDate();
+    int month = d.month();
+    int year = 0;
+    char season = 'a';
+
+    // transitions last sunday in March and October
+    switch(month) {
+    case 1:
+    case 2:
+        year = d.year()-1;
+        season = 'b';
+        break;
+    case 3: {
+        QDate s = d;
+        s.setDate(d.year(), month+1, 1);
+        s = s.addDays(0-s.dayOfWeek());
+        if(d<s) {
+            year = d.year()-1;
+            season = 'b';
+        } else {
+            year = d.year();
+            season = 'a';
+        }
+            }
+            break;
+    case 4:
+    case 5:
+    case 6:
+    case 7:
+    case 8:
+    case 9:
+        year = d.year();
+        season = 'a';
+        break;
+    case 10: {
+        QDate s = d;
+        s.setDate(d.year(), month+1, 1);
+        int n = s.dayOfWeek();
+        s = s.addDays(0-n);
+        if(d<s) {
+            year = d.year();
+            season = 'a';
+        } else {
+            year = d.year();
+            season = 'b';
+        }
+             }
+             break;
+    case 11:
+    case 12:
+        year = d.year();
+        season = 'b';
+    }
+    return QString("http://eibispace.de/dx/sked-%1%2.csv").arg(season).arg(year-2000,2);
+}
+
+#ifdef QT_GUI_LIB
+void SetStatus(CMultColorLED* LED, ETypeRxStatus state)
+{
+    switch(state)
+    {
+    case NOT_PRESENT:
+        LED->Reset(); /* GREY */
+        break;
+
+    case CRC_ERROR:
+        LED->SetLight(CMultColorLED::RL_RED);
+        break;
+
+    case DATA_ERROR:
+        LED->SetLight(CMultColorLED::RL_YELLOW);
+        break;
+
+    case RX_OK:
+        LED->SetLight(CMultColorLED::RL_GREEN);
+        break;
+    }
+}
+
+void ColumnParamFromStr(QTreeWidget* treeWidget, const QString& strColumnParam)
+{
+    QStringList list(strColumnParam.split(QChar('|')));
+    const int n = list.count(); /* width and position */
+    if (n == 2)
+    {
+        for (int j = 0; j < n; j++)
+        {
+            int c = treeWidget->header()->count();
+            QStringList values(list[j].split(QChar(',')));
+            const int lc = (int)values.count();
+            if (lc < c)
+                c = lc;
+            for (int i = 0; i < c; i++)
+            {
+                int v = values[i].toInt();
+                if (!j) /* width*/
+                    treeWidget->header()->resizeSection(i, v);
+                else /* position */
+                    treeWidget->header()->moveSection(treeWidget->header()->visualIndex(i), v);
+            }
+        }
+    }
+    else
+    {
+        treeWidget->header()->resizeSections(QHeaderView::ResizeToContents);
+        treeWidget->header()->resizeSections(QHeaderView::Interactive);
+        treeWidget->header()->resizeSection(0, treeWidget->header()->minimumSectionSize());
+    }
+}
+
+void ColumnParamToStr(QTreeWidget* treeWidget, QString& strColumnParam)
+{
+    strColumnParam = "";
+    const int n = 2; /* width and position */
+    for (int j = 0; j < n; j++)
+    {
+        const int c = treeWidget->header()->count();
+        for (int i = 0; i < c; i++)
+        {
+            int v;
+            if (!j) /* width*/
+                v = treeWidget->header()->sectionSize(i);
+            else /* position */
+                v = treeWidget->header()->visualIndex(i);
+            QString strValue;
+            strValue.setNum(v);
+            strColumnParam += strValue;
+            if (i < (c-1))
+                strColumnParam += ",";
+        }
+        if (j < (n-1))
+            strColumnParam += "|";
+    }
+}
+#endif
+
diff --git a/src/util-QT/Util.h b/src/util-QT/Util.h
new file mode 100644
index 0000000..894f519
--- /dev/null
+++ b/src/util-QT/Util.h
@@ -0,0 +1,68 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer, Andrea Russo, David Flamand
+ *
+ * Description:
+ *
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#ifndef __UTIL_QT_UTIL_H
+#define __UTIL_QT_UTIL_H
+
+#include <QString>
+#ifdef QT_GUI_LIB
+# include "../GUI-QT/MultColorLED.h"
+# include <QTreeWidget>
+#endif
+#include "../Parameter.h"
+
+class CDRMTransceiver;
+class CService;
+
+QString VerifyFilename(QString filename);
+
+QString VerifyHtmlPath(QString path);
+
+QString UrlEncodePath(QString url);
+
+bool IsUrlDirectory(QString url);
+
+QString& Linkify(QString& text, QString linkColor=QString());
+
+void CreateDirectories(const QString& strFilename);
+
+void RestartTransceiver(CDRMTransceiver *DRMTransceiver);
+
+QString	GetCodecString(const CService&);
+QString	GetTypeString(const CService&);
+QString GetDataTypeString(const CService&);
+
+QString getAMScheduleUrl();
+
+#ifdef QT_GUI_LIB
+void SetStatus(CMultColorLED*, ETypeRxStatus);
+void ColumnParamFromStr(QTreeWidget* treeWidget, const QString& strColumnParam);
+void ColumnParamToStr(QTreeWidget* treeWidget, QString& strColumnParam);
+#endif
+
+#endif // __UTIL_QT_UTIL_H
diff --git a/src/util-QT/epgdec.cpp b/src/util-QT/epgdec.cpp
new file mode 100644
index 0000000..a075fb0
--- /dev/null
+++ b/src/util-QT/epgdec.cpp
@@ -0,0 +1,637 @@
+/******************************************************************************\
+ * British Broadcasting Corporation
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Julian Cable
+ *
+ * Description:
+ *	ETSI DAB/DRM Electronic Programme Guide XML Decompressor
+ *
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include <string>
+#include <map>
+#include <iostream>
+#include <sstream>
+#include "epgdec.h"
+#include "../datadecoding/DABMOT.h"
+#include "../util/Utilities.h"
+
+static QDomElement element(QDomDocument& doc, const tag_length_value& tlv);
+
+void
+CEPGDecoder::decode (const vector<_BYTE>& vecData)
+{
+    /* clear the doc, allowing re-use */
+    doc.setContent (QString (""));
+    tag_length_value tlv(&vecData[0]);
+    if(tlv.is_epg()) {
+      doc.appendChild (element(doc, tlv));
+    }
+}
+
+typedef enum { nu_attr, enum_attr, string_attr, u16_attr, u24_attr, datetime_attr,
+  duration_attr, sid_attr, genre_href_attr, bitrate_attr} enum_attr_t;
+
+typedef struct
+{
+    const char *name;
+    const char **vals;
+    enum_attr_t decode;
+} dectab;
+
+static char token_list[20][255];
+
+static uint32_t default_content_id;
+
+static const char *enums0[] = { (char*)2, "DAB", "DRM" };
+static const char *enums1[] = { (char*)9, 0, "series",
+    "show",
+    "programConcept",
+    "magazine",
+    "programCompilation",
+    "otherCollection",
+    "otherChoice",
+    "topic"
+};
+static const char *enums2[] = { (char*)3, "URL", "DAB", "DRM" };
+static const char *enums3[] = { (char*)4, "identical", "more", "less", "similar" };
+static const char *enums4[] = { (char*)2, "primary", "alternative" };
+static const char *enums5[] = { (char*)7, "audio", "DLS",
+    "MOTSlideshow", "MOTBWS", "TPEG", "DGPS", "proprietary"
+};
+static const char *enums6[] = { (char*)2, "primary", "secondary" };
+static const char *enums7[] = { (char*)2, "none", "unspecified" };
+static const char *enums8[] = { (char*)2, "on-air", "off-air" };
+static const char *enums9[] = { (char*)2, "no", "yes" };
+static const char *enums10[] =
+    { (char*)4, 0, "logo_unrestricted", "logo_mono_square",
+    "logo_colour_square", "logo_mono_rectangle"
+};
+
+static const char *enums11[] = { (char*)3, "main", "secondary", "other" };
+
+static const char *classificationScheme[] = {
+    0,
+    "IntentionCS",
+    "FormatCS",
+    "ContentCS",
+    "IntendedAudienceCS",
+    "OriginationCS",
+    "ContentalertCS",
+    "MediaTypeCS",
+    "AtmosphereCS",
+    0, 0, 0, 0, 0, 0, 0
+};
+
+
+static dectab attribute_tags_epg[] = {
+    {"system", enums0, enum_attr},
+    {"id", 0, string_attr}
+};
+
+static dectab attribute_tags_sch[] = {
+    {"version", 0, u16_attr},
+    {"creationTime", 0, datetime_attr},
+    {"originator", 0, string_attr}
+};
+
+static dectab attribute_tags_si[] = {
+    {"version", 0, u16_attr},
+    {"creationTime", 0, datetime_attr},
+    {"originator", 0, string_attr},
+    {"serviceProvider", 0, string_attr},
+    {"system", enums0, enum_attr}
+};
+
+static dectab attribute_tags2[] = {
+    {"shortId", 0, u24_attr},
+    {"version", 0, u16_attr},
+    {"type", enums1, enum_attr},
+    {"numOfItems", 0, u16_attr},
+};
+static dectab attribute_tags_scope[] = {
+    {"startTime", 0, datetime_attr},
+    {"stopTime", 0, datetime_attr}
+};
+static dectab attribute_tags4[] = {
+    {"protocol", enums2, enum_attr},
+    {"type", enums3, enum_attr},
+    {"url", 0, string_attr},
+};
+//static dectab attribute_tags5[] = {
+//    {"id", 0, string_attr},
+//    {"version", 0, u16_attr}
+//};
+static dectab attribute_tags6[] = {
+    {"type", enums4, enum_attr},
+    {"kHz", 0, u24_attr}
+};
+static dectab attribute_tags7[] = {
+    {"version", 0, u16_attr},
+    {"format", enums5, enum_attr},
+    {"Not used", 0, nu_attr},
+    {"bitrate", 0, bitrate_attr}
+};
+static dectab attribute_tags8[] = {
+    {"id", 0, string_attr},
+    {"type", enums6, enum_attr}
+};
+static dectab attribute_tags_name[] = {
+    {"xml:lang", 0, string_attr}
+};
+static dectab attribute_tags10[] = {
+    {"mimeValue", 0, string_attr},
+    {"xml:lang", 0, string_attr},
+    {"url", 0, string_attr},
+    {"type", enums10, enum_attr},
+    {"width", 0, u16_attr},
+    {"height", 0, u16_attr}
+};
+static dectab attribute_tags11[] = {
+    {"time", 0, datetime_attr},
+    {"duration", 0, duration_attr},
+    {"actualTime", 0, datetime_attr},
+    {"actualDuration", 0, duration_attr}
+};
+static dectab attribute_tags12[] = {
+    {"id", 0, sid_attr},
+    {"trigger", 0, u16_attr}
+};
+static dectab attribute_tags13[] = {
+    {"id", 0, string_attr},
+    {"shortId", 0, u24_attr},
+    {"index", 0, u16_attr}
+};
+static dectab attribute_tags14[] = {
+    {"url", 0, string_attr},
+    {"mimeValue", 0, string_attr},
+    {"xml:lang", 0, string_attr},
+    {"description", 0, string_attr},
+    {"expiryTime", 0, datetime_attr}
+};
+static dectab attribute_tags15[] = {
+    {"id", 0, string_attr},
+    {"shortId", 0, u24_attr},
+    {"version", 0, u16_attr},
+    {"recommendation", enums9, enum_attr},
+    {"broadcast", enums8, enum_attr},
+    {"Not used", 0, nu_attr},
+    {"xml:lang", 0, string_attr},
+    {"bitrate", 0, string_attr}
+};
+static dectab attribute_tags_genre[] = {
+    {"href", 0, genre_href_attr},
+    {"type", enums11, enum_attr}
+};
+
+static dectab attribute_tags18[] = {
+    {"type", enums7, enum_attr}
+};
+
+struct eltab_t {
+  const char * element_name;
+  dectab* tags;
+  size_t size;
+};
+
+static eltab_t element_tables[] = {
+    { "", 0, 0 },
+    { "", 0, 0 },
+    { "epg", attribute_tags_epg, sizeof (attribute_tags_epg) / sizeof (dectab) },
+    { "serviceInformation", attribute_tags_si, sizeof (attribute_tags_si) / sizeof (dectab) },
+    { "", 0, 0 },
+    { "", 0, 0 },
+    { "", 0, 0 },
+    { "", 0, 0 },
+    { "", 0, 0 },
+    { "", 0, 0 },
+    { "", 0, 0 },
+    { "", 0, 0 },
+    { "", 0, 0 },
+    { "", 0, 0 },
+    { "", 0, 0 },
+    { "", 0, 0 },
+    { "shortName", attribute_tags_name, sizeof (attribute_tags_name) / sizeof (dectab) },
+    { "mediumName", attribute_tags_name, sizeof (attribute_tags_name) / sizeof (dectab) },
+    { "longName", attribute_tags_name, sizeof (attribute_tags_name) / sizeof (dectab) },
+    { "mediaDescription", 0, 0 },
+    { "genre", attribute_tags_genre, sizeof (attribute_tags_genre) / sizeof (dectab) },
+    { "CA", attribute_tags18, sizeof (attribute_tags18) / sizeof (dectab) },
+    { "keywords", attribute_tags_name, sizeof (attribute_tags_name) / sizeof (dectab) },
+    { "memberOf", attribute_tags13, sizeof (attribute_tags13) / sizeof (dectab) },
+    { "link", attribute_tags14, sizeof (attribute_tags14) / sizeof (dectab) },
+    { "location", 0, 0 },
+    { "shortDescription", attribute_tags_name, sizeof (attribute_tags_name) / sizeof (dectab) },
+    { "longDescription", attribute_tags_name, sizeof (attribute_tags_name) / sizeof (dectab) },
+    { "programme", attribute_tags15, sizeof (attribute_tags15) / sizeof (dectab) },
+    { "", 0, 0 },
+    { "", 0, 0 },
+    { "", 0, 0 },
+    { "programmeGroups", attribute_tags_sch, sizeof (attribute_tags_sch) / sizeof (dectab) },
+    { "schedule", attribute_tags_sch, sizeof (attribute_tags_sch) / sizeof (dectab) },
+    { "alternateSource", attribute_tags4, sizeof (attribute_tags4) / sizeof (dectab) },
+    { "programmeGroup", attribute_tags2, sizeof (attribute_tags2) / sizeof (dectab) },
+    { "scope", attribute_tags_scope, sizeof (attribute_tags_scope) / sizeof (dectab) },
+    { "serviceScope", attribute_tags12, sizeof (attribute_tags12) / sizeof (dectab) },
+    { "ensemble", attribute_tags6, sizeof (attribute_tags6) / sizeof (dectab) },
+    { "frequency", attribute_tags7, sizeof (attribute_tags7) / sizeof (dectab) },
+    { "service", attribute_tags8, sizeof (attribute_tags8) / sizeof (dectab) },
+    { "serviceID", attribute_tags6, sizeof (attribute_tags6) / sizeof (dectab) },
+    { "epgLanguage", attribute_tags_name, sizeof (attribute_tags_name) / sizeof (dectab) },
+    { "multimedia", attribute_tags10, sizeof (attribute_tags10) / sizeof (dectab) },
+    { "time", attribute_tags11, sizeof (attribute_tags11) / sizeof (dectab) },
+    { "bearer", attribute_tags12, sizeof (attribute_tags12) / sizeof (dectab) },
+    { "programmeEvent", attribute_tags15, sizeof (attribute_tags15) / sizeof (dectab) },
+    { "relativeTime", attribute_tags11, sizeof (attribute_tags11) / sizeof (dectab) },
+    { "simulcast", attribute_tags_epg, sizeof (attribute_tags_epg) / sizeof (dectab) }
+};
+
+
+
+
+string decode_string (const _BYTE * p, size_t len);
+const string element_name (_BYTE tag);
+static void attribute(map<string,string>& out, _BYTE element_tag, tag_length_value& tlv);
+static void string_token_table(const tag_length_value& tlv);
+
+uint16_t
+get_uint16 (const _BYTE* p)
+{
+    uint16_t h = p[0], l = p[1];
+    return ((h << 8) | l);
+}
+
+uint32_t
+get_uint24 (const _BYTE* p)
+{
+    uint32_t h = p[0], m = p[1], l = p[2];
+    return ((((h << 8) | m) << 8) | l);
+}
+
+tag_length_value::tag_length_value(const _BYTE* q)
+{
+  _BYTE* p=const_cast<_BYTE*>(q);
+  tag = *p++;
+  length = *p++;
+  if (length == 0xFE) {
+     length = get_uint16(p);
+     p+=2;
+  }
+  else if (length == 0xFF) {
+     length = get_uint24(p);
+     p+=3;
+  }
+  value = p;
+}
+
+static QDomElement
+element(QDomDocument& doc, const tag_length_value& tlv)
+{
+  QString name (element_tables[tlv.tag].element_name);
+  QDomElement e = doc.createElement (name);
+  map<string,string> attr;
+  _BYTE* end = tlv.value+tlv.length;
+  dectab* at = element_tables[tlv.tag].tags;
+  /* set default attributes */
+  for(size_t k=0; k<element_tables[tlv.tag].size; k++) {
+    if(at[k].decode == enum_attr)
+      attr[at[k].name] = at[k].vals[1];
+  }
+  tag_length_value a(tlv.value);
+  while(a.is_attribute())
+  {
+      attribute(attr, tlv.tag, a);
+      _BYTE* p = a.value+a.length;
+      if(p>=end)
+        break;
+      tag_length_value b(p);
+      a = b;
+  }
+  for(map<string,string>::iterator i = attr.begin(); i != attr.end(); i++)
+    e.setAttribute (QString(i->first.c_str()), QString().fromUtf8(i->second.c_str()));
+  _BYTE* p = a.value;
+  while(p<end)
+  {
+      if(a.is_string_token_table() && !tlv.is_child_element())
+          string_token_table(a);
+      else if(a.is_default_id() && !tlv.is_child_element()) {
+	      default_content_id = get_uint24(p);
+	      p+=3;
+      }
+      else if(a.is_child_element()) {
+		e.appendChild (element(doc, a));
+	}
+      else if(a.is_cdata()) {
+          string value = decode_string(a.value, a.length);
+	  QDomText t = doc.createTextNode (QString ().fromUtf8 (value.c_str()));
+	  e.appendChild (t);
+      }
+      p = a.value+a.length;
+      if(p>=end)
+        break;
+      tag_length_value b(p);
+      a = b;
+  }
+  return e;
+}
+
+static string
+decode_genre_href (const _BYTE* p, size_t len)
+{
+    int cs = p[0] & 0xff;
+    if(cs < 1 || cs > 8)
+	    return "";
+    stringstream out;
+    out << "urn:tva:metadata:cs:" << classificationScheme[cs] << ":2005:";
+    switch (len)
+      {
+      case 2:
+	  out << cs << '.' << int(p[1]);
+	  break;
+      case 3:
+	  out << cs << '.' << int(p[1]) << '.' << int(p[2]);
+	  break;
+      case 4:
+	  out << cs << '.' << int(p[1]) << '.' << int(p[2]) << '.' << int(p[3]);
+	  break;
+      }
+    return out.str();
+}
+
+string
+decode_string (const _BYTE* p, size_t len)
+{
+    size_t i;
+    string out;
+    for (i = 0; i < len; i++)
+    {
+	  char c = p[i];
+	  if (1 <= c && c <= 19)
+	      if (c == 0x9 || c == 0xa || c == 0xd)
+		      out += c;
+	      else
+		      out += token_list[p[i]];
+	  else
+	      out += c;
+    }
+    return out;
+}
+
+static string
+decode_uint16 (const _BYTE* p)
+{
+    stringstream out;
+    out << get_uint16(p);
+    return out.str();
+}
+
+static string
+decode_uint24 (const _BYTE* p)
+{
+    stringstream out;
+    out << int(get_uint24(p));
+    return out.str();
+}
+
+static string
+decode_sid (const _BYTE* p)
+{
+    stringstream out;
+    out << hex << int(p[0]) << '.' << int(p[1]) << '.' << int(p[2]);
+    return out.str();
+}
+
+static string
+decode_dateandtime(const _BYTE* p)
+{
+    uint32_t mjd;
+    uint32_t h = p[0], m = p[1], l = p[2];
+    uint16_t n, year;
+    int month, day;
+    int hours, minutes, seconds = 0;
+    int utc_flag, lto_flag, sign = 0, lto = 0;
+    mjd = (((((h << 8) | m) << 8) | l) >> 6) & 0x1ffff;
+    lto_flag = p[2] & 0x10;
+    utc_flag = p[2] & 0x08;
+    n = (p[2] << 8) | p[3];
+    hours = (n >> 6) & 0x1f;
+    minutes = n & 0x3f;
+    n = 4;
+    if (utc_flag)
+    {
+    	seconds = p[n] >> 2;
+    	n += 2;
+    }
+    //cerr << mjd << " " << hours << ":" << minutes;
+    stringstream out;
+    string tz = "Z";
+    if (lto_flag)
+    {
+    	sign = p[n] & 0x20;
+    	lto = p[n] & 0x3f;
+    	int mins = 60*hours+minutes;
+	//cerr << " lto: " << sign << " " << lto;
+    	if(sign)
+    	{
+	    mins -= 30*lto;
+	    if(mins<0)
+	    {
+		mjd--;
+		mins += 24*60;
+	    }
+    	}
+    	else
+    	{
+	    mins += 30*lto;
+	    if(mins>(24*60))
+	    {
+		mjd++;
+		mins -= 24*60;
+	    }
+    	}
+	hours = mins / 60;
+	minutes = mins % 60;
+	stringstream tzs;
+	tzs << (sign ? '-' : '+');
+	int ltoh = lto/2;
+	if(ltoh<10) tzs << '0';
+	tzs << ltoh << ':';
+	int ltom = (30 * lto) % 30;
+	if(ltom<10) tzs << '0';
+	tzs << ltom;
+	tz = tzs.str();
+    }
+    if(hours>=24)
+    {
+	      hours -= 24;
+	      mjd++;
+    }
+    CModJulDate ModJulDate(mjd);
+    year = ModJulDate.GetYear();
+    month = ModJulDate.GetMonth();
+    day = ModJulDate.GetDay();
+    out << year << '-';
+    if(month<10) out << '0';
+    out << int(month) << '-';
+    if(day<10) out << '0';
+    out << int(day) << 'T';
+    if(hours<10) out << '0';
+    out << hours << ':';
+    if(minutes<10) out << '0';
+    out << minutes << ':';
+    if(seconds<10) out << '0';
+    out << seconds << tz;
+    //cerr << " -> " << out.str() << endl;
+    return out.str();
+}
+
+static string
+decode_duration (const _BYTE* p)
+{
+    uint16_t hours, minutes, seconds;
+    seconds = get_uint16(p);
+    minutes = seconds / 60;
+    seconds = seconds % 60;
+    hours = minutes / 60;
+    minutes = minutes % 60;
+    stringstream out;
+    out << "PT";
+    if(hours>0)
+	out << hours << 'H';
+    if(minutes>0)
+	out <<  minutes << 'M';
+    if(seconds>0)
+	out << seconds << 'S';
+    return out.str();
+}
+
+static string
+decode_bitrate (const _BYTE* p)
+{
+    stringstream out;
+    uint16_t n = get_uint16(p);
+    out << float(n) / 0.1f;
+    return out.str();
+}
+
+static string
+decode_attribute_name(const dectab& tab)
+{
+	if (tab.name == NULL)
+	  {
+	      return "unknown";
+	  }
+	if (strlen (tab.name) > 64) /* some reasonably big number */
+	  {
+	      return "too long";
+	  }
+     return tab.name;
+}
+
+static string
+decode_attribute_value (enum_attr_t format, const _BYTE* p, size_t len)
+{
+    switch(format) {
+    case nu_attr:
+         return "undefined";
+         break;
+    case enum_attr:
+         return "undecoded enum";
+         break;
+    case string_attr:
+         return decode_string(p, len);
+         break;
+    case u16_attr:
+         return decode_uint16(p);
+         break;
+    case u24_attr:
+         return decode_uint24(p);
+         break;
+    case datetime_attr:
+         return decode_dateandtime(p);
+         break;
+    case duration_attr:
+         return decode_duration(p);
+         break;
+    case sid_attr:
+         return decode_sid(p);
+         break;
+    case genre_href_attr:
+         return decode_genre_href(p, len);
+         break;
+    case bitrate_attr:
+         return decode_bitrate(p);
+         break;
+	default:
+		 return "";
+		 break;
+    }
+}
+
+static void attribute(map<string,string>& out, _BYTE element_tag, tag_length_value& tlv)
+{
+  size_t el = size_t(element_tag);
+  size_t e = sizeof (element_tables) / sizeof (eltab_t);
+  if (el >= e)
+    {
+      cerr << "illegal element id" << int(el) << endl;
+      return;
+    }
+  eltab_t a = element_tables[el];
+  size_t attr = tlv.tag&0x0f;
+  size_t n = a.size;
+  if (attr >= n) {
+        cerr << "out of range attribute id " << attr << " for element id " << int(el) << endl;
+  } else {
+    dectab tab = a.tags[attr];
+    string name = decode_attribute_name(tab);
+    string value;
+    if(tab.decode == enum_attr) {
+		/* needed for 64 bit compatibility */
+		ptrdiff_t index = tlv.value[0];
+		ptrdiff_t num_vals = (tab.vals[0] - (const char*)0);
+		if(index<=num_vals && index>0)
+			value = tab.vals[index];
+		else
+			value = "out of range";
+    } else {
+      value = decode_attribute_value(tab.decode, tlv.value, tlv.length);
+    }
+    out[name] = value;
+  }
+}
+
+static void string_token_table(const tag_length_value& tlv)
+{
+	  size_t i = 0;
+	  _BYTE* p = tlv.value;
+	  for (i = 0; i < 20; i++)
+	      token_list[i][0] = 0;
+	  for (i = 0; i < tlv.length;)
+	    {
+		_BYTE tok = p[i++];
+		size_t tlen = p[i++];
+		memcpy (token_list[tok], &p[i], tlen);
+		token_list[tok][tlen] = 0;
+		i += tlen;
+	    }
+}
diff --git a/src/util-QT/epgdec.h b/src/util-QT/epgdec.h
new file mode 100644
index 0000000..2374f9f
--- /dev/null
+++ b/src/util-QT/epgdec.h
@@ -0,0 +1,67 @@
+/******************************************************************************\
+ * British Broadcasting Corporation
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Julian Cable
+ *
+ * Description:
+ *	ETSI DAB/DRM Electronic Programme Guide XML Decompressor
+ *
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#ifndef _EPGDEC_H
+#define _EPGDEC_H
+#include "../GlobalDefinitions.h"
+#include <QDomDocument>
+#include <vector>
+using namespace std;
+
+class tag_length_value
+{
+public:
+
+      tag_length_value(const _BYTE* p);
+
+      bool is_cdata() const { return tag == 1; }
+      bool is_epg() const { return tag == 2; }
+      bool is_service_information() const { return tag == 3; }
+      bool is_string_token_table() const { return tag == 4; }
+      bool is_default_id() const { return tag == 5; }
+      bool is_child_element() const { return (5<tag) && (tag<0x80); }
+      bool is_attribute() const { return tag>=0x80; }
+
+      uint8_t tag;
+      size_t length;
+      _BYTE* value;
+};
+
+class CEPGDecoder
+{
+  public:
+    CEPGDecoder ():doc()
+    {
+    }
+    void decode (const vector<_BYTE>&);
+
+    QDomDocument doc;
+
+};
+#endif
diff --git a/src/util-QT/scheduleloader.cpp b/src/util-QT/scheduleloader.cpp
new file mode 100644
index 0000000..2d99f1a
--- /dev/null
+++ b/src/util-QT/scheduleloader.cpp
@@ -0,0 +1,53 @@
+#include "scheduleloader.h"
+#include <QMessageBox>
+#include <QNetworkRequest>
+#include <QFile>
+#include <QUrl>
+
+ScheduleLoader::ScheduleLoader():QObject(),filename(),manager(new QNetworkAccessManager(this))
+{
+    connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(OnUrlFinished(QNetworkReply*)));
+}
+
+void ScheduleLoader::fetch(QString url, QString file)
+{
+    filename = file;
+    if (QMessageBox::information(NULL, tr("Dream Schedule Update"),
+        tr("Dream tries to download the newest schedule\n"
+        "Your computer must be connected to the internet.\n\n"
+        "The current file will be overwritten.\n"
+        "Do you want to continue?"),
+        QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes )
+    {
+        /* Try to download the current schedule. Copy the file to the
+        current working directory (which is "QDir().absFilePath(NULL)") */
+        manager->get(QNetworkRequest(QUrl(url)));
+    }
+}
+
+void ScheduleLoader::OnUrlFinished(QNetworkReply* reply)
+{
+    if(reply->error()==QNetworkReply::NoError)
+    {
+        QFile f(filename);
+        if(f.open(QIODevice::WriteOnly)) {
+            f.write(reply->readAll());
+            f.close();
+            /* Notify the user that update was successful */
+            QMessageBox::information(NULL, "Dream", tr("Update successful."), QMessageBox::Ok);
+            emit fileReady();
+        } else {
+            QMessageBox::information(NULL, "Dream", tr("Can't save new schedule"), QMessageBox::Ok);
+        }
+    }
+    else
+    {
+        QMessageBox::information(NULL, "Dream",
+         tr("Update failed. The following things may have caused the "
+           "failure:\n"
+           "\t- the internet connection was not set up properly\n"
+           "\t- the server is currently not available\n"
+           "\t- the file 'schedule.ini' could not be written"),
+                                 QMessageBox::Ok);
+    }
+}
diff --git a/src/util-QT/scheduleloader.h b/src/util-QT/scheduleloader.h
new file mode 100644
index 0000000..fb62286
--- /dev/null
+++ b/src/util-QT/scheduleloader.h
@@ -0,0 +1,25 @@
+#ifndef SCHEDULELOADER_H
+#define SCHEDULELOADER_H
+
+#include <QObject>
+#include <QString>
+#include <QNetworkReply>
+#include <QNetworkAccessManager>
+
+class ScheduleLoader: public QObject
+{
+    Q_OBJECT
+public:
+    ScheduleLoader();
+    void fetch(QString, QString);
+private:
+    QString filename;
+    QNetworkAccessManager *manager;
+
+private slots:
+    void OnUrlFinished(QNetworkReply*);
+signals:
+    void fileReady();
+};
+
+#endif // SCHEDULELOADER_H
diff --git a/src/util/AudioFile.h b/src/util/AudioFile.h
new file mode 100644
index 0000000..98ff16b
--- /dev/null
+++ b/src/util/AudioFile.h
@@ -0,0 +1,116 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *	Class for writing wav-files
+ *	
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later 
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT 
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#if !defined(AUDIOFILE_H__FD6B234594328533_80UWFB06C2AC__INCLUDED_)
+#define AUDIOFILE_H__FD6B234594328533_80UWFB06C2AC__INCLUDED_
+
+
+/* Classes ********************************************************************/
+class CWaveFile
+{
+public:
+	CWaveFile() : pFile(NULL), iBytesWritten(0) {}
+	virtual ~CWaveFile() {if (pFile != NULL) Close();}
+
+	void Open(const string strFileName, const int iSampleRate)
+	{
+		if (pFile != NULL)
+			Close();
+
+		uint32_t sr = uint32_t(iSampleRate);
+		const CWaveHdr WaveHeader =
+		{
+			/* Use always stereo and PCM */
+			{'R', 'I', 'F', 'F'}, 0, {'W', 'A', 'V', 'E'},
+			{'f', 'm', 't', ' '}, 16, 1, 2, sr,
+			sr * 4 /* same as block align */,
+			4 /* block align */, 16,
+			{'d', 'a', 't', 'a'}, 0
+		};
+
+		pFile = fopen(strFileName.c_str(), "wb");
+		if (pFile != NULL)
+		{
+			iBytesWritten = sizeof(CWaveHdr);
+			(void)fwrite((const void*) &WaveHeader, size_t(sizeof(CWaveHdr)), size_t(1), pFile);
+		}
+	}
+
+	void AddStereoSample(const _SAMPLE sLeft, const _SAMPLE sRight)
+	{
+		if (pFile != NULL)
+		{
+			iBytesWritten += 2 * sizeof(_SAMPLE);
+			(void)fwrite((const void*) &sLeft, size_t(2), size_t(1), pFile);
+			(void)fwrite((const void*) &sRight, size_t(2), size_t(1), pFile);
+		}
+	}
+
+	void Close()
+	{
+		if (pFile != NULL)
+		{
+			const uint32_t iFileLength = iBytesWritten - 8;
+			fseek(pFile, 4 /* offset */, SEEK_SET /* origin */);
+			(void)fwrite((const void*) &iFileLength, size_t(4), size_t(1), pFile);
+
+			const uint32_t iDataLength = iBytesWritten - sizeof(CWaveHdr);
+			fseek(pFile, 40 /* offset */, SEEK_SET /* origin */);
+			(void)fwrite((const void*) &iDataLength, size_t(4), size_t(1), pFile);
+
+			fclose(pFile);
+			pFile = NULL;
+		}
+	}
+
+protected:
+	struct CWaveHdr
+	{
+		/* Wave header struct */
+		char cMainChunk[4]; /* "RIFF" */
+		uint32_t length; /* Length of file */
+		char cChunkType[4]; /* "WAVE" */
+		char cSubChunk[4]; /* "fmt " */
+		uint32_t cLength; /* Length of cSubChunk (always 16 bytes) */
+		uint16_t iFormatTag; /* waveform code: PCM */
+		uint16_t iChannels; /* Number of channels */
+		uint32_t iSamplesPerSec; /* Sample-rate */
+		uint32_t iAvgBytesPerSec;
+		uint16_t iBlockAlign; /* Bytes per sample */
+		uint16_t iBitsPerSample;
+		char cDataChunk[4]; /* "data" */
+		uint32_t iDataLength; /* Length of data */
+	};
+
+	FILE*		pFile;
+	uint32_t	iBytesWritten;
+};
+
+
+#endif // AUDIOFILE_H__FD6B234594328533_80UWFB06C2AC__INCLUDED_
diff --git a/src/util/Buffer.h b/src/util/Buffer.h
new file mode 100644
index 0000000..ea2a062
--- /dev/null
+++ b/src/util/Buffer.h
@@ -0,0 +1,333 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ * Transfer buffer between different modules
+ *
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#if !defined(PUFFER_H__3B0BA660_CA63_4344_BB2B_23E7A0D31912__INCLUDED_)
+#define PUFFER_H__3B0BA660_CA63_4344_BB2B_23E7A0D31912__INCLUDED_
+
+#include "../GlobalDefinitions.h"
+#include "Vector.h"
+
+
+/* Classes ********************************************************************/
+/* Buffer base class */
+template<class TData> class CBuffer
+{
+public:
+	CBuffer() : iBufferSize(0), bRequestFlag(FALSE) {}
+	virtual	~CBuffer() {}
+
+	void			SetRequestFlag(const _BOOLEAN bNewRequestFlag)
+						{bRequestFlag = bNewRequestFlag;}
+	_BOOLEAN		GetRequestFlag() const {return bRequestFlag;}
+
+	/* Virtual function to be declared by the derived object */
+	virtual void				Init(const int iNewBufferSize);
+	virtual CVectorEx<TData>*	Get(const int iRequestedSize) = 0;
+	virtual CVectorEx<TData>*	QueryWriteBuffer() = 0;
+	virtual void				Put(const int iOfferedSize) = 0;
+	virtual void				Clear() = 0;
+	virtual int					GetFillLevel() const = 0;
+
+protected:
+	CVectorEx<TData>	vecBuffer;
+	int					iBufferSize;
+
+	_BOOLEAN			bRequestFlag;
+};
+
+/* Single block buffer */
+template<class TData> class CSingleBuffer : public CBuffer<TData>
+{
+public:
+	CSingleBuffer() : iFillLevel(0) {}
+	CSingleBuffer(const int iNBufSize) {Init(iNBufSize);}
+	virtual	~CSingleBuffer() {}
+
+	virtual void				Init(const int iNewBufferSize);
+	virtual CVectorEx<TData>*	Get(const int iRequestedSize);
+	virtual CVectorEx<TData>*	QueryWriteBuffer() {return &(this->vecBuffer);}
+	virtual void				Put(const int iOfferedSize);
+	virtual void				Clear() {iFillLevel = 0;}
+	virtual int					GetFillLevel() const {return iFillLevel;}
+
+protected:
+	int iFillLevel;
+};
+
+/* Cyclic buffer */
+template<class TData> class CCyclicBuffer : public CBuffer<TData>
+{
+public:
+	enum EBufferState {BS_FULL, BS_EMPTY}; // BS: Buffer Status
+
+	CCyclicBuffer() {Clear();}
+	CCyclicBuffer(const int iNBufSize) {Init(iNBufSize);}
+	virtual	~CCyclicBuffer() {}
+
+	virtual void				Init(const int iNewBufferSize);
+	virtual CVectorEx<TData>*	Get(const int iRequestedSize);
+	virtual CVectorEx<TData>*	QueryWriteBuffer() {return &vecInOutBuffer;}
+	virtual void				Put(const int iOfferedSize);
+	virtual void				Clear();
+	virtual int					GetFillLevel() const;
+
+protected:
+	CVectorEx<TData>	vecInOutBuffer;
+
+	int					iPut;
+	int					iGet;
+	EBufferState		iBufferState;
+};
+
+
+/* Implementation *************************************************************/
+template<class TData> void CBuffer<TData>::Init(const int iNewBufferSize)
+{
+	/* Assign buffer size */
+	iBufferSize = iNewBufferSize;
+
+	/* Allocate memory for data field */
+	vecBuffer.Init(iBufferSize);
+}
+
+
+/******************************************************************************\
+* Single block buffer														   *
+\******************************************************************************/
+template<class TData> void CSingleBuffer<TData>::Init(const int iNewBufferSize)
+{
+	/* Only initialize buffer when size has changed, otherwise preserve data */
+	if (iNewBufferSize != this->iBufferSize)
+	{
+		CBuffer<TData>::Init(iNewBufferSize);
+
+		/* Reset buffer parameters (empty buffer) */
+		iFillLevel = 0;
+	}
+}
+
+template<class TData> CVectorEx<TData>* CSingleBuffer<TData>::Get(const int iRequestedSize)
+{
+	/* Get data */
+#ifdef _DEBUG_DREAM
+	if (iRequestedSize > iFillLevel)
+	{
+		DebugError("SingleBuffer Get()", "FillLevel",
+			iFillLevel, "Requested size", iRequestedSize);
+	}
+#endif
+
+	/* Block is read, buffer is now empty again */
+	iFillLevel -= iRequestedSize;
+
+	return &(this->vecBuffer);
+}
+
+template<class TData> void CSingleBuffer<TData>::Put(const int iOfferedSize)
+{
+	/* New Block was added, set new fill level */
+	iFillLevel += iOfferedSize;
+
+#ifdef _DEBUG_DREAM
+	if (iFillLevel > this->iBufferSize)
+	{
+		DebugError("SingleBuffer Put()", "FillLevel",
+			iFillLevel, "Buffer size", this->iBufferSize);
+	}
+#endif
+}
+
+
+/******************************************************************************\
+* Cyclic buffer																   *
+\******************************************************************************/
+template<class TData> void CCyclicBuffer<TData>::Init(const int iNewBufferSize)
+{
+	/* Only initialize buffer when size has changed, otherwise preserve data */
+	if (iNewBufferSize != this->iBufferSize)
+	{
+		CBuffer<TData>::Init(iNewBufferSize);
+
+		/* Make in- and output buffer the same size as the main buffer to
+		   make sure that the worst-case is no problem */
+		vecInOutBuffer.Init(iNewBufferSize);
+
+		/* Reset buffer parameters (empty buffer) */
+		iPut = 0;
+		iGet = 0;
+		iBufferState = BS_EMPTY;
+	}
+}
+
+template<class TData> void CCyclicBuffer<TData>::Clear()
+{
+	/* Clear buffer by resetting the pointer */
+	iPut = 0;
+	iGet = 0;
+	iBufferState = BS_EMPTY;
+	this->bRequestFlag = FALSE;
+}
+
+template<class TData> CVectorEx<TData>* CCyclicBuffer<TData>::Get(const int iRequestedSize)
+{
+	int	i;
+	int	iAvailSpace;
+	int iElementCount;
+
+	/* Test if enough data is available for reading */
+	iAvailSpace = iPut - iGet;
+	/* Test if wrap is needed */
+	if ((iAvailSpace < 0) || ((iAvailSpace == 0) && (iBufferState == BS_FULL)))
+		iAvailSpace += this->iBufferSize;
+
+#ifdef _DEBUG_DREAM
+	if (iAvailSpace < iRequestedSize)
+	{
+		DebugError("CyclicBuffer Get()", "Available space",
+			iAvailSpace, "Requested size", iAvailSpace);
+	}
+#endif
+
+
+	/* Get data ------------------------------------------------------------- */
+	iElementCount = 0;
+
+	/* Test if data can be read in one block */
+	if (this->iBufferSize - iGet < iRequestedSize)
+	{
+		/* Data must be read in two portions */
+		for (i = iGet; i < this->iBufferSize; i++)
+		{
+			vecInOutBuffer[iElementCount] = this->vecBuffer[i];
+			iElementCount++;
+		}
+		for (i = 0; i < iRequestedSize - this->iBufferSize + iGet; i++)
+		{
+			vecInOutBuffer[iElementCount] = this->vecBuffer[i];
+			iElementCount++;
+		}
+	}
+	else
+	{
+		/* Data can be read in one block */
+		for (i = iGet; i < iGet + iRequestedSize; i++)
+		{
+			vecInOutBuffer[iElementCount] = this->vecBuffer[i];
+			iElementCount++;
+		}
+	}
+
+	/* Adjust iGet pointer */
+	iGet += iRequestedSize;
+	if (iGet >= this->iBufferSize)
+		iGet -= this->iBufferSize;
+
+	/* Test if buffer is empty. If yes, set empty-flag */
+	if ((iGet == iPut) && (iRequestedSize > 0))
+		iBufferState = BS_EMPTY;
+
+	return &vecInOutBuffer;
+}
+
+template<class TData> void CCyclicBuffer<TData>::Put(const int iOfferedSize)
+{
+	int	iAvailSpace;
+	int	i;
+	int iElementCount;
+
+	/* Test if enough data is available for writing */
+	iAvailSpace = iGet - iPut;
+	/* Test if wrap is needed */
+	if ((iAvailSpace < 0) || ((iAvailSpace == 0) && (iBufferState == BS_EMPTY)))
+		iAvailSpace += this->iBufferSize;
+
+#ifdef _DEBUG_DREAM
+	if (iAvailSpace < iOfferedSize)
+	{
+		DebugError("CyclicBuffer Put()", "Available space",
+			iAvailSpace, "Offered size", iOfferedSize);
+	}
+#endif
+
+
+	/* Put data ------------------------------------------------------------- */
+	iElementCount = 0;
+
+	/* Test if data can be written in one block */
+	if (this->iBufferSize - iPut < iOfferedSize)
+	{
+		/* Data must be written in two steps */
+		for (i = iPut; i < this->iBufferSize; i++)
+		{
+			this->vecBuffer[i] = vecInOutBuffer[iElementCount];
+			iElementCount++;
+		}
+		for (i = 0; i < iOfferedSize - this->iBufferSize + iPut; i++)
+		{
+			this->vecBuffer[i] = vecInOutBuffer[iElementCount];
+			iElementCount++;
+		}
+	}
+	else
+	{
+		/* Data can be written in one block */
+		for (i = iPut; i < iPut + iOfferedSize; i++)
+		{
+			this->vecBuffer[i] = vecInOutBuffer[iElementCount];
+			iElementCount++;
+		}
+	}
+
+	/* Adjust iPut pointer */
+	iPut += iOfferedSize;
+	if (iPut >= this->iBufferSize)
+		iPut -= this->iBufferSize;
+
+	/* Test if buffer is full. If yes, set full-flag */
+	if ((iGet == iPut) && (iOfferedSize > 0))
+		iBufferState = BS_FULL;
+}
+
+template<class TData> int CCyclicBuffer<TData>::GetFillLevel() const
+{
+	int iFillLevel;
+
+	/* Calculate the available data in the buffer. Test if wrap is needed!
+	   Take into account the flag-information (full or empty buffer) */
+	iFillLevel = iPut - iGet;
+	if ((iFillLevel == 0) && (iBufferState == BS_FULL))
+		iFillLevel = this->iBufferSize;
+	if (iFillLevel < 0)
+		iFillLevel += this->iBufferSize;	/* Wrap around */
+
+	return iFillLevel;
+}
+
+
+#endif // !defined(PUFFER_H__3B0BA660_CA63_4344_BB2B_23E7A0D31912__INCLUDED_)
diff --git a/src/util/CRC.cpp b/src/util/CRC.cpp
new file mode 100644
index 0000000..feaedc7
--- /dev/null
+++ b/src/util/CRC.cpp
@@ -0,0 +1,120 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+
+ NOTE:
+ This code is NOT speed optimized! We should calculate the CRC byte-wise and
+ precalculate the results in a table (TODO!)
+
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "CRC.h"
+
+
+/* Implementation *************************************************************/
+void CCRC::Reset(const int iNewDegree)
+{
+	/* Build mask of bit, which was shifted out of the shift register */
+	iBitOutPosMask = 1 << iNewDegree;
+
+	/* Index of vector storing the polynominals for CRC calculation */
+	iDegIndex = iNewDegree - 1;
+
+	/* Init state shift-register with ones. Set all registers to "1" with
+	   bit-wise not operation */
+	iStateShiftReg = ~uint32_t(0);
+}
+
+void CCRC::AddByte(const _BYTE byNewInput)
+{
+	for (int i = 0; i < SIZEOF__BYTE; i++)
+	{
+		/* Shift bits in shift-register for transistion */
+		iStateShiftReg <<= 1;
+
+		/* Take bit, which was shifted out of the register-size and place it
+		   at the beginning (LSB)
+		   (If condition is not satisfied, implicitely a "0" is added) */
+		if ((iStateShiftReg & iBitOutPosMask) > 0)
+			iStateShiftReg |= 1;
+
+		/* Add new data bit to the LSB */
+		if ((byNewInput & (1 << (SIZEOF__BYTE - i - 1))) > 0)
+			iStateShiftReg ^= 1;
+
+		/* Add mask to shift-register if first bit is true */
+		if (iStateShiftReg & 1)
+			iStateShiftReg ^= iPolynMask[iDegIndex];
+	}
+}
+
+void CCRC::AddBit(const _BINARY biNewInput)
+{
+	/* Shift bits in shift-register for transistion */
+	iStateShiftReg <<= 1;
+
+	/* Take bit, which was shifted out of the register-size and place it
+	   at the beginning (LSB)
+	   (If condition is not satisfied, implicitely a "0" is added) */
+	if ((iStateShiftReg & iBitOutPosMask) > 0)
+		iStateShiftReg |= 1;
+
+	/* Add new data bit to the LSB */
+	if (biNewInput > 0)
+		iStateShiftReg ^= 1;
+
+	/* Add mask to shift-register if first bit is true */
+	if (iStateShiftReg & 1)
+		iStateShiftReg ^= iPolynMask[iDegIndex];
+}
+
+uint32_t CCRC::GetCRC()
+{
+	/* Return inverted shift-register (1's complement) */
+	iStateShiftReg = ~iStateShiftReg;
+
+	/* Remove bit which where shifted out of the shift-register frame */
+	return iStateShiftReg & (iBitOutPosMask - 1);
+}
+
+_BOOLEAN CCRC::CheckCRC(const uint32_t iCRC)
+{
+    if (iCRC == GetCRC())
+		return TRUE;
+	else
+		return FALSE;
+}
+
+CCRC::CCRC()
+{
+	/* These polynominals are used in the DRM-standard */
+	iPolynMask[0] = 0;
+	iPolynMask[1] = 1 << 1;
+	iPolynMask[2] = 1 << 1;
+	iPolynMask[4] = (1 << 1) | (1 << 2) | (1 << 4);
+	iPolynMask[5] = (1 << 1) | (1 << 2) | (1 << 3) | (1 << 5);
+	iPolynMask[7] = (1 << 2) | (1 << 3) | (1 << 4);
+	iPolynMask[15] = (1 << 5) | (1 << 12);
+}
diff --git a/src/util/CRC.h b/src/util/CRC.h
new file mode 100644
index 0000000..8602fcc
--- /dev/null
+++ b/src/util/CRC.h
@@ -0,0 +1,57 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *	See CRC.cpp
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#if !defined(CRC_H__3B0BA660_CA63_4VASDGLJNAJ2B_23E7A0D31912__INCLUDED_)
+#define CRC_H__3B0BA660_CA63_4VASDGLJNAJ2B_23E7A0D31912__INCLUDED_
+
+#include "../GlobalDefinitions.h"
+
+
+/* Classes ********************************************************************/
+class CCRC
+{
+public:
+	CCRC();
+	virtual ~CCRC() {}
+
+	void Reset(const int iNewDegree);
+	void AddByte(const _BYTE byNewInput);
+	void AddBit(const _BINARY biNewInput);
+	_BOOLEAN CheckCRC(const uint32_t iCRC);
+	uint32_t GetCRC();
+
+protected:
+	int			iDegIndex;
+	uint32_t	iBitOutPosMask;
+
+	uint32_t	iPolynMask[16];
+	uint32_t	iStateShiftReg;
+};
+
+
+#endif // !defined(CRC_H__3B0BA660_CA63_4VASDGLJNAJ2B_23E7A0D31912__INCLUDED_)
diff --git a/src/util/FileTyper.cpp b/src/util/FileTyper.cpp
new file mode 100644
index 0000000..29e8172
--- /dev/null
+++ b/src/util/FileTyper.cpp
@@ -0,0 +1,89 @@
+/******************************************************************************\
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Julian Cable
+ *
+ * Description:
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "FileTyper.h"
+
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+
+#ifdef HAVE_LIBSNDFILE
+# include <sndfile.h>
+#endif
+
+#ifdef HAVE_LIBPCAP
+# include <cstdio>
+# include <pcap.h>
+#endif
+
+using namespace std;
+
+FileTyper::FileTyper()
+{
+}
+
+FileTyper::type FileTyper::resolve(const string& str)
+{
+    // allow parameters at end of string starting with a #
+    string s;
+    size_t n = str.find_last_of('#');
+    if(n==string::npos)
+        s = str;
+    else
+        s = str.substr(0, n);
+#ifdef HAVE_LIBSNDFILE
+    SF_INFO info;
+    info.format=0;
+    SNDFILE* fd = sf_open(s.c_str(), SFM_READ, &info);
+    if(fd)
+    {
+        sf_close(fd);
+        return pcm;
+    }
+#endif
+#ifdef HAVE_LIBPCAP
+    char errbuf[PCAP_ERRBUF_SIZE];
+    pcap_t* pF = pcap_open_offline(s.c_str(), errbuf);
+    if(pF)
+    {
+        pcap_close(pF);
+        return pcap;
+    }
+#endif
+    FILE* f = fopen(s.c_str(), "rb");
+    if (f)
+    {
+        char c[5];
+        size_t r = fread(&c, 1, 4, f); (void)r;
+        fclose(f);
+        c[4]='\0';
+        if(strcmp(c, "fio_")==0) return file_framing;
+        c[2]='\0';
+        if(strcmp(c, "AF")==0) return raw_af;
+        if(strcmp(c, "PF")==0) return raw_pft;
+    }
+    return pcm;
+}
diff --git a/src/util/FileTyper.h b/src/util/FileTyper.h
new file mode 100644
index 0000000..4c489d2
--- /dev/null
+++ b/src/util/FileTyper.h
@@ -0,0 +1,41 @@
+/******************************************************************************\
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Julian Cable
+ *
+ * Description:
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#ifndef FILETYPER_H
+#define FILETYPER_H
+
+#include <string>
+
+class FileTyper
+{
+public:
+    enum type { pcap, file_framing, raw_af, raw_pft, pcm };
+    FileTyper();
+    static type resolve(const std::string& s);
+    static bool is_rxstat(type t) { return t != pcm; }
+};
+
+#endif // FILETYPER_H
diff --git a/src/util/Hamlib.cpp b/src/util/Hamlib.cpp
new file mode 100644
index 0000000..a50a3cc
--- /dev/null
+++ b/src/util/Hamlib.cpp
@@ -0,0 +1,758 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "Hamlib.h"
+#include <iostream>
+#include <sstream>
+#include <cstring>
+#include <cstdlib>
+#if defined(_WIN32)
+# ifdef HAVE_SETUPAPI
+#  ifndef INITGUID
+#   define INITGUID 1
+#  endif
+#  include <windows.h>
+#  include <setupapi.h>
+# endif
+#elif defined(__APPLE__)
+#include <CoreFoundation/CoreFoundation.h>
+#include <IOKit/IOKitLib.h>
+#include <IOKit/serial/IOSerialKeys.h>
+#endif
+
+/*
+	This code is based on patches and example code from Tomi Manninen and
+	Stephane Fillod (developer of hamlib)
+*/
+CHamlib::CHamlib():SpecDRMRigs(), CapsHamlibModels(),
+pRig(NULL), bSMeterIsSupported(FALSE),
+bModRigSettings(FALSE), iHamlibModelID(0),
+strHamlibConf(""), strSettings(""), iFreqOffset(0),
+modes(), levels(), functions(), parameters(), config()
+{
+#ifdef RIG_MODEL_DWT
+	/* Digital World Traveller */
+	RigSpecialParameters(RIG_MODEL_DWT, "", 0, "");
+#endif
+
+#ifdef RIG_MODEL_G303
+	/* Winradio G303 */
+	RigSpecialParameters(RIG_MODEL_G303, "l_ATT=0,l_AGC=3", 0,
+						 "l_ATT=0,l_AGC=3");
+#endif
+
+#ifdef RIG_MODEL_G313
+	/* Winradio G313 */
+	RigSpecialParameters(RIG_MODEL_G313, "l_ATT=0,l_AGC=3", 0,
+						 "l_ATT=0,l_AGC=3");
+#endif
+
+#ifdef RIG_MODEL_AR7030
+	/* AOR 7030 */
+//  vecSpecDRMRigs.Add(CSpecDRMRig(RIG_MODEL_AR7030,
+//      "m_CW=9500,l_IF=-4200,l_AGC=3", 5 /* kHz frequency offset */,
+//      "l_AGC=3"));
+	RigSpecialParameters(RIG_MODEL_AR7030, "m_AM=3,l_AGC=5",
+						 0 /* kHz frequency offset */ ,
+						 "m_AM=6,l_AGC=5");
+#endif
+
+#ifdef RIG_MODEL_ELEKTOR304
+	/* Elektor 3/04 */
+	RigSpecialParameters(RIG_MODEL_ELEKTOR304, "", 0, "");
+#endif
+
+#ifdef RIG_MODEL_ELEKTOR507
+    /* Elektor 5/07 */
+    RigSpecialParameters(RIG_MODEL_ELEKTOR507, "",
+						-12 /* kHz frequency offset */ ,
+						"");
+#endif
+
+#ifdef RIG_MODEL_NRD535
+	/* JRC NRD 535 */
+	RigSpecialParameters(RIG_MODEL_NRD535,
+						 "l_CWPITCH=-5000,m_CW=12000,l_IF=-2000,l_AGC=3"
+						 /* AGC=slow */ ,
+						 3 /* kHz frequency offset */ ,
+						 "l_AGC=3");
+#endif
+
+#ifdef RIG_MODEL_RX320
+	/* TenTec RX320D */
+	RigSpecialParameters(RIG_MODEL_RX320, "l_AF=1,l_AGC=3,m_AM=6000", 0,
+						 "l_AGC=3");
+#endif
+
+#ifdef RIG_MODEL_RX340
+	/* TenTec RX340D */
+	RigSpecialParameters(RIG_MODEL_RX340,
+						 "l_AF=1,m_USB=16000,l_AGC=3,l_IF=2000",
+						 -12 /* kHz frequency offset */ ,
+						 "l_AGC=3");
+#endif
+
+	/* Load all available front-end remotes in hamlib library */
+	rig_load_all_backends();
+
+	/* Get all models which are available.
+	 * A call-back function is called to return the different rigs */
+	rig_list_foreach(PrintHamlibModelList, this);
+}
+
+CHamlib::~CHamlib()
+{
+	if (pRig != NULL)
+	{
+		/* close everything */
+		rig_close(pRig);
+		rig_cleanup(pRig);
+	}
+}
+
+void
+CHamlib::RigSpecialParameters(rig_model_t id, const string & sSet, int iFrOff,
+							  const string & sModSet)
+{
+	CapsHamlibModels[id].bIsSpecRig = TRUE;
+	SpecDRMRigs[id] = CSpecDRMRig(sSet, iFrOff, sModSet);
+}
+
+void
+CHamlib::GetRigList(map < rig_model_t, SDrRigCaps > &rigs)
+{
+	rigs = CapsHamlibModels;
+}
+
+void
+CHamlib::GetPortList(map < string, string > &ports)
+{
+	ports.clear();
+/* Port for use with 'NET rigctl' */
+	ports["localhost:4532"] = "localhost:4532";
+/* Config string for com-port selection is different in Windows and Linux */
+#ifdef _WIN32
+# ifdef HAVE_SETUPAPI
+	GUID guid = GUID_DEVINTERFACE_COMPORT;
+	HDEVINFO hDevInfoSet = SetupDiGetClassDevs(&guid, NULL, NULL,
+											   DIGCF_PRESENT |
+											   DIGCF_DEVICEINTERFACE);
+	if (hDevInfoSet != INVALID_HANDLE_VALUE)
+	{
+		SP_DEVINFO_DATA devInfo;
+		devInfo.cbSize = sizeof(SP_DEVINFO_DATA);
+		for (int i = 0; SetupDiEnumDeviceInfo(hDevInfoSet, i, &devInfo); i++)
+		{
+			HKEY hDeviceKey =
+				SetupDiOpenDevRegKey(hDevInfoSet, &devInfo, DICS_FLAG_GLOBAL,
+									 0, DIREG_DEV, KEY_QUERY_VALUE);
+			if (hDeviceKey)
+			{
+				char szPortName[256];
+				DWORD dwSize = sizeof(szPortName);
+				DWORD dwType = 0;
+				if ((RegQueryValueExA
+					 (hDeviceKey, "PortName", NULL, &dwType,
+					  reinterpret_cast < LPBYTE > (szPortName),
+					  &dwSize) == ERROR_SUCCESS) && (dwType == REG_SZ))
+				{
+					char szFriendlyName[256];
+					DWORD dwSize = sizeof(szFriendlyName);
+					DWORD dwType = 0;
+					if (SetupDiGetDeviceRegistryPropertyA
+						(hDevInfoSet, &devInfo, SPDRP_DEVICEDESC, &dwType,
+						 reinterpret_cast < PBYTE > (szFriendlyName), dwSize,
+						 &dwSize) && (dwType == REG_SZ))
+						ports[string(szFriendlyName) + " " + szPortName] = szPortName;
+					else
+						ports[szPortName] = szPortName;
+				}
+
+				RegCloseKey(hDeviceKey);
+			}
+		}
+
+		SetupDiDestroyDeviceInfoList(hDevInfoSet);
+	}
+# endif
+	if (ports.empty())
+	{
+		ports["COM1"] = "COM1";
+		ports["COM2"] = "COM2";
+		ports["COM3"] = "COM3 ";
+		ports["COM4"] = "COM4 ";
+		ports["COM5"] = "COM5 ";
+	}
+#elif defined(__APPLE__)
+    io_iterator_t serialPortIterator;
+    kern_return_t			kernResult;
+    CFMutableDictionaryRef	classesToMatch;
+
+    // Serial devices are instances of class IOSerialBSDClient
+    classesToMatch = IOServiceMatching(kIOSerialBSDServiceValue);
+    if (classesToMatch == NULL)
+    {
+        fprintf(stderr, "IOServiceMatching returned a NULL dictionary.\n");
+    }
+    else
+	{
+        CFDictionarySetValue(classesToMatch,
+                             CFSTR(kIOSerialBSDTypeKey),
+                             CFSTR(kIOSerialBSDRS232Type));
+
+	}
+    kernResult = IOServiceGetMatchingServices(kIOMasterPortDefault, classesToMatch, &serialPortIterator);
+    if (KERN_SUCCESS != kernResult)
+    {
+        fprintf(stderr, "IOServiceGetMatchingServices returned %d\n", kernResult);
+    }
+
+    io_object_t		modemService;
+
+    // Iterate across all modems found. In this example, we bail after finding the first modem.
+
+    while ((modemService = IOIteratorNext(serialPortIterator)))
+    {
+        CFStringRef	bsdPathAsCFString;
+
+		// Get the callout device's path (/dev/cu.xxxxx). The callout device should almost always be
+		// used: the dialin device (/dev/tty.xxxxx) would be used when monitoring a serial port for
+		// incoming calls, e.g. a fax listener.
+
+		bsdPathAsCFString = CFStringRef(IORegistryEntryCreateCFProperty(modemService,
+                                                            CFSTR(kIOCalloutDeviceKey),
+                                                            kCFAllocatorDefault,
+                                                            0));
+        if (bsdPathAsCFString)
+        {
+            Boolean result;
+			char bsdPath[256];
+
+            // Convert the path from a CFString to a C (NUL-terminated) string for use
+			// with the POSIX open() call.
+
+			result = CFStringGetCString(bsdPathAsCFString,
+                                        bsdPath,
+                                        sizeof(bsdPath),
+                                        kCFStringEncodingUTF8);
+            CFRelease(bsdPathAsCFString);
+
+            if (result)
+			{
+				// make the name a bit more friendly for the menu
+				string s,t=bsdPath;
+				size_t p = t.find('.');
+				if(p<string::npos)
+					s = t.substr(p+1);
+				else
+					s = t;
+				ports[s] = bsdPath;
+            }
+        }
+
+        // Release the io_service_t now that we are done with it.
+
+		(void) IOObjectRelease(modemService);
+    }
+#elif defined(__unix__)
+// TODO find better way to enumerate serial device
+	_BOOLEAN bOK = FALSE;
+// hal-find-by-capability no longer available on recent linux distro, give an shell error message.
+// now check if the command exist before executing
+//	FILE *p = popen("hal-find-by-capability --capability serial", "r");
+	FILE *p = popen("type hal-find-by-capability >/dev/null 2>&1 && hal-find-by-capability --capability serial", "r");
+	if (p != NULL)
+	{
+		while (!feof(p))
+		{
+			char buf[1024];
+			buf[0] = 0;
+			char* r = fgets(buf, sizeof(buf), p);
+			if (strlen(buf) > 0)
+			{
+				string s =
+// hal-get-property no longer available on recent linux distro, give an shell error message.
+// now check if the command exist before executing
+//					string("hal-get-property --key serial.device --udi ") +
+					string("type hal-get-property >/dev/null 2>&1 && hal-get-property --key serial.device --udi ") +
+					buf;
+				FILE *p2 = popen(s.c_str(), "r");
+				if (p2 != NULL)
+				{
+					buf[0] = 0;
+					r = fgets(buf, sizeof(buf), p2);
+					size_t n = strlen(buf);
+					if (n > 0)
+					{
+						if (buf[n - 1] == '\n')
+							buf[n - 1] = 0;
+						ports[buf] = buf;
+						bOK = TRUE;
+					}
+					pclose(p2);
+				}
+			}
+			(void)r;
+		}
+		pclose(p);
+	}
+	if (!bOK)
+	{
+# ifdef __linux__
+		ports["ttyS0"] = "/dev/ttyS0";
+		ports["ttyS1"] = "/dev/ttyS1";
+		ports["ttyUSB0"] = "/dev/ttyUSB0";
+# endif
+	}
+#endif
+}
+
+void
+CHamlib::SetComPort(const string & port)
+{
+	config["rig_pathname"] = port;
+	SetHamlibModelID(iHamlibModelID);
+}
+
+string CHamlib::GetComPort() const
+{
+	map < string, string >::const_iterator m = config.find("rig_pathname");
+	if (m == config.end())
+		return "";
+	return m->second;
+}
+
+int
+CHamlib::PrintHamlibModelList(const struct rig_caps *caps, void *data)
+{
+	/* Access data members of class through pointer ((CHamlib*) data) */
+	CHamlib & Hamlib = *((CHamlib *) data);
+
+	/* Store new model in class. Use only relevant information */
+	_BOOLEAN bIsSpec =
+		Hamlib.SpecDRMRigs.find(caps->rig_model) != Hamlib.SpecDRMRigs.end();
+
+	Hamlib.CapsHamlibModels[caps->rig_model] =
+		SDrRigCaps(caps->mfg_name, caps->model_name, caps->status, bIsSpec);
+
+	return 1;					/* !=0, we want them all! */
+}
+
+void
+CHamlib::LoadSettings(CSettings & s)
+{
+	rig_model_t model = s.Get("Hamlib", "hamlib-model", 0);
+
+	if (model != 0)
+	{
+		/* Hamlib configuration string */
+		string strHamlibConf = s.Get("Hamlib", "hamlib-config");
+
+		if (model == RIG_MODEL_G313)
+		{
+			string kwd, val;
+#ifdef __linux__
+			kwd = "if_path";
+            val = "/tmp/g313if";
+#endif
+#ifdef _WIN32
+			kwd = "wodeviceid";
+			val = "-2";
+#endif
+			if(kwd!="")
+			{
+				if (strHamlibConf=="")
+				{
+					strHamlibConf = kwd + "=" + val;
+				}
+				else
+				{
+					// don't overwrite a saved value
+					if(strHamlibConf.find_first_of(kwd)==string::npos)
+					{
+						strHamlibConf += "," + kwd + "=" + val;
+					}
+				}
+			}
+		}
+		if (strHamlibConf != "")
+		{
+			istringstream params(strHamlibConf);
+			while (!params.eof())
+			{
+				string name, value;
+				getline(params, name, '=');
+				getline(params, value, ',');
+				config[name] = value;
+			}
+		}
+
+		/* Enable DRM modified receiver flag */
+		bModRigSettings = s.Get("Hamlib", "enmodrig", FALSE);
+
+		strSettings = s.Get("Hamlib", "settings");
+		iFreqOffset = s.Get("Hamlib", "freqoffset", 0);
+
+		if (strSettings != "" || iFreqOffset != 0)
+		{
+			if (bModRigSettings)
+				RigSpecialParameters(model, "", iFreqOffset, strSettings);
+			else
+				RigSpecialParameters(model, strSettings, iFreqOffset, "");
+		}
+
+		/* Hamlib Model ID */
+		SetHamlibModelID(model);
+	}
+
+	s.Put("Hamlib", "hamlib-model", model);
+	s.Put("Hamlib", "hamlib-config", strHamlibConf);
+	s.Put("Hamlib", "settings", strSettings);
+	s.Put("Hamlib", "freqoffset", iFreqOffset);
+}
+
+void
+CHamlib::SaveSettings(CSettings & s)
+{
+	/* Hamlib Model ID */
+	s.Put("Hamlib", "hamlib-model", iHamlibModelID);
+
+	/* Hamlib configuration string */
+	stringstream ss;
+	string sep = "";
+	for (map < string, string >::iterator i = config.begin();
+		 i != config.end(); i++)
+	{
+		ss << sep << i->first << "=" << i->second;
+		sep = ",";
+	}
+
+	s.Put("Hamlib", "hamlib-config", ss.str());
+
+	/* Enable DRM modified receiver flag */
+	s.Put("Hamlib", "enmodrig", bModRigSettings);
+
+	s.Put("Hamlib", "settings", strSettings);
+
+	s.Put("Hamlib", "freqoffset", iFreqOffset);
+}
+
+_BOOLEAN
+CHamlib::SetFrequency(const int iFreqkHz)
+{
+	_BOOLEAN bSucceeded = FALSE;
+
+	/* Check if rig was opend properly */
+	if (pRig != NULL)
+	{
+		/* Set frequency (consider frequency offset and conversion
+		   from kHz to Hz by " * 1000 ") */
+		if (rig_set_freq(pRig, RIG_VFO_CURR, (iFreqkHz + iFreqOffset) * 1000)
+			== RIG_OK)
+		{
+			bSucceeded = TRUE;
+		}
+	}
+
+	return bSucceeded;
+}
+
+CHamlib::ESMeterState CHamlib::GetSMeter(_REAL & rCurSigStr)
+{
+	ESMeterState
+		eRetVal = SS_NOTVALID;
+	rCurSigStr = (_REAL) 0.0;
+
+	if ((pRig != NULL) && (bSMeterIsSupported == TRUE))
+	{
+		value_t
+			tVal;
+		const int
+			iHamlibRetVal =
+			rig_get_level(pRig, RIG_VFO_CURR, RIG_LEVEL_STRENGTH, &tVal);
+
+		if (!iHamlibRetVal)
+		{
+			rCurSigStr = (_REAL) tVal.i;
+			eRetVal = SS_VALID;
+		}
+
+		/* If a time-out happened, do not update s-meter anymore (disable it) */
+		if (iHamlibRetVal == -RIG_ETIMEOUT)
+		{
+			bSMeterIsSupported = FALSE;
+			eRetVal = SS_TIMEOUT;
+		}
+	}
+
+	return eRetVal;
+}
+
+void
+CHamlib::ConfigureRig(const string & strSet)
+{
+	/* Parse special settings */
+	istringstream params(strSet);
+	while (!params.eof())
+	{
+		string p, name, value;
+
+		getline(params, p, '_');
+		getline(params, name, '=');
+		getline(params, value, ',');
+		if (p == "" || p.length() != 1 || name == "" || value == "")
+		{
+			/* Malformatted config string */
+			rig_cleanup(pRig);
+			pRig = NULL;
+
+			throw CGenErr(string("Malformatted config string: ") + strSet);
+		}
+		switch (p[0])
+		{
+		case 'm':
+			modes[name] = value;
+			break;
+		case 'l':
+			levels[name] = value;
+			break;
+		case 'f':
+			functions[name] = value;
+			break;
+		case 'p':
+			parameters[name] = value;
+			break;
+		default:
+			cerr << "Rig unknown setting: " << p << "_" << name <<
+				"=" << value << endl;
+		}
+	}
+}
+
+void
+CHamlib::SetRigModes()
+{
+	for (map < string, string >::const_iterator i = modes.begin();
+		 i != modes.end(); i++)
+	{
+		rmode_t mode = rig_parse_mode(i->first.c_str());
+		if (mode != RIG_MODE_NONE)
+		{
+			int ret =
+				rig_set_mode(pRig, RIG_VFO_CURR, mode,
+							 atoi(i->second.c_str()));
+			if (ret != RIG_OK)
+				cerr << "Rig set mode failed: " << rigerror(ret) << endl;
+		}
+	}
+}
+
+void
+CHamlib::SetRigLevels()
+{
+	for (map < string, string >::const_iterator i = levels.begin();
+		 i != levels.end(); i++)
+	{
+		setting_t setting = rig_parse_level(i->first.c_str());
+		if (setting != RIG_LEVEL_NONE)
+		{
+			value_t val;
+			if (RIG_LEVEL_IS_FLOAT(setting))
+				val.f = atof(i->second.c_str());
+			else
+				val.i = atoi(i->second.c_str());
+
+			int ret = rig_set_level(pRig, RIG_VFO_CURR, setting, val);
+			if (ret != RIG_OK)
+				cerr << "Rig set level failed: " << rigerror(ret) << endl;
+		}
+	}
+}
+
+void
+CHamlib::SetRigFuncs()
+{
+	for (map < string, string >::const_iterator i = functions.begin();
+		 i != functions.end(); i++)
+	{
+		setting_t setting = rig_parse_func(i->first.c_str());
+		if (setting != RIG_FUNC_NONE)
+		{
+			int ret =
+				rig_set_func(pRig, RIG_VFO_CURR, setting,
+							 atoi(i->second.c_str()));
+			if (ret != RIG_OK)
+				cerr << "Rig set func failed: " << rigerror(ret) << endl;
+		}
+	}
+}
+
+void
+CHamlib::SetRigParams()
+{
+	for (map < string, string >::const_iterator i = parameters.begin();
+		 i != parameters.end(); i++)
+	{
+		setting_t setting = rig_parse_parm(i->first.c_str());
+		if (setting != RIG_PARM_NONE)
+		{
+			value_t val;
+			if (RIG_PARM_IS_FLOAT(setting))
+				val.f = atof(i->second.c_str());
+			else
+				val.i = atoi(i->second.c_str());
+			int ret = rig_set_parm(pRig, setting, val);
+			if (ret != RIG_OK)
+				cerr << "Rig set parm failed: " << rigerror(ret) << endl;
+		}
+	}
+}
+
+void
+CHamlib::SetRigConfig()
+{
+	for (map < string, string >::const_iterator i = config.begin();
+		 i != config.end(); i++)
+	{
+	    cerr << i->first << ":" << i->second << endl;
+		int ret =
+			rig_set_conf(pRig, rig_token_lookup(pRig, i->first.c_str()),
+						 i->second.c_str());
+		if (ret != RIG_OK)
+		{
+			rig_cleanup(pRig);
+			pRig = NULL;
+			throw CGenErr("Rig set conf failed.");
+		}
+	}
+}
+
+void
+CHamlib::SetEnableModRigSettings(const _BOOLEAN bNSM)
+{
+	if (bModRigSettings != bNSM)
+	{
+		/* Set internal parameter */
+		bModRigSettings = bNSM;
+
+		/* Hamlib must be re-initialized with new parameter */
+		SetHamlibModelID(iHamlibModelID);
+	}
+}
+
+void
+CHamlib::SetHamlibModelID(const rig_model_t model)
+{
+	int ret;
+
+	/* Set value for current selected model ID */
+	iHamlibModelID = model;
+
+	/* Init frequency offset */
+	iFreqOffset = 0;
+
+	try
+	{
+		/* If rig was already open, close it first */
+		if (pRig != NULL)
+		{
+			/* Close everything */
+			rig_close(pRig);
+			rig_cleanup(pRig);
+			pRig = NULL;
+		}
+
+		if (iHamlibModelID == 0)
+			throw CGenErr("No rig model ID selected.");
+
+		/* Check for special DRM front-end selection */
+		map < rig_model_t, CSpecDRMRig >::const_iterator s =
+			SpecDRMRigs.find(iHamlibModelID);
+		if (s != SpecDRMRigs.end())
+		{
+			/* Get correct parameter string */
+			if (bModRigSettings == TRUE)
+				strSettings = s->second.strDRMSetMod;
+			else
+			{
+				strSettings = s->second.strDRMSetNoMod;
+
+				/* Additionally, set frequency offset for this special rig */
+				iFreqOffset = s->second.iFreqOffs;
+			}
+			if (strSettings != "")
+			{
+				ConfigureRig(strSettings);
+			}
+		}
+
+		/* Init rig */
+		pRig = rig_init(iHamlibModelID);
+		if (pRig == NULL)
+			throw CGenErr("Initialization of hamlib failed.");
+
+		SetRigConfig();
+
+		/* Open rig */
+		ret = rig_open(pRig);
+		if (ret != RIG_OK)
+		{
+			/* Fail! */
+			rig_cleanup(pRig);
+			pRig = NULL;
+
+			throw CGenErr("Rig open failed.");
+		}
+
+		/* Ignore result, some rigs don't have support for this */
+		rig_set_powerstat(pRig, RIG_POWER_ON);
+
+		SetRigModes();
+		SetRigLevels();
+		SetRigFuncs();
+		SetRigParams();
+
+		/* Check if s-meter capabilities are available */
+		if (pRig != NULL)
+		{
+			/* Check if s-meter can be used. Disable GUI control if not */
+			if (rig_has_get_level(pRig, RIG_LEVEL_STRENGTH))
+				bSMeterIsSupported = TRUE;
+			else
+				bSMeterIsSupported = FALSE;
+		}
+	}
+
+	catch(CGenErr GenErr)
+	{
+		/* Print error message */
+		cerr << GenErr.strError << endl;
+
+		/* Disable s-meter */
+		bSMeterIsSupported = FALSE;
+	}
+}
diff --git a/src/util/Hamlib.h b/src/util/Hamlib.h
new file mode 100644
index 0000000..314d9c1
--- /dev/null
+++ b/src/util/Hamlib.h
@@ -0,0 +1,138 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *	Implements:
+ *	- Hamlib interface
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#ifndef __HAMLIB_H
+#define __HAMLIB_H
+
+#include "../GlobalDefinitions.h"
+#include "Settings.h"
+#include <hamlib/rig.h>
+
+class CHamlib
+{
+public:
+	enum ESMeterState {SS_VALID, SS_NOTVALID, SS_TIMEOUT};
+
+	CHamlib();
+	virtual ~CHamlib();
+
+	struct SDrRigCaps
+	{
+		SDrRigCaps() : strManufacturer(""), strModelName(""),
+			eRigStatus(RIG_STATUS_ALPHA),bIsSpecRig(FALSE) {}
+		SDrRigCaps(const string& strNMan, const string& strNModN, rig_status_e eNSt, _BOOLEAN bNsp) :
+			strManufacturer(strNMan), strModelName(strNModN), eRigStatus(eNSt),
+			bIsSpecRig(bNsp)
+			{}
+		SDrRigCaps(const SDrRigCaps& nSDRC) :
+			strManufacturer(nSDRC.strManufacturer),
+			strModelName(nSDRC.strModelName),
+			eRigStatus(nSDRC.eRigStatus), bIsSpecRig(nSDRC.bIsSpecRig) {}
+
+		inline SDrRigCaps& operator=(const SDrRigCaps& cNew)
+		{
+			strManufacturer = cNew.strManufacturer;
+			strModelName = cNew.strModelName;
+			eRigStatus = cNew.eRigStatus;
+			bIsSpecRig = cNew.bIsSpecRig;
+			return *this;
+		}
+
+		string			strManufacturer;
+		string			strModelName;
+		rig_status_e	eRigStatus;
+		_BOOLEAN		bIsSpecRig;
+	};
+
+	_BOOLEAN		SetFrequency(const int iFreqkHz);
+	ESMeterState	GetSMeter(_REAL& rCurSigStr);
+
+	/* backend selection */
+	void			GetRigList(map<rig_model_t,SDrRigCaps>&);
+	void			SetHamlibModelID(const rig_model_t model);
+	rig_model_t		GetHamlibModelID() const {return iHamlibModelID;}
+
+	/* com port selection */
+	void			GetPortList(map<string,string>&);
+	void			SetComPort(const string&);
+	string			GetComPort() const;
+
+	void			SetEnableModRigSettings(const _BOOLEAN bNSM);
+	_BOOLEAN		GetEnableModRigSettings() const {return bModRigSettings;}
+	string			GetInfo() const;
+
+	void			RigSpecialParameters(rig_model_t id, const string& sSet, int iFrOff, const string& sModSet);
+	void			ConfigureRig(const string & strSet);
+	void			LoadSettings(CSettings& s);
+	void			SaveSettings(CSettings& s);
+
+protected:
+	class CSpecDRMRig
+	{
+	public:
+		CSpecDRMRig() : strDRMSetMod(""), strDRMSetNoMod(""), iFreqOffs(0) {}
+		CSpecDRMRig(const CSpecDRMRig& nSpec) :
+			strDRMSetMod(nSpec.strDRMSetMod),
+			strDRMSetNoMod(nSpec.strDRMSetNoMod), iFreqOffs(nSpec.iFreqOffs) {}
+		CSpecDRMRig(string sSet, int iNFrOff, string sModSet) :
+			strDRMSetMod(sModSet), strDRMSetNoMod(sSet), iFreqOffs(iNFrOff) {}
+
+		string		strDRMSetMod; /* Special DRM settings (modified) */
+		string		strDRMSetNoMod; /* Special DRM settings (not mod.) */
+		int			iFreqOffs; /* Frequency offset */
+	};
+
+	map<rig_model_t,CSpecDRMRig>	SpecDRMRigs;
+	map<rig_model_t,SDrRigCaps>		CapsHamlibModels;
+
+	void EnableSMeter(const _BOOLEAN bStatus);
+
+	static int			PrintHamlibModelList(const struct rig_caps* caps, void* data);
+	void				SetRigModes();
+	void				SetRigLevels();
+	void				SetRigFuncs();
+	void				SetRigParams();
+	void				SetRigConfig();
+
+	RIG*				pRig;
+	_BOOLEAN			bSMeterIsSupported;
+	_BOOLEAN			bModRigSettings;
+	rig_model_t			iHamlibModelID;
+	string				strHamlibConf;
+	string				strSettings;
+	int					iFreqOffset;
+	map<string,string> modes;
+	map<string,string> levels;
+	map<string,string> functions;
+	map<string,string> parameters;
+	map<string,string> config;
+
+};
+
+#endif
diff --git a/src/util/LibraryLoader.h b/src/util/LibraryLoader.h
new file mode 100644
index 0000000..d1925fd
--- /dev/null
+++ b/src/util/LibraryLoader.h
@@ -0,0 +1,98 @@
+/******************************************************************************\
+ *
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	David Flamand
+ *
+ * Description:
+ *	Dynamic Link Library Loader
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#ifndef _LIBRARYLOADER_H_
+#define _LIBRARYLOADER_H_
+
+#ifdef _WIN32
+# include <windows.h>
+# define LOADLIB(a) (void*)LoadLibraryA(a)
+# define GETPROC(a, b) (void*)GetProcAddress((HMODULE)a, b)
+# define FREELIB(a) FreeLibrary((HMODULE)a)
+#else
+# include <dlfcn.h>
+# define LOADLIB(a) dlopen(a, RTLD_LOCAL | RTLD_NOW)
+# define GETPROC(a, b) dlsym(a, b)
+# define FREELIB(a) dlclose(a)
+#endif
+
+typedef struct LIBFUNC
+{
+	const char *pcFunctionName;
+	void **ppvFunctionAddress;
+	void *pvDummyFunctionAddress;
+} LIBFUNC;
+
+class CLibraryLoader
+{
+public:
+	static void* Load(const char** LibraryNames, const LIBFUNC* LibFuncs, bool (*LibCheckCallback)()=NULL)
+	{
+		void* hLib = NULL;
+		for (int l = 0; LibraryNames[l]; l++)
+		{
+			hLib = LOADLIB(LibraryNames[l]);
+			if (hLib != NULL)
+			{
+				int f;
+				for (f = 0; LibFuncs[f].pcFunctionName; f++)
+				{
+					void *pvFunc = GETPROC(hLib, LibFuncs[f].pcFunctionName);
+					if (!pvFunc)
+						break;
+					*LibFuncs[f].ppvFunctionAddress = pvFunc;
+				}
+				if (!LibFuncs[f].pcFunctionName)
+				{
+					if (LibCheckCallback==NULL || LibCheckCallback())
+						break;
+				}
+				FREELIB(hLib);
+				hLib = NULL;
+			}
+		}
+		if (hLib == NULL)
+		{
+			for (int f = 0; LibFuncs[f].pcFunctionName; f++)
+				*LibFuncs[f].ppvFunctionAddress = LibFuncs[f].pvDummyFunctionAddress;
+		}
+		return hLib;
+	}
+	static void Free(void** hLib, const LIBFUNC* LibFuncs)
+	{
+		for (int f = 0; LibFuncs[f].pcFunctionName; f++)
+			*LibFuncs[f].ppvFunctionAddress = LibFuncs[f].pvDummyFunctionAddress;
+		if (*hLib != NULL)
+		{
+			FREELIB(*hLib);
+			*hLib = NULL;
+		}
+	}
+};
+
+#endif
diff --git a/src/util/LogPrint.cpp b/src/util/LogPrint.cpp
new file mode 100644
index 0000000..08bc19d
--- /dev/null
+++ b/src/util/LogPrint.cpp
@@ -0,0 +1,187 @@
+/******************************************************************************\
+ *
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Oliver Haffenden
+ *
+ * Description:
+ * log-printing
+ * subsystem - essentially just a wrapper for printf.
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "LogPrint.h"
+
+#include <cstdarg>
+#include <cstdio>
+#include <cstring>
+
+void logStatus(char *format, ...) {
+	char s[256];
+    va_list args;
+    va_start(args, format);
+
+	vsprintf(s, format, args);
+	CLogPrinter::GetInstance()->LogStatus(s);
+} 
+
+void logWarning(char *format, ...) {
+	char s[256];
+    va_list args;
+    va_start(args, format);
+
+	vsprintf(s, format, args);
+	CLogPrinter::GetInstance()->LogWarning(s);
+} 
+
+void logError(char *format, ...) {
+	char s[256];
+    va_list args;
+    va_start(args, format);
+
+	vsprintf(s, format, args);
+	CLogPrinter::GetInstance()->LogWarning(s);
+} 
+
+CLogPrinter * CLogPrinter::mpFirstInstance = 0;
+CLogPrinter * CLogPrinter::mpNullPrinter = 0;
+
+CLogPrinter * CLogPrinter::GetInstance(void)
+{
+	if (mpFirstInstance == 0)
+		mpFirstInstance = GetNullInstance();
+
+	return mpFirstInstance;
+}
+
+void CLogPrinter::AddInstance(CChainingLogPrinter *pInstance)
+{
+	pInstance->SetNextInstance(GetInstance());
+	mpFirstInstance = pInstance;
+}
+
+CLogPrinter * CLogPrinter::GetNullInstance(void)
+{
+	if (!mpNullPrinter)
+		mpNullPrinter = new CNullLogPrinter;
+	return mpNullPrinter;
+}
+
+CChainingLogPrinter::CChainingLogPrinter()
+{
+	mpNextInstance = GetNullInstance(); 
+	AddInstance(this);
+}
+
+void CChainingLogPrinter::LogStatus(char *s)
+{
+	LogStatusSpecific(s);
+	mpNextInstance->LogStatus(s);
+}
+
+void CChainingLogPrinter::LogWarning(char *s)
+{
+	LogWarningSpecific(s);
+	mpNextInstance->LogWarning(s);
+}
+
+void CChainingLogPrinter::LogError(char *s)
+{
+	LogErrorSpecific(s);
+	mpNextInstance->LogWarning(s);
+}
+
+void CChainingLogPrinter::SetNextInstance(CLogPrinter *pInstance)
+{
+	mpNextInstance = pInstance;
+}
+
+
+CFileLogPrinter::CFileLogPrinter()
+{
+	mpLogFile = fopen("DebugLog.txt", "a");
+	fprintf(mpLogFile, "Start of logfile\n");
+	fflush(mpLogFile);
+}
+
+
+void CFileLogPrinter::LogStatusSpecific(char *s)
+{
+	fprintf(mpLogFile, "STATUS: %s\n",s);
+	fflush(mpLogFile);
+}
+
+void CFileLogPrinter::LogWarningSpecific(char *s)
+{
+	fprintf(mpLogFile, "WARNING: %s\n",s);
+	fflush(mpLogFile);
+}
+
+void CFileLogPrinter::LogErrorSpecific(char *s)
+{
+	fprintf(mpLogFile, "ERROR: %s\n",s);
+	fflush(mpLogFile);
+}
+
+CFileLogPrinter *CFileLogPrinter::mpInstance = 0;
+void CFileLogPrinter::Instantiate()
+{
+	if (!mpInstance)
+		mpInstance = new CFileLogPrinter;
+}
+
+void CPrintfLogPrinter::LogStatusSpecific(char *s)
+{
+	fprintf(stderr, "STATUS: %s\n",s);
+	fflush(stderr);
+}
+
+void CPrintfLogPrinter::LogWarningSpecific(char *s)
+{
+	fprintf(stderr, "WARNING: %s\n",s);
+	fflush(stderr);
+}
+
+void CPrintfLogPrinter::LogErrorSpecific(char *s)
+{
+	fprintf(stderr, "ERROR: %s\n",s);
+	fflush(stderr);
+}
+
+void CNullLogPrinter::LogStatus(char *)
+{
+}
+
+void CNullLogPrinter::LogWarning(char *)
+{
+}
+
+void CNullLogPrinter::LogError(char *)
+{
+}
+
+CPrintfLogPrinter *CPrintfLogPrinter::mpInstance = 0;
+void CPrintfLogPrinter::Instantiate()
+{
+	if (!mpInstance)
+		mpInstance = new CPrintfLogPrinter;
+}
+
+CPrintfLogPrinter::CPrintfLogPrinter() {}
diff --git a/src/util/LogPrint.h b/src/util/LogPrint.h
new file mode 100644
index 0000000..8c583d6
--- /dev/null
+++ b/src/util/LogPrint.h
@@ -0,0 +1,124 @@
+/******************************************************************************\
+ *
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Oliver Haffenden
+ *
+ * Description:
+//This is a temporary implementation of the new log-printing
+//subsystem - essentially just a wrapper for printf.
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#ifndef LOG_PRINT_H_INCLUDED
+#define LOG_PRINT_H_INCLUDED
+
+#include <cstdlib>
+#include <cstdio>
+
+void logStatus(char *format, ...);
+void logWarning(char *format, ...);
+void logError(char *format, ...);
+
+class CChainingLogPrinter;
+
+class CLogPrinter
+{
+public:
+	CLogPrinter() {}
+	virtual ~CLogPrinter() {}
+
+	virtual void LogStatus(char *s) = 0;
+	virtual void LogWarning(char *s) = 0;
+	virtual void LogError(char *s) = 0;
+
+
+	static CLogPrinter *GetInstance(void);
+
+protected:
+	static void AddInstance(CChainingLogPrinter *pInstance);
+	static CLogPrinter * GetNullInstance(void);
+
+private:
+	static CLogPrinter *mpFirstInstance;
+	static CLogPrinter *mpNullPrinter;
+};
+
+
+class CChainingLogPrinter : public CLogPrinter
+{
+	friend class CLogPrinter;
+public:
+	virtual void LogStatus(char *s);
+	virtual void LogWarning(char *s);
+	virtual void LogError(char *s);
+
+	virtual void LogStatusSpecific(char *s) = 0;
+	virtual void LogWarningSpecific(char *s) = 0;
+	virtual void LogErrorSpecific(char *s) = 0;
+
+protected:
+	void SetNextInstance(CLogPrinter *pInstance);
+	CChainingLogPrinter();
+
+private:
+	CLogPrinter *mpNextInstance;
+};
+
+class CFileLogPrinter : public CChainingLogPrinter
+{
+public:
+	virtual void LogStatusSpecific(char *s);
+	virtual void LogWarningSpecific(char *s);
+	virtual void LogErrorSpecific(char *s);
+
+	static void Instantiate();
+protected:
+	CFileLogPrinter();
+private:
+	FILE *mpLogFile;
+	static CFileLogPrinter *mpInstance;
+};
+
+class CPrintfLogPrinter : public CChainingLogPrinter
+{
+public:
+	virtual void LogStatusSpecific(char *string);
+	virtual void LogWarningSpecific(char *string);
+	virtual void LogErrorSpecific(char *string);
+
+	static void Instantiate();
+protected:
+	CPrintfLogPrinter();
+
+private:
+	static CPrintfLogPrinter *mpInstance;
+};
+
+class CNullLogPrinter : public CLogPrinter
+{
+public:
+	virtual void LogStatus(char *string);
+	virtual void LogWarning(char *string);
+	virtual void LogError(char *string);
+};
+
+
+#endif
diff --git a/src/util/Modul.h b/src/util/Modul.h
new file mode 100644
index 0000000..c46e9ce
--- /dev/null
+++ b/src/util/Modul.h
@@ -0,0 +1,1303 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *	High level class for all modules. The common functionality for reading
+ *	and writing the transfer-buffers are implemented here.
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#if !defined(AFX_MODUL_H__41E39CD3_2AEC_400E_907B_148C0EC17A43__INCLUDED_)
+#define AFX_MODUL_H__41E39CD3_2AEC_400E_907B_148C0EC17A43__INCLUDED_
+
+#include "Buffer.h"
+#include "Vector.h"
+#include "../Parameter.h"
+#include <iostream>
+
+
+/* Classes ********************************************************************/
+/* CModul ------------------------------------------------------------------- */
+template<class TInput, class TOutput>
+class CModul
+{
+public:
+	CModul();
+	virtual ~CModul() {}
+
+	virtual void Init(CParameter& Parameter);
+	virtual void Init(CParameter& Parameter, CBuffer<TOutput>& OutputBuffer);
+
+protected:
+	CVectorEx<TInput>*	pvecInputData;
+	CVectorEx<TOutput>*	pvecOutputData;
+
+	/* Max block-size are used to determine the size of the required buffer */
+	int					iMaxOutputBlockSize;
+	/* Actual read (or written) size of the data */
+	int					iInputBlockSize;
+	int					iOutputBlockSize;
+
+	void				Lock() {Mutex.Lock();}
+	void				Unlock() {Mutex.Unlock();}
+
+	void				InitThreadSave(CParameter& Parameter);
+	virtual void		InitInternal(CParameter& Parameter) = 0;
+	void				ProcessDataThreadSave(CParameter& Parameter);
+	virtual void		ProcessDataInternal(CParameter& Parameter) = 0;
+
+private:
+	CMutex				Mutex;
+};
+
+
+/* CTransmitterModul -------------------------------------------------------- */
+template<class TInput, class TOutput>
+class CTransmitterModul : public CModul<TInput, TOutput>
+{
+public:
+	CTransmitterModul();
+	virtual ~CTransmitterModul() {}
+
+	virtual void		Init(CParameter& Parameter);
+	virtual void		Init(CParameter& Parameter,
+							 CBuffer<TOutput>& OutputBuffer);
+	virtual void		ReadData(CParameter& Parameter,
+								 CBuffer<TOutput>& OutputBuffer);
+	virtual _BOOLEAN	ProcessData(CParameter& Parameter,
+									CBuffer<TInput>& InputBuffer,
+									CBuffer<TOutput>& OutputBuffer);
+	virtual void		ProcessData(CParameter& Parameter,
+									CBuffer<TInput>& InputBuffer,
+									CBuffer<TInput>& InputBuffer2,
+									CBuffer<TInput>& InputBuffer3,
+									CBuffer<TOutput>& OutputBuffer);
+	virtual _BOOLEAN	WriteData(CParameter& Parameter,
+								  CBuffer<TInput>& InputBuffer);
+
+protected:
+	/* Additional buffers if the derived class has multiple input streams */
+	CVectorEx<TInput>*	pvecInputData2;
+	CVectorEx<TInput>*	pvecInputData3;
+
+	/* Actual read (or written) size of the data */
+	int					iInputBlockSize2;
+	int					iInputBlockSize3;
+};
+
+
+/* CReceiverModul ----------------------------------------------------------- */
+template<class TInput, class TOutput>
+class CReceiverModul : public CModul<TInput, TOutput>
+{
+public:
+	CReceiverModul();
+	virtual ~CReceiverModul() {}
+
+	void				SetInitFlag() {bDoInit = TRUE;}
+	virtual void		Init(CParameter& Parameter);
+	virtual void		Init(CParameter& Parameter,
+							 CBuffer<TOutput>& OutputBuffer);
+	virtual void		Init(CParameter& Parameter,
+							 CBuffer<TOutput>& OutputBuffer,
+							 CBuffer<TOutput>& OutputBuffer2);
+	virtual void		Init(CParameter& Parameter,
+							 CBuffer<TOutput>& OutputBuffer,
+							 CBuffer<TOutput>& OutputBuffer2,
+							 CBuffer<TOutput>& OutputBuffer3);
+	virtual void		Init(CParameter& Parameter,
+							 CBuffer<TOutput>& OutputBuffer,
+							 CBuffer<TOutput>& OutputBuffer2,
+							 vector< CSingleBuffer<TOutput> >& vecOutputBuffer);
+	virtual void		Init(CParameter& Parameter,
+							 vector< CSingleBuffer<TOutput> >& vecOutputBuffer);
+	virtual void		ReadData(CParameter& Parameter,
+								 CBuffer<TOutput>& OutputBuffer);
+	virtual _BOOLEAN	ProcessData(CParameter& Parameter,
+									CBuffer<TInput>& InputBuffer,
+									CBuffer<TOutput>& OutputBuffer);
+	virtual _BOOLEAN	ProcessData(CParameter& Parameter,
+									CBuffer<TInput>& InputBuffer,
+									CBuffer<TOutput>& OutputBuffer,
+									CBuffer<TOutput>& OutputBuffer2);
+	virtual _BOOLEAN	ProcessData(CParameter& Parameter,
+									CBuffer<TInput>& InputBuffer,
+									CBuffer<TOutput>& OutputBuffer,
+									CBuffer<TOutput>& OutputBuffer2,
+									CBuffer<TOutput>& OutputBuffer3);
+	virtual _BOOLEAN	ProcessData(CParameter& Parameter,
+									CBuffer<TInput>& InputBuffer,
+									CBuffer<TOutput>& OutputBuffer,
+									CBuffer<TOutput>& OutputBuffer2,
+									vector< CSingleBuffer<TOutput> >& vecOutputBuffer);
+	virtual _BOOLEAN	ProcessData(CParameter& Parameter,
+									CBuffer<TInput>& InputBuffer,
+									vector< CSingleBuffer<TOutput> >& vecOutputBuffer);
+	virtual _BOOLEAN	WriteData(CParameter& Parameter,
+								  CBuffer<TInput>& InputBuffer);
+
+protected:
+	void SetBufReset1() {bResetBuf = TRUE;}
+	void SetBufReset2() {bResetBuf2 = TRUE;}
+	void SetBufReset3() {bResetBuf3 = TRUE;}
+	void SetBufResetN() {for(size_t i=0; i<vecbResetBuf.size(); i++)
+     vecbResetBuf[i] = TRUE;}
+
+	/* Additional buffers if the derived class has multiple output streams */
+	CVectorEx<TOutput>*	pvecOutputData2;
+	CVectorEx<TOutput>*	pvecOutputData3;
+	vector<CVectorEx<TOutput>*>	vecpvecOutputData;
+
+	/* Max block-size are used to determine the size of the required buffer */
+	int					iMaxOutputBlockSize2;
+	int					iMaxOutputBlockSize3;
+	vector<int>			veciMaxOutputBlockSize;
+	/* Actual read (or written) size of the data */
+	int					iOutputBlockSize2;
+	int					iOutputBlockSize3;
+	vector<int>			veciOutputBlockSize;
+
+private:
+	/* Init flag */
+	_BOOLEAN			bDoInit;
+
+	/* Reset flags for output cyclic-buffers */
+	_BOOLEAN			bResetBuf;
+	_BOOLEAN			bResetBuf2;
+	_BOOLEAN			bResetBuf3;
+	vector<_BOOLEAN>	vecbResetBuf;
+};
+
+
+/* CSimulationModul --------------------------------------------------------- */
+template<class TInput, class TOutput, class TInOut2>
+class CSimulationModul : public CModul<TInput, TOutput>
+{
+public:
+	CSimulationModul();
+	virtual ~CSimulationModul() {}
+
+	virtual void		Init(CParameter& Parameter);
+	virtual void		Init(CParameter& Parameter,
+							 CBuffer<TOutput>& OutputBuffer);
+	virtual void		Init(CParameter& Parameter,
+							 CBuffer<TOutput>& OutputBuffer,
+							 CBuffer<TInOut2>& OutputBuffer2);
+	virtual void		TransferData(CParameter& Parameter,
+									 CBuffer<TInput>& InputBuffer,
+									 CBuffer<TOutput>& OutputBuffer);
+
+
+// TEST "ProcessDataIn" "ProcessDataOut"
+	virtual _BOOLEAN	ProcessDataIn(CParameter& Parameter,
+									  CBuffer<TInput>& InputBuffer,
+									  CBuffer<TInOut2>& InputBuffer2,
+									  CBuffer<TOutput>& OutputBuffer);
+	virtual _BOOLEAN	ProcessDataOut(CParameter& Parameter,
+									   CBuffer<TInput>& InputBuffer,
+									   CBuffer<TOutput>& OutputBuffer,
+									   CBuffer<TInOut2>& OutputBuffer2);
+
+
+protected:
+	/* Additional buffers if the derived class has multiple output streams */
+	CVectorEx<TInOut2>*	pvecOutputData2;
+
+	/* Max block-size are used to determine the size of the requiered buffer */
+	int					iMaxOutputBlockSize2;
+	/* Actual read (or written) size of the data */
+	int					iOutputBlockSize2;
+
+	/* Additional buffers if the derived class has multiple input streams */
+	CVectorEx<TInOut2>*	pvecInputData2;
+
+	/* Actual read (or written) size of the data */
+	int					iInputBlockSize2;
+};
+
+
+/* Implementation *************************************************************/
+/******************************************************************************\
+* CModul                                                                       *
+\******************************************************************************/
+template<class TInput, class TOutput>
+CModul<TInput, TOutput>::CModul()
+{
+	/* Initialize everything with zeros */
+	iMaxOutputBlockSize = 0;
+	iInputBlockSize = 0;
+	iOutputBlockSize = 0;
+	pvecInputData = NULL;
+	pvecOutputData = NULL;
+}
+
+template<class TInput, class TOutput>
+void CModul<TInput, TOutput>::ProcessDataThreadSave(CParameter& Parameter)
+{
+	/* Get a lock for the resources */
+	Lock();
+
+	/* Call processing routine of derived modul */
+	ProcessDataInternal(Parameter);
+
+	/* Unlock resources */
+	Unlock();
+}
+
+template<class TInput, class TOutput>
+void CModul<TInput, TOutput>::InitThreadSave(CParameter& Parameter)
+{
+	/* Get a lock for the resources */
+	Lock();
+
+	try
+	{
+		/* Call init of derived modul */
+		InitInternal(Parameter);
+
+		/* Unlock resources */
+		Unlock();
+	}
+
+	catch (CGenErr)
+	{
+		/* Unlock resources */
+		Unlock();
+
+		/* Throws the same error again which was send by the function */
+		throw;
+	}
+}
+
+template<class TInput, class TOutput>
+void CModul<TInput, TOutput>::Init(CParameter& Parameter)
+{
+	/* Init some internal variables */
+	iInputBlockSize = 0;
+
+	/* Call init of derived modul */
+	InitThreadSave(Parameter);
+}
+
+template<class TInput, class TOutput>
+void CModul<TInput, TOutput>::Init(CParameter& Parameter,
+								   CBuffer<TOutput>& OutputBuffer)
+{
+	/* Init some internal variables */
+	iMaxOutputBlockSize = 0;
+	iInputBlockSize = 0;
+	iOutputBlockSize = 0;
+
+	/* Call init of derived modul */
+	InitThreadSave(Parameter);
+
+	/* Init output transfer buffer */
+	if (iMaxOutputBlockSize != 0)
+		OutputBuffer.Init(iMaxOutputBlockSize);
+	else
+	{
+		if (iOutputBlockSize != 0)
+			OutputBuffer.Init(iOutputBlockSize);
+	}
+}
+
+
+/******************************************************************************\
+* Transmitter modul (CTransmitterModul)                                        *
+\******************************************************************************/
+template<class TInput, class TOutput>
+CTransmitterModul<TInput, TOutput>::CTransmitterModul()
+{
+	/* Initialize all member variables with zeros */
+	iInputBlockSize2 = 0;
+	iInputBlockSize3 = 0;
+	pvecInputData2 = NULL;
+	pvecInputData3 = NULL;
+}
+
+template<class TInput, class TOutput>
+void CTransmitterModul<TInput, TOutput>::Init(CParameter& Parameter)
+{
+	/* Init some internal variables */
+	iInputBlockSize2 = 0;
+	iInputBlockSize3 = 0;
+
+	/* Init base-class */
+	CModul<TInput, TOutput>::Init(Parameter);
+}
+
+template<class TInput, class TOutput>
+void CTransmitterModul<TInput, TOutput>::Init(CParameter& Parameter,
+											  CBuffer<TOutput>& OutputBuffer)
+{
+	/* Init some internal variables */
+	iInputBlockSize2 = 0;
+	iInputBlockSize3 = 0;
+
+	/* Init base-class */
+	CModul<TInput, TOutput>::Init(Parameter, OutputBuffer);
+}
+
+template<class TInput, class TOutput>
+_BOOLEAN CTransmitterModul<TInput, TOutput>::
+	ProcessData(CParameter& Parameter, CBuffer<TInput>& InputBuffer,
+				CBuffer<TOutput>& OutputBuffer)
+{
+	/* OUTPUT-DRIVEN modul implementation in the transmitter ---------------- */
+	/* Look in output buffer if data is requested */
+	if (OutputBuffer.GetRequestFlag() == TRUE)
+	{
+		/* Check, if enough input data is available */
+		if (InputBuffer.GetFillLevel() < this->iInputBlockSize)
+		{
+			/* Set request flag */
+			InputBuffer.SetRequestFlag(TRUE);
+
+			return FALSE;
+		}
+
+		/* Get vector from transfer-buffer */
+		this->pvecInputData = InputBuffer.Get(this->iInputBlockSize);
+
+		/* Query vector from output transfer-buffer for writing */
+		this->pvecOutputData = OutputBuffer.QueryWriteBuffer();
+
+		/* Copy extended data from vectors */
+		(*(this->pvecOutputData)).
+			SetExData((*(this->pvecInputData)).GetExData());
+
+		/* Call the underlying processing-routine */
+		this->ProcessDataInternal(Parameter);
+
+		/* Write processed data from internal memory in transfer-buffer */
+		OutputBuffer.Put(this->iOutputBlockSize);
+
+		/* Data was provided, clear data request */
+		OutputBuffer.SetRequestFlag(FALSE);
+	}
+
+	return TRUE;
+}
+
+template<class TInput, class TOutput>
+void CTransmitterModul<TInput, TOutput>::
+	ProcessData(CParameter& Parameter, CBuffer<TInput>& InputBuffer,
+				CBuffer<TInput>& InputBuffer2,
+				CBuffer<TInput>& InputBuffer3,
+				CBuffer<TOutput>& OutputBuffer)
+{
+	/* OUTPUT-DRIVEN modul implementation in the transmitter ---------------- */
+	/* Look in output buffer if data is requested */
+	if (OutputBuffer.GetRequestFlag() == TRUE)
+	{
+		/* Check, if enough input data is available from all sources */
+		if (InputBuffer.GetFillLevel() < this->iInputBlockSize)
+		{
+			/* Set request flag */
+			InputBuffer.SetRequestFlag(TRUE);
+
+			return;
+		}
+		if (InputBuffer2.GetFillLevel() < iInputBlockSize2)
+		{
+			/* Set request flag */
+			InputBuffer2.SetRequestFlag(TRUE);
+
+			return;
+		}
+		if (InputBuffer3.GetFillLevel() < iInputBlockSize3)
+		{
+			/* Set request flag */
+			InputBuffer3.SetRequestFlag(TRUE);
+
+			return;
+		}
+
+		/* Get vectors from transfer-buffers */
+		this->pvecInputData = InputBuffer.Get(this->iInputBlockSize);
+		pvecInputData2 = InputBuffer2.Get(iInputBlockSize2);
+		pvecInputData3 = InputBuffer3.Get(iInputBlockSize3);
+
+		/* Query vector from output transfer-buffer for writing */
+		this->pvecOutputData = OutputBuffer.QueryWriteBuffer();
+
+		/* Call the underlying processing-routine */
+		this->ProcessDataInternal(Parameter);
+
+		/* Write processed data from internal memory in transfer-buffer */
+		OutputBuffer.Put(this->iOutputBlockSize);
+
+		/* Data was provided, clear data request */
+		OutputBuffer.SetRequestFlag(FALSE);
+	}
+}
+
+template<class TInput, class TOutput>
+void CTransmitterModul<TInput, TOutput>::
+	ReadData(CParameter& Parameter, CBuffer<TOutput>& OutputBuffer)
+{
+	/* OUTPUT-DRIVEN modul implementation in the transmitter ---------------- */
+	/* Look in output buffer if data is requested */
+	if (OutputBuffer.GetRequestFlag() == TRUE)
+	{
+		/* Read data and write it in the transfer-buffer.
+		   Query vector from output transfer-buffer for writing */
+		this->pvecOutputData = OutputBuffer.QueryWriteBuffer();
+
+		/* Call the underlying processing-routine */
+		this->ProcessDataInternal(Parameter);
+
+		/* Write processed data from internal memory in transfer-buffer */
+		OutputBuffer.Put(this->iOutputBlockSize);
+
+		/* Data was provided, clear data request */
+		OutputBuffer.SetRequestFlag(FALSE);
+	}
+}
+
+template<class TInput, class TOutput>
+_BOOLEAN CTransmitterModul<TInput, TOutput>::
+	WriteData(CParameter& Parameter, CBuffer<TInput>& InputBuffer)
+{
+	/* OUTPUT-DRIVEN modul implementation in the transmitter */
+	/* Check, if enough input data is available */
+	if (InputBuffer.GetFillLevel() < this->iInputBlockSize)
+	{
+		/* Set request flag */
+		InputBuffer.SetRequestFlag(TRUE);
+
+		return FALSE;
+	}
+
+	/* Get vector from transfer-buffer */
+	this->pvecInputData = InputBuffer.Get(this->iInputBlockSize);
+
+	/* Call the underlying processing-routine */
+	this->ProcessDataInternal(Parameter);
+
+	return TRUE;
+}
+
+
+/******************************************************************************\
+* Receiver modul (CReceiverModul)                                              *
+\******************************************************************************/
+template<class TInput, class TOutput>
+CReceiverModul<TInput, TOutput>::CReceiverModul()
+{
+	/* Initialize all member variables with zeros */
+	iMaxOutputBlockSize2 = 0;
+	iMaxOutputBlockSize3 = 0;
+	iOutputBlockSize2 = 0;
+	iOutputBlockSize3 = 0;
+	pvecOutputData2 = NULL;
+	pvecOutputData3 = NULL;
+	bResetBuf = FALSE;
+	bResetBuf2 = FALSE;
+	bResetBuf3 = FALSE;
+	bDoInit = FALSE;
+}
+
+template<class TInput, class TOutput> void
+CReceiverModul<TInput, TOutput>::Init(CParameter& Parameter)
+{
+	/* Init base-class */
+	CModul<TInput, TOutput>::Init(Parameter);
+}
+
+template<class TInput, class TOutput> void
+CReceiverModul<TInput, TOutput>::Init(CParameter& Parameter,
+									  CBuffer<TOutput>& OutputBuffer)
+{
+	/* Init flag */
+	bResetBuf = FALSE;
+
+	/* Init base-class */
+	CModul<TInput, TOutput>::Init(Parameter, OutputBuffer);
+}
+
+template<class TInput, class TOutput> void
+CReceiverModul<TInput, TOutput>::Init(CParameter& Parameter,
+									  CBuffer<TOutput>& OutputBuffer,
+									  CBuffer<TOutput>& OutputBuffer2)
+{
+	/* Init some internal variables */
+	iMaxOutputBlockSize2 = 0;
+	iOutputBlockSize2 = 0;
+	bResetBuf = FALSE;
+	bResetBuf2 = FALSE;
+
+	/* Init base-class */
+	CModul<TInput, TOutput>::Init(Parameter, OutputBuffer);
+
+	/* Init output transfer buffers */
+	if (iMaxOutputBlockSize2 != 0)
+		OutputBuffer2.Init(iMaxOutputBlockSize2);
+	else
+	{
+		if (iOutputBlockSize2 != 0)
+			OutputBuffer2.Init(iOutputBlockSize2);
+	}
+}
+
+template<class TInput, class TOutput> void
+CReceiverModul<TInput, TOutput>::Init(CParameter& Parameter,
+									  CBuffer<TOutput>& OutputBuffer,
+									  CBuffer<TOutput>& OutputBuffer2,
+									  CBuffer<TOutput>& OutputBuffer3)
+{
+	/* Init some internal variables */
+	iMaxOutputBlockSize2 = 0;
+	iMaxOutputBlockSize3 = 0;
+	iOutputBlockSize2 = 0;
+	iOutputBlockSize3 = 0;
+	bResetBuf = FALSE;
+	bResetBuf2 = FALSE;
+	bResetBuf3 = FALSE;
+
+	/* Init base-class */
+	CModul<TInput, TOutput>::Init(Parameter, OutputBuffer);
+
+	/* Init output transfer buffers */
+	if (iMaxOutputBlockSize2 != 0)
+		OutputBuffer2.Init(iMaxOutputBlockSize2);
+	else
+	{
+		if (iOutputBlockSize2 != 0)
+			OutputBuffer2.Init(iOutputBlockSize2);
+	}
+
+	if (iMaxOutputBlockSize3 != 0)
+		OutputBuffer3.Init(iMaxOutputBlockSize3);
+	else
+	{
+		if (iOutputBlockSize3 != 0)
+			OutputBuffer3.Init(iOutputBlockSize3);
+	}
+}
+
+template<class TInput, class TOutput> void
+CReceiverModul<TInput, TOutput>::Init(CParameter& Parameter,
+									  CBuffer<TOutput>& OutputBuffer,
+									  CBuffer<TOutput>& OutputBuffer2,
+									  vector< CSingleBuffer<TOutput> >& vecOutputBuffer)
+{
+	size_t i;
+	/* Init some internal variables */
+	iMaxOutputBlockSize2 = 0;
+	iMaxOutputBlockSize3 = 0;
+	veciMaxOutputBlockSize.resize(vecOutputBuffer.size());
+    for(i=0; i<veciMaxOutputBlockSize.size(); i++)
+		veciMaxOutputBlockSize[i]=0;
+	iOutputBlockSize2 = 0;
+	iOutputBlockSize3 = 0;
+	veciOutputBlockSize.resize(vecOutputBuffer.size());
+    for(i=0; i<veciOutputBlockSize.size(); i++)
+		veciOutputBlockSize[i]=0;
+	bResetBuf = FALSE;
+	bResetBuf2 = FALSE;
+	bResetBuf3 = FALSE;
+	vecbResetBuf.resize(vecOutputBuffer.size());
+    for(i=0; i<vecbResetBuf.size(); i++)
+		vecbResetBuf[i]=FALSE;
+
+	/* Init base-class */
+	CModul<TInput, TOutput>::Init(Parameter, OutputBuffer);
+
+	/* Init output transfer buffers */
+	if (iMaxOutputBlockSize2 != 0)
+		OutputBuffer2.Init(iMaxOutputBlockSize2);
+	else
+	{
+		if (iOutputBlockSize2 != 0)
+			OutputBuffer2.Init(iOutputBlockSize2);
+	}
+
+    for(i=0; i<veciMaxOutputBlockSize.size(); i++)
+    {
+		if (veciMaxOutputBlockSize[i] != 0)
+			vecOutputBuffer[i].Init(veciMaxOutputBlockSize[i]);
+		else
+		{
+			if (veciOutputBlockSize[i] != 0)
+				vecOutputBuffer[i].Init(veciOutputBlockSize[i]);
+		}
+    }
+}
+
+template<class TInput, class TOutput> void
+CReceiverModul<TInput, TOutput>::Init(CParameter& Parameter,
+					vector< CSingleBuffer<TOutput> >& vecOutputBuffer)
+{
+	size_t i;
+	/* Init some internal variables */
+	veciMaxOutputBlockSize.resize(vecOutputBuffer.size());
+    for(i=0; i<veciMaxOutputBlockSize.size(); i++)
+		veciMaxOutputBlockSize[i]=0;
+	veciOutputBlockSize.resize(vecOutputBuffer.size());
+    for(i=0; i<veciOutputBlockSize.size(); i++)
+		veciOutputBlockSize[i]=0;
+	vecbResetBuf.resize(vecOutputBuffer.size());
+    for(i=0; i<vecbResetBuf.size(); i++)
+		vecbResetBuf[i]=FALSE;
+
+	/* Init base-class */
+	CModul<TInput, TOutput>::Init(Parameter);
+
+	/* Init output transfer buffers */
+    for(i=0; i<veciMaxOutputBlockSize.size(); i++)
+    {
+		if (veciMaxOutputBlockSize[i] != 0)
+			vecOutputBuffer[i].Init(veciMaxOutputBlockSize[i]);
+		else
+		{
+			if (veciOutputBlockSize[i] != 0)
+				vecOutputBuffer[i].Init(veciOutputBlockSize[i]);
+		}
+    }
+}
+
+template<class TInput, class TOutput>
+_BOOLEAN CReceiverModul<TInput, TOutput>::
+	ProcessData(CParameter& Parameter, CBuffer<TInput>& InputBuffer,
+				CBuffer<TOutput>& OutputBuffer)
+{
+	/* Check initialization flag. The initialization must be done OUTSIDE
+	   the processing routine. This is ensured by doing it here, where we
+	   have control of calling the processing routine. Therefore we
+	   introduced the flag */
+	if (bDoInit == TRUE)
+	{
+		/* Call init routine */
+		Init(Parameter, OutputBuffer);
+
+		/* Reset init flag */
+		bDoInit = FALSE;
+	}
+
+	/* Special case if input block size is zero */
+	if (this->iInputBlockSize == 0)
+	{
+		InputBuffer.Clear();
+
+		return FALSE;
+	}
+
+	/* INPUT-DRIVEN modul implementation in the receiver -------------------- */
+	/* This flag shows, if enough data was in the input buffer for processing */
+	_BOOLEAN bEnoughData = FALSE;
+
+	/* Check if enough data is available in the input buffer for processing */
+	if (InputBuffer.GetFillLevel() >= this->iInputBlockSize)
+	{
+		bEnoughData = TRUE;
+
+		/* Get vector from transfer-buffer */
+		this->pvecInputData = InputBuffer.Get(this->iInputBlockSize);
+
+		/* Query vector from output transfer-buffer for writing */
+		this->pvecOutputData = OutputBuffer.QueryWriteBuffer();
+
+		/* Copy extended data from vectors */
+		(*(this->pvecOutputData)).
+			SetExData((*(this->pvecInputData)).GetExData());
+
+		/* Call the underlying processing-routine */
+		this->ProcessDataThreadSave(Parameter);
+
+		/* Reset output-buffers if flag was set by processing routine */
+		if (bResetBuf == TRUE)
+		{
+			/* Reset flag and clear buffer */
+			bResetBuf = FALSE;
+			OutputBuffer.Clear();
+		}
+		else
+		{
+			/* Write processed data from internal memory in transfer-buffer */
+			OutputBuffer.Put(this->iOutputBlockSize);
+		}
+	}
+
+	return bEnoughData;
+}
+
+template<class TInput, class TOutput>
+_BOOLEAN CReceiverModul<TInput, TOutput>::
+	ProcessData(CParameter& Parameter, CBuffer<TInput>& InputBuffer,
+				CBuffer<TOutput>& OutputBuffer,
+				CBuffer<TOutput>& OutputBuffer2)
+{
+	/* Check initialization flag. The initialization must be done OUTSIDE
+	   the processing routine. This is ensured by doing it here, where we
+	   have control of calling the processing routine. Therefore we
+	   introduced the flag */
+	if (bDoInit == TRUE)
+	{
+		/* Call init routine */
+		Init(Parameter, OutputBuffer, OutputBuffer2);
+
+		/* Reset init flag */
+		bDoInit = FALSE;
+	}
+
+	/* This flag shows, if enough data was in the input buffer for processing */
+	_BOOLEAN bEnoughData = FALSE;
+
+	/* INPUT-DRIVEN modul implementation in the receiver -------------------- */
+	/* Check if enough data is available in the input buffer for processing */
+	if (InputBuffer.GetFillLevel() >= this->iInputBlockSize)
+	{
+		bEnoughData = TRUE;
+
+		/* Get vector from transfer-buffer */
+		this->pvecInputData = InputBuffer.Get(this->iInputBlockSize);
+
+		/* Query vector from output transfer-buffer for writing */
+		this->pvecOutputData = OutputBuffer.QueryWriteBuffer();
+		pvecOutputData2 = OutputBuffer2.QueryWriteBuffer();
+
+		/* Call the underlying processing-routine */
+		this->ProcessDataThreadSave(Parameter);
+
+		/* Reset output-buffers if flag was set by processing routine */
+		if (bResetBuf == TRUE)
+		{
+			/* Reset flag and clear buffer */
+			bResetBuf = FALSE;
+			OutputBuffer.Clear();
+		}
+		else
+		{
+			/* Write processed data from internal memory in transfer-buffer */
+			OutputBuffer.Put(this->iOutputBlockSize);
+		}
+
+		if (bResetBuf2 == TRUE)
+		{
+			/* Reset flag and clear buffer */
+			bResetBuf2 = FALSE;
+			OutputBuffer2.Clear();
+		}
+		else
+		{
+			/* Write processed data from internal memory in transfer-buffer */
+			OutputBuffer2.Put(iOutputBlockSize2);
+		}
+	}
+
+	return bEnoughData;
+}
+
+template<class TInput, class TOutput>
+_BOOLEAN CReceiverModul<TInput, TOutput>::
+	ProcessData(CParameter& Parameter, CBuffer<TInput>& InputBuffer,
+				CBuffer<TOutput>& OutputBuffer,
+				CBuffer<TOutput>& OutputBuffer2,
+				CBuffer<TOutput>& OutputBuffer3)
+{
+	/* Check initialization flag. The initialization must be done OUTSIDE
+	   the processing routine. This is ensured by doing it here, where we
+	   have control of calling the processing routine. Therefore we
+	   introduced the flag */
+	if (bDoInit == TRUE)
+	{
+		/* Call init routine */
+		Init(Parameter, OutputBuffer, OutputBuffer2, OutputBuffer3);
+
+		/* Reset init flag */
+		bDoInit = FALSE;
+	}
+
+	/* This flag shows, if enough data was in the input buffer for processing */
+	_BOOLEAN bEnoughData = FALSE;
+
+	/* INPUT-DRIVEN modul implementation in the receiver -------------------- */
+	/* Check if enough data is available in the input buffer for processing */
+	if (InputBuffer.GetFillLevel() >= this->iInputBlockSize)
+	{
+		bEnoughData = TRUE;
+
+		/* Get vector from transfer-buffer */
+		this->pvecInputData = InputBuffer.Get(this->iInputBlockSize);
+
+		/* Query vector from output transfer-buffer for writing */
+		this->pvecOutputData = OutputBuffer.QueryWriteBuffer();
+		pvecOutputData2 = OutputBuffer2.QueryWriteBuffer();
+		pvecOutputData3 = OutputBuffer3.QueryWriteBuffer();
+
+		/* Call the underlying processing-routine */
+		this->ProcessDataThreadSave(Parameter);
+
+		/* Reset output-buffers if flag was set by processing routine */
+		if (bResetBuf == TRUE)
+		{
+			/* Reset flag and clear buffer */
+			bResetBuf = FALSE;
+			OutputBuffer.Clear();
+		}
+		else
+		{
+			/* Write processed data from internal memory in transfer-buffer */
+			OutputBuffer.Put(this->iOutputBlockSize);
+		}
+
+		if (bResetBuf2 == TRUE)
+		{
+			/* Reset flag and clear buffer */
+			bResetBuf2 = FALSE;
+			OutputBuffer2.Clear();
+		}
+		else
+		{
+			/* Write processed data from internal memory in transfer-buffer */
+			OutputBuffer2.Put(iOutputBlockSize2);
+		}
+
+		if (bResetBuf3 == TRUE)
+		{
+			/* Reset flag and clear buffer */
+			bResetBuf3 = FALSE;
+			OutputBuffer3.Clear();
+		}
+		else
+		{
+			/* Write processed data from internal memory in transfer-buffer */
+			OutputBuffer3.Put(iOutputBlockSize3);
+		}
+	}
+
+	return bEnoughData;
+}
+
+template<class TInput, class TOutput>
+_BOOLEAN CReceiverModul<TInput, TOutput>::
+	ProcessData(CParameter& Parameter, CBuffer<TInput>& InputBuffer,
+				CBuffer<TOutput>& OutputBuffer,
+				CBuffer<TOutput>& OutputBuffer2,
+				vector< CSingleBuffer<TOutput> >& vecOutputBuffer)
+{
+	/* Check initialization flag. The initialization must be done OUTSIDE
+	   the processing routine. This is ensured by doing it here, where we
+	   have control of calling the processing routine. Therefore we
+	   introduced the flag */
+	if (bDoInit == TRUE)
+	{
+		/* Call init routine */
+		Init(Parameter, OutputBuffer, OutputBuffer2, vecOutputBuffer);
+
+		/* Reset init flag */
+		bDoInit = FALSE;
+	}
+
+	/* This flag shows, if enough data was in the input buffer for processing */
+	_BOOLEAN bEnoughData = FALSE;
+
+	/* INPUT-DRIVEN modul implementation in the receiver -------------------- */
+	/* Check if enough data is available in the input buffer for processing */
+	if (InputBuffer.GetFillLevel() >= this->iInputBlockSize)
+	{
+		size_t i;
+		bEnoughData = TRUE;
+
+		/* Get vector from transfer-buffer */
+		this->pvecInputData = InputBuffer.Get(this->iInputBlockSize);
+
+		/* Query vector from output transfer-buffer for writing */
+		this->pvecOutputData = OutputBuffer.QueryWriteBuffer();
+		pvecOutputData2 = OutputBuffer2.QueryWriteBuffer();
+		vecpvecOutputData.resize(vecOutputBuffer.size());
+		for(i=0; i<vecOutputBuffer.size(); i++)
+		{
+			vecpvecOutputData[i] = vecOutputBuffer[i].QueryWriteBuffer();
+		}
+
+		/* Call the underlying processing-routine */
+		this->ProcessDataThreadSave(Parameter);
+
+		/* Reset output-buffers if flag was set by processing routine */
+		if (bResetBuf == TRUE)
+		{
+			/* Reset flag and clear buffer */
+			bResetBuf = FALSE;
+			OutputBuffer.Clear();
+		}
+		else
+		{
+			/* Write processed data from internal memory in transfer-buffer */
+			OutputBuffer.Put(this->iOutputBlockSize);
+		}
+
+		if (bResetBuf2 == TRUE)
+		{
+			/* Reset flag and clear buffer */
+			bResetBuf2 = FALSE;
+			OutputBuffer2.Clear();
+		}
+		else
+		{
+			/* Write processed data from internal memory in transfer-buffer */
+			OutputBuffer2.Put(iOutputBlockSize2);
+		}
+
+		for(i=0; i<vecOutputBuffer.size(); i++)
+		{
+			if (vecbResetBuf[i] == TRUE)
+			{
+				/* Reset flag and clear buffer */
+				vecbResetBuf[i] = FALSE;
+				vecOutputBuffer[i].Clear();
+			}
+			else
+			{
+				/* Write processed data from internal memory in transfer-buffer */
+				vecOutputBuffer[i].Put(veciOutputBlockSize[i]);
+			}
+		}
+	}
+
+	return bEnoughData;
+}
+
+template<class TInput, class TOutput>
+_BOOLEAN CReceiverModul<TInput, TOutput>::
+	ProcessData(CParameter& Parameter, CBuffer<TInput>& InputBuffer,
+				vector< CSingleBuffer<TOutput> >& vecOutputBuffer)
+{
+	/* Check initialization flag. The initialization must be done OUTSIDE
+	   the processing routine. This is ensured by doing it here, where we
+	   have control of calling the processing routine. Therefore we
+	   introduced the flag */
+	if (bDoInit == TRUE)
+	{
+		/* Call init routine */
+		Init(Parameter, vecOutputBuffer);
+
+		/* Reset init flag */
+		bDoInit = FALSE;
+	}
+
+	/* This flag shows, if enough data was in the input buffer for processing */
+	_BOOLEAN bEnoughData = FALSE;
+
+	/* INPUT-DRIVEN modul implementation in the receiver -------------------- */
+	/* Check if enough data is available in the input buffer for processing */
+	if (InputBuffer.GetFillLevel() >= this->iInputBlockSize)
+	{
+		size_t i;
+		bEnoughData = TRUE;
+
+		/* Get vector from transfer-buffer */
+		this->pvecInputData = InputBuffer.Get(this->iInputBlockSize);
+
+		/* Query vector from output transfer-buffer for writing */
+		vecpvecOutputData.resize(vecOutputBuffer.size());
+		for(i=0; i<vecOutputBuffer.size(); i++)
+		{
+			vecpvecOutputData[i] = vecOutputBuffer[i].QueryWriteBuffer();
+		}
+
+		/* Call the underlying processing-routine */
+		this->ProcessDataThreadSave(Parameter);
+
+		/* Reset output-buffers if flag was set by processing routine */
+		for(i=0; i<vecOutputBuffer.size(); i++)
+		{
+			if (vecbResetBuf[i] == TRUE)
+			{
+				/* Reset flag and clear buffer */
+				vecbResetBuf[i] = FALSE;
+				vecOutputBuffer[i].Clear();
+			}
+			else
+			{
+				/* Write processed data from internal memory in transfer-buffer */
+				vecOutputBuffer[i].Put(veciOutputBlockSize[i]);
+			}
+		}
+	}
+
+	return bEnoughData;
+}
+
+template<class TInput, class TOutput>
+void CReceiverModul<TInput, TOutput>::
+	ReadData(CParameter& Parameter, CBuffer<TOutput>& OutputBuffer)
+{
+	/* Check initialization flag. The initialization must be done OUTSIDE
+	   the processing routine. This is ensured by doing it here, where we
+	   have control of calling the processing routine. Therefore we
+	   introduced the flag */
+	if (bDoInit == TRUE)
+	{
+		/* Call init routine */
+		Init(Parameter, OutputBuffer);
+
+		/* Reset init flag */
+		bDoInit = FALSE;
+	}
+
+	/* INPUT-DRIVEN modul implementation in the receiver -------------------- */
+	/* Query vector from output transfer-buffer for writing */
+	this->pvecOutputData = OutputBuffer.QueryWriteBuffer();
+
+	/* Call the underlying processing-routine */
+	this->ProcessDataThreadSave(Parameter);
+
+	/* Reset output-buffers if flag was set by processing routine */
+	if (bResetBuf == TRUE)
+	{
+		/* Reset flag and clear buffer */
+		bResetBuf = FALSE;
+		OutputBuffer.Clear();
+	}
+	else
+	{
+		/* Write processed data from internal memory in transfer-buffer */
+		OutputBuffer.Put(this->iOutputBlockSize);
+	}
+}
+
+template<class TInput, class TOutput>
+_BOOLEAN CReceiverModul<TInput, TOutput>::
+	WriteData(CParameter& Parameter, CBuffer<TInput>& InputBuffer)
+{
+	/* Check initialization flag. The initialization must be done OUTSIDE
+	   the processing routine. This is ensured by doing it here, where we
+	   have control of calling the processing routine. Therefore we
+	   introduced the flag */
+	if (bDoInit == TRUE)
+	{
+		/* Call init routine */
+		Init(Parameter);
+
+		/* Reset init flag */
+		bDoInit = FALSE;
+	}
+
+	/* Special case if input block size is zero and buffer, too */
+	if ((InputBuffer.GetFillLevel() == 0) && (this->iInputBlockSize == 0))
+	{
+		InputBuffer.Clear();
+		return FALSE;
+	}
+
+	/* INPUT-DRIVEN modul implementation in the receiver -------------------- */
+	/* This flag shows, if enough data was in the input buffer for processing */
+	_BOOLEAN bEnoughData = FALSE;
+
+	/* Check if enough data is available in the input buffer for processing */
+	if (InputBuffer.GetFillLevel() >= this->iInputBlockSize)
+	{
+		bEnoughData = TRUE;
+
+		/* Get vector from transfer-buffer */
+		this->pvecInputData = InputBuffer.Get(this->iInputBlockSize);
+
+		/* Call the underlying processing-routine */
+		this->ProcessDataThreadSave(Parameter);
+	}
+
+	return bEnoughData;
+}
+
+
+/******************************************************************************\
+* Simulation modul (CSimulationModul)                                          *
+\******************************************************************************/
+template<class TInput, class TOutput, class TInOut2>
+CSimulationModul<TInput, TOutput, TInOut2>::CSimulationModul()
+{
+	/* Initialize all member variables with zeros */
+	iMaxOutputBlockSize2 = 0;
+	iOutputBlockSize2 = 0;
+	iInputBlockSize2 = 0;
+	pvecOutputData2 = NULL;
+	pvecInputData2 = NULL;
+}
+
+template<class TInput, class TOutput, class TInOut2>
+void CSimulationModul<TInput, TOutput, TInOut2>::Init(CParameter& Parameter)
+{
+	/* Init base-class */
+	CModul<TInput, TOutput>::Init(Parameter);
+}
+
+template<class TInput, class TOutput, class TInOut2>
+void CSimulationModul<TInput, TOutput, TInOut2>::
+	Init(CParameter& Parameter,
+		 CBuffer<TOutput>& OutputBuffer)
+{
+	/* Init base-class */
+	CModul<TInput, TOutput>::Init(Parameter, OutputBuffer);
+}
+
+template<class TInput, class TOutput, class TInOut2>
+void CSimulationModul<TInput, TOutput, TInOut2>::
+	Init(CParameter& Parameter,
+		 CBuffer<TOutput>& OutputBuffer,
+		 CBuffer<TInOut2>& OutputBuffer2)
+{
+	/* Init some internal variables */
+	iMaxOutputBlockSize2 = 0;
+	iOutputBlockSize2 = 0;
+
+	/* Init base-class */
+	CModul<TInput, TOutput>::Init(Parameter, OutputBuffer);
+
+	/* Init output transfer buffers */
+	if (iMaxOutputBlockSize2 != 0)
+		OutputBuffer2.Init(iMaxOutputBlockSize2);
+	else
+	{
+		if (iOutputBlockSize2 != 0)
+			OutputBuffer2.Init(iOutputBlockSize2);
+	}
+}
+
+template<class TInput, class TOutput, class TInOut2>
+void CSimulationModul<TInput, TOutput, TInOut2>::
+	TransferData(CParameter& Parameter,
+				 CBuffer<TInput>& InputBuffer,
+				 CBuffer<TOutput>& OutputBuffer)
+{
+	/* TransferData needed for simulation */
+	/* Check, if enough input data is available */
+	if (InputBuffer.GetFillLevel() < this->iInputBlockSize)
+	{
+		/* Set request flag */
+		InputBuffer.SetRequestFlag(TRUE);
+
+		return;
+	}
+
+	/* Get vector from transfer-buffer */
+	this->pvecInputData = InputBuffer.Get(this->iInputBlockSize);
+
+	/* Query vector from output transfer-buffer for writing */
+	this->pvecOutputData = OutputBuffer.QueryWriteBuffer();
+
+	/* Call the underlying processing-routine */
+	this->ProcessDataInternal(Parameter);
+
+	/* Write processed data from internal memory in transfer-buffer */
+	OutputBuffer.Put(this->iOutputBlockSize);
+}
+
+template<class TInput, class TOutput, class TInOut2>
+_BOOLEAN CSimulationModul<TInput, TOutput, TInOut2>::
+	ProcessDataIn(CParameter& Parameter,
+				  CBuffer<TInput>& InputBuffer,
+				  CBuffer<TInOut2>& InputBuffer2,
+				  CBuffer<TOutput>& OutputBuffer)
+{
+	/* This flag shows, if enough data was in the input buffer for processing */
+	_BOOLEAN bEnoughData = FALSE;
+
+	/* Check if enough data is available in the input buffer for processing */
+	if ((InputBuffer.GetFillLevel() >= this->iInputBlockSize) &&
+		(InputBuffer2.GetFillLevel() >= iInputBlockSize2))
+	{
+		bEnoughData = TRUE;
+
+		/* Get vector from transfer-buffer */
+		this->pvecInputData = InputBuffer.Get(this->iInputBlockSize);
+		pvecInputData2 = InputBuffer2.Get(iInputBlockSize2);
+
+		/* Query vector from output transfer-buffer for writing */
+		this->pvecOutputData = OutputBuffer.QueryWriteBuffer();
+
+		/* Copy extended data from FIRST input vector (definition!) */
+		(*(this->pvecOutputData)).
+			SetExData((*(this->pvecInputData)).GetExData());
+
+		/* Call the underlying processing-routine */
+		this->ProcessDataInternal(Parameter);
+
+		/* Write processed data from internal memory in transfer-buffer */
+		OutputBuffer.Put(this->iOutputBlockSize);
+	}
+
+	return bEnoughData;
+}
+
+template<class TInput, class TOutput, class TInOut2>
+_BOOLEAN CSimulationModul<TInput, TOutput, TInOut2>::
+	ProcessDataOut(CParameter& Parameter,
+				   CBuffer<TInput>& InputBuffer,
+				   CBuffer<TOutput>& OutputBuffer,
+				   CBuffer<TInOut2>& OutputBuffer2)
+{
+	/* This flag shows, if enough data was in the input buffer for processing */
+	_BOOLEAN bEnoughData = FALSE;
+
+	/* Check if enough data is available in the input buffer for processing */
+	if (InputBuffer.GetFillLevel() >= this->iInputBlockSize)
+	{
+		bEnoughData = TRUE;
+
+		/* Get vector from transfer-buffer */
+		this->pvecInputData = InputBuffer.Get(this->iInputBlockSize);
+
+		/* Query vector from output transfer-buffer for writing */
+		this->pvecOutputData = OutputBuffer.QueryWriteBuffer();
+		pvecOutputData2 = OutputBuffer2.QueryWriteBuffer();
+
+		/* Call the underlying processing-routine */
+		this->ProcessDataInternal(Parameter);
+
+		/* Write processed data from internal memory in transfer-buffers */
+		OutputBuffer.Put(this->iOutputBlockSize);
+		OutputBuffer2.Put(iOutputBlockSize2);
+	}
+
+	return bEnoughData;
+}
+
+/* Take an input buffer and split it 2 ways */
+
+template<class TInput>
+class CSplitModul: public CReceiverModul<TInput, TInput>
+{
+protected:
+	virtual void SetInputBlockSize(CParameter& Parameters) = 0;
+
+	virtual void InitInternal(CParameter& Parameters)
+	{
+		this->SetInputBlockSize(Parameters);
+		this->iOutputBlockSize = this->iInputBlockSize;
+		this->iOutputBlockSize2 = this->iInputBlockSize;
+	}
+
+	virtual void ProcessDataInternal(CParameter&)
+	{
+		for (int i = 0; i < this->iInputBlockSize; i++)
+		{
+			TInput n = (*(this->pvecInputData))[i];
+			(*this->pvecOutputData)[i] = n;
+			(*this->pvecOutputData2)[i] = n;
+		}
+	}
+};
+
+#endif // !defined(AFX_MODUL_H__41E39CD3_2AEC_400E_907B_148C0EC17A43__INCLUDED_)
diff --git a/src/util/Pacer.h b/src/util/Pacer.h
new file mode 100644
index 0000000..043ebe5
--- /dev/null
+++ b/src/util/Pacer.h
@@ -0,0 +1,28 @@
+#ifndef PACER_H_INCLUDED
+#define PACER_H_INCLUDED
+
+#include "../GlobalDefinitions.h"
+
+#ifdef _WIN32
+# ifdef _WIN32_WINNT
+#  undef _WIN32_WINNT
+# endif
+# define _WIN32_WINNT _WIN32_WINNT_WINXP
+# include <windows.h>
+#endif
+
+class CPacer
+{
+public:
+	CPacer(uint64_t ns);
+	~CPacer();
+	uint64_t nstogo();
+	void wait();
+protected:
+	uint64_t timekeeper;
+	uint64_t interval;
+#ifdef _WIN32
+	HANDLE hTimer;
+#endif
+};
+#endif
diff --git a/src/util/Reassemble.cpp b/src/util/Reassemble.cpp
new file mode 100644
index 0000000..ee2a027
--- /dev/null
+++ b/src/util/Reassemble.cpp
@@ -0,0 +1,170 @@
+/******************************************************************************\
+ * BBC World Service
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Julian Cable
+ *
+ * Description:
+ *	General Purpose Packet ReassemblerNs for data packet mode, MOT and PFT
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "Reassemble.h"
+#include <iostream>
+
+CReassemblerN::CReassemblerN (const CReassemblerN & r):iLastSegmentNum (r.iLastSegmentNum),
+		iLastSegmentSize (r.iLastSegmentSize),
+		iSegmentSize (r.iSegmentSize), Tracker (r.Tracker), bReady (r.bReady)
+{
+	vecData.resize (r.vecData.size ());
+	vecData = r.vecData;
+	vecLastSegment.resize (r.vecLastSegment.size ());
+	vecLastSegment = r.vecLastSegment;
+}
+
+CReassemblerN & CReassemblerN::operator= (const CReassemblerN & r)
+{
+	iLastSegmentNum = r.iLastSegmentNum;
+	iLastSegmentSize = r.iLastSegmentSize;
+	iSegmentSize = r.iSegmentSize;
+	Tracker = r.Tracker;
+	vecData.resize (r.vecData.size ());
+	vecData = r.vecData;
+	vecLastSegment.resize (r.vecLastSegment.size ());
+	vecLastSegment = r.vecLastSegment;
+	bReady = r.bReady;
+
+	return *this;
+}
+
+void
+CReassemblerN::AddSegment (vector<_BYTE> &vecDataIn, int iSegNum, _BOOLEAN bLast)
+{
+	if (bLast)
+	{
+		if (iLastSegmentNum == -1)
+		{
+			iLastSegmentNum = iSegNum;
+			iLastSegmentSize = vecDataIn.size();
+			/* three cases:
+			   1: single segment - easy! (actually degenerate with case 3)
+			   2: multi-segment and the last segment came first.
+			   3: normal - some segment, not the last, came first, 
+			   we know the segment size
+			 */
+			if (iSegNum == 0)
+			{					/* case 1 */
+				iSegmentSize = vecDataIn.size();
+				copyin (vecDataIn, 0);
+			}
+			else if (iSegmentSize == 0)
+			{					/* case 2 */
+				cachelast (vecDataIn, vecDataIn.size());
+			}
+			else
+			{					/* case 3 */
+				copyin (vecDataIn, iSegNum);
+			}
+		}						/* otherwise do nothing as we already have the last segment */
+	}
+	else
+	{
+		iSegmentSize = vecDataIn.size();
+		if (Tracker.HaveSegment (iSegNum) == FALSE)
+		{
+			copyin (vecDataIn, iSegNum);
+		}
+	}
+	Tracker.AddSegment (iSegNum);	/* tracking the last segment makes the Ready work! */
+
+	if ((iLastSegmentSize != -1)	/* we have the last segment */
+		&& (bReady == false)	/* we haven't already completed reassembly */
+		&& Tracker.Ready ()		/* there are no gaps */
+		)
+	{
+		if (vecLastSegment.size () > 0)
+		{
+			/* we have everything, but the last segment came first */
+			copylast ();
+		}
+		bReady = true;
+	}
+}
+
+void
+CReassemblerN::copyin (vector < _BYTE > &vecDataIn, size_t iSegNum)
+{
+    size_t offset = iSegNum * iSegmentSize;
+    size_t iNewSize = offset + vecDataIn.size();
+    if (vecData.size () < iNewSize)
+		vecData.resize (iNewSize);
+    for (size_t i = 0; i < vecDataIn.size(); i++)
+		vecData[offset + i] = vecDataIn[i];
+}
+
+void
+CReassemblerN::cachelast (vector < _BYTE > &vecDataIn, size_t iSegSize)
+{
+    vecLastSegment.resize (iSegSize);
+    for (size_t i = 0; i < iSegSize; i++)
+		vecLastSegment[i] = vecDataIn[i];
+}
+
+void
+CReassemblerN::copylast ()
+{
+    size_t offset = iLastSegmentNum * iSegmentSize;
+    vecData.resize (vecData.size()+vecLastSegment.size ());
+    for (size_t i = 0; i < size_t (vecLastSegment.size ()); i++)
+		vecData[offset + i] = vecLastSegment[i];
+    vecLastSegment.resize (0);
+}
+
+void
+CBitReassemblerN::copyin (CVector < _BYTE > &vecDataIn, size_t iSegNum)
+{
+	size_t iSize = size_t(iSegmentSize) * (bPack?1:8);
+    size_t offset = iSegNum * iSize;
+    size_t iNewSize = offset + iSize;
+    if (vecData.size() < iNewSize)
+		vecData.resize (iNewSize);
+    for (size_t i = 0; i < iSize; i++)
+		vecData[offset + i] = _BYTE(vecDataIn.Separate (bPack?8:1));
+}
+
+void
+CBitReassemblerN::cachelast (CVector < _BYTE > &vecDataIn, size_t iSegSize)
+{
+	size_t iSize = size_t(iSegSize) * (bPack?1:8);
+    vecLastSegment.resize (iSize);
+    for (size_t i = 0; i < iSize; i++)
+		vecLastSegment[i] = _BYTE(vecDataIn.Separate (bPack?8:1));
+}
+
+void
+CBitReassemblerN::copylast ()
+{
+	int iSize = iSegmentSize * (bPack?1:8);
+    size_t offset = iLastSegmentNum * iSize;
+    vecData.resize (vecData.size()+vecLastSegment.size ());
+    for (size_t i = 0; i < size_t (vecLastSegment.size ()); i++)
+		vecData[offset + i] = vecLastSegment[i];
+    vecLastSegment.resize (0);
+}
diff --git a/src/util/Reassemble.h b/src/util/Reassemble.h
new file mode 100644
index 0000000..3d07d13
--- /dev/null
+++ b/src/util/Reassemble.h
@@ -0,0 +1,201 @@
+/******************************************************************************\
+ * BBC World Service
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Julian Cable
+ *
+ * Description:
+ *	See Reassemble.cpp
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#ifndef REASSEMBLE_H_INCLUDED
+#define REASSEMBLE_H_INCLUDED
+
+#include "Vector.h"
+
+class CSegmentTrackerN
+{
+public:
+
+	CSegmentTrackerN():vecbHaveSegment() { }
+
+	void Reset ()
+	{
+		vecbHaveSegment.clear ();
+	}
+
+	size_t size ()
+	{
+		return vecbHaveSegment.size ();
+	}
+
+	_BOOLEAN Ready ()
+	{
+		if (vecbHaveSegment.size () == 0)
+			return FALSE;
+		for (size_t i = 0; i < vecbHaveSegment.size (); i++)
+		{
+			if (vecbHaveSegment[i] == FALSE)
+			{
+				return FALSE;
+			}
+		}
+		return TRUE;
+	}
+
+	void AddSegment (int iSegNum)
+	{
+		if ((iSegNum + 1) > int (vecbHaveSegment.size ()))
+			vecbHaveSegment.resize (iSegNum + 1, FALSE);
+		vecbHaveSegment[iSegNum] = TRUE;
+	}
+
+	_BOOLEAN HaveSegment (int iSegNum)
+	{
+		if (iSegNum < int (vecbHaveSegment.size ()))
+			return vecbHaveSegment[iSegNum];
+		return FALSE;
+	}
+
+protected:
+	vector < _BOOLEAN > vecbHaveSegment;
+};
+
+/* The base class reassembles chunks of byte vectors into one big vector.
+ * It assumes that all chunks except the last chunk are the same size.
+ * Usage:
+ *
+ * CReassemblerN o;
+ * o.AddSegment (veco, iSegSize, 1);
+ * o.AddSegment (veco, iSegSize, 3);
+ * o.AddSegment (veco, iSegSize, 7, TRUE); // last segment, ie there are 8 segments, 0..7
+ * o.AddSegment (veco, iSegSize, 2);
+ * o.AddSegment (veco, iSegSize, 4);
+ * o.AddSegment (veco, iSegSize, 6);
+ * o.AddSegment (veco, iSegSize, 5);
+ * o.AddSegment (veco, iSegSize, 0);
+ * if(o.Ready())
+ *   vecoComplete = o.vecData;
+ *
+ */
+
+class CReassemblerN
+{
+public:
+
+	CReassemblerN(): vecData(), vecLastSegment(),
+		iLastSegmentNum(-1), iLastSegmentSize(-1), iSegmentSize(0),
+		Tracker(), bReady(false)
+	{
+	}
+
+	CReassemblerN (const CReassemblerN & r);
+
+	virtual ~CReassemblerN ()
+	{
+	}
+
+	CReassemblerN & operator= (const CReassemblerN & r);
+
+	void Reset ()
+	{
+		vecData.resize (0);
+		vecLastSegment.resize (0);
+		iLastSegmentNum = -1;
+		iLastSegmentSize = -1;
+		iSegmentSize = 0;
+		Tracker.Reset ();
+		bReady = false;
+	}
+
+	_BOOLEAN Ready ()
+	{
+		return bReady;
+	}
+
+	void AddSegment (vector<_BYTE> &vecDataIn, int iSegNum, _BOOLEAN bLast);
+
+	vector<_BYTE> vecData;
+
+protected:
+
+	virtual void copyin (vector<_BYTE> &vecDataIn, size_t iSegNum);
+	virtual void cachelast (vector<_BYTE> &vecDataIn, size_t iSegSize);
+	virtual void copylast ();
+
+	vector<_BYTE> vecLastSegment;
+	int iLastSegmentNum;
+	int iLastSegmentSize;
+	size_t iSegmentSize;
+	CSegmentTrackerN Tracker;
+	bool bReady;
+};
+
+/* CBitReassemblerN uses the Dream CVector class to take a vector of bytes, each holding one bit.
+ * It reassembles the segments into another vector, either of bits or of bytes by packing.
+ * Packing reduces the amount of storage needed and prepares the output vector to be used in
+ * applications expecting vectors of bytes, such as zlib.
+ *
+ * The major difference to the base class is that the input vector may have a header in front
+ * of the data. This will be ignored as long as the bitaccess pointer in the CVector is correctly
+ * positioned.
+ */
+
+class CBitReassemblerN:public CReassemblerN
+{
+public:
+
+	CBitReassemblerN():CReassemblerN(),bPack(false)
+	{
+	}
+
+	CBitReassemblerN(const CBitReassemblerN& r):CReassemblerN(r),bPack(r.bPack)
+	{
+	}
+
+	inline CBitReassemblerN & operator= (const CBitReassemblerN & r)
+	{
+		CReassemblerN(*this) = r;
+		bPack = r.bPack;
+		return *this;
+	}
+
+protected:
+
+	virtual void copyin (CVector < _BYTE > &vecDataIn, size_t iSegNum);
+	virtual void cachelast (CVector < _BYTE > &vecDataIn, size_t iSegSize);
+	virtual void copylast ();
+
+	bool bPack;
+};
+
+class CByteReassemblerN:public CBitReassemblerN
+{
+public:
+
+	CByteReassemblerN():CBitReassemblerN()
+	{
+		bPack = true;
+	}
+
+};
+
+#endif
diff --git a/src/util/Settings.cpp b/src/util/Settings.cpp
new file mode 100644
index 0000000..eb2b71d
--- /dev/null
+++ b/src/util/Settings.cpp
@@ -0,0 +1,903 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer, Tomi Manninen, Stephane Fillod, Robert Kesterson,
+ *	Andrea Russo, Andrew Murphy
+ *
+ * Description:
+ *
+ * 10/01/2001-2014
+ *  - parameters for rsci by Andrew Murphy
+ * 07/27/2001-2014
+ *  - included stlini routines written by Robert Kesterson
+ * 04/15/2001-2014 Tomi Manninen, Stephane Fillod
+ *  - Hamlib
+ * 10/03/2003 Tomi Manninen / OH2BNS
+ *  - Initial (basic) code for command line argument parsing (argv)
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "Settings.h"
+#include <fstream>
+#include <sstream>
+#include <iostream>
+#include <iomanip>
+#include <cstring>
+#include <cstdlib>
+using namespace std;
+#include "FileTyper.h"
+
+/* Implementation *************************************************************/
+void
+CSettings::Load(int argc, char **argv)
+{
+	/* First load settings from init-file and then parse command line arguments.
+	   The command line arguments overwrite settings in init-file! */
+	(void)LoadIni(DREAM_INIT_FILE_NAME);
+	ParseArguments(argc, argv);
+}
+
+void
+CSettings::Save()
+{
+	/* Just write settings in init-file */
+	SaveIni(DREAM_INIT_FILE_NAME);
+}
+
+string
+CSettings::Get(const string & section, const string & key, const string & def) const
+{
+	return GetIniSetting(section, key, def);
+}
+
+void
+CSettings::Put(const string & section, const string & key, const string& value)
+{
+	PutIniSetting(section, key, value);
+}
+
+bool
+CSettings::Get(const string & section, const string & key, const bool def) const
+{
+	return GetIniSetting(section, key, def?"1":"0")=="1";
+}
+
+void CSettings::Put(const string& section, const string& key, const bool value)
+{
+	PutIniSetting(section, key, value?"1":"0");
+}
+
+int
+CSettings::Get(const string & section, const string & key, const int def) const
+{
+	const string strGetIni = GetIniSetting(section, key);
+
+	/* Check if it is a valid parameter */
+	if (strGetIni.empty())
+		return def;
+
+	stringstream s(strGetIni);
+	int iValue;
+	s >> iValue;
+	return iValue;
+}
+
+void
+CSettings::Put(const string & section, const string & key, const int value)
+{
+	stringstream s;
+	s << value;
+	PutIniSetting(section, key, s.str());
+}
+
+_REAL
+CSettings::Get(const string & section, const string & key, const _REAL def) const
+{
+	string s = GetIniSetting(section, key, "");
+	if(s != "")
+	{
+		stringstream ss(s);
+		_REAL rValue;
+		ss >> rValue;
+		return rValue;
+	}
+	return def;
+}
+
+void
+CSettings::Put(const string & section, const string & key, const _REAL value)
+{
+	stringstream s;
+	s << setiosflags(ios::left);
+	s << setw(11);
+	s << setiosflags(ios::fixed);
+	s << setprecision(7);
+	s << value;
+	PutIniSetting(section, key, s.str());
+}
+
+void
+CSettings::Get(const string& section, CWinGeom& value) const
+{
+	value.iXPos = Get(section, "x", 0);
+	value.iYPos = Get(section, "y", 0);
+	value.iWSize = Get(section, "width", 0);
+	value.iHSize = Get(section, "height", 0);
+}
+
+void
+CSettings::Put(const string& section, const CWinGeom& value)
+{
+	stringstream s;
+	s << value.iXPos;
+	PutIniSetting(section, "x", s.str());
+	s.str("");
+	s << value.iYPos;
+	PutIniSetting(section, "y", s.str());
+	s.str("");
+	s << value.iWSize;
+	PutIniSetting(section, "width", s.str());
+	s.str("");
+	s << value.iHSize;
+	PutIniSetting(section, "height", s.str());
+	s.str("");
+}
+
+int
+CSettings::IsReceiver(const char *argv0)
+{
+#ifdef EXECUTABLE_NAME
+	/* Give the possibility to launch directly dream transmitter
+	   with a symbolic link to the executable, a 't' need to be 
+	   appended to the symbolic link name */
+# define _xstr(s) _str(s)
+# define _str(s) #s
+# ifndef _WIN32
+	const int pathseparator = '/';
+# else
+	const int pathseparator = '\\';
+# endif
+	const char *str = strrchr(argv0, pathseparator);
+	return strcmp(str ? str+1 : argv0, _xstr(EXECUTABLE_NAME) "t") != 0;
+#else
+	(void)argv0;
+	return TRUE;
+#endif
+}
+
+void
+CSettings::FileArg(const string& str)
+{
+    // Identify the type of file
+    FileTyper::type t = FileTyper::resolve(str);
+    if(FileTyper::is_rxstat(t))
+    {
+		// it's an RSI or MDI input file
+		Put("command", "rsiin", str);
+	}
+	else
+	{
+		// its an I/Q or I/F file
+		Put("command", "fileio", str);
+	}
+}
+/* Command line argument parser ***********************************************/
+void
+CSettings::ParseArguments(int argc, char **argv)
+{
+	_BOOLEAN bIsReceiver;
+	_REAL rArgument;
+	string strArgument;
+	string rsiOutProfile="A";
+
+	bIsReceiver = IsReceiver(argv[0]);
+
+	/* QT docu: argv()[0] is the program name, argv()[1] is the first
+	   argument and argv()[argc()-1] is the last argument.
+	   Start with first argument, therefore "i = 1" */
+	if (bIsReceiver)
+	{
+		for (int i = 1; i < argc; i++)
+		{
+			/* DRM transmitter mode flag ---------------------------------------- */
+			if (GetFlagArgument(argc, argv, i, "-t", "--transmitter") == TRUE)
+			{
+				bIsReceiver = FALSE;
+				break;
+			}
+		}
+	}
+
+	const char* ReceiverTransmitter = bIsReceiver ? "Receiver" : "Transmitter";
+	Put("command", "mode", bIsReceiver ? string("receive") : string("transmit"));
+
+	for (int i = 1; i < argc; i++)
+	{
+		/* DRM transmitter mode flag ---------------------------------------- */
+		if (GetFlagArgument(argc, argv, i, "-t", "--transmitter") == TRUE)
+			continue;
+
+		/* Sample rate ------------------------------------------------------ */
+		if (GetNumericArgument(argc, argv, i, "-R", "--samplerate",
+							   -1e9, +1e9, rArgument) == TRUE)
+		{
+			Put(ReceiverTransmitter, "samplerateaud", int (rArgument));
+			Put(ReceiverTransmitter, "sampleratesig", int (rArgument));
+			continue;
+		}
+
+		/* Audio sample rate ------------------------------------------------ */
+		if (GetNumericArgument(argc, argv, i, "--audsrate", "--audsrate",
+							   -1e9, +1e9, rArgument) == TRUE)
+		{
+			Put(ReceiverTransmitter, "samplerateaud", int (rArgument));
+			continue;
+		}
+
+		/* Signal sample rate ------------------------------------------------ */
+		if (GetNumericArgument(argc, argv, i, "--sigsrate", "--sigsrate",
+							   -1e9, +1e9, rArgument) == TRUE)
+		{
+			Put(ReceiverTransmitter, "sampleratesig", int (rArgument));
+			continue;
+		}
+
+		/* Sound In device -------------------------------------------------- */
+		if (GetStringArgument(argc, argv, i, "-I", "--snddevin",
+							  strArgument) == TRUE)
+		{
+			Put(ReceiverTransmitter, "snddevin", strArgument);
+			continue;
+		}
+
+		/* Sound Out device ------------------------------------------------- */
+		if (GetStringArgument(argc, argv, i, "-O", "--snddevout",
+							  strArgument) == TRUE)
+		{
+			Put(ReceiverTransmitter, "snddevout", strArgument);
+			continue;
+		}
+
+		/* Signal upscale ratio --------------------------------------------- */
+		if (GetNumericArgument(argc, argv, i, "-U", "--sigupratio",
+							  1, 2, rArgument) == TRUE)
+		{
+			Put("Receiver", "sigupratio", rArgument);
+			continue;
+		}
+
+		/* Flip spectrum flag ----------------------------------------------- */
+		if (GetNumericArgument(argc, argv, i, "-p", "--flipspectrum",
+							   0, 1, rArgument) == TRUE)
+		{
+			Put("Receiver", "flipspectrum", int (rArgument));
+			continue;
+		}
+
+		/* Mute audio flag -------------------------------------------------- */
+		if (GetNumericArgument(argc, argv, i, "-m", "--muteaudio",
+							   0, 1, rArgument) == TRUE)
+		{
+			Put("Receiver", "muteaudio", int (rArgument));
+			continue;
+		}
+
+		/* Reverb audio flag ------------------------------------------------ */
+		if (GetNumericArgument(argc, argv, i, "-b", "--reverb",
+							   0, 1, rArgument) == TRUE)
+		{
+			Put("Receiver", "reverb", int (rArgument));
+			continue;
+		}
+
+		/* Bandpass filter flag --------------------------------------------- */
+		if (GetNumericArgument(argc, argv, i, "-F", "--filter",
+							   0, 1, rArgument) == TRUE)
+		{
+			Put("Receiver", "filter", int (rArgument));
+			continue;
+		}
+
+		/* Modified metrics flag -------------------------------------------- */
+		if (GetNumericArgument(argc, argv, i, "-D", "--modmetric",
+							   0, 1, rArgument) == TRUE)
+		{
+			Put("Receiver", "modmetric", int (rArgument));
+			continue;
+		}
+
+		/* Do not use sound card, read from file ---------------------------- */
+		if (GetStringArgument(argc, argv, i, "-f", "--fileio",
+							  strArgument) == TRUE)
+		{
+			FileArg(strArgument);
+			continue;
+		}
+
+		/* Write output data to file as WAV --------------------------------- */
+		if (GetStringArgument(argc, argv, i, "-w", "--writewav",
+							  strArgument) == TRUE)
+		{
+			Put("command", "writewav", strArgument);
+			continue;
+		}
+
+		/* Number of iterations for MLC setting ----------------------------- */
+		if (GetNumericArgument(argc, argv, i, "-i", "--mlciter", 0,
+							   MAX_NUM_MLC_IT, rArgument) == TRUE)
+		{
+			Put("Receiver", "mlciter", int (rArgument));
+			continue;
+		}
+
+		/* Sample rate offset start value ----------------------------------- */
+		if (GetNumericArgument(argc, argv, i, "-s", "--sampleoff",
+							   MIN_SAM_OFFS_INI, MAX_SAM_OFFS_INI,
+							   rArgument) == TRUE)
+		{
+			Put("Receiver", "sampleoff", rArgument);
+			continue;
+		}
+
+		/* Frequency acquisition search window size ------------------------- */
+		if (GetNumericArgument(argc, argv, i, "-S", "--fracwinsize", -1,
+							   MAX_FREQ_AQC_SE_WIN_SZ, rArgument) == TRUE)
+		{
+			Put("command", "fracwinsize", rArgument);
+			continue;
+		}
+
+		/* Frequency acquisition search window center ----------------------- */
+		if (GetNumericArgument(argc, argv, i, "-E", "--fracwincent", -1,
+							   MAX_FREQ_AQC_SE_WIN_CT, rArgument) == TRUE)
+		{
+			Put("command", "fracwincent", rArgument);
+			continue;
+		}
+
+		/* Input channel selection ------------------------------------------ */
+		if (GetNumericArgument(argc, argv, i, "-c", "--inchansel", 0,
+							   MAX_VAL_IN_CHAN_SEL, rArgument) == TRUE)
+		{
+			Put("Receiver", "inchansel", (int) rArgument);
+			continue;
+		}
+
+		/* Output channel selection ----------------------------------------- */
+		if (GetNumericArgument(argc, argv, i, "-u", "--outchansel", 0,
+							   MAX_VAL_OUT_CHAN_SEL, rArgument) == TRUE)
+		{
+			Put("Receiver", "outchansel", (int) rArgument);
+			continue;
+		}
+
+		/* Wanted RF Frequency   -------------------------------------------- */
+		if (GetNumericArgument(argc, argv, i, "-r", "--frequency", 0,
+							   MAX_RF_FREQ, rArgument) == TRUE)
+		{
+			Put("Receiver", "frequency", (int) rArgument);
+			continue;
+		}
+
+		/* if 0 then only measure PSD when RSCI in use otherwise always measure it ---- */
+		if (GetNumericArgument(argc, argv, i, "--enablepsd", "--enablepsd", 0, 1,
+							   rArgument) == TRUE)
+		{
+			Put("Receiver", "measurepsdalways", (int) rArgument);
+			continue;
+		}
+
+		/* Enable/Disable epg decoding -------------------------------------- */
+//		if (GetNumericArgument(argc, argv, i, "-e", "--decodeepg", 0,
+//							   1, rArgument) == TRUE)
+//		{
+//			Put("EPG", "decodeepg", (int) rArgument);
+//			continue;
+//		}
+
+#ifdef QT_CORE_LIB /* QThread needed for log file timing */
+
+		/* log enable flag  ------------------------------------------------- */
+		if (GetNumericArgument(argc, argv, i, "-g", "--enablelog", 0, 1,
+							   rArgument) == TRUE)
+		{
+			Put("Logfile", "enablelog", (int) rArgument);
+			continue;
+		}
+
+		/* log file delay value  -------------------------------------------- */
+		if (GetNumericArgument(argc, argv, i, "-l", "--logdelay", 0,
+							   MAX_SEC_LOG_FI_START, rArgument) == TRUE)
+		{
+			Put("Logfile", "delay", (int) rArgument);
+			continue;
+		}
+
+		/* read DRMlog.ini style schedule file ------------------------------ */
+		if (GetStringArgument(argc, argv, i, "-L", "--schedule", strArgument) == TRUE)
+		{
+			Put("command", "schedule", strArgument);
+			continue;
+		}
+
+		/* Latitude string for log file ------------------------------------- */
+		if (GetStringArgument(argc, argv, i, "-a", "--latitude",
+							  strArgument) == TRUE)
+		{
+			Put("Logfile", "latitude", strArgument);
+			continue;
+		}
+
+		/* Longitude string for log file ------------------------------------ */
+		if (GetStringArgument(argc, argv, i, "-o", "--longitude",
+							  strArgument) == TRUE)
+		{
+			Put("Logfile", "longitude", strArgument);
+			continue;
+		}
+
+
+		/* Plot Style main plot --------------------------------------------- */
+		if (GetNumericArgument(argc, argv, i, "-y", "--sysevplotstyle", 0,
+							   MAX_COLOR_SCHEMES_VAL, rArgument) == TRUE)
+		{
+			Put("System Evaluation Dialog", "plotstyle", (int) rArgument);
+			continue;
+		}
+
+
+#endif
+		/* MDI out address -------------------------------------------------- */
+		if (GetStringArgument(argc, argv, i, "--mdiout", "--mdiout",
+							  strArgument) == TRUE)
+		{
+			cerr <<
+				"content server mode not implemented yet, perhaps you wanted rsiout"
+				<< endl;
+			continue;
+		}
+
+		/* MDI in address --------------------------------------------------- */
+		if (GetStringArgument(argc, argv, i, "--mdiin", "--mdiin",
+							  strArgument) == TRUE)
+		{
+			cerr <<
+				"modulator mode not implemented yet, perhaps you wanted rsiin"
+				<< endl;
+			continue;
+		}
+
+		/* RSCI status output profile --------------------------------------- */
+		if (GetStringArgument(argc, argv, i, "--rsioutprofile", "--rsioutprofile",
+							  strArgument) == TRUE)
+		{
+			rsiOutProfile = strArgument;
+			continue;
+		}
+
+		/* RSCI status out address ------------------------------------------ */
+		if (GetStringArgument(argc, argv, i, "--rsiout", "--rsiout",
+							  strArgument) == TRUE)
+		{
+			string s = Get("command", "rsiout", string(""));
+			if(s == "")
+				Put("command", "rsiout", rsiOutProfile+":"+strArgument);
+			else
+				Put("command", "rsiout", s+" "+rsiOutProfile+":"+strArgument);
+			continue;
+		}
+
+		/* RSCI status in address ------------------------------------------- */
+		if (GetStringArgument(argc, argv, i, "--rsiin", "--rsiin",
+							  strArgument) == TRUE)
+		{
+			Put("command", "rsiin", strArgument);
+			continue;
+		}
+
+		/* RSCI control out address ----------------------------------------- */
+		if (GetStringArgument(argc, argv, i, "--rciout", "--rciout",
+							  strArgument) == TRUE)
+		{
+			Put("command", "rciout", strArgument);
+			continue;
+		}
+
+		/* OPH: RSCI control in address ------------------------------------- */
+		if (GetStringArgument(argc, argv, i, "--rciin", "--rciin",
+							  strArgument) == TRUE)
+		{
+			string s = Get("command", "rciin", string(""));
+			if(s == "")
+				Put("command", "rciin", strArgument);
+			else
+				Put("command", "rciin", s+" "+strArgument);
+			continue;
+		}
+
+        if (GetNumericArgument(argc, argv, i, "-permissive",
+                "--permissive", 0, 1, rArgument) == TRUE)
+        {
+            Put("command", "permissive", (int) rArgument);
+            continue;
+        }
+
+		if (GetStringArgument (argc, argv, i,
+				"--rsirecordprofile", "--rsirecordprofile", strArgument) == TRUE)
+		{
+			Put("command", "rsirecordprofile", strArgument);
+			continue;
+		}
+
+		if (GetStringArgument (argc, argv, i,
+				"--rsirecordtype", "--rsirecordtype", strArgument) == TRUE)
+		{
+			Put("command", "rsirecordtype", strArgument);
+			continue;
+		}
+
+		if (GetNumericArgument (argc, argv, i,
+				"--recordiq", "--recordiq", 0, 1, rArgument) == TRUE)
+		{
+			Put("command", "recordiq", int (rArgument));
+			continue;
+		}
+
+#ifdef HAVE_LIBHAMLIB
+		/* Hamlib config string --------------------------------------------- */
+		if (GetStringArgument(argc, argv, i, "-C", "--hamlib-config",
+							  strArgument) == TRUE)
+		{
+			Put("Hamlib", "hamlib-config", strArgument);
+			continue;
+		}
+
+		/* Hamlib Model ID -------------------------------------------------- */
+		if (GetNumericArgument(argc, argv, i, "-M", "--hamlib-model", 0,
+							   MAX_ID_HAMLIB, rArgument) == TRUE)
+		{
+			Put("Hamlib", "hamlib-model", int (rArgument));
+			continue;
+		}
+
+		/* Enable s-meter flag ---------------------------------------------- */
+		if (GetNumericArgument(argc, argv, i, "-T", "--ensmeter",
+							   0, 1, rArgument) == TRUE)
+		{
+			Put("Hamlib", "ensmeter", int (rArgument));
+			continue;
+		}
+#endif
+		/* invoke test functionality ---------------------------------------- */
+		if (GetStringArgument(argc, argv, i, "--test", "--test", strArgument) == TRUE)
+		{
+			Put("command", "test", strArgument);
+			continue;
+		}
+
+
+		/* Help (usage) flag ------------------------------------------------ */
+		if ((!strcmp(argv[i], "--help")) ||
+			(!strcmp(argv[i], "-h")) || (!strcmp(argv[i], "-?")))
+		{
+			Put("command", "mode", "help");
+			continue;
+		}
+
+		/* not an option ---------------------------------------------------- */
+		if(argv[i][0] != '-')
+		{
+			FileArg(string(argv[i]));
+			continue;
+		}
+
+		/* Unknown option --------------------------------------------------- */
+		cerr << argv[0] << ": ";
+		cerr << "Unknown option '" << argv[i] << "' -- use '--help' for help"
+			<< endl;
+
+		exit(1);
+	}
+}
+
+/*
+ Option argument:
+  <b> boolean (0=off, 1=on)
+  <n> integer number
+  <r> real number
+  <s> string
+*/
+
+const char *
+CSettings::UsageArguments()
+{
+	/* The text below must be translatable */
+	return
+		"Usage: $EXECNAME [option [argument]] | [input file]\n"
+		"\n"
+		"Recognized options:\n"
+		"  -t, --transmitter            DRM transmitter mode\n"
+		"  -p <b>, --flipspectrum <b>   flip input spectrum (0: off; 1: on)\n"
+		"  -i <n>, --mlciter <n>        number of MLC iterations (allowed range: 0...4 default: 1)\n"
+		"  -s <r>, --sampleoff <r>      sample rate offset initial value [Hz] (allowed range: -200.0...200.0)\n"
+		"  -m <b>, --muteaudio <b>      mute audio output (0: off; 1: on)\n"
+		"  -b <b>, --reverb <b>         audio reverberation on drop-out (0: off; 1: on)\n"
+		"  -f <s>, --fileio <s>         disable sound card, use file <s> instead\n"
+		"  -w <s>, --writewav <s>       write output to wave file\n"
+		"  -S <r>, --fracwinsize <r>    freq. acqu. search window size [Hz] (-1.0: sample rate / 2 (default))\n"
+		"  -E <r>, --fracwincent <r>    freq. acqu. search window center [Hz] (-1.0: sample rate / 4 (default))\n"
+		"  -F <b>, --filter <b>         apply bandpass filter (0: off; 1: on)\n"
+		"  -D <b>, --modmetric <b>      enable modified metrics (0: off; 1: on)\n"
+		"  -c <n>, --inchansel <n>      input channel selection\n"
+		"                               0: left channel;                     1: right channel;\n"
+		"                               2: mix both channels (default);      3: subtract right from left;\n"
+		"                               4: I / Q input positive;             5: I / Q input negative;\n"
+		"                               6: I / Q input positive (0 Hz IF);   7: I / Q input negative (0 Hz IF)\n"
+		"                               8: I / Q input positive split;       9: I / Q input negative split\n"
+		"  -u <n>, --outchansel <n>     output channel selection\n"
+		"                               0: L -> L, R -> R (default);   1: L -> L, R muted;   2: L muted, R -> R\n"
+		"                               3: mix -> L, R muted;          4: L muted, mix -> R\n"
+#ifdef QT_CORE_LIB
+		"  -g <b>, --enablelog <b>      enable/disable logging (0: no logging; 1: logging)\n"
+		"  -r <n>, --frequency <n>      set frequency [kHz] for log file\n"
+		"  -l <n>, --logdelay <n>       delay start of logging by <n> seconds, allowed range: 0...3600)\n"
+		"  -L <s>, --schedule <s>       read DRMlog.ini style schedule file and obey it\n"
+		"  -y <n>, --sysevplotstyle <n> set style for main plot\n"
+		"                               0: blue-white (default);   1: green-black;   2: black-grey\n"
+#endif
+		"  --enablepsd <b>              if 0 then only measure PSD when RSCI in use otherwise always measure it\n"
+		"  --mdiout <s>                 MDI out address format [IP#:]IP#:port (for Content Server)\n"
+		"  --mdiin  <s>                 MDI in address (for modulator) [[IP#:]IP:]port\n"
+		"  --rsioutprofile <s>          MDI/RSCI output profile: A|B|C|D|Q|M\n"
+		"  --rsiout <s>                 MDI/RSCI output address format [IP#:]IP#:port (prefix address with 'p' to enable the simple PFT)\n"
+		"  --rsiin <s>                  MDI/RSCI input address format [[IP#:]IP#:]port\n"
+		"  --rciout <s>                 RSCI Control output format IP#:port\n"
+		"  --rciin <s>                  RSCI Control input address number format [IP#:]port\n"
+		"  --rsirecordprofile <s>       RSCI recording profile: A|B|C|D|Q|M\n"
+		"  --rsirecordtype <s>          RSCI recording file type: raw|ff|pcap\n"
+		"  --recordiq <b>               enable/disable recording an I/Q file\n"
+		"  --permissive <b>             enable decoding of bad RSCI frames (0: off; 1: on)\n"
+		"  -R <n>, --samplerate <n>     set audio and signal sound card sample rate [Hz]\n"
+		"  --audsrate <n>               set audio sound card sample rate [Hz] (allowed range: 8000...192000)\n"
+		"  --sigsrate <n>               set signal sound card sample rate [Hz] (allowed values: 24000, 48000, 96000, 192000)\n"
+		"  -I <s>, --snddevin <s>       set sound in device\n"
+		"  -O <s>, --snddevout <s>      set sound out device\n"
+		"  -U <n>, --sigupratio <n>     set signal upscale ratio (allowed values: 1, 2)\n"
+#ifdef HAVE_LIBHAMLIB
+		"  -M <n>, --hamlib-model <n>   set Hamlib radio model ID\n"
+		"  -C <s>, --hamlib-config <s>  set Hamlib config parameter\n"
+		"  -T <b>, --ensmeter <b>       enable S-Meter (0: off; 1: on)\n"
+#endif
+		"  --test <n>                   if 1 then some test setup will be done\n"
+		"  -h, -?, --help               this help text\n"
+		"\n"
+		"Example: $EXECNAME -p --sampleoff -0.23 -i 2"
+#ifdef QT_NETWORK_LIB
+		" -r 6140 --rsiout 127.0.0.1:3002"
+#endif
+		"";
+}
+
+_BOOLEAN
+CSettings::GetFlagArgument(int, char **argv, int &i,
+						   string strShortOpt, string strLongOpt)
+{
+	if ((!strShortOpt.compare(argv[i])) || (!strLongOpt.compare(argv[i])))
+		return TRUE;
+	else
+		return FALSE;
+}
+
+_BOOLEAN
+CSettings::GetStringArgument(int argc, char **argv, int &i,
+							 string strShortOpt, string strLongOpt,
+							 string & strArg)
+{
+	if ((!strShortOpt.compare(argv[i])) || (!strLongOpt.compare(argv[i])))
+	{
+		if (++i >= argc)
+		{
+			cerr << argv[0] << ": ";
+			cerr << "'" << strLongOpt << "' needs a string argument" << endl;
+			exit(1);
+		}
+
+		strArg = argv[i];
+
+		return TRUE;
+	}
+	else
+		return FALSE;
+}
+
+_BOOLEAN
+CSettings::GetNumericArgument(int argc, char **argv, int &i,
+							  string strShortOpt, string strLongOpt,
+							  _REAL rRangeStart, _REAL rRangeStop,
+							  _REAL & rValue)
+{
+	if ((!strShortOpt.compare(argv[i])) || (!strLongOpt.compare(argv[i])))
+	{
+		if (++i >= argc)
+		{
+			cerr << argv[0] << ": ";
+			cerr << "'" << strLongOpt << "' needs a numeric argument between "
+				<< rRangeStart << " and " << rRangeStop << endl;
+			exit(1);
+		}
+
+		char *p;
+		rValue = strtod(argv[i], &p);
+		if (*p || rValue < rRangeStart || rValue > rRangeStop)
+		{
+			cerr << argv[0] << ": ";
+			cerr << "'" << strLongOpt << "' needs a numeric argument between "
+				<< rRangeStart << " and " << rRangeStop << endl;
+			exit(1);
+		}
+
+		return TRUE;
+	}
+	else
+		return FALSE;
+}
+
+/* INI File routines using the STL ********************************************/
+/* The following code was taken from "INI File Tools (STLINI)" written by
+   Robert Kesterson in 1999. The original files are stlini.cpp and stlini.h.
+   The homepage is http://robertk.com/source
+
+   Copyright August 18, 1999 by Robert Kesterson */
+
+string
+CIniFile::GetIniSetting(const string& section,
+	 const string& key, const string& defaultval) const
+{
+	string result(defaultval);
+	const_cast<CMutex*>(&Mutex)->Lock();
+	INIFile::const_iterator iSection = ini.find(section);
+	if (iSection != ini.end())
+	{
+		INISection::const_iterator apair = iSection->second.find(key);
+		if (apair != iSection->second.end())
+		{
+			result = apair->second;
+		}
+	}
+	const_cast<CMutex*>(&Mutex)->Unlock();
+	return result;
+}
+
+void
+CIniFile::PutIniSetting(const string& section, const string& key, const string& value)
+{
+	Mutex.Lock();
+
+	/* null key is ok and empty value is ok but empty both is not useful */
+	if(key != "" || value != "")
+		ini[section][key]=value;
+
+	Mutex.Unlock();
+}
+
+bool
+CIniFile::LoadIni(const char *filename)
+{
+	string section;
+	ifstream file(filename);
+
+	bool ok = false;
+
+	while (file.good())
+	{
+		ok = true;
+
+		if(file.peek() == '[')
+		{
+			file.ignore(); // read '['
+			getline(file, section, ']');
+			file.ignore(80, '\n'); // read eol
+		}
+		else if(file.peek() == '\r')
+		{
+			file.ignore(); // read '\r'
+		}
+		else if(file.peek() == '\n')
+		{
+			file.ignore(10, '\n'); // read eol
+		}
+		else
+		{
+			string key,value;
+			getline(file, key, '=');
+			getline(file, value);
+			int n = int(value.length())-1;
+			if(n >= 0)
+			{
+				if(value[n] == '\r') // remove CR if file has DOS line endings
+					PutIniSetting(section, key, value.substr(0,n));
+				else
+					PutIniSetting(section, key, value);
+			}
+		}
+	}
+	return ok;
+}
+
+void
+CIniFile::SaveIni(const char *filename) const
+{
+	fstream file(filename, std::ios::out);
+	SaveIni(file);
+	file.close();
+}
+
+void
+CIniFile::SaveIni(ostream& file) const
+{
+	_BOOLEAN bFirstSection = TRUE;	/* Init flag */
+	if (!file.good())
+		return;
+
+	/* Just iterate the hashes and values and dump them to the stream */
+	for(INIFile::const_iterator section = ini.begin(); section != ini.end(); section++)
+	{
+		if (section->first != "command")
+		{
+			if (section->first > "")
+			{
+				if (bFirstSection == TRUE)
+				{
+					/* Don't put a newline at the beginning of the first section */
+					file << "[" << section->first << "]" << std::endl;
+
+					/* Reset flag */
+					bFirstSection = FALSE;
+				}
+				else
+					file << std::endl << "[" << section-> first << "]" << std::endl;
+			}
+
+			INISection::const_iterator pair = section->second.begin();
+
+			while (pair != section->second.end())
+			{
+				if (pair->second > "")
+					file << pair->first << "=" << pair->second << std::endl;
+				else
+					file << pair->first << "=" << std::endl;
+				pair++;
+			}
+		}
+	}
+}
+
+/* Return true or false depending on whether the first string is less than the
+   second */
+bool
+StlIniCompareStringNoCase::operator() (const string & x, const string & y) const
+{
+#ifdef _WIN32
+	return (_stricmp(x.c_str(), y.c_str()) < 0) ? true : false;
+#else
+	return (strcasecmp(x.c_str(), y.c_str()) < 0) ? true : false;
+#endif /* strcasecmp */
+}
diff --git a/src/util/Settings.h b/src/util/Settings.h
new file mode 100644
index 0000000..56d7e7a
--- /dev/null
+++ b/src/util/Settings.h
@@ -0,0 +1,183 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer, Robert Kesterson, Andrew Murphy
+ *
+ * Description:
+ *
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#if !defined(SETTINGS_H__3B0BA660_DGEG56GE64B2B_23DSG9876D31912__INCLUDED_)
+#define SETTINGS_H__3B0BA660_DGEG56GE64B2B_23DSG9876D31912__INCLUDED_
+
+#include "../GlobalDefinitions.h"
+#include <map>
+#include <string>
+
+
+/* Definitions ****************************************************************/
+#define DREAM_INIT_FILE_NAME		"Dream.ini"
+
+/* Maximum number of sound devices */
+#define MAX_NUM_SND_DEV				10
+
+/* Maximum number of iterations in MLC decoder */
+#define MAX_NUM_MLC_IT				4
+
+/* Maximum value of input/output channel selection */
+#define MAX_VAL_IN_CHAN_SEL			9
+#define MAX_VAL_OUT_CHAN_SEL		4
+
+/* Minimum and maximum of initial sample rate offset parameter */
+#define MIN_SAM_OFFS_INI			-200
+#define MAX_SAM_OFFS_INI			200
+
+/* Maximum for frequency acqisition search window size and center frequency */
+#define MAX_FREQ_AQC_SE_WIN_SZ		(+1e6)
+#define MAX_FREQ_AQC_SE_WIN_CT		(+1e6)
+
+/* Maximum carrier frequency  */
+# define MAX_RF_FREQ				30000 /* kHz */
+
+#ifdef QT_CORE_LIB
+/* Maximum minutes for delayed log file start */
+# define MAX_SEC_LOG_FI_START		3600 /* seconds */
+
+/* Maximum value for window position and size */
+# define MAX_WIN_GEOM_VAL			10000 /* Pixel */
+
+/* Maximum value for color schemes for main plot */
+# define MAX_COLOR_SCHEMES_VAL		(NUM_AVL_COLOR_SCHEMES_PLOT - 1)
+
+# define MAX_MDI_PORT_IN_NUM		65535
+#endif
+
+#ifdef HAVE_LIBHAMLIB
+/* Maximum ID number for hamlib library */
+# define MAX_ID_HAMLIB				32768
+#endif
+
+/* max magnitude of front-end cal factor */
+#define MAX_CAL_FACTOR				200
+
+/* change this if you expect to have huge lines in your INI files. Note that
+   this is the max size of a single line, NOT the max number of lines */
+#define MAX_INI_LINE				500
+
+/* Maximum number of chart windows and plot types */
+#define MAX_NUM_CHART_WIN_EV_DLG	50
+#define MAX_IND_CHART_TYPES			1000
+
+/* Maximum for preview */
+#define MAX_NUM_SEC_PREVIEW			3600
+
+/* Maximum value for rgb-colors encoded as integers */
+#define MAX_NUM_COL_MAIN_DISP		16777215
+
+/* Maximum for font weight (99 is written into the Qt reference manual) */
+#define MAX_FONT_WEIGHT				99
+
+/* Maximum for font point size (256 it is maybe not true but we assume that
+   this is a good value */
+#define MAX_FONT_POINT_SIZE			256
+
+/* Minimum number of seconds for MOT BWS refresh */
+#define MIN_MOT_BWS_REFRESH_TIME	5
+
+/* Miximum number of seconds for MOT BWS refresh */
+#define MAX_MOT_BWS_REFRESH_TIME	1800
+
+/* number of available color schemes for the plot */
+#define NUM_AVL_COLOR_SCHEMES_PLOT				3
+
+/* Classes ********************************************************************/
+	/* Function declarations for stlini code written by Robert Kesterson */
+	struct StlIniCompareStringNoCase
+	{
+		bool operator()(const std::string& x, const std::string& y) const;
+	};
+	/* These typedefs just make the code a bit more readable */
+	typedef std::map<string, string, StlIniCompareStringNoCase > INISection;
+	typedef std::map<string, INISection , StlIniCompareStringNoCase > INIFile;
+
+	class CWinGeom
+	{
+	public:
+		CWinGeom() : iXPos(0), iYPos(0), iHSize(0), iWSize(0) {}
+
+		int iXPos, iYPos;
+		int iHSize, iWSize;
+	};
+
+class CIniFile
+{
+public:
+	CIniFile() {}
+	virtual ~CIniFile() {}
+	void SaveIni(ostream&) const;
+	void SaveIni(const char*) const;
+	bool LoadIni(const char*);
+
+	string GetIniSetting(const string& strSection, const string& strKey,
+				const string& strDefaultVal = "") const;
+	void PutIniSetting(const string& strSection, const string& strKey="",
+				const string& strVal = "");
+protected:
+	INIFile ini;
+	CMutex Mutex;
+};
+
+class CSettings: public CIniFile
+{
+public:
+	CSettings() {}
+	void Load(int argc, char** argv);
+	void Save();
+	void Clear();
+	string Get(const string& section, const string& key, const string& def="") const;
+	void Put(const string& section, const string& key, const string& value);
+	bool Get(const string& section, const string& key, const bool def) const;
+	void Put(const string& section, const string& key, const bool value);
+	int Get(const string& section, const string& key, const int def) const;
+	void Put(const string& section, const string& key, const int value);
+	_REAL Get(const string& section, const string& key, const _REAL def) const;
+	void Put(const string& section, const string& key, const _REAL value);
+	void Get(const string& section, CWinGeom&) const;
+	void Put(const string& section, const CWinGeom&);
+	const char* UsageArguments();
+
+protected:
+	int IsReceiver(const char *argv0);
+	void ParseArguments(int argc, char** argv);
+	void FileArg(const string&);
+	_BOOLEAN GetFlagArgument(int argc, char** argv, int& i, string strShortOpt,
+							 string strLongOpt);
+	_BOOLEAN GetNumericArgument(int argc, char** argv, int& i,
+								string strShortOpt, string strLongOpt,
+								_REAL rRangeStart, _REAL rRangeStop,
+								_REAL& rValue);
+	_BOOLEAN GetStringArgument(int argc, char** argv, int& i,
+							   string strShortOpt, string strLongOpt,
+							   string& strArg);
+};
+
+#endif // !defined(SETTINGS_H__3B0BA660_DGEG56GE64B2B_23DSG9876D31912__INCLUDED_)
diff --git a/src/util/Utilities.cpp b/src/util/Utilities.cpp
new file mode 100644
index 0000000..114dad0
--- /dev/null
+++ b/src/util/Utilities.cpp
@@ -0,0 +1,462 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "Utilities.h"
+#include <sstream>
+#include <cstring>
+#if defined(_WIN32)
+# ifdef HAVE_SETUPAPI
+#  ifndef INITGUID
+#   define INITGUID 1
+#  endif
+#  include <windows.h>
+#  include <setupapi.h>
+# endif
+#elif defined(__APPLE__)
+#include <CoreFoundation/CoreFoundation.h>
+#include <IOKit/IOKitLib.h>
+#include <IOKit/serial/IOSerialKeys.h>
+#endif
+
+/* Implementation *************************************************************/
+/******************************************************************************\
+* Thread safe counter                                                          *
+\******************************************************************************/
+unsigned int CCounter::operator++()
+	{ unsigned int value; mutex.Lock(); value = ++count; mutex.Unlock(); return value; }
+unsigned int CCounter::operator++(int)
+	{ unsigned int value; mutex.Lock(); value = count++; mutex.Unlock(); return value; }
+unsigned int CCounter::operator--()
+	{ unsigned int value; mutex.Lock(); value = --count; mutex.Unlock(); return value; }
+unsigned int CCounter::operator--(int)
+	{ unsigned int value; mutex.Lock(); value = count--; mutex.Unlock(); return value; }
+CCounter::operator unsigned int()
+	{ unsigned int value; mutex.Lock(); value = count;   mutex.Unlock(); return value; }
+unsigned int CCounter::operator=(unsigned int value)
+	{ mutex.Lock(); count = value; mutex.Unlock(); return value; }
+
+/******************************************************************************\
+* Signal level meter                                                           *
+\******************************************************************************/
+void
+CSignalLevelMeter::Update(const _REAL rVal)
+{
+	/* Search for maximum. Decrease this max with time */
+	/* Decrease max with time */
+	if (rCurLevel >= METER_FLY_BACK)
+		rCurLevel -= METER_FLY_BACK;
+	else
+	{
+		if ((rCurLevel <= METER_FLY_BACK) && (rCurLevel > 1))
+			rCurLevel -= 2;
+	}
+
+	/* Search for max */
+	const _REAL rCurAbsVal = Abs(rVal);
+	if (rCurAbsVal > rCurLevel)
+		rCurLevel = rCurAbsVal;
+}
+
+void
+CSignalLevelMeter::Update(const CVector < _REAL > vecrVal)
+{
+	/* Do the update for entire vector */
+	const int iVecSize = vecrVal.Size();
+	for (int i = 0; i < iVecSize; i++)
+		Update(vecrVal[i]);
+}
+
+void
+CSignalLevelMeter::Update(const CVector < _SAMPLE > vecsVal)
+{
+	/* Do the update for entire vector, convert to real */
+	const int iVecSize = vecsVal.Size();
+	for (int i = 0; i < iVecSize; i++)
+		Update((_REAL) vecsVal[i]);
+}
+
+_REAL CSignalLevelMeter::Level()
+{
+	const _REAL
+		rNormMicLevel = rCurLevel / _MAXSHORT;
+
+	/* Logarithmic measure */
+	if (rNormMicLevel > 0)
+		return 20.0 * log10(rNormMicLevel);
+	else
+		return RET_VAL_LOG_0;
+}
+
+/******************************************************************************\
+* Bandpass filter                                                              *
+\******************************************************************************/
+void
+CDRMBandpassFilt::Process(CVector < _COMPLEX > &veccData)
+{
+	int i;
+
+	/* Copy CVector data in CMatlibVector */
+	for (i = 0; i < iBlockSize; i++)
+		cvecDataTmp[i] = veccData[i];
+
+	/* Apply FFT filter */
+	cvecDataTmp =
+		CComplexVector(FftFilt
+					   (cvecB, Real(cvecDataTmp), rvecZReal, FftPlanBP),
+					   FftFilt(cvecB, Imag(cvecDataTmp), rvecZImag,
+							   FftPlanBP));
+
+	/* Copy CVector data in CMatlibVector */
+	for (i = 0; i < iBlockSize; i++)
+		veccData[i] = cvecDataTmp[i];
+}
+
+void
+CDRMBandpassFilt::Init(int iSampleRate, int iNewBlockSize, _REAL rOffsetHz,
+					   ESpecOcc eSpecOcc, EFiltType eNFiTy)
+{
+	CReal rMargin = 0.0;
+
+	/* Set internal parameter */
+	iBlockSize = iNewBlockSize;
+
+	/* Init temporary vector */
+	cvecDataTmp.Init(iBlockSize);
+
+	/* Choose correct filter for chosen DRM bandwidth. Also, adjust offset
+	   frequency for different modes. E.g., 5 kHz mode is on the right side
+	   of the DC frequency */
+	CReal rNormCurFreqOffset = rOffsetHz / iSampleRate;
+	/* Band-pass filter bandwidth */
+	CReal rBPFiltBW = ((CReal) 10000.0 + rMargin) / iSampleRate;
+
+	/* Negative margin for receiver filter for better interferer rejection */
+	if (eNFiTy == FT_TRANSMITTER)
+		rMargin = (CReal) 300.0;	/* Hz */
+	else
+		rMargin = (CReal) - 200.0;	/* Hz */
+
+	switch (eSpecOcc)
+	{
+	case SO_0:
+		rBPFiltBW = ((CReal) 4500.0 + rMargin) / iSampleRate;
+
+		/* Completely on the right side of DC */
+		rNormCurFreqOffset =
+			(rOffsetHz + (CReal) 2190.0) / iSampleRate;
+		break;
+
+	case SO_1:
+		rBPFiltBW = ((CReal) 5000.0 + rMargin) / iSampleRate;
+
+		/* Completely on the right side of DC */
+		rNormCurFreqOffset =
+			(rOffsetHz + (CReal) 2440.0) / iSampleRate;
+		break;
+
+	case SO_2:
+		rBPFiltBW = ((CReal) 9000.0 + rMargin) / iSampleRate;
+
+		/* Centered */
+		rNormCurFreqOffset = rOffsetHz / iSampleRate;
+		break;
+
+	case SO_3:
+		rBPFiltBW = ((CReal) 10000.0 + rMargin) / iSampleRate;
+
+		/* Centered */
+		rNormCurFreqOffset = rOffsetHz / iSampleRate;
+		break;
+
+	case SO_4:
+		rBPFiltBW = ((CReal) 18000.0 + rMargin) / iSampleRate;
+
+		/* Main part on the right side of DC */
+		rNormCurFreqOffset =
+			(rOffsetHz + (CReal) 4500.0) / iSampleRate;
+		break;
+
+	case SO_5:
+		rBPFiltBW = ((CReal) 20000.0 + rMargin) / iSampleRate;
+
+		/* Main part on the right side of DC */
+		rNormCurFreqOffset =
+			(rOffsetHz + (CReal) 5000.0) / iSampleRate;
+		break;
+	case SO_6: // TODO
+		;
+	}
+
+	/* FFT plan is initialized with the long length */
+	FftPlanBP.Init(iBlockSize * 2);
+
+	/* State memory (init with zeros) and data vector */
+	rvecZReal.Init(iBlockSize, (CReal) 0.0);
+	rvecZImag.Init(iBlockSize, (CReal) 0.0);
+	rvecDataReal.Init(iBlockSize);
+	rvecDataImag.Init(iBlockSize);
+
+	/* "+ 1" because of the Nyquist frequency (filter in frequency domain) */
+	cvecB.Init(iBlockSize + 1);
+
+	/* Actual filter design */
+	CRealVector vecrFilter(iBlockSize);
+	vecrFilter = FirLP(rBPFiltBW, Nuttallwin(iBlockSize));
+
+	/* Copy actual filter coefficients. It is important to initialize the
+	   vectors with zeros because we also do a zero-padding */
+	CRealVector rvecB(2 * iBlockSize, (CReal) 0.0);
+
+	/* Modulate filter to shift it to the correct IF frequency */
+	for (int i = 0; i < iBlockSize; i++)
+	{
+		rvecB[i] =
+			vecrFilter[i] * Cos((CReal) 2.0 * crPi * rNormCurFreqOffset * i);
+	}
+
+	/* Transformation in frequency domain for fft filter */
+	cvecB = rfft(rvecB, FftPlanBP);
+}
+
+/******************************************************************************\
+* Modified Julian Date                                                         *
+\******************************************************************************/
+void
+CModJulDate::Set(const uint32_t iModJulDate)
+{
+	uint32_t iZ, iA, iAlpha, iB, iC, iD, iE;
+	_REAL rJulDate/*, rF*/;
+
+	/* Definition of the Modified Julian Date */
+	rJulDate = (_REAL) iModJulDate + 2400000.5;
+
+	/* Get "real" date out of Julian Date
+	   (Taken from "http://mathforum.org/library/drmath/view/51907.html") */
+	// 1. Add .5 to the JD and let Z = integer part of (JD+.5) and F the
+	// fractional part F = (JD+.5)-Z
+	iZ = (uint32_t) (rJulDate + (_REAL) 0.5);
+//	rF = (rJulDate + (_REAL) 0.5) - iZ;
+
+	// 2. If Z < 2299161, take A = Z
+	// If Z >= 2299161, calculate alpha = INT((Z-1867216.25)/36524.25)
+	// and A = Z + 1 + alpha - INT(alpha/4).
+	if (iZ < 2299161)
+		iA = iZ;
+	else
+	{
+		iAlpha = (int) (((_REAL) iZ - (_REAL) 1867216.25) / (_REAL) 36524.25);
+		iA = iZ + 1 + iAlpha - (int) ((_REAL) iAlpha / (_REAL) 4.0);
+	}
+
+	// 3. Then calculate:
+	// B = A + 1524
+	// C = INT( (B-122.1)/365.25)
+	// D = INT( 365.25*C )
+	// E = INT( (B-D)/30.6001 )
+	iB = iA + 1524;
+	iC = (int) (((_REAL) iB - (_REAL) 122.1) / (_REAL) 365.25);
+	iD = (int) ((_REAL) 365.25 * iC);
+	iE = (int) (((_REAL) iB - iD) / (_REAL) 30.6001);
+
+	// The day of the month dd (with decimals) is:
+	// dd = B - D - INT(30.6001*E) + F
+	iDay = iB - iD - (int) ((_REAL) 30.6001 * iE);	// + rF;
+
+	// The month number mm is:
+	// mm = E - 1, if E < 13.5
+	// or
+	// mm = E - 13, if E > 13.5
+	if ((_REAL) iE < 13.5)
+		iMonth = iE - 1;
+	else
+		iMonth = iE - 13;
+
+	// The year yyyy is:
+	// yyyy = C - 4716   if m > 2.5
+	// or
+	// yyyy = C - 4715   if m < 2.5
+	if ((_REAL) iMonth > 2.5)
+		iYear = iC - 4716;
+	else
+		iYear = iC - 4715;
+}
+
+void
+CModJulDate::Get(const uint32_t iYear, const uint32_t iMonth, const uint32_t iDay)
+{
+	/* Taken from "http://en.wikipedia.org/wiki/Julian_day" */
+	uint32_t a = (14 - iMonth) / 12;
+	uint32_t y = iYear + 4800 - a;
+	uint32_t m = iMonth + 12*a - 3;;
+	uint32_t iJulDate = iDay + (153*m+2)/5 + 365*y + y/4 - y/100 + y/400 - 32045;
+	iModJulDate = iJulDate - 2400001;
+}
+
+/******************************************************************************\
+* Audio Reverberation                                                          *
+\******************************************************************************/
+/*
+	The following code is based on "JCRev: John Chowning's reverberator class"
+	by Perry R. Cook and Gary P. Scavone, 1995 - 2001-2014
+	which is in "The Synthesis ToolKit in C++ (STK)"
+	http://ccrma.stanford.edu/software/stk
+
+	Original description:
+	This class is derived from the CLM JCRev function, which is based on the use
+	of networks of simple allpass and comb delay filters. This class implements
+	three series allpass units, followed by four parallel comb filters, and two
+	decorrelation delay lines in parallel at the output.
+*/
+void CAudioReverb::Init(CReal rT60, int iSampleRate)
+{
+	/* Delay lengths for 44100 Hz sample rate */
+	int lengths[9] = { 1777, 1847, 1993, 2137, 389, 127, 43, 211, 179 };
+	const CReal scaler = CReal(iSampleRate) / 44100.0;
+
+	int delay, i;
+	if (scaler != 1.0)
+	{
+		for (i = 0; i < 9; i++)
+		{
+			delay = (int) Floor(scaler * lengths[i]);
+
+			if ((delay & 1) == 0)
+				delay++;
+
+			while (!isPrime(delay))
+				delay += 2;
+
+			lengths[i] = delay;
+		}
+	}
+
+	for (i = 0; i < 3; i++)
+		allpassDelays_[i].Init(lengths[i + 4]);
+
+	for (i = 0; i < 4; i++)
+		combDelays_[i].Init(lengths[i]);
+
+	setT60(rT60, iSampleRate);
+	allpassCoefficient_ = (CReal) 0.7;
+	Clear();
+}
+
+_BOOLEAN CAudioReverb::isPrime(const int number)
+{
+/*
+	Returns true if argument value is prime. Taken from "class Effect" in
+	"STK abstract effects parent class".
+*/
+	if (number == 2)
+		return TRUE;
+
+	if (number & 1)
+	{
+		for (int i = 3; i < (int) Sqrt((CReal) number) + 1; i += 2)
+		{
+			if ((number % i) == 0)
+				return FALSE;
+		}
+
+		return TRUE;			/* prime */
+	}
+	else
+		return FALSE;			/* even */
+}
+
+void
+CAudioReverb::Clear()
+{
+	/* Reset and clear all internal state */
+	allpassDelays_[0].Reset(0);
+	allpassDelays_[1].Reset(0);
+	allpassDelays_[2].Reset(0);
+	combDelays_[0].Reset(0);
+	combDelays_[1].Reset(0);
+	combDelays_[2].Reset(0);
+	combDelays_[3].Reset(0);
+}
+
+void
+CAudioReverb::setT60(const CReal rT60, int iSampleRate)
+{
+	/* Set the reverberation T60 decay time */
+	for (int i = 0; i < 4; i++)
+	{
+		combCoefficient_[i] = pow((CReal) 10.0, (CReal) (-3.0 * combDelays_[i].  Size() / (rT60 * iSampleRate)));
+	}
+}
+
+CReal CAudioReverb::ProcessSample(const CReal rLInput, const CReal rRInput)
+{
+	/* Compute one output sample */
+	CReal
+		temp,
+		temp0,
+		temp1,
+		temp2;
+
+	/* Mix stereophonic input signals to mono signal (since the maximum value of
+	   the input signal is 0.5 * max due to the current implementation in
+	   AudioSourceDecoder.cpp, we cannot get an overrun) */
+	const CReal
+		input = rLInput + rRInput;
+
+	temp = allpassDelays_[0].Get();
+	temp0 = allpassCoefficient_ * temp;
+	temp0 += input;
+	allpassDelays_[0].Add((int) temp0);
+	temp0 = -(allpassCoefficient_ * temp0) + temp;
+
+	temp = allpassDelays_[1].Get();
+	temp1 = allpassCoefficient_ * temp;
+	temp1 += temp0;
+	allpassDelays_[1].Add((int) temp1);
+	temp1 = -(allpassCoefficient_ * temp1) + temp;
+
+	temp = allpassDelays_[2].Get();
+	temp2 = allpassCoefficient_ * temp;
+	temp2 += temp1;
+	allpassDelays_[2].Add((int) temp2);
+	temp2 = -(allpassCoefficient_ * temp2) + temp;
+
+	const CReal
+		temp3 = temp2 + (combCoefficient_[0] * combDelays_[0].Get());
+	const CReal
+		temp4 = temp2 + (combCoefficient_[1] * combDelays_[1].Get());
+	const CReal
+		temp5 = temp2 + (combCoefficient_[2] * combDelays_[2].Get());
+	const CReal
+		temp6 = temp2 + (combCoefficient_[3] * combDelays_[3].Get());
+
+	combDelays_[0].Add((int) temp3);
+	combDelays_[1].Add((int) temp4);
+	combDelays_[2].Add((int) temp5);
+	combDelays_[3].Add((int) temp6);
+
+	return temp3 + temp4 + temp5 + temp6;
+}
diff --git a/src/util/Utilities.h b/src/util/Utilities.h
new file mode 100644
index 0000000..42ba620
--- /dev/null
+++ b/src/util/Utilities.h
@@ -0,0 +1,184 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *	Implements:
+ *	- Signal level meter
+ *	- Bandpass filter
+ *	- Modified Julian Date
+ *	- Reverberation effect
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#if !defined(UTILITIES_H__3B0BA660_CA63_4344_B3452345D31912__INCLUDED_)
+#define UTILITIES_H__3B0BA660_CA63_4344_B3452345D31912__INCLUDED_
+
+#include "../GlobalDefinitions.h"
+#include "Settings.h"
+#include "Vector.h"
+#include "../matlib/Matlib.h"
+#include <map>
+#include <iostream>
+
+#ifdef HAVE_LIBHAMLIB
+# include <hamlib/rig.h>
+#endif
+
+
+/* Definitions ****************************************************************/
+#define	METER_FLY_BACK					15
+
+/* Classes ********************************************************************/
+/* Thread safe counter ------------------------------------------------------ */
+class CCounter
+{
+public:
+	CCounter() : count(0) {}
+	~CCounter() {}
+	unsigned int operator++();
+	unsigned int operator++(int);
+	unsigned int operator--();
+	unsigned int operator--(int);
+	operator unsigned int();
+	unsigned int operator=(unsigned int value);
+private:
+	CMutex mutex;
+	unsigned int count;
+};
+
+
+/* Signal level meter ------------------------------------------------------- */
+class CSignalLevelMeter
+{
+public:
+	CSignalLevelMeter() : rCurLevel((_REAL) 0.0) {}
+	virtual ~CSignalLevelMeter() {}
+
+	void Init(_REAL rStartVal) {rCurLevel = Abs(rStartVal);}
+	void Update(const _REAL rVal);
+	void Update(const CVector<_REAL> vecrVal);
+	void Update(const CVector<_SAMPLE> vecsVal);
+	_REAL Level();
+
+protected:
+	_REAL rCurLevel;
+};
+
+
+/* Bandpass filter ---------------------------------------------------------- */
+class CDRMBandpassFilt
+{
+public:
+	enum EFiltType {FT_TRANSMITTER, FT_RECEIVER};
+
+	void Init(int iSampleRate, int iNewBlockSize, _REAL rOffsetHz,
+		ESpecOcc eSpecOcc, EFiltType eNFiTy);
+	void Process(CVector<_COMPLEX>& veccData);
+
+protected:
+	int				iBlockSize;
+
+	CComplexVector	cvecDataTmp;
+
+	CRealVector		rvecZReal; /* State memory real part */
+	CRealVector		rvecZImag; /* State memory imaginary part */
+	CRealVector		rvecDataReal;
+	CRealVector		rvecDataImag;
+	CFftPlans		FftPlanBP;
+	CComplexVector	cvecB;
+};
+
+
+/* Modified Julian Date ----------------------------------------------------- */
+class CModJulDate
+{
+public:
+	CModJulDate() : iYear(0), iDay(0), iMonth(0), iModJulDate(0) {}
+	CModJulDate(const uint32_t iModJulDate) {Set(iModJulDate);}
+	CModJulDate(const uint32_t iYear, const uint32_t iMonth, const uint32_t iDay)
+		{Get(iYear, iMonth, iDay);}
+
+	void Set(const uint32_t iModJulDate);
+	void Get(const uint32_t iYear, const uint32_t iMonth, const uint32_t iDay);
+
+	int GetYear() {return iYear;}
+	int GetDay() {return iDay;}
+	int GetMonth() {return iMonth;}
+	int GetModJulDate() {return iModJulDate;}
+
+protected:
+	int iYear, iDay, iMonth, iModJulDate;
+};
+
+
+/* Audio Reverbration ------------------------------------------------------- */
+class CAudioReverb
+{
+public:
+	CAudioReverb() {}
+	void Init(CReal rT60, int iSampleRate);
+	void Clear();
+	CReal ProcessSample(const CReal rLInput, const CReal rRInput);
+
+protected:
+	void setT60(const CReal rT60, int iSampleRate);
+	_BOOLEAN isPrime(const int number);
+
+	CFIFO<int>	allpassDelays_[3];
+	CFIFO<int>	combDelays_[4];
+	CReal		allpassCoefficient_;
+	CReal		combCoefficient_[4];
+};
+
+inline int Complement2toInt(const unsigned int iSize, CVector<_BINARY>* pbiData)
+{
+	int iVal = 0;
+	const int iVecSize = iSize - 1;
+
+	_BINARY bSign = (_BINARY)(*pbiData).Separate(1);
+
+	if (bSign == 0)
+		iVal = (int) (*pbiData).Separate(iVecSize);
+	else
+	{
+		int k;
+
+		unsigned int iPowerOf2 = 1;
+
+		iPowerOf2 <<= (iVecSize - 1); /* power(2,iVecSize-1) */
+
+		for (k = iVecSize - 1; k >= 0; k--)
+		{
+			if ((*pbiData).Separate(1) == 0)
+				iVal = iVal + iPowerOf2;
+
+			iPowerOf2 >>= 1; /* divide for 2 */
+		}
+
+		iVal = -1 * (iVal + 1);
+	}
+
+	return iVal;
+}
+
+#endif // !defined(UTILITIES_H__3B0BA660_CA63_4344_B3452345D31912__INCLUDED_)
diff --git a/src/util/Vector.h b/src/util/Vector.h
new file mode 100644
index 0000000..c08747f
--- /dev/null
+++ b/src/util/Vector.h
@@ -0,0 +1,515 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *	
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later 
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT 
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#if !defined(VECTOR_H__3B0BA660_CA6LIUBEFIB2B_23E7A0D31912__INCLUDED_)
+#define VECTOR_H__3B0BA660_CA6LIUBEFIB2B_23E7A0D31912__INCLUDED_
+
+#include "../GlobalDefinitions.h"
+#include <vector>
+
+
+/******************************************************************************\
+* CVector base class                                                           *
+\******************************************************************************/
+template<class TData> class CVector : public vector<TData>
+{
+public:
+	CVector() : iBitArrayCounter(0), iVectorSize(0) {pData = this->begin();}
+	CVector(const int iNeSi) {Init(iNeSi);}
+	CVector(const int iNeSi, const TData tInVa) {Init(iNeSi, tInVa);}
+	virtual	~CVector() {}
+
+	/* Copy constructor: The order of the initialization list must not be
+	   changed. First, the base class must be initialized, then the pData
+	   pointer must be set to the new data source. The bit access is, by
+	   default, reset */
+	CVector(const CVector<TData>& vecI) :
+		vector<TData>(static_cast<const vector<TData>&>(vecI)),
+		iBitArrayCounter(0), iVectorSize(vecI.Size()) {pData = this->begin();}
+
+	virtual void Init(const int iNewSize);
+
+	/* Use this init to give all elements a defined value */
+	virtual void Init(const int iNewSize, const TData tIniVal);
+	void Reset(const TData tResetVal);
+
+	void Enlarge(const int iAddedSize);
+	void Add(const TData& tI) {Enlarge(1); pData[iVectorSize - 1] = tI;}
+
+	inline int Size() const {return iVectorSize;}
+
+	/* This operator allows for a l-value assignment of this object:
+	   CVector[x] = y is possible */
+	inline TData& operator[](const int iPos) {
+#ifdef _DEBUG_
+		if ((iPos < 0) || (iPos > iVectorSize - 1))
+		{
+			DebugError("Writing vector out of bounds", "Vector size",
+				iVectorSize, "New parameter", iPos);
+		}
+#endif		
+		return pData[iPos];}
+
+	inline TData operator[](const int iPos) const {
+#ifdef _DEBUG_
+		if ((iPos < 0) || (iPos > iVectorSize - 1))
+		{
+			DebugError("Reading vector out of bounds", "Vector size",
+				iVectorSize, "New parameter", iPos);
+		}
+#endif
+		return pData[iPos];}
+
+	inline CVector<TData>& operator=(const CVector<TData>& vecI) {
+#ifdef _DEBUG_
+		/* Vectors which shall be copied MUST have same size! (If this is
+		   satisfied, the parameter "iVectorSize" must not be adjusted as
+		   a side effect) */
+		if (vecI.Size() != iVectorSize)
+		{
+			DebugError("Vector operator=() different size", "Vector size",
+				iVectorSize, "New parameter", vecI.Size());
+		}
+#endif
+		vector<TData>::operator=(vecI);
+
+		/* Reset my data pointer in case, the operator=() of the base class
+		   did change the actual memory */
+		pData = this->begin();
+
+		return *this;
+	}
+
+
+	/* Bit operation functions */
+	void		Enqueue(uint32_t iInformation, const int iNumOfBits);
+	uint32_t	Separate(const int iNumOfBits);
+	void		ResetBitAccess() {iBitArrayCounter = 0;}
+
+protected:
+	typename vector<TData>::iterator	pData;
+	int									iBitArrayCounter;
+	int									iVectorSize;
+};
+
+
+/* Implementation *************************************************************/
+template<class TData> void CVector<TData>::Init(const int iNewSize)
+{
+	iVectorSize = iNewSize;
+
+	/* Clear old buffer and reserve memory for new buffer, get iterator
+	   for pointer operations */
+	this->clear();
+	this->resize(iNewSize);
+	pData = this->begin();
+}
+
+template<class TData> void CVector<TData>::Init(const int iNewSize, 
+												const TData tIniVal)
+{
+	/* Call actual init routine */
+	Init(iNewSize);
+
+	/* Set values */
+	Reset(tIniVal);
+}
+
+template<class TData> void CVector<TData>::Enlarge(const int iAddedSize)
+{
+	iVectorSize += iAddedSize;
+	this->resize(iVectorSize);
+
+	/* We have to reset the pointer since it could be that the vector size was
+	   zero before enlarging the vector */
+	pData = this->begin();
+}
+
+template<class TData> void CVector<TData>::Reset(const TData tResetVal)
+{
+	/* Set all values to reset value */
+	for (int i = 0; i < iVectorSize; i++)
+		pData[i] = tResetVal;
+}
+
+template<class TData> void CVector<TData>::Enqueue(uint32_t iInformation,
+												   const int iNumOfBits)
+{
+	/* Enqueue bits in bit array */
+	for (int i = 0; i < iNumOfBits; i++)
+	{
+		/* We want to put the bits on the array with the MSB first
+		 * - Visual Studio 2010 was getting this wrong
+		 */
+		if(iInformation & 1)
+			operator[](iBitArrayCounter + iNumOfBits - i - 1) = 1;
+		else
+			operator[](iBitArrayCounter + iNumOfBits - i - 1) = 0;
+
+		/* Shift one bit to mask next bit at LSB-position */
+		iInformation >>= 1;
+	}
+
+	iBitArrayCounter += iNumOfBits;
+}
+
+template<class TData> uint32_t CVector<TData>::Separate(const int iNumOfBits)
+{
+	uint32_t iInformation;
+
+	/* Check, if current position plus new bit-size is smaller than the maximum
+	   length of the bit vector. Error code: return a "0" */
+	if (iBitArrayCounter + iNumOfBits > iVectorSize)
+		return 0;
+
+	/* Separate out bits from bit-array */
+	iInformation = 0;
+	for (int i = 0; i < iNumOfBits; i++)
+	{
+		/* MSB comes first, therefore shift left */
+		iInformation <<= 1;
+
+		iInformation |= pData[iBitArrayCounter + i] & 1;
+	}
+
+	iBitArrayCounter += iNumOfBits;
+
+	return iInformation;
+}
+
+
+/******************************************************************************\
+* CShiftRegister class                                                         *
+\******************************************************************************/
+template<class TData> class CShiftRegister : public CVector<TData>
+{
+public:
+	CShiftRegister() : CVector<TData>() {}
+	CShiftRegister(const int iNeSi) : CVector<TData>(iNeSi) {}
+	CShiftRegister(const int iNeSi, const TData tInVa) :
+		CVector<TData>(iNeSi, tInVa) {}
+
+	/* Add one value at the beginning, shift the others to the right */
+	void AddBegin(const TData tNewD);
+
+	/* Add one value at the end, shift the others to the left */
+	void AddEnd(const TData tNewD);
+
+	/* Add a vector at the end, shift others to the left */
+	void AddEnd(const CVector<TData>& vectNewD, const int iLen);
+};
+
+
+/* Implementation *************************************************************/
+template<class TData> void CShiftRegister<TData>::AddBegin(const TData tNewD)
+{
+	/* Shift old values */
+	for (int i = this->iVectorSize - 1; i > 0; i--)
+		this->pData[i] = this->pData[i - 1];
+
+	/* Add new value */
+	this->pData[0] = tNewD;
+}
+
+template<class TData> void CShiftRegister<TData>::AddEnd(const TData tNewD)
+{
+	/* Shift old values */
+	for (int i = 0; i < this->iVectorSize - 1; i++)
+		this->pData[i] = this->pData[i + 1];
+
+	/* Add new value */
+	this->pData[this->iVectorSize - 1] = tNewD;
+}
+
+template<class TData> void CShiftRegister<TData>::AddEnd(const CVector<TData>& vectNewD,
+														 const int iLen)
+{
+	int i, iBlockEnd, iMovLen;
+
+	iBlockEnd = this->iVectorSize - iLen;
+	iMovLen = iLen;
+
+	/* Shift old values */
+	for (i = 0; i < iBlockEnd; i++)
+		this->pData[i] = this->pData[iMovLen++];
+
+	/* Add new block of data */
+	for (i = 0; i < iLen; i++)
+		this->pData[iBlockEnd++] = vectNewD[i];
+}
+
+
+/******************************************************************************\
+* CFIFO class (first in, first out)                                            *
+\******************************************************************************/
+template<class TData> class CFIFO : public CVector<TData>
+{
+public:
+	CFIFO() : CVector<TData>(), iCurIdx(0) {}
+	CFIFO(const int iNeSi) : CVector<TData>(iNeSi), iCurIdx(0) {}
+	CFIFO(const int iNeSi, const TData tInVa) :
+		CVector<TData>(iNeSi, tInVa), iCurIdx(0) {}
+
+	void Add(const TData tNewD);
+	inline TData Get() {return this->pData[iCurIdx];}
+
+	virtual void Init(const int iNewSize);
+	virtual void Init(const int iNewSize, const TData tIniVal);
+
+protected:
+	int iCurIdx;
+};
+
+template<class TData> void CFIFO<TData>::Init(const int iNewSize)
+{
+	iCurIdx = 0;
+	CVector<TData>::Init(iNewSize);
+}
+
+template<class TData> void CFIFO<TData>::Init(const int iNewSize,
+											  const TData tIniVal)
+{
+	iCurIdx = 0;
+	CVector<TData>::Init(iNewSize, tIniVal);
+}
+
+template<class TData> void CFIFO<TData>::Add(const TData tNewD)
+{
+	this->pData[iCurIdx] = tNewD;
+
+	/* Increment index */
+	iCurIdx++;
+	if (iCurIdx >= this->iVectorSize)
+		iCurIdx = 0;
+}
+
+
+/******************************************************************************\
+* CMovingAv class (moving average)                                             *
+\******************************************************************************/
+template<class TData> class CMovingAv : public CVector<TData>
+{
+public:
+	CMovingAv() : CVector<TData>(), iCurIdx(0) {}
+	CMovingAv(const int iNeSi) : CVector<TData>(iNeSi), iCurIdx(0) {}
+	CMovingAv(const int iNeSi, const TData tInVa) :
+		CVector<TData>(iNeSi, tInVa), iCurIdx(0) {}
+
+	void Add(const TData tNewD);
+	inline TData GetAverage() {return tCurAvResult;}
+
+	virtual void Init(const int iNewSize);
+	void InitVec(const int iNewSize, const int iNewVecSize);
+
+protected:
+	int		iCurIdx;
+	TData	tCurAvResult;
+};
+
+template<class TData> void CMovingAv<TData>::InitVec(const int iNewSize,
+													 const int iNewVecSize)
+{
+	iCurIdx = 0;
+	CVector<TData>::Init(iNewSize);
+
+	/* Init each vector in vector */
+	for (int i = 0; i < iNewSize; i++)
+		this->pData[i].Init(iNewVecSize, 0);
+
+	/* Init current average result */
+	tCurAvResult.Init(iNewVecSize, 0);
+}
+
+template<class TData> void CMovingAv<TData>::Init(const int iNewSize)
+{
+	iCurIdx = 0;
+	tCurAvResult = TData(0); /* Only for scalars! */
+	CVector<TData>::Init(iNewSize);
+}
+
+template<class TData> void CMovingAv<TData>::Add(const TData tNewD)
+{
+/*
+	Optimized calculation of the moving average. We only add a new value and
+	subtract the old value from the result. We only need one addition and a
+	history buffer
+*/
+	/* Subtract oldest value */
+	tCurAvResult -= this->pData[iCurIdx];
+
+	/* Add new value and write in memory */
+	tCurAvResult += tNewD;
+	this->pData[iCurIdx] = tNewD;
+
+	/* Increase position pointer and test if wrap */
+	iCurIdx++;
+	if (iCurIdx >= this->iVectorSize)
+		iCurIdx = 0;
+}
+
+
+/******************************************************************************\
+* CVectorEx class (Extended vector with additional information)                *
+\******************************************************************************/
+class CExtendedVecData
+{
+public:
+	/* Symbol ID of the current block. This number only identyfies the
+	   position in a frame, NOT in a super-frame */
+	int			iSymbolID;
+
+	/* This flag indicates that the symbol ID has changed */
+	_BOOLEAN	bSymbolIDHasChanged;
+
+	/* The channel estimation needs information about timing corrections,
+	   because it is using information from the symbol memory */
+	int			iCurTimeCorr;
+};
+
+template<class TData> class CVectorEx : public CVector<TData>
+{
+public:
+	CVectorEx() {}
+	virtual	~CVectorEx() {}
+
+	CExtendedVecData&	GetExData() {return ExtendedData;}
+	void				SetExData(CExtendedVecData& NewExData) 
+							{ExtendedData = NewExData;}
+
+protected:
+	CExtendedVecData ExtendedData;
+};
+
+
+/******************************************************************************\
+* CMatrix base class                                                           *
+\******************************************************************************/
+template<class TData> class CMatrix
+{
+public:
+	CMatrix() : ppData(NULL), iRow(0), iCol(0) {}
+	CMatrix(const int iNewR, const int iNewC) {Init(iNewR, iNewC);}
+	CMatrix(const int iNewR, const int iNewC, const TData tInVa) 
+		{Init(iNewR, iNewC, tInVa);}
+	CMatrix(const CMatrix& m): ppData(NULL) {
+		Init(m.iRow,m.iCol); 
+		for (int i=0; i<m.NumRows(); i++)
+			ppData[i] = m[i];
+	}
+	virtual	~CMatrix();
+
+	void Init(const int iNewRow, const int iNewColumn);
+
+	/* Use this init to give all elements a defined value */
+	void Init(const int iNewRow, const int iNewColumn, const TData tIniVal);
+	void Reset(const TData tResetVal);
+
+	inline CVector<TData>& operator[](const int iPos) const {
+#ifdef _DEBUG_
+		if ((iPos < 0) || (iPos > iRow - 1))
+		{
+			DebugError("Matrix: Writing vector out of bounds", "Row size",
+				iRow, "New parameter", iPos);
+		}
+#endif		
+		return ppData[iPos];}
+
+	inline CMatrix& operator=(const CMatrix& m) {
+		this->Init(m.NumRows(), m.NumColumns());
+		for (int i=0; i<m.NumRows(); i++)
+			this->ppData[i] = m[i];
+		return *this;
+	}
+
+#ifdef _DEBUG_
+	inline CVector<TData> operator[](const int iPos) const {
+		if ((iPos < 0) || (iPos > iRow - 1))
+		{
+			DebugError("Matrix: Reading vector out of bounds", "Row size",
+				iRow, "New parameter", iPos);
+		}
+		return ppData[iPos];}
+#endif
+	inline int NumRows(void) const { return iRow;}
+	inline int NumColumns(void) const { return iCol;}
+
+protected:
+	CVector<TData>*	ppData;
+	int				iRow;
+	int				iCol;
+};
+
+
+/* Implementation *************************************************************/
+template<class TData> void CMatrix<TData>::Init(const int iNewRow,
+												const int iNewColumn)
+{
+	iRow = iNewRow;
+	iCol = iNewColumn;
+
+	if (iRow > 0)
+	{
+		/* Delete resources from previous init */
+		if (ppData != NULL)
+			delete[] ppData;
+
+		/* Allocate new memory for history buffer */
+		ppData = new CVector<TData>[iRow];
+		for (int i = 0; i < iRow; i++)
+			ppData[i].Init(iNewColumn);
+	}
+}
+
+template<class TData> void CMatrix<TData>::Init(const int iNewRow,
+												const int iNewColumn,
+												const TData tIniVal)
+{
+	/* Call actual init routine */
+	Init(iNewRow, iNewColumn);
+
+	/* Set values */
+	Reset(tIniVal);
+}
+
+template<class TData> void CMatrix<TData>::Reset(const TData tResetVal)
+{
+	/* Set all values to reset value */
+	for (int i = 0; i < iRow; i++)
+		for (int j = 0; j < ppData[i].Size(); j++)
+			ppData[i][j] = tResetVal;
+}
+
+template<class TData> CMatrix<TData>::~CMatrix()
+{
+	/* Delete buffer */
+	if (ppData != NULL)
+		delete[] ppData;
+}
+
+
+#endif // !defined(VECTOR_H__3B0BA660_CA6LIUBEFIB2B_23E7A0D31912__INCLUDED_)
diff --git a/src/windows/Pacer.cpp b/src/windows/Pacer.cpp
new file mode 100644
index 0000000..e8c3d66
--- /dev/null
+++ b/src/windows/Pacer.cpp
@@ -0,0 +1,57 @@
+
+#include "../util/Pacer.h"
+
+/* The FILETIME structure is a 64-bit value representing
+ * the number of 100-nanosecond intervals since January 1, 1601.
+ */
+
+CPacer::CPacer(uint64_t ns)
+{
+    FILETIME ft;
+    hTimer = CreateWaitableTimer(NULL, TRUE, TEXT("CPacerTimer"));
+    if (hTimer==NULL)
+    {
+        throw "Create Timer failed ";
+    }
+    GetSystemTimeAsFileTime(&ft);
+    interval = ns/100;
+    timekeeper = *(uint64_t*)&ft;
+    timekeeper += interval;
+    LARGE_INTEGER liDueTime;
+    liDueTime.QuadPart = timekeeper;
+    if (!SetWaitableTimer(hTimer, &liDueTime, 0, NULL, NULL, 0))
+    {
+        throw "Set Timer failed ";
+    }
+}
+
+CPacer::~CPacer()
+{
+    CancelWaitableTimer(hTimer);
+}
+
+uint64_t CPacer::nstogo()
+{
+    FILETIME ft;
+    LARGE_INTEGER liNow;
+    GetSystemTimeAsFileTime(&ft);
+    liNow.LowPart = ft.dwLowDateTime;
+    liNow.HighPart = ft.dwHighDateTime;
+    return (uint64_t)100*(timekeeper - liNow.QuadPart);
+}
+
+void CPacer::wait()
+{
+    if (WaitForSingleObject(hTimer, INFINITE) !=WAIT_OBJECT_0)
+    {
+        throw "Wait on Timer failed ";
+    }
+    /* and re-arm */
+    timekeeper += interval;
+    LARGE_INTEGER liDueTime;
+    liDueTime.QuadPart = timekeeper;
+    if (!SetWaitableTimer(hTimer, &liDueTime, 0, NULL, NULL, 0))
+    {
+        throw "Set Timer failed ";
+    }
+}
diff --git a/src/windows/Sound.cpp b/src/windows/Sound.cpp
new file mode 100644
index 0000000..422df00
--- /dev/null
+++ b/src/windows/Sound.cpp
@@ -0,0 +1,650 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ * Sound card interface for Windows operating systems
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#include "Sound.h"
+#include <iostream>
+
+
+static UINT FindDevice(const vector<string>& vecstrDevices, const string& names)
+{
+	UINT uDeviceID = WAVE_MAPPER;
+	for (UINT i = 0; i < UINT(vecstrDevices.size()); i++)
+	{
+		if (vecstrDevices[i] == names)
+		{
+			uDeviceID = i - 1; /* the first device is always the WAVE_MAPPER (defined as ((UINT)-1)) */
+			break;
+		}
+	}
+	return uDeviceID;
+}
+
+
+/* Implementation *************************************************************/
+/******************************************************************************\
+* Wave in                                                                      *
+\******************************************************************************/
+
+CSoundIn::CSoundIn():CSoundInInterface(),m_WaveIn(NULL)
+{
+    int i;
+
+    /* Get the number of audio capture devices in this computer, check range */
+    int iNumDevs = waveInGetNumDevs();
+
+    if (iNumDevs == 0)
+        return;
+
+    /* Init buffer pointer to zero */
+    for (i = 0; i < NUM_SOUND_BUFFERS_IN; i++)
+    {
+        memset(&m_WaveInHeader[i], 0, sizeof(WAVEHDR));
+        psSoundcardBuffer[i] = NULL;
+    }
+
+	/* Default device WAVE_MAPPER */
+	vecstrDevices.push_back("");
+
+	/* Get info about the devices and store the names */
+    for (i = 0; i < iNumDevs; i++)
+        if (!waveInGetDevCaps(i, &m_WaveInDevCaps, sizeof(WAVEINCAPS)))
+            vecstrDevices.push_back(m_WaveInDevCaps.szPname);
+
+    /* We use an event controlled wave-in structure */
+    /* Create events */
+    m_WaveEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+
+    /* Set flag to open devices */
+    bChangDev = TRUE;
+
+    /* Blocking wave in is default */
+    bBlocking = TRUE;
+}
+
+CSoundIn::~CSoundIn()
+{
+    /* Delete allocated memory */
+    for (int i = 0; i < NUM_SOUND_BUFFERS_IN; i++)
+    {
+        if (psSoundcardBuffer[i] != NULL)
+            delete[] psSoundcardBuffer[i];
+    }
+
+    /* Close the handle for the events */
+    if (m_WaveEvent != NULL)
+        CloseHandle(m_WaveEvent);
+}
+
+_BOOLEAN CSoundIn::Read(CVector<short>& psData)
+{
+    int			i;
+    _BOOLEAN	bError;
+
+    /* Check if device must be opened or reinitialized */
+    if (bChangDev == TRUE)
+    {
+        /* Reinit sound interface */
+        Init(iSampleRate, iBufferSize, bBlocking);
+
+        /* Reset flag */
+        bChangDev = FALSE;
+    }
+
+    /* Wait until data is available */
+    if (!(m_WaveInHeader[iWhichBuffer].dwFlags & WHDR_DONE))
+    {
+        if (bBlocking == TRUE)
+            WaitForSingleObject(m_WaveEvent, INFINITE);
+        else
+            return FALSE;
+    }
+
+    /* Check if buffers got lost */
+    int iNumInBufDone = 0;
+    for (i = 0; i < NUM_SOUND_BUFFERS_IN; i++)
+    {
+        if (m_WaveInHeader[i].dwFlags & WHDR_DONE)
+            iNumInBufDone++;
+    }
+
+    /* If the number of done buffers equals the total number of buffers, it is
+       very likely that a buffer got lost -> set error flag */
+    if (iNumInBufDone == NUM_SOUND_BUFFERS_IN)
+        bError = TRUE;
+    else
+        bError = FALSE;
+
+    /* Copy data from sound card in output buffer */
+    for (i = 0; i < iBufferSize; i++)
+        psData[i] = psSoundcardBuffer[iWhichBuffer][i];
+
+    /* Add the buffer so that it can be filled with new samples */
+    AddBuffer();
+
+    /* In case more than one buffer was ready, reset event */
+    ResetEvent(m_WaveEvent);
+    return bError;
+}
+
+void CSoundIn::AddBuffer()
+{
+    /* Unprepare old wave-header */
+    waveInUnprepareHeader(
+        m_WaveIn, &m_WaveInHeader[iWhichBuffer], sizeof(WAVEHDR));
+
+    /* Prepare buffers for sending to sound interface */
+    PrepareBuffer(iWhichBuffer);
+
+    /* Send buffer to driver for filling with new data */
+    waveInAddBuffer(m_WaveIn, &m_WaveInHeader[iWhichBuffer], sizeof(WAVEHDR));
+
+    /* Toggle buffers */
+    iWhichBuffer++;
+    if (iWhichBuffer == NUM_SOUND_BUFFERS_IN)
+        iWhichBuffer = 0;
+}
+
+void CSoundIn::PrepareBuffer(int iBufNum)
+{
+    /* Set struct entries */
+    m_WaveInHeader[iBufNum].lpData = (LPSTR) &psSoundcardBuffer[iBufNum][0];
+    m_WaveInHeader[iBufNum].dwBufferLength = iBufferSize * BYTES_PER_SAMPLE;
+    m_WaveInHeader[iBufNum].dwFlags = 0;
+
+    /* Prepare wave-header */
+    waveInPrepareHeader(m_WaveIn, &m_WaveInHeader[iBufNum], sizeof(WAVEHDR));
+}
+
+_BOOLEAN CSoundIn::Init(int iNewSampleRate, int iNewBufferSize, _BOOLEAN bNewBlocking)
+{
+    _BOOLEAN bChanged = FALSE;
+
+	/* Set internal parameter */
+    iBufferSize = iNewBufferSize;
+    bBlocking = bNewBlocking;
+
+	/* Check if device must be opened or reinitialized */
+    if (bChangDev == TRUE || iSampleRate != iNewSampleRate)
+    {
+        iSampleRate = iNewSampleRate;
+
+        OpenDevice();
+
+        /* Reset flag */
+        bChangDev = FALSE;
+
+        /* Reset interface so that all buffers are returned from the interface */
+        waveInReset(m_WaveIn);
+        waveInStop(m_WaveIn);
+
+        /* Reset current buffer ID (it is important to do this BEFORE calling
+           "AddInBuffer()" */
+        iWhichBuffer = 0;
+
+        /* Create memory for sound card buffer */
+        for (int i = 0; i < NUM_SOUND_BUFFERS_IN; i++)
+        {
+            /* Unprepare old wave-header in case that we "re-initialized" this
+               module. Calling "waveInUnprepareHeader()" with an unprepared
+               buffer (when the module is initialized for the first time) has
+               simply no effect */
+            waveInUnprepareHeader(m_WaveIn, &m_WaveInHeader[i], sizeof(WAVEHDR));
+
+            if (psSoundcardBuffer[i] != NULL)
+                delete[] psSoundcardBuffer[i];
+
+            psSoundcardBuffer[i] = new short[iBufferSize];
+
+
+            /* Send all buffers to driver for filling the queue ----------------- */
+            /* Prepare buffers before sending them to the sound interface */
+            PrepareBuffer(i);
+
+            AddBuffer();
+        }
+
+        /* This reset event is very important for initialization, otherwise we will
+           get errors! */
+        ResetEvent(m_WaveEvent);
+
+	    /* Notify that sound capturing can start now */
+        waveInStart(m_WaveIn);
+
+        bChanged = TRUE;
+    }
+
+    return bChanged;
+}
+
+void CSoundIn::OpenDevice()
+{
+    /* Init wave-format structure */
+    sWaveFormatEx.wFormatTag = WAVE_FORMAT_PCM;
+    sWaveFormatEx.nChannels = NUM_IN_OUT_CHANNELS;
+    sWaveFormatEx.wBitsPerSample = BITS_PER_SAMPLE;
+    sWaveFormatEx.nSamplesPerSec = iSampleRate;
+    sWaveFormatEx.nBlockAlign = sWaveFormatEx.nChannels *
+                                sWaveFormatEx.wBitsPerSample / 8;
+    sWaveFormatEx.nAvgBytesPerSec = sWaveFormatEx.nBlockAlign *
+                                    sWaveFormatEx.nSamplesPerSec;
+    sWaveFormatEx.cbSize = 0;
+
+	/* Open wave-input and set call-back mechanism to event handle */
+    if (m_WaveIn != NULL)
+    {
+        waveInReset(m_WaveIn);
+        waveInClose(m_WaveIn);
+    }
+
+    /* Get device ID */
+	UINT mmdev = FindDevice(vecstrDevices, sCurDev);
+
+    MMRESULT result = waveInOpen(&m_WaveIn, mmdev, &sWaveFormatEx,
+                                 (DWORD_PTR) m_WaveEvent, 0, CALLBACK_EVENT);
+    if (result != MMSYSERR_NOERROR)
+        throw CGenErr("Sound Interface Start, waveInOpen() failed. This error "
+                      "usually occurs if another application blocks the sound in.");
+}
+
+void CSoundIn::SetDev(string sNewDev)
+{
+    /* Change only in case new device id is not already active */
+    if (sNewDev != sCurDev)
+    {
+        sCurDev = sNewDev;
+        bChangDev = TRUE;
+    }
+}
+
+void CSoundIn::Enumerate(vector<string>& names, vector<string>& descriptions)
+{
+    names = vecstrDevices;
+	descriptions.clear();
+}
+
+string	CSoundIn::GetDev()
+{
+    return sCurDev;
+}
+
+void CSoundIn::Close()
+{
+    int			i;
+    MMRESULT	result;
+
+    /* Reset audio driver */
+    if (m_WaveIn != NULL)
+    {
+        result = waveInReset(m_WaveIn);
+        if (result != MMSYSERR_NOERROR)
+            throw CGenErr("Sound Interface, waveInReset() failed.");
+    }
+
+    /* Set event to ensure that thread leaves the waiting function */
+    if (m_WaveEvent != NULL)
+        SetEvent(m_WaveEvent);
+
+    /* Unprepare wave-headers */
+    if (m_WaveIn != NULL)
+    {
+        for (i = 0; i < NUM_SOUND_BUFFERS_IN; i++)
+        {
+            result = waveInUnprepareHeader(
+                         m_WaveIn, &m_WaveInHeader[i], sizeof(WAVEHDR));
+
+            if (result != MMSYSERR_NOERROR)
+                throw CGenErr("Sound Interface, waveInUnprepareHeader()"
+                              " failed.");
+        }
+
+        /* Close the sound in device */
+        result = waveInClose(m_WaveIn);
+        if (result != MMSYSERR_NOERROR)
+            throw CGenErr("Sound Interface, waveInClose() failed.");
+
+        m_WaveIn = NULL;
+	}
+
+    /* Set flag to open devices the next time it is initialized */
+    bChangDev = TRUE;
+}
+/******************************************************************************\
+* Wave out                                                                     *
+\******************************************************************************/
+CSoundOut::CSoundOut():CSoundOutInterface(),m_WaveOut(NULL)
+{
+    int i;
+
+    /* Get the number of digital audio devices in this computer, check range */
+    int iNumDevs = waveOutGetNumDevs();
+
+    if (iNumDevs == 0)
+        return;
+
+    /* Init buffer pointer to zero */
+    for (i = 0; i < NUM_SOUND_BUFFERS_OUT; i++)
+    {
+        memset(&m_WaveOutHeader[i], 0, sizeof(WAVEHDR));
+        psPlaybackBuffer[i] = NULL;
+    }
+
+	/* Default device WAVE_MAPPER */
+	vecstrDevices.push_back("");
+
+	/* Get info about the devices and store the names */
+    for (i = 0; i < iNumDevs; i++)
+        if (!waveOutGetDevCaps(i, &m_WaveOutDevCaps, sizeof(WAVEOUTCAPS)))
+            vecstrDevices.push_back(m_WaveOutDevCaps.szPname);
+
+    /* We use an event controlled wave-out structure */
+    /* Create events */
+    m_WaveEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+
+    /* Set flag to open devices */
+    bChangDev = TRUE;
+
+    /* TODO does not work well with hot pluggable devices! */
+//    iCurDev = iNumDevs-1;
+
+    /* Non-blocking wave out is default */
+    bBlocking = FALSE;
+}
+
+CSoundOut::~CSoundOut()
+{
+    /* Delete allocated memory */
+    for (int i = 0; i < NUM_SOUND_BUFFERS_OUT; i++)
+    {
+        if (psPlaybackBuffer[i] != NULL)
+            delete[] psPlaybackBuffer[i];
+    }
+
+    /* Close the handle for the events */
+    if (m_WaveEvent != NULL)
+        CloseHandle(m_WaveEvent);
+}
+
+_BOOLEAN CSoundOut::Write(CVector<short>& psData)
+{
+    int			i, j;
+    int			iCntPrepBuf;
+    int			iIndexDoneBuf;
+    _BOOLEAN	bError=FALSE;
+
+    /* Check if device must be opened or reinitialized */
+    if (bChangDev == TRUE)
+    {
+        /* Reinit sound interface */
+        Init(iSampleRate, iBufferSize, bBlocking);
+
+        /* Reset flag */
+        bChangDev = FALSE;
+    }
+
+    /* Get number of "done"-buffers and position of one of them */
+    GetDoneBuffer(iCntPrepBuf, iIndexDoneBuf);
+
+    /* Now check special cases (Buffer is full or empty) */
+    if (iCntPrepBuf == 0)
+    {
+        if (bBlocking == TRUE)
+        {
+            /* Blocking wave out routine. Needed for transmitter. Always
+               ensure that the buffer is completely filled to avoid buffer
+               underruns */
+            while (iCntPrepBuf == 0)
+            {
+                WaitForSingleObject(m_WaveEvent, INFINITE);
+
+                GetDoneBuffer(iCntPrepBuf, iIndexDoneBuf);
+            }
+        }
+        else
+        {
+            /* All buffers are filled, dump new block ----------------------- */
+// It would be better to kill half of the buffer blocks to set the start
+// back to the middle: TODO
+cerr << "sound out buffers full" << endl;
+            return TRUE; /* An error occurred */
+        }
+    }
+    else if (iCntPrepBuf == NUM_SOUND_BUFFERS_OUT)
+    {
+        /* ---------------------------------------------------------------------
+           Buffer is empty -> send as many cleared blocks to the sound-
+           interface until half of the buffer size is reached */
+        /* Send half of the buffer size blocks to the sound-interface */
+        for (j = 0; j < NUM_SOUND_BUFFERS_OUT / 2; j++)
+        {
+            /* First, clear these buffers */
+            for (i = 0; i < iBufferSize; i++)
+                psPlaybackBuffer[j][i] = 0;
+
+            /* Then send them to the interface */
+            AddBuffer(j);
+        }
+
+        /* Set index for done buffer */
+        iIndexDoneBuf = NUM_SOUND_BUFFERS_OUT / 2;
+
+cerr << "sound out buffers empty" << endl;
+        bError = TRUE;
+    }
+    else
+        bError = FALSE;
+
+    /* Copy stereo data from input in soundcard buffer */
+    for (i = 0; i < iBufferSize; i++)
+        psPlaybackBuffer[iIndexDoneBuf][i] = psData[i];
+
+    /* Now, send the current block */
+    AddBuffer(iIndexDoneBuf);
+
+    return bError;
+}
+
+void CSoundOut::GetDoneBuffer(int& iCntPrepBuf, int& iIndexDoneBuf)
+{
+    /* Get number of "done"-buffers and position of one of them */
+    iCntPrepBuf = 0;
+    for (int i = 0; i < NUM_SOUND_BUFFERS_OUT; i++)
+    {
+        if (m_WaveOutHeader[i].dwFlags & WHDR_DONE)
+        {
+            iCntPrepBuf++;
+            iIndexDoneBuf = i;
+        }
+    }
+}
+
+void CSoundOut::AddBuffer(int iBufNum)
+{
+    /* Unprepare old wave-header */
+    waveOutUnprepareHeader(
+        m_WaveOut, &m_WaveOutHeader[iBufNum], sizeof(WAVEHDR));
+
+    /* Prepare buffers for sending to sound interface */
+    PrepareBuffer(iBufNum);
+
+    /* Send buffer to driver for filling with new data */
+    waveOutWrite(m_WaveOut, &m_WaveOutHeader[iBufNum], sizeof(WAVEHDR));
+}
+
+void CSoundOut::PrepareBuffer(int iBufNum)
+{
+    /* Set Header data */
+    m_WaveOutHeader[iBufNum].lpData = (LPSTR) &psPlaybackBuffer[iBufNum][0];
+    m_WaveOutHeader[iBufNum].dwBufferLength = iBufferSize * BYTES_PER_SAMPLE;
+    m_WaveOutHeader[iBufNum].dwFlags = 0;
+
+    /* Prepare wave-header */
+    waveOutPrepareHeader(m_WaveOut, &m_WaveOutHeader[iBufNum], sizeof(WAVEHDR));
+}
+
+_BOOLEAN CSoundOut::Init(int iNewSampleRate, int iNewBufferSize, _BOOLEAN bNewBlocking)
+{
+    _BOOLEAN bChanged = FALSE;
+
+	/* Set internal parameters */
+    iBufferSize = iNewBufferSize;
+    bBlocking = bNewBlocking;
+
+    /* Check if device must be opened or reinitialized */
+    if (bChangDev == TRUE || iSampleRate != iNewSampleRate)
+    {
+        iSampleRate = iNewSampleRate;
+
+        OpenDevice();
+
+        /* Reset flag */
+        bChangDev = FALSE;
+
+        /* Reset interface */
+        waveOutReset(m_WaveOut);
+
+        for (int j = 0; j < NUM_SOUND_BUFFERS_OUT; j++)
+        {
+            /* Unprepare old wave-header (in case header was not prepared before,
+               simply nothing happens with this function call */
+            waveOutUnprepareHeader(m_WaveOut, &m_WaveOutHeader[j], sizeof(WAVEHDR));
+
+            /* Create memory for playback buffer */
+            if (psPlaybackBuffer[j] != NULL)
+                delete[] psPlaybackBuffer[j];
+
+            psPlaybackBuffer[j] = new short[iBufferSize];
+
+            /* Clear new buffer */
+            for (int i = 0; i < iBufferSize; i++)
+                psPlaybackBuffer[j][i] = 0;
+
+            /* Prepare buffer for sending to the sound interface */
+            PrepareBuffer(j);
+
+            /* Initially, send all buffers to the interface */
+            AddBuffer(j);
+        }
+
+        bChanged = TRUE;
+    }
+
+    return bChanged;
+}
+
+void CSoundOut::OpenDevice()
+{
+    /* Init wave-format structure */
+    sWaveFormatEx.wFormatTag = WAVE_FORMAT_PCM;
+    sWaveFormatEx.nChannels = NUM_IN_OUT_CHANNELS;
+    sWaveFormatEx.wBitsPerSample = BITS_PER_SAMPLE;
+    sWaveFormatEx.nSamplesPerSec = iSampleRate;
+    sWaveFormatEx.nBlockAlign = sWaveFormatEx.nChannels *
+                                sWaveFormatEx.wBitsPerSample / 8;
+    sWaveFormatEx.nAvgBytesPerSec = sWaveFormatEx.nBlockAlign *
+                                    sWaveFormatEx.nSamplesPerSec;
+    sWaveFormatEx.cbSize = 0;
+
+    if (m_WaveOut != NULL)
+    {
+        waveOutReset(m_WaveOut);
+        waveOutClose(m_WaveOut);
+    }
+
+    /* Get device ID */
+	UINT mmdev = FindDevice(vecstrDevices, sCurDev);
+
+    MMRESULT result = waveOutOpen(&m_WaveOut, mmdev, &sWaveFormatEx,
+                                  (DWORD_PTR) m_WaveEvent, 0, CALLBACK_EVENT);
+    if (result != MMSYSERR_NOERROR)
+        throw CGenErr("Sound Interface Start, waveOutOpen() failed.");
+}
+
+void CSoundOut::Enumerate(vector<string>& names, vector<string>& descriptions)
+{
+    names = vecstrDevices;
+	descriptions.clear();
+}
+
+string CSoundOut::GetDev()
+{
+    return sCurDev;
+}
+
+void CSoundOut::SetDev(string sNewDev)
+{
+    /* Change only in case new device id is not already active */
+    if (sNewDev != sCurDev)
+    {
+        sCurDev = sNewDev;
+        bChangDev = TRUE;
+    }
+}
+
+
+void CSoundOut::Close()
+{
+    int			i;
+    MMRESULT	result;
+
+    /* Reset audio driver */
+    if (m_WaveOut != NULL)
+    {
+        result = waveOutReset(m_WaveOut);
+        if (result != MMSYSERR_NOERROR)
+            throw CGenErr("Sound Interface, waveOutReset() failed.");
+    }
+
+    /* Set event to ensure that thread leaves the waiting function */
+    if (m_WaveEvent != NULL)
+        SetEvent(m_WaveEvent);
+
+    /* Unprepare wave-headers */
+    if (m_WaveOut != NULL)
+    {
+        for (i = 0; i < NUM_SOUND_BUFFERS_OUT; i++)
+        {
+            result = waveOutUnprepareHeader(
+                         m_WaveOut, &m_WaveOutHeader[i], sizeof(WAVEHDR));
+
+            if (result != MMSYSERR_NOERROR)
+                throw CGenErr("Sound Interface, waveOutUnprepareHeader()"
+                              " failed.");
+        }
+
+        /* Close the sound out device */
+        result = waveOutClose(m_WaveOut);
+        if (result != MMSYSERR_NOERROR)
+            throw CGenErr("Sound Interface, waveOutClose() failed.");
+
+        m_WaveOut = NULL;
+	}
+
+    /* Set flag to open devices the next time it is initialized */
+    bChangDev = TRUE;
+}
+
diff --git a/src/windows/Sound.h b/src/windows/Sound.h
new file mode 100644
index 0000000..cfedb8a
--- /dev/null
+++ b/src/windows/Sound.h
@@ -0,0 +1,122 @@
+/******************************************************************************\
+ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
+ * Copyright (c) 2001-2014
+ *
+ * Author(s):
+ *	Volker Fischer
+ *
+ * Description:
+ *	See Sound.cpp
+ *
+ ******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+\******************************************************************************/
+
+#if !defined(AFX_SOUNDIN_H__9518A621_7F78_11D3_8C0D_EEBF182CF549__INCLUDED_)
+#define AFX_SOUNDIN_H__9518A621_7F78_11D3_8C0D_EEBF182CF549__INCLUDED_
+
+#include "../sound/soundinterface.h"
+#include <windows.h>
+#include <mmsystem.h>
+
+/* Set this number as high as we have to prebuffer symbols for one MSC block.
+   In case of robustness mode D we have 24 symbols */
+#define NUM_SOUND_BUFFERS_IN	24		/* Number of sound card buffers */
+
+#ifdef QT_GUI_LIB
+# define NUM_SOUND_BUFFERS_OUT	6		/* Number of sound card buffers */
+#else
+# define NUM_SOUND_BUFFERS_OUT	3		/* Number of sound card buffers */
+#endif
+#define	NUM_IN_OUT_CHANNELS		2		/* Stereo */
+#define	BITS_PER_SAMPLE			16		/* Use all bits of the D/A-converter */
+#define BYTES_PER_SAMPLE		2		/* Number of bytes per sample */
+
+/* Classes ********************************************************************/
+class CSoundIn : public CSoundInInterface
+{
+    public:
+    CSoundIn();
+virtual ~CSoundIn();
+
+virtual _BOOLEAN	Init(int iSampleRate, int iNewBufferSize, _BOOLEAN bNewBlocking);
+virtual _BOOLEAN	Read(CVector<short>& psData);
+virtual void		Enumerate(vector<string>& names, vector<string>& descriptions);
+virtual string		GetDev();
+virtual void		SetDev(string sNewDev);
+virtual void		Close();
+
+protected:
+void		OpenDevice();
+void		PrepareBuffer(int iBufNum);
+void		AddBuffer();
+
+vector<string>	vecstrDevices;
+string			sCurDev;
+WAVEFORMATEX	sWaveFormatEx;
+_BOOLEAN		bChangDev;
+HANDLE			m_WaveEvent;
+int			iSampleRate;
+int			iBufferSize;
+int			iWhichBuffer;
+_BOOLEAN		bBlocking;
+
+/* Wave in */
+WAVEINCAPS		m_WaveInDevCaps;
+HWAVEIN			m_WaveIn;
+WAVEHDR			m_WaveInHeader[NUM_SOUND_BUFFERS_IN];
+short*			psSoundcardBuffer[NUM_SOUND_BUFFERS_IN];
+
+};
+
+class CSoundOut : public CSoundOutInterface
+{
+    public:
+    CSoundOut();
+virtual ~CSoundOut();
+
+virtual _BOOLEAN	Init(int iSampleRate, int iNewBufferSize, _BOOLEAN bNewBlocking);
+virtual _BOOLEAN	Write(CVector<short>& psData);
+virtual void		Enumerate(vector<string>& names, vector<string>& descriptions);
+virtual string		GetDev();
+virtual void		SetDev(string sNewDev);
+virtual void		Close();
+
+protected:
+void		OpenDevice();
+void		PrepareBuffer(int iBufNum);
+void		AddBuffer(int iBufNum);
+void		GetDoneBuffer(int& iCntPrepBuf, int& iIndexDoneBuf);
+
+vector<string>	vecstrDevices;
+string			sCurDev;
+WAVEFORMATEX	sWaveFormatEx;
+_BOOLEAN		bChangDev;
+HANDLE			m_WaveEvent;
+int			iSampleRate;
+int			iBufferSize;
+int			iWhichBuffer;
+_BOOLEAN		bBlocking;
+
+/* Wave out */
+WAVEOUTCAPS		m_WaveOutDevCaps;
+HWAVEOUT		m_WaveOut;
+short*			psPlaybackBuffer[NUM_SOUND_BUFFERS_OUT];
+WAVEHDR			m_WaveOutHeader[NUM_SOUND_BUFFERS_OUT];
+};
+
+#endif // !defined(AFX_SOUNDIN_H__9518A621_7F78_11D3_8C0D_EEBF182CF549__INCLUDED_)
diff --git a/src/windows/platform_util.cpp b/src/windows/platform_util.cpp
new file mode 100644
index 0000000..57bd93f
--- /dev/null
+++ b/src/windows/platform_util.cpp
@@ -0,0 +1,23 @@
+
+#include "platform_util.h"
+
+#include <windows.h>
+
+time_t timegm(struct tm *tm)
+{
+    SYSTEMTIME st;
+    st.wYear = tm->tm_year+1900;
+    st.wMonth = tm->tm_mon+1;
+    st.wDay = tm->tm_mday;
+    st.wHour = 0;
+    st.wMinute = 0;
+    st.wSecond = 0;
+    st.wMilliseconds = 0;
+    FILETIME ft;
+    SystemTimeToFileTime(&st, &ft);
+    ULARGE_INTEGER uli;
+    uli.LowPart = ft.dwLowDateTime;
+    uli.HighPart = ft.dwHighDateTime;
+    return (time_t)(uli.QuadPart/10000000 - 11644473600);
+}
+
diff --git a/src/windows/platform_util.h b/src/windows/platform_util.h
new file mode 100644
index 0000000..7c72185
--- /dev/null
+++ b/src/windows/platform_util.h
@@ -0,0 +1,8 @@
+#ifndef UTIL_H
+#define UTIL_H
+
+#include <time.h>
+
+time_t timegm(struct tm* const);
+
+#endif // UTIL_H
diff --git a/windows/dream.iss b/windows/dream.iss
new file mode 100644
index 0000000..92a54f4
--- /dev/null
+++ b/windows/dream.iss
@@ -0,0 +1,35 @@
+; Dream
+[Setup]
+AppName=Dream
+AppVersion=2.1
+DefaultDirName={pf}\Dream
+DefaultGroupName=Dream
+UninstallDisplayIcon={app}\Dream.exe
+Compression=lzma2
+SolidCompression=yes
+OutputDir=.
+                           
+[Files]
+Source: "Dream.exe"; DestDir: "{app}"
+Source: "libfftw3-3.dll"; DestDir: "{app}"
+Source: "libhamlib-2.dll"; DestDir: "{app}"
+Source: "libopus-0.dll"; DestDir: "{app}"
+Source: "libsndfile-1.dll"; DestDir: "{app}"
+Source: "libspeexdsp.dll"; DestDir: "{app}"
+Source: "libusb0.dll"; DestDir: "{app}"
+Source: "Packet.dll"; DestDir: "{app}"
+Source: "QtCore4.dll"; DestDir: "{app}"
+Source: "QtGui4.dll"; DestDir: "{app}"
+Source: "QtNetwork4.dll"; DestDir: "{app}"
+Source: "QtOpenGL4.dll"; DestDir: "{app}"
+Source: "QtSql4.dll"; DestDir: "{app}"
+Source: "QtSvg4.dll"; DestDir: "{app}"
+Source: "QtWebKit4.dll"; DestDir: "{app}"
+Source: "QtXml4.dll"; DestDir: "{app}"
+Source: "qwt.dll"; DestDir: "{app}"
+Source: "wpcap.dll"; DestDir: "{app}"
+Source: "zlib1.dll"; DestDir: "{app}"
+Source: "Readme.txt"; DestDir: "{app}"
+
+[Icons]
+Name: "{group}\Dream"; Filename: "{app}\Dream.exe"
diff --git a/windows/dream.rc b/windows/dream.rc
new file mode 100644
index 0000000..44fd25d
--- /dev/null
+++ b/windows/dream.rc
@@ -0,0 +1 @@
+101	ICON    DISCARDABLE     "..\\src\\GUI-QT\\res\\MainIcon.ico"
diff --git a/windows/faadconfig.h b/windows/faadconfig.h
new file mode 100644
index 0000000..3ec1144
--- /dev/null
+++ b/windows/faadconfig.h
@@ -0,0 +1,4 @@
+#include <memory.h>
+#include <string.h>
+#define DRM 1
+#define DRM_PS 1
\ No newline at end of file
diff --git a/windows/libfaac.sln b/windows/libfaac.sln
new file mode 100644
index 0000000..8c6d6bf
--- /dev/null
+++ b/windows/libfaac.sln
@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual C++ Express 2008
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libfaac", "libfaac.vcproj", "{11CA1C2C-05BA-4EC7-8FD0-670241B89110}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Win32 = Debug|Win32
+		Release|Win32 = Release|Win32
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{11CA1C2C-05BA-4EC7-8FD0-670241B89110}.Debug|Win32.ActiveCfg = Debug|Win32
+		{11CA1C2C-05BA-4EC7-8FD0-670241B89110}.Debug|Win32.Build.0 = Debug|Win32
+		{11CA1C2C-05BA-4EC7-8FD0-670241B89110}.Release|Win32.ActiveCfg = Release|Win32
+		{11CA1C2C-05BA-4EC7-8FD0-670241B89110}.Release|Win32.Build.0 = Release|Win32
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
diff --git a/windows/libfaac.vcproj b/windows/libfaac.vcproj
new file mode 100644
index 0000000..8b06d1b
--- /dev/null
+++ b/windows/libfaac.vcproj
@@ -0,0 +1,331 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="9.00"
+	Name="faac_drm"
+	ProjectGUID="{11CA1C2C-05BA-4EC7-8FD0-670241B89110}"
+	RootNamespace="libfaac"
+	Keyword="Win32Proj"
+	TargetFrameworkVersion="0"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="..\libs"
+			IntermediateDirectory="Debug"
+			ConfigurationType="4"
+			BuildLogFile="$(IntDir)\FaacBuildLog.htm"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\..\faac\include"
+				PreprocessorDefinitions="WIN32;_DEBUG;_LIB;DRM;FAACAPI=__stdcall"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="false"
+				DebugInformationFormat="4"
+				CompileAs="0"
+				DisableSpecificWarnings="4996"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+				LinkLibraryDependencies="true"
+				OutputFile="$(OutDir)\$(ProjectName)d.lib"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+				CommandLine="copy ..\..\faac\include\faac.h ..\libs&#x0D;&#x0A;copy ..\..\faac\include\faaccfg.h ..\libs&#x0D;&#x0A;"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="..\libs"
+			IntermediateDirectory="Release"
+			ConfigurationType="4"
+			WholeProgramOptimization="1"
+			BuildLogFile="$(IntDir)\FaacBuildLog.htm"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="3"
+				EnableIntrinsicFunctions="true"
+				WholeProgramOptimization="true"
+				AdditionalIncludeDirectories="..\libs"
+				PreprocessorDefinitions="NDEBUG;_LIB;DRM;FAACAPI=__stdcall"
+				StringPooling="true"
+				MinimalRebuild="true"
+				SmallerTypeCheck="false"
+				RuntimeLibrary="0"
+				EnableFunctionLevelLinking="true"
+				EnableEnhancedInstructionSet="2"
+				UsePrecompiledHeader="0"
+				ProgramDataBaseFileName="$(IntDir)\faacvc90.pdb"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="false"
+				CompileAs="0"
+				DisableSpecificWarnings="4996"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+				LinkLibraryDependencies="true"
+				AdditionalLibraryDirectories="$(OutDir)"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+				CommandLine="copy ..\..\faac\include\faac.h ..\libs&#x0D;&#x0A;copy ..\..\faac\include\faaccfg.h ..\libs&#x0D;&#x0A;"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Header Files"
+			Filter="h;hpp;hxx;hm;inl;inc;xsd"
+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+			>
+			<File
+				RelativePath="..\..\faac\libfaac\aacquant.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faac\libfaac\backpred.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faac\libfaac\bitstream.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faac\libfaac\channels.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faac\libfaac\coder.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faac\include\faac.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faac\include\faaccfg.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faac\libfaac\fft.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faac\libfaac\filtbank.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faac\libfaac\frame.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faac\libfaac\huffman.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faac\libfaac\hufftab.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faac\libfaac\ltp.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faac\libfaac\midside.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faac\libfaac\psych.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faac\libfaac\tns.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faac\libfaac\util.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faac\libfaac\version.h"
+				>
+			</File>
+			<Filter
+				Name="kiss_fft"
+				>
+				<File
+					RelativePath="..\..\faac\libfaac\kiss_fft\_kiss_fft_guts.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\faac\libfaac\kiss_fft\kiss_fft.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\faac\libfaac\kiss_fft\kiss_fftr.h"
+					>
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="Source Files"
+			Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+			>
+			<File
+				RelativePath="..\..\faac\libfaac\aacquant.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faac\libfaac\backpred.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faac\libfaac\bitstream.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faac\libfaac\channels.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faac\libfaac\fft.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faac\libfaac\filtbank.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faac\libfaac\frame.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faac\libfaac\huffman.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faac\libfaac\ltp.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faac\libfaac\midside.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faac\libfaac\psychkni.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faac\libfaac\tns.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faac\libfaac\util.c"
+				>
+			</File>
+			<Filter
+				Name="kiss_fft"
+				>
+				<File
+					RelativePath="..\..\faac\libfaac\kiss_fft\kiss_fft.c"
+					>
+				</File>
+				<File
+					RelativePath="..\..\faac\libfaac\kiss_fft\kiss_fftr.c"
+					>
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
diff --git a/windows/libfaad.sln b/windows/libfaad.sln
new file mode 100644
index 0000000..7a954fe
--- /dev/null
+++ b/windows/libfaad.sln
@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual C++ Express 2008
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libfaad", "libfaad.vcproj", "{76AF9D0B-41B0-4870-8DFB-D805FA7239D9}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Win32 = Debug|Win32
+		Release|Win32 = Release|Win32
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{76AF9D0B-41B0-4870-8DFB-D805FA7239D9}.Debug|Win32.ActiveCfg = Debug|Win32
+		{76AF9D0B-41B0-4870-8DFB-D805FA7239D9}.Debug|Win32.Build.0 = Debug|Win32
+		{76AF9D0B-41B0-4870-8DFB-D805FA7239D9}.Release|Win32.ActiveCfg = Release|Win32
+		{76AF9D0B-41B0-4870-8DFB-D805FA7239D9}.Release|Win32.Build.0 = Release|Win32
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
diff --git a/windows/libfaad.vcproj b/windows/libfaad.vcproj
new file mode 100644
index 0000000..577668a
--- /dev/null
+++ b/windows/libfaad.vcproj
@@ -0,0 +1,577 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="9.00"
+	Name="faad_drm"
+	ProjectGUID="{76AF9D0B-41B0-4870-8DFB-D805FA7239D9}"
+	RootNamespace="libfaad"
+	Keyword="Win32Proj"
+	TargetFrameworkVersion="0"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="..\libs"
+			IntermediateDirectory="Debug"
+			ConfigurationType="4"
+			BuildLogFile="$(IntDir)\FaadBuildLog.htm"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+				CommandLine="copy faadconfig.h ..\..\faad2\config.h"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\..\faad2\include"
+				PreprocessorDefinitions="HAVE_CONFIG_H;NEAACDECAPI=__stdcall"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				UsePrecompiledHeader="0"
+				ProgramDataBaseFileName="$(IntDir)\faad_vc90.pdb"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="false"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+				LinkLibraryDependencies="true"
+				OutputFile="$(OutDir)\$(ProjectName)d.lib"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+				CommandLine="copy ..\..\faad2\include\neaacdec.h "$(OutDir)""
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="..\libs"
+			IntermediateDirectory="Release"
+			ConfigurationType="4"
+			BuildLogFile="$(IntDir)\FaadBuildLog.htm"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+				CommandLine="copy faadconfig.h ..\..\faad2\config.h"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				AdditionalIncludeDirectories="..\..\faad2\include"
+				PreprocessorDefinitions="HAVE_CONFIG_H;NEAACDECAPI=__stdcall"
+				RuntimeLibrary="0"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+				LinkLibraryDependencies="true"
+				AdditionalLibraryDirectories="$(OutDir)"
+				IgnoreAllDefaultLibraries="true"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+				CommandLine="copy ..\..\faad2\include\neaacdec.h "$(OutDir)""
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Header Files"
+			Filter="h;hpp;hxx;hm;inl;inc;xsd"
+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+			>
+			<File
+				RelativePath="..\..\faad2\libfaad\analysis.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\bits.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\cfft.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\cfft_tab.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\common.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\decoder.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\drc.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\drm_dec.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\error.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\include\faad.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\filtbank.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\fixed.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\huffman.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\ic_predict.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\iq_table.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\is.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\kbd_win.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\lt_predict.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\mdct.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\mdct_tab.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\mp4.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\ms.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\include\neaacdec.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\output.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\pns.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\ps_dec.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\ps_tables.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\pulse.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\rvlc.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\sbr_dct.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\sbr_dec.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\sbr_e_nf.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\sbr_fbt.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\sbr_hfadj.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\sbr_hfgen.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\sbr_huff.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\sbr_noise.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\sbr_qmf.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\sbr_qmf_c.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\sbr_syntax.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\sbr_tf_grid.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\sine_win.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\specrec.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\ssr.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\ssr_fb.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\ssr_ipqf.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\ssr_win.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\structs.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\syntax.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\tns.h"
+				>
+			</File>
+			<Filter
+				Name="codebook"
+				>
+				<File
+					RelativePath="..\..\faad2\libfaad\codebook\hcb.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\faad2\libfaad\codebook\hcb_1.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\faad2\libfaad\codebook\hcb_10.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\faad2\libfaad\codebook\hcb_11.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\faad2\libfaad\codebook\hcb_2.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\faad2\libfaad\codebook\hcb_3.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\faad2\libfaad\codebook\hcb_4.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\faad2\libfaad\codebook\hcb_5.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\faad2\libfaad\codebook\hcb_6.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\faad2\libfaad\codebook\hcb_7.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\faad2\libfaad\codebook\hcb_8.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\faad2\libfaad\codebook\hcb_9.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\faad2\libfaad\codebook\hcb_sf.h"
+					>
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="Source Files"
+			Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+			>
+			<File
+				RelativePath="..\..\faad2\libfaad\bits.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\cfft.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\common.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\decoder.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\drc.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\drm_dec.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\error.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\filtbank.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\hcr.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\huffman.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\ic_predict.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\is.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\lt_predict.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\mdct.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\mp4.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\ms.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\output.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\pns.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\ps_dec.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\ps_syntax.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\pulse.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\rvlc.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\sbr_dct.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\sbr_dec.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\sbr_e_nf.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\sbr_fbt.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\sbr_hfadj.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\sbr_hfgen.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\sbr_huff.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\sbr_qmf.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\sbr_syntax.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\sbr_tf_grid.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\specrec.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\ssr.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\ssr_fb.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\ssr_ipqf.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\syntax.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\faad2\libfaad\tns.c"
+				>
+			</File>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
diff --git a/windows/libfftw.vcproj b/windows/libfftw.vcproj
new file mode 100644
index 0000000..18dba82
--- /dev/null
+++ b/windows/libfftw.vcproj
@@ -0,0 +1,763 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="9.00"
+	Name="libfftw"
+	ProjectGUID="{DE82AB84-73F9-468D-90E0-6E494F71622A}"
+	RootNamespace="libfftw"
+	Keyword="Win32Proj"
+	TargetFrameworkVersion="0"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="..\libs"
+			IntermediateDirectory="Debug"
+			ConfigurationType="4"
+			BuildLogFile="$(IntDir)\FftwBuildLog.htm"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="3"
+				InlineFunctionExpansion="2"
+				EnableIntrinsicFunctions="true"
+				FavorSizeOrSpeed="1"
+				EnableFiberSafeOptimizations="true"
+				WholeProgramOptimization="false"
+				AdditionalIncludeDirectories=""..\..\fftw-2.1.5\fftw""
+				PreprocessorDefinitions="WIN32;_DEBUG;_LIB;HAVE_WIN32"
+				StringPooling="true"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="0"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				EnableEnhancedInstructionSet="2"
+				FloatingPointExceptions="false"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="1"
+				DisableSpecificWarnings="4996"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+				OutputFile="$(OutDir)fftwd.lib"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+				CommandLine="copy "$(TargetPath)" "$(InputDir)..\libs"&#x0D;&#x0A;copy "$(InputDir)..\..\fftw-2.1.5\fftw\fftw.h" "$(InputDir)..\libs"&#x0D;&#x0A;copy "$(InputDir)..\..\fftw-2.1.5\rfftw\rfftw.h" "$(InputDir)..\libs"&#x0D;&#x0A;"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="..\libs"
+			IntermediateDirectory="Release"
+			ConfigurationType="4"
+			BuildLogFile="$(IntDir)\FftwBuildLog.htm"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="3"
+				FavorSizeOrSpeed="1"
+				EnableFiberSafeOptimizations="true"
+				AdditionalIncludeDirectories=""..\..\fftw-2.1.5\fftw""
+				PreprocessorDefinitions="WIN32;NDEBUG;_LIB;"
+				RuntimeLibrary="0"
+				EnableEnhancedInstructionSet="2"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="false"
+				DebugInformationFormat="3"
+				DisableSpecificWarnings="4996"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+				OutputFile="$(OutDir)\fftw.lib"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+				Description="Install files for Dream"
+				CommandLine="copy "$(InputDir)..\..\fftw-2.1.5\fftw\fftw.h" "$(InputDir)..\libs"&#x0D;&#x0A;copy "$(InputDir)..\..\fftw-2.1.5\rfftw\rfftw.h" "$(InputDir)..\libs"&#x0D;&#x0A;"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Header Files"
+			Filter="h;hpp;hxx;hm;inl;inc;xsd"
+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+			>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\config.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\fftw-int.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\fftw.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\rfftw\rfftw.h"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Resource Files"
+			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
+			UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+			>
+		</Filter>
+		<Filter
+			Name="Source Files"
+			Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+			>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\config.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\executor.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\rfftw\fcr_1.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\rfftw\fcr_10.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\rfftw\fcr_11.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\rfftw\fcr_12.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\rfftw\fcr_128.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\rfftw\fcr_13.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\rfftw\fcr_14.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\rfftw\fcr_15.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\rfftw\fcr_16.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\rfftw\fcr_2.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\rfftw\fcr_3.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\rfftw\fcr_32.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\rfftw\fcr_4.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\rfftw\fcr_5.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\rfftw\fcr_6.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\rfftw\fcr_64.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\rfftw\fcr_7.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\rfftw\fcr_8.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\rfftw\fcr_9.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\fftwf77.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\fftwnd.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\rfftw\fhb_10.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\rfftw\fhb_16.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\rfftw\fhb_2.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\rfftw\fhb_3.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\rfftw\fhb_32.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\rfftw\fhb_4.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\rfftw\fhb_5.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\rfftw\fhb_6.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\rfftw\fhb_7.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\rfftw\fhb_8.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\rfftw\fhb_9.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\rfftw\fhf_10.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\rfftw\fhf_16.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\rfftw\fhf_2.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\rfftw\fhf_3.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\rfftw\fhf_32.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\rfftw\fhf_4.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\rfftw\fhf_5.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\rfftw\fhf_6.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\rfftw\fhf_7.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\rfftw\fhf_8.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\rfftw\fhf_9.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\fn_1.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\fn_10.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\fn_11.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\fn_12.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\fn_13.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\fn_14.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\fn_15.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\fn_16.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\fn_2.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\fn_3.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\fn_32.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\fn_4.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\fn_5.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\fn_6.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\fn_64.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\fn_7.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\fn_8.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\fn_9.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\fni_1.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\fni_10.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\fni_11.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\fni_12.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\fni_13.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\fni_14.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\fni_15.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\fni_16.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\fni_2.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\fni_3.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\fni_32.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\fni_4.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\fni_5.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\fni_6.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\fni_64.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\fni_7.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\fni_8.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\fni_9.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\rfftw\frc_1.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\rfftw\frc_10.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\rfftw\frc_11.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\rfftw\frc_12.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\rfftw\frc_128.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\rfftw\frc_13.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\rfftw\frc_14.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\rfftw\frc_15.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\rfftw\frc_16.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\rfftw\frc_2.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\rfftw\frc_3.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\rfftw\frc_32.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\rfftw\frc_4.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\rfftw\frc_5.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\rfftw\frc_6.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\rfftw\frc_64.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\rfftw\frc_7.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\rfftw\frc_8.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\rfftw\frc_9.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\ftw_10.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\ftw_16.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\ftw_2.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\ftw_3.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\ftw_32.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\ftw_4.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\ftw_5.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\ftw_6.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\ftw_64.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\ftw_7.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\ftw_8.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\ftw_9.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\ftwi_10.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\ftwi_16.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\ftwi_2.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\ftwi_3.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\ftwi_32.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\ftwi_4.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\ftwi_5.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\ftwi_6.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\ftwi_64.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\ftwi_7.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\ftwi_8.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\ftwi_9.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\generic.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\malloc.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\planner.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\putils.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\rader.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\rfftw\rconfig.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\rfftw\rexec.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\rfftw\rexec2.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\rfftw\rfftwf77.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\rfftw\rfftwnd.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\rfftw\rgeneric.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\rfftw\rplanner.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\timer.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\twiddle.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\wisdom.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\fftw-2.1.5\fftw\wisdomio.c"
+				>
+			</File>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
diff --git a/windows/qwt.vcproj b/windows/qwt.vcproj
new file mode 100644
index 0000000..8714776
--- /dev/null
+++ b/windows/qwt.vcproj
@@ -0,0 +1,1076 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="9.00"
+	Name="qwt"
+	ProjectGUID="{923E2707-8E52-3149-831C-A450E228D6BA}"
+	RootNamespace="qwt"
+	TargetFrameworkVersion="131072"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="..\libs"
+			IntermediateDirectory="Release\"
+			ConfigurationType="4"
+			UseOfMFC="0"
+			ATLMinimizesCRunTimeLibraryUsage="false"
+			BuildLogFile="$(IntDir)\QwtBuildLog.htm"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				WarningLevel="0"
+				DefaultCharType="0"
+				EnableErrorChecks="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				AdditionalOptions="-Zm200 -w34100 -w34189"
+				Optimization="1"
+				AdditionalIncludeDirectories=""..\..\qwt-4.2.0\include";"$(QTDIR)\include";"..\..\qwt-4.2.0\src\moc\";"$(QTDIR)\mkspecs\win32-msvc.net""
+				PreprocessorDefinitions="QT_NO_DEBUG,NDEBUG,_WINDOWS,UNICODE,WIN32,QT_DLL,QWT_DLL,QWT_MAKEDLL,QT_DLL,QT_THREAD_SUPPORT,NDEBUG"
+				GeneratePreprocessedFile="0"
+				ExceptionHandling="1"
+				RuntimeLibrary="0"
+				BufferSecurityCheck="false"
+				RuntimeTypeInfo="true"
+				AssemblerListingLocation="Release\"
+				ObjectFile="Release\"
+				ProgramDataBaseFileName=".\"
+				WarningLevel="3"
+				SuppressStartupBanner="true"
+				DebugInformationFormat="0"
+				DisableSpecificWarnings="4996"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="NDEBUG"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+				CommandLine="mkdir ..\libs\qwt&#x0D;&#x0A;copy ..\..\qwt-4.2.0\include\* ..\libs\qwt&#x0D;&#x0A;"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="..\libs"
+			IntermediateDirectory="Debug\"
+			ConfigurationType="2"
+			UseOfMFC="0"
+			ATLMinimizesCRunTimeLibraryUsage="false"
+			BuildLogFile="$(IntDir)\QwtBuildLog.htm"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				WarningLevel="0"
+				DefaultCharType="0"
+				EnableErrorChecks="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				AdditionalOptions="-Zm200 -GX -GX -w34100 -w34189"
+				Optimization="1"
+				AdditionalIncludeDirectories=""..\..\qwt-4.2.0\include";"$(QTDIR)\include";"..\..\qwt-4.2.0\src\moc\";"$(QTDIR)\mkspecs\win32-msvc.net""
+				PreprocessorDefinitions="QT_NO_DEBUG,_WINDOWS,UNICODE,WIN32,QT_DLL,QWT_DLL,QWT_MAKEDLL,QT_DLL,QT_THREAD_SUPPORT"
+				GeneratePreprocessedFile="0"
+				ExceptionHandling="1"
+				RuntimeLibrary="2"
+				BufferSecurityCheck="false"
+				RuntimeTypeInfo="true"
+				AssemblerListingLocation="Debug\"
+				ObjectFile="Debug\"
+				ProgramDataBaseFileName=".\"
+				WarningLevel="3"
+				SuppressStartupBanner="true"
+				DebugInformationFormat="0"
+				DisableSpecificWarnings="4996"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="NDEBUG"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				IgnoreImportLibrary="true"
+				AdditionalDependencies="qt-mt3.lib kernel32.lib user32.lib gdi32.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib imm32.lib winmm.lib wsock32.lib winspool.lib"
+				OutputFile="qwt.dll"
+				SuppressStartupBanner="true"
+				AdditionalLibraryDirectories="$(QTDIR)\lib"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile=""
+				SubSystem="2"
+				BaseAddress="0x39D00000"
+				RandomizedBaseAddress="1"
+				DataExecutionPrevention="0"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Source Files"
+			Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+			>
+			<File
+				RelativePath="..\..\qwt-4.2.0\src\qwt_analog_clock.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\qwt-4.2.0\src\qwt_arrbtn.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\qwt-4.2.0\src\qwt_autoscl.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\qwt-4.2.0\src\qwt_compass.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\qwt-4.2.0\src\qwt_compass_rose.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\qwt-4.2.0\src\qwt_counter.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\qwt-4.2.0\src\qwt_curve.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\qwt-4.2.0\src\qwt_data.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\qwt-4.2.0\src\qwt_dial.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\qwt-4.2.0\src\qwt_dial_needle.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\qwt-4.2.0\src\qwt_dimap.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\qwt-4.2.0\src\qwt_double_rect.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\qwt-4.2.0\src\qwt_drange.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\qwt-4.2.0\src\qwt_dyngrid_layout.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\qwt-4.2.0\src\qwt_event_pattern.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\qwt-4.2.0\src\qwt_grid.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\qwt-4.2.0\src\qwt_knob.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\qwt-4.2.0\src\qwt_layout_metrics.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\qwt-4.2.0\src\qwt_legend.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\qwt-4.2.0\src\qwt_marker.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\qwt-4.2.0\src\qwt_math.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\qwt-4.2.0\src\qwt_paint_buffer.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\qwt-4.2.0\src\qwt_painter.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\qwt-4.2.0\src\qwt_picker.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\qwt-4.2.0\src\qwt_picker_machine.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\qwt-4.2.0\src\qwt_plot.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\qwt-4.2.0\src\qwt_plot_axis.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\qwt-4.2.0\src\qwt_plot_canvas.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\qwt-4.2.0\src\qwt_plot_curve.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\qwt-4.2.0\src\qwt_plot_grid.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\qwt-4.2.0\src\qwt_plot_item.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\qwt-4.2.0\src\qwt_plot_layout.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\qwt-4.2.0\src\qwt_plot_marker.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\qwt-4.2.0\src\qwt_plot_picker.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\qwt-4.2.0\src\qwt_plot_print.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\qwt-4.2.0\src\qwt_plot_printfilter.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\qwt-4.2.0\src\qwt_plot_zoomer.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\qwt-4.2.0\src\qwt_push_button.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\qwt-4.2.0\src\qwt_rect.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\qwt-4.2.0\src\qwt_scale.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\qwt-4.2.0\src\qwt_scldiv.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\qwt-4.2.0\src\qwt_scldraw.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\qwt-4.2.0\src\qwt_sclif.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\qwt-4.2.0\src\qwt_sldbase.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\qwt-4.2.0\src\qwt_slider.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\qwt-4.2.0\src\qwt_spline.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\qwt-4.2.0\src\qwt_symbol.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\qwt-4.2.0\src\qwt_text.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\qwt-4.2.0\src\qwt_thermo.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\qwt-4.2.0\src\qwt_wheel.cpp"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Header Files"
+			Filter="h;hpp;hxx;hm;inl"
+			>
+			<File
+				RelativePath="include\qwt.h"
+				>
+			</File>
+			<File
+				RelativePath="include\qwt_analog_clock.h"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="Moc'ing ..\..\qwt-4.2.0\include\qwt_analog_clock.h..."
+						CommandLine="$(QTDIR)\bin\moc.exe ..\..\qwt-4.2.0\include\qwt_analog_clock.h -o ..\..\qwt-4.2.0\src\moc\moc_qwt_analog_clock.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe"
+						Outputs="..\..\qwt-4.2.0\src\moc\moc_qwt_analog_clock.cpp"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="Moc'ing ..\..\qwt-4.2.0\include\qwt_analog_clock.h..."
+						CommandLine="$(QTDIR)\bin\moc.exe ..\..\qwt-4.2.0\include\qwt_analog_clock.h -o ..\..\qwt-4.2.0\src\moc\moc_qwt_analog_clock.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe"
+						Outputs="..\..\qwt-4.2.0\src\moc\moc_qwt_analog_clock.cpp"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="include\qwt_array.h"
+				>
+			</File>
+			<File
+				RelativePath="include\qwt_arrbtn.h"
+				>
+			</File>
+			<File
+				RelativePath="include\qwt_autoscl.h"
+				>
+			</File>
+			<File
+				RelativePath="include\qwt_compass.h"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="Moc'ing ..\..\qwt-4.2.0\include\qwt_compass.h..."
+						CommandLine="$(QTDIR)\bin\moc.exe ..\..\qwt-4.2.0\include\qwt_compass.h -o ..\..\qwt-4.2.0\src\moc\moc_qwt_compass.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe"
+						Outputs="..\..\qwt-4.2.0\src\moc\moc_qwt_compass.cpp"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="Moc'ing ..\..\qwt-4.2.0\include\qwt_compass.h..."
+						CommandLine="$(QTDIR)\bin\moc.exe ..\..\qwt-4.2.0\include\qwt_compass.h -o ..\..\qwt-4.2.0\src\moc\moc_qwt_compass.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe"
+						Outputs="..\..\qwt-4.2.0\src\moc\moc_qwt_compass.cpp"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="include\qwt_compass_rose.h"
+				>
+			</File>
+			<File
+				RelativePath="include\qwt_counter.h"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="Moc'ing ..\..\qwt-4.2.0\include\qwt_counter.h..."
+						CommandLine="$(QTDIR)\bin\moc.exe ..\..\qwt-4.2.0\include\qwt_counter.h -o ..\..\qwt-4.2.0\src\moc\moc_qwt_counter.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe"
+						Outputs="..\..\qwt-4.2.0\src\moc\moc_qwt_counter.cpp"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="Moc'ing ..\..\qwt-4.2.0\include\qwt_counter.h..."
+						CommandLine="$(QTDIR)\bin\moc.exe ..\..\qwt-4.2.0\include\qwt_counter.h -o ..\..\qwt-4.2.0\src\moc\moc_qwt_counter.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe"
+						Outputs="..\..\qwt-4.2.0\src\moc\moc_qwt_counter.cpp"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="include\qwt_curve.h"
+				>
+			</File>
+			<File
+				RelativePath="include\qwt_data.h"
+				>
+			</File>
+			<File
+				RelativePath="include\qwt_dial.h"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="Moc'ing ..\..\qwt-4.2.0\include\qwt_dial.h..."
+						CommandLine="$(QTDIR)\bin\moc.exe ..\..\qwt-4.2.0\include\qwt_dial.h -o ..\..\qwt-4.2.0\src\moc\moc_qwt_dial.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe"
+						Outputs="..\..\qwt-4.2.0\src\moc\moc_qwt_dial.cpp"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="Moc'ing ..\..\qwt-4.2.0\include\qwt_dial.h..."
+						CommandLine="$(QTDIR)\bin\moc.exe ..\..\qwt-4.2.0\include\qwt_dial.h -o ..\..\qwt-4.2.0\src\moc\moc_qwt_dial.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe"
+						Outputs="..\..\qwt-4.2.0\src\moc\moc_qwt_dial.cpp"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="include\qwt_dial_needle.h"
+				>
+			</File>
+			<File
+				RelativePath="include\qwt_dimap.h"
+				>
+			</File>
+			<File
+				RelativePath="include\qwt_double_rect.h"
+				>
+			</File>
+			<File
+				RelativePath="include\qwt_drange.h"
+				>
+			</File>
+			<File
+				RelativePath="include\qwt_dyngrid_layout.h"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="Moc'ing ..\..\qwt-4.2.0\include\qwt_dyngrid_layout.h..."
+						CommandLine="$(QTDIR)\bin\moc.exe ..\..\qwt-4.2.0\include\qwt_dyngrid_layout.h -o ..\..\qwt-4.2.0\src\moc\moc_qwt_dyngrid_layout.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe"
+						Outputs="..\..\qwt-4.2.0\src\moc\moc_qwt_dyngrid_layout.cpp"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="Moc'ing ..\..\qwt-4.2.0\include\qwt_dyngrid_layout.h..."
+						CommandLine="$(QTDIR)\bin\moc.exe ..\..\qwt-4.2.0\include\qwt_dyngrid_layout.h -o ..\..\qwt-4.2.0\src\moc\moc_qwt_dyngrid_layout.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe"
+						Outputs="..\..\qwt-4.2.0\src\moc\moc_qwt_dyngrid_layout.cpp"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="include\qwt_event_pattern.h"
+				>
+			</File>
+			<File
+				RelativePath="include\qwt_global.h"
+				>
+			</File>
+			<File
+				RelativePath="include\qwt_grid.h"
+				>
+			</File>
+			<File
+				RelativePath="include\qwt_knob.h"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="Moc'ing ..\..\qwt-4.2.0\include\qwt_knob.h..."
+						CommandLine="$(QTDIR)\bin\moc.exe ..\..\qwt-4.2.0\include\qwt_knob.h -o ..\..\qwt-4.2.0\src\moc\moc_qwt_knob.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe"
+						Outputs="..\..\qwt-4.2.0\src\moc\moc_qwt_knob.cpp"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="Moc'ing ..\..\qwt-4.2.0\include\qwt_knob.h..."
+						CommandLine="$(QTDIR)\bin\moc.exe ..\..\qwt-4.2.0\include\qwt_knob.h -o ..\..\qwt-4.2.0\src\moc\moc_qwt_knob.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe"
+						Outputs="..\..\qwt-4.2.0\src\moc\moc_qwt_knob.cpp"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="include\qwt_layout_metrics.h"
+				>
+			</File>
+			<File
+				RelativePath="include\qwt_legend.h"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="Moc'ing ..\..\qwt-4.2.0\include\qwt_legend.h..."
+						CommandLine="$(QTDIR)\bin\moc.exe ..\..\qwt-4.2.0\include\qwt_legend.h -o ..\..\qwt-4.2.0\src\moc\moc_qwt_legend.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe"
+						Outputs="..\..\qwt-4.2.0\src\moc\moc_qwt_legend.cpp"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="Moc'ing ..\..\qwt-4.2.0\include\qwt_legend.h..."
+						CommandLine="$(QTDIR)\bin\moc.exe ..\..\qwt-4.2.0\include\qwt_legend.h -o ..\..\qwt-4.2.0\src\moc\moc_qwt_legend.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe"
+						Outputs="..\..\qwt-4.2.0\src\moc\moc_qwt_legend.cpp"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="include\qwt_marker.h"
+				>
+			</File>
+			<File
+				RelativePath="include\qwt_math.h"
+				>
+			</File>
+			<File
+				RelativePath="include\qwt_paint_buffer.h"
+				>
+			</File>
+			<File
+				RelativePath="include\qwt_painter.h"
+				>
+			</File>
+			<File
+				RelativePath="include\qwt_picker.h"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="Moc'ing ..\..\qwt-4.2.0\include\qwt_picker.h..."
+						CommandLine="$(QTDIR)\bin\moc.exe ..\..\qwt-4.2.0\include\qwt_picker.h -o ..\..\qwt-4.2.0\src\moc\moc_qwt_picker.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe"
+						Outputs="..\..\qwt-4.2.0\src\moc\moc_qwt_picker.cpp"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="Moc'ing ..\..\qwt-4.2.0\include\qwt_picker.h..."
+						CommandLine="$(QTDIR)\bin\moc.exe ..\..\qwt-4.2.0\include\qwt_picker.h -o ..\..\qwt-4.2.0\src\moc\moc_qwt_picker.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe"
+						Outputs="..\..\qwt-4.2.0\src\moc\moc_qwt_picker.cpp"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="include\qwt_picker_machine.h"
+				>
+			</File>
+			<File
+				RelativePath="include\qwt_plot.h"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="Moc'ing ..\..\qwt-4.2.0\include\qwt_plot.h..."
+						CommandLine="$(QTDIR)\bin\moc.exe ..\..\qwt-4.2.0\include\qwt_plot.h -o ..\..\qwt-4.2.0\src\moc\moc_qwt_plot.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe"
+						Outputs="..\..\qwt-4.2.0\src\moc\moc_qwt_plot.cpp"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="Moc'ing ..\..\qwt-4.2.0\include\qwt_plot.h..."
+						CommandLine="$(QTDIR)\bin\moc.exe ..\..\qwt-4.2.0\include\qwt_plot.h -o ..\..\qwt-4.2.0\src\moc\moc_qwt_plot.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe"
+						Outputs="..\..\qwt-4.2.0\src\moc\moc_qwt_plot.cpp"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="include\qwt_plot_canvas.h"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="Moc'ing ..\..\qwt-4.2.0\include\qwt_plot_canvas.h..."
+						CommandLine="$(QTDIR)\bin\moc.exe ..\..\qwt-4.2.0\include\qwt_plot_canvas.h -o ..\..\qwt-4.2.0\src\moc\moc_qwt_plot_canvas.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe"
+						Outputs="..\..\qwt-4.2.0\src\moc\moc_qwt_plot_canvas.cpp"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="Moc'ing ..\..\qwt-4.2.0\include\qwt_plot_canvas.h..."
+						CommandLine="$(QTDIR)\bin\moc.exe ..\..\qwt-4.2.0\include\qwt_plot_canvas.h -o ..\..\qwt-4.2.0\src\moc\moc_qwt_plot_canvas.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe"
+						Outputs="..\..\qwt-4.2.0\src\moc\moc_qwt_plot_canvas.cpp"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="include\qwt_plot_classes.h"
+				>
+			</File>
+			<File
+				RelativePath="include\qwt_plot_dict.h"
+				>
+			</File>
+			<File
+				RelativePath="include\qwt_plot_item.h"
+				>
+			</File>
+			<File
+				RelativePath="include\qwt_plot_layout.h"
+				>
+			</File>
+			<File
+				RelativePath="include\qwt_plot_picker.h"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="Moc'ing ..\..\qwt-4.2.0\include\qwt_plot_picker.h..."
+						CommandLine="$(QTDIR)\bin\moc.exe ..\..\qwt-4.2.0\include\qwt_plot_picker.h -o ..\..\qwt-4.2.0\src\moc\moc_qwt_plot_picker.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe"
+						Outputs="..\..\qwt-4.2.0\src\moc\moc_qwt_plot_picker.cpp"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="Moc'ing ..\..\qwt-4.2.0\include\qwt_plot_picker.h..."
+						CommandLine="$(QTDIR)\bin\moc.exe ..\..\qwt-4.2.0\include\qwt_plot_picker.h -o ..\..\qwt-4.2.0\src\moc\moc_qwt_plot_picker.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe"
+						Outputs="..\..\qwt-4.2.0\src\moc\moc_qwt_plot_picker.cpp"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="include\qwt_plot_printfilter.h"
+				>
+			</File>
+			<File
+				RelativePath="include\qwt_plot_zoomer.h"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="Moc'ing ..\..\qwt-4.2.0\include\qwt_plot_zoomer.h..."
+						CommandLine="$(QTDIR)\bin\moc.exe ..\..\qwt-4.2.0\include\qwt_plot_zoomer.h -o ..\..\qwt-4.2.0\src\moc\moc_qwt_plot_zoomer.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe"
+						Outputs="..\..\qwt-4.2.0\src\moc\moc_qwt_plot_zoomer.cpp"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="Moc'ing ..\..\qwt-4.2.0\include\qwt_plot_zoomer.h..."
+						CommandLine="$(QTDIR)\bin\moc.exe ..\..\qwt-4.2.0\include\qwt_plot_zoomer.h -o ..\..\qwt-4.2.0\src\moc\moc_qwt_plot_zoomer.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe"
+						Outputs="..\..\qwt-4.2.0\src\moc\moc_qwt_plot_zoomer.cpp"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="include\qwt_push_button.h"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="Moc'ing ..\..\qwt-4.2.0\include\qwt_push_button.h..."
+						CommandLine="$(QTDIR)\bin\moc.exe ..\..\qwt-4.2.0\include\qwt_push_button.h -o ..\..\qwt-4.2.0\src\moc\moc_qwt_push_button.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe"
+						Outputs="..\..\qwt-4.2.0\src\moc\moc_qwt_push_button.cpp"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="Moc'ing ..\..\qwt-4.2.0\include\qwt_push_button.h..."
+						CommandLine="$(QTDIR)\bin\moc.exe ..\..\qwt-4.2.0\include\qwt_push_button.h -o ..\..\qwt-4.2.0\src\moc\moc_qwt_push_button.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe"
+						Outputs="..\..\qwt-4.2.0\src\moc\moc_qwt_push_button.cpp"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="include\qwt_rect.h"
+				>
+			</File>
+			<File
+				RelativePath="include\qwt_scale.h"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="Moc'ing ..\..\qwt-4.2.0\include\qwt_scale.h..."
+						CommandLine="$(QTDIR)\bin\moc.exe ..\..\qwt-4.2.0\include\qwt_scale.h -o ..\..\qwt-4.2.0\src\moc\moc_qwt_scale.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe"
+						Outputs="..\..\qwt-4.2.0\src\moc\moc_qwt_scale.cpp"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="Moc'ing ..\..\qwt-4.2.0\include\qwt_scale.h..."
+						CommandLine="$(QTDIR)\bin\moc.exe ..\..\qwt-4.2.0\include\qwt_scale.h -o ..\..\qwt-4.2.0\src\moc\moc_qwt_scale.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe"
+						Outputs="..\..\qwt-4.2.0\src\moc\moc_qwt_scale.cpp"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="include\qwt_scldiv.h"
+				>
+			</File>
+			<File
+				RelativePath="include\qwt_scldraw.h"
+				>
+			</File>
+			<File
+				RelativePath="include\qwt_sclif.h"
+				>
+			</File>
+			<File
+				RelativePath="include\qwt_sldbase.h"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="Moc'ing ..\..\qwt-4.2.0\include\qwt_sldbase.h..."
+						CommandLine="$(QTDIR)\bin\moc.exe ..\..\qwt-4.2.0\include\qwt_sldbase.h -o ..\..\qwt-4.2.0\src\moc\moc_qwt_sldbase.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe"
+						Outputs="..\..\qwt-4.2.0\src\moc\moc_qwt_sldbase.cpp"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="Moc'ing ..\..\qwt-4.2.0\include\qwt_sldbase.h..."
+						CommandLine="$(QTDIR)\bin\moc.exe ..\..\qwt-4.2.0\include\qwt_sldbase.h -o ..\..\qwt-4.2.0\src\moc\moc_qwt_sldbase.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe"
+						Outputs="..\..\qwt-4.2.0\src\moc\moc_qwt_sldbase.cpp"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="include\qwt_slider.h"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="Moc'ing ..\..\qwt-4.2.0\include\qwt_slider.h..."
+						CommandLine="$(QTDIR)\bin\moc.exe ..\..\qwt-4.2.0\include\qwt_slider.h -o ..\..\qwt-4.2.0\src\moc\moc_qwt_slider.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe"
+						Outputs="..\..\qwt-4.2.0\src\moc\moc_qwt_slider.cpp"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="Moc'ing ..\..\qwt-4.2.0\include\qwt_slider.h..."
+						CommandLine="$(QTDIR)\bin\moc.exe ..\..\qwt-4.2.0\include\qwt_slider.h -o ..\..\qwt-4.2.0\src\moc\moc_qwt_slider.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe"
+						Outputs="..\..\qwt-4.2.0\src\moc\moc_qwt_slider.cpp"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="include\qwt_spline.h"
+				>
+			</File>
+			<File
+				RelativePath="include\qwt_symbol.h"
+				>
+			</File>
+			<File
+				RelativePath="include\qwt_text.h"
+				>
+			</File>
+			<File
+				RelativePath="include\qwt_thermo.h"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="Moc'ing ..\..\qwt-4.2.0\include\qwt_thermo.h..."
+						CommandLine="$(QTDIR)\bin\moc.exe ..\..\qwt-4.2.0\include\qwt_thermo.h -o ..\..\qwt-4.2.0\src\moc\moc_qwt_thermo.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe"
+						Outputs="..\..\qwt-4.2.0\src\moc\moc_qwt_thermo.cpp"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="Moc'ing ..\..\qwt-4.2.0\include\qwt_thermo.h..."
+						CommandLine="$(QTDIR)\bin\moc.exe ..\..\qwt-4.2.0\include\qwt_thermo.h -o ..\..\qwt-4.2.0\src\moc\moc_qwt_thermo.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe"
+						Outputs="..\..\qwt-4.2.0\src\moc\moc_qwt_thermo.cpp"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="include\qwt_wheel.h"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="Moc'ing ..\..\qwt-4.2.0\include\qwt_wheel.h..."
+						CommandLine="$(QTDIR)\bin\moc.exe ..\..\qwt-4.2.0\include\qwt_wheel.h -o ..\..\qwt-4.2.0\src\moc\moc_qwt_wheel.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe"
+						Outputs="..\..\qwt-4.2.0\src\moc\moc_qwt_wheel.cpp"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="Moc'ing ..\..\qwt-4.2.0\include\qwt_wheel.h..."
+						CommandLine="$(QTDIR)\bin\moc.exe ..\..\qwt-4.2.0\include\qwt_wheel.h -o ..\..\qwt-4.2.0\src\moc\moc_qwt_wheel.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe"
+						Outputs="..\..\qwt-4.2.0\src\moc\moc_qwt_wheel.cpp"
+					/>
+				</FileConfiguration>
+			</File>
+		</Filter>
+		<Filter
+			Name="Generated MOC Files"
+			Filter="cpp;c;cxx;moc"
+			>
+			<File
+				RelativePath="..\..\qwt-4.2.0\src\moc\moc_qwt_analog_clock.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\qwt-4.2.0\src\moc\moc_qwt_compass.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\qwt-4.2.0\src\moc\moc_qwt_counter.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\qwt-4.2.0\src\moc\moc_qwt_dial.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\qwt-4.2.0\src\moc\moc_qwt_dyngrid_layout.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\qwt-4.2.0\src\moc\moc_qwt_knob.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\qwt-4.2.0\src\moc\moc_qwt_legend.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\qwt-4.2.0\src\moc\moc_qwt_picker.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\qwt-4.2.0\src\moc\moc_qwt_plot.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\qwt-4.2.0\src\moc\moc_qwt_plot_canvas.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\qwt-4.2.0\src\moc\moc_qwt_plot_picker.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\qwt-4.2.0\src\moc\moc_qwt_plot_zoomer.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\qwt-4.2.0\src\moc\moc_qwt_push_button.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\qwt-4.2.0\src\moc\moc_qwt_scale.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\qwt-4.2.0\src\moc\moc_qwt_sldbase.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\qwt-4.2.0\src\moc\moc_qwt_slider.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\qwt-4.2.0\src\moc\moc_qwt_thermo.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\qwt-4.2.0\src\moc\moc_qwt_wheel.cpp"
+				>
+			</File>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-hamradio/dream.git



More information about the pkg-hamradio-commits mailing list