diff options
Diffstat (limited to 'src')
72 files changed, 14809 insertions, 0 deletions
diff --git a/src/DabMux.cpp b/src/DabMux.cpp new file mode 100644 index 0000000..59278f9 --- /dev/null +++ b/src/DabMux.cpp @@ -0,0 +1,3549 @@ +/* + Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, + 2011 Her Majesty the Queen in Right of Canada (Communications + Research Center Canada) + */ +/* + This file is part of CRC-DabMux. + + CRC-DabMux is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + CRC-DabMux is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CRC-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <iostream> +#include <fstream> +#include <iomanip> +#include <cstdio> +#include <cstring> +#include <errno.h> + +using namespace std; +#include <vector> +#include <set> +#include <functional> +#include <algorithm> + +#ifdef _WIN32 +# include <time.h> +# include <process.h> +# include <io.h> +# include <conio.h> +# include <winsock2.h> // For types... +typedef u_char uint8_t; +typedef WORD uint16_t; +typedef DWORD32 uint32_t; + +# ifndef __MINGW32__ +# include "xgetopt.h" +# endif +# define read _read +# define snprintf _snprintf +# define sleep(a) Sleep((a) * 1000) +#else +# include <netinet/in.h> +# include <unistd.h> +# include <sys/time.h> +# include <sys/wait.h> +# include <sys/socket.h> +# include <sys/ioctl.h> +# include <sys/times.h> + +# include <linux/if_packet.h> +# include <linux/netdevice.h> +#endif + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <signal.h> + +#ifdef _WIN32 +# pragma warning ( disable : 4103 ) +# include "Eti.h" +# pragma warning ( default : 4103 ) +#else +# include "Eti.h" +#endif +#include "dabInputFile.h" +#include "dabInputFifo.h" +#include "dabInputMpegFile.h" +#include "dabInputMpegFifo.h" +#include "dabInputDabplusFile.h" +#include "dabInputDabplusFifo.h" +#include "dabInputPacketFile.h" +#include "dabInputEnhancedPacketFile.h" +#include "dabInputEnhancedFifo.h" +#include "dabInputUdp.h" +#include "dabInputBridgeUdp.h" +#include "dabInputSlip.h" +#include "dabInputTest.h" +#include "dabInputPrbs.h" +#include "dabInputRawFile.h" +#include "dabInputRawFifo.h" +#include "dabInputDmbFile.h" +#include "dabInputDmbUdp.h" + + +#include "dabOutput.h" +#include "crc.h" +#include "UdpSocket.h" +#include "InetAddress.h" +#include "dabUtils.h" +#include "PcDebug.h" + + +// DAB Mode +#define DEFAULT_DAB_MODE 2 + +// Taille de la trame de donnee, sous-canal 3, nb de paquets de 64bits, +// STL3 * 8 = x kbytes par trame ETI + +// Data bitrate in kbits/s. Must be 64 kb/s multiple. +#define DEFAULT_DATA_BITRATE 384 +#define DEFAULT_PACKET_BITRATE 32 + +// Etiquettes des sous-canaux et de l'ensemble, 16 characteres incluant les +// espaces +#define DEFAULT_ENSEMBLE_LABEL "CRC-Dr.Radio" +#define DEFAULT_ENSEMBLE_SHORT_LABEL 0xe000 +#define DEFAULT_ENSEMBLE_ID 0xc000 +#define DEFAULT_ENSEMBLE_ECC 0xa1 + +//Numeros des sous-canaux +#define DEFAULT_SERVICE_ID 50 +#define DEFAULT_PACKET_ADDRESS 0 + + +struct dabOutput { + const char* outputProto; + const char* outputName; + void* data; + dabOutputOperations operations; +}; + + +struct dabLabel { + char text[16]; + uint16_t flag; +}; + + +struct dabService; +struct dabComponent; +struct dabSubchannel; +struct dabEnsemble { + uint16_t id; + uint8_t ecc; + dabLabel label; + uint8_t mode; + vector<dabService*> services; + vector<dabComponent*> components; + vector<dabSubchannel*> subchannels; +}; + + +struct dabProtectionShort { + unsigned char tableSwitch; + unsigned char tableIndex; +}; + + +struct dabProtectionLong { + unsigned char option; +}; + + +struct dabProtection { + unsigned char level; + unsigned char form; + union { + dabProtectionShort shortForm; + dabProtectionLong longForm; + }; +}; + + +struct dabSubchannel { + const char* inputProto; + const char* inputName; + void* data; + dabInputOperations operations; + unsigned char id; + unsigned char type; + uint16_t startAddress; + uint16_t bitrate; + dabProtection protection; +}; + + +class SubchannelId : public std::binary_function <dabSubchannel*, int, bool> { +public: + bool operator()(const dabSubchannel* subchannel, const int id) const { + return subchannel->id == id; + } +}; + + +vector<dabSubchannel*>::iterator getSubchannel( + vector<dabSubchannel*>& subchannels, int id) +{ + return find_if( + subchannels.begin(), + subchannels.end(), + bind2nd(SubchannelId(), id) + ); +} + + +struct dabAudioComponent { +}; + + +struct dabDataComponent { +}; + + +struct dabFidcComponent { +}; + + +struct dabPacketComponent { + uint16_t id; + uint16_t address; + uint16_t appType; + bool datagroup; +}; + + +struct dabComponent { + dabLabel label; + uint32_t serviceId; + uint8_t subchId; + uint8_t type; + uint8_t SCIdS; + union { + dabAudioComponent audio; + dabDataComponent data; + dabFidcComponent fidc; + dabPacketComponent packet; + }; + + bool isPacketComponent(vector<dabSubchannel*>& subchannels) + { + if (subchId > 63) { + etiLog.printHeader(TcpLog::ERR, + "You must define subchannel id in the " + "packet component before defining packet "); + return false; + } + if (getSubchannel(subchannels, subchId) == subchannels.end()) { + etiLog.printHeader(TcpLog::ERR, + "Invalid subchannel id in the packet component " + "for defining packet "); + return false; + } + if ((*getSubchannel(subchannels, subchId))->type != 3) { + etiLog.printHeader(TcpLog::ERR, + "Invalid component type for defining packet "); + return false; + } + return true; + } +}; + + +vector<dabComponent*>::iterator getComponent( + vector<dabComponent*>& components, + uint32_t serviceId, + vector<dabComponent*>::iterator current) +{ + if (current == components.end()) { + current = components.begin(); + } else { + ++current; + } + + while (current != components.end()) { + if ((*current)->serviceId == serviceId) { + return current; + } + ++current; + } + + return components.end(); +} + + +vector<dabComponent*>::iterator getComponent( + vector<dabComponent*>& components, + uint32_t serviceId) { + return getComponent(components, serviceId, components.end()); +} + + +struct dabService { + dabLabel label; + uint32_t id; + unsigned char pty; + unsigned char language; + bool program; + + unsigned char getType(dabEnsemble* ensemble) + { + vector<dabSubchannel*>::iterator subchannel; + vector<dabComponent*>::iterator component = + getComponent(ensemble->components, id); + if (component == ensemble->components.end()) { + return 4; + } + subchannel = getSubchannel(ensemble->subchannels, (*component)->subchId); + if (subchannel == ensemble->subchannels.end()) { + return 8; + } + + return (*subchannel)->type; + } + unsigned char nbComponent(vector<dabComponent*>& components) + { + int nb = 0; + vector<dabComponent*>::iterator current; + + for (current = components.begin(); current != components.end(); + ++current) { + if ((*current)->serviceId == id) { + ++nb; + } + } + return nb; + } +}; + + +vector<dabService*>::iterator getService( + dabComponent* component, + vector<dabService*>& services) +{ + vector<dabService*>::iterator service; + + for (service = services.begin(); service != services.end(); ++service) { + if ((*service)->id == component->serviceId) { + break; + } + } + + return service; +} + + +/****************************************************************************** + ***************** Definitions des stuctures des FIGs ********************** + ******************************************************************************/ +struct FIGtype0 { + uint8_t Length:5; + uint8_t FIGtypeNumber:3; + uint8_t Extension:5; + uint8_t PD:1; + uint8_t OE:1; + uint8_t CN:1; +} PACKED; + + +struct FIGtype0_0 { + uint8_t Length:5; + uint8_t FIGtypeNumber:3; + uint8_t Extension:5; + uint8_t PD:1; + uint8_t OE:1; + uint8_t CN:1; + + uint16_t EId; + uint8_t CIFcnt_hight:5; + uint8_t Al:1; + uint8_t Change:2; + uint8_t CIFcnt_low:8; +} PACKED; + + +struct FIGtype0_2 { + uint8_t Length:5; + uint8_t FIGtypeNumber:3; + uint8_t Extension:5; + uint8_t PD:1; + uint8_t OE:1; + uint8_t CN:1; +} PACKED; + + +struct FIGtype0_2_Service { + uint16_t SId; + uint8_t NbServiceComp:4; + uint8_t CAId:3; + uint8_t Local_flag:1; +} PACKED; + + +struct FIGtype0_2_Service_data { + uint32_t SId; + uint8_t NbServiceComp:4; + uint8_t CAId:3; + uint8_t Local_flag:1; +} PACKED; + + +struct FIGtype0_2_audio_component { + uint8_t ASCTy:6; + uint8_t TMid:2; + uint8_t CA_flag:1; + uint8_t PS:1; + uint8_t SubChId:6; +} PACKED; + + +struct FIGtype0_2_data_component { + uint8_t DSCTy:6; + uint8_t TMid:2; + uint8_t CA_flag:1; + uint8_t PS:1; + uint8_t SubChId:6; +} PACKED; + + +struct FIGtype0_2_packet_component { + uint8_t SCId_high:6; + uint8_t TMid:2; + uint8_t CA_flag:1; + uint8_t PS:1; + uint8_t SCId_low:6; + void setSCId(uint16_t SCId) { + SCId_high = SCId >> 6; + SCId_low = SCId & 0x3f; + } +} PACKED; + + +struct FIGtype0_3_header { + uint8_t Length:5; + uint8_t FIGtypeNumber:3; + uint8_t Extension:5; + uint8_t PD:1; + uint8_t OE:1; + uint8_t CN:1; +} PACKED; + + +/* Warning: When bit SCCA_flag is unset(0), the multiplexer R&S does not send + * the SCCA field. But, in the Factum ETI analyzer, if this field is not there, + * it is an error. + */ +struct FIGtype0_3_data { + uint8_t SCId_high; + uint8_t SCCA_flag:1; + uint8_t rfa:3; + uint8_t SCId_low:4; + uint8_t DSCTy:6; + uint8_t rfu:1; + uint8_t DG_flag:1; + uint8_t Packet_address_high:2; + uint8_t SubChId:6; + uint8_t Packet_address_low; + uint16_t SCCA; + void setSCId(uint16_t SCId) { + SCId_high = SCId >> 4; + SCId_low = SCId & 0xf; + } + void setPacketAddress(uint16_t address) { + Packet_address_high = address >> 8; + Packet_address_low = address & 0xff; + } +} PACKED; + + +struct FIGtype0_8_short { + uint8_t SCIdS:4; + uint8_t rfa_1:3; + uint8_t ext:1; + uint8_t Id:6; + uint8_t MscFic:1; + uint8_t LS:1; + uint8_t rfa_2; +} PACKED; + + +struct FIGtype0_8_long { + uint8_t SCIdS:4; + uint8_t rfa_1:3; + uint8_t ext:1; + uint8_t SCId_high:4; + uint8_t rfa:3; + uint8_t LS:1; + uint8_t SCId_low; + uint8_t rfa_2; + void setSCId(uint16_t id) { + SCId_high = id >> 8; + SCId_low = id & 0xff; + } + uint16_t getSCid() { + return (SCId_high << 8) | SCId_low; + } +} PACKED; + + +struct FIGtype0_9 { + uint8_t Length:5; + uint8_t FIGtypeNumber:3; + uint8_t Extension:5; + uint8_t PD:1; + uint8_t OE:1; + uint8_t CN:1; + + uint8_t ensembleLto:6; + uint8_t lto:1; + uint8_t ext:1; + uint8_t ensembleEcc; + uint8_t tableId; +} PACKED; + + +struct FIGtype0_10 { + uint8_t Length:5; + uint8_t FIGtypeNumber:3; + uint8_t Extension:5; + uint8_t PD:1; + uint8_t OE:1; + uint8_t CN:1; + + uint8_t MJD_high:7; + uint8_t RFU:1; + uint8_t MJD_med; + uint8_t Hours_high:3; + uint8_t UTC:1; + uint8_t ConfInd:1; + uint8_t LSI:1; + uint8_t MJD_low:2; + uint8_t Minutes:6; + uint8_t Hours_low:2; + void setMJD(uint32_t date) { + MJD_high = (date >> 10) & 0x7f; + MJD_med = (date >> 2) & 0xff; + MJD_low = date & 0x03; + } + void setHours(uint16_t hours) { + Hours_high = (hours >> 2) & 0x07; + Hours_low = hours & 0x03; + } +} PACKED; + + +struct FIGtype0_17_programme { + uint16_t SId; + uint8_t NFC:2; + uint8_t Rfa:2; + uint8_t CC:1; + uint8_t L:1; + uint8_t PS:1; + uint8_t SD:1; +} PACKED; + + +struct FIGtype0_1 { + uint8_t Length:5; + uint8_t FIGtypeNumber:3; + uint8_t Extension:5; + uint8_t PD:1; + uint8_t OE:1; + uint8_t CN:1; +} PACKED; + + +struct FIG_01_SubChannel_ShortF { + uint8_t StartAdress_high:2; + uint8_t SubChId:6; + uint8_t StartAdress_low:8; + uint8_t TableIndex:6; + uint8_t TableSwitch:1; + uint8_t Short_Long_form:1; +} PACKED; + + +struct FIG_01_SubChannel_LongF { + uint8_t StartAdress_high:2; + uint8_t SubChId:6; + uint8_t StartAdress_low:8; + uint8_t Sub_ChannelSize_high:2; + uint8_t ProtectionLevel:2; + uint8_t Option:3; + uint8_t Short_Long_form:1; + uint8_t Sub_ChannelSize_low:8; +} PACKED; + + +struct FIG0_13_shortAppInfo { + uint16_t SId; + uint8_t No:4; + uint8_t SCIdS:4; +} PACKED; + + +struct FIG0_13_longAppInfo { + uint32_t SId; + uint8_t No:4; + uint8_t SCIdS:4; +} PACKED; + + +struct FIG0_13_app { + uint8_t typeHigh; + uint8_t length:5; + uint8_t typeLow:3; + void setType(uint16_t type) { + typeHigh = type >> 3; + typeLow = type & 0x1f; + } +} PACKED; + + +struct FIGtype1_0 { + uint8_t Length:5; + uint8_t FIGtypeNumber:3; + uint8_t Extension:3; + uint8_t OE:1; + uint8_t Charset:4; + + uint16_t EId; +} PACKED; + + +struct FIGtype1_1 { + uint8_t Length:5; + uint8_t FIGtypeNumber:3; + uint8_t Extension:3; + uint8_t OE:1; + uint8_t Charset:4; + + uint16_t Sld; +} PACKED; + + +struct FIGtype1_5 { + uint8_t Length:5; + uint8_t FIGtypeNumber:3; + uint8_t Extension:3; + uint8_t OE:1; + uint8_t Charset:4; + uint32_t SId; +} PACKED; + + +struct FIGtype1_4_programme { + uint8_t Length:5; + uint8_t FIGtypeNumber:3; + uint8_t Extension:3; + uint8_t OE:1; + uint8_t Charset:4; + uint8_t SCIdS:4; + uint8_t rfa:3; + uint8_t PD:1; + uint16_t SId; +} PACKED; + + +struct FIGtype1_4_data { + uint8_t Length:5; + uint8_t FIGtypeNumber:3; + uint8_t Extension:3; + uint8_t OE:1; + uint8_t Charset:4; + uint8_t SCIdS:4; + uint8_t rfa:3; + uint8_t PD:1; + uint32_t SId; +} PACKED; + + +#ifdef _WIN32 +# pragma pack(pop) +#endif + +static unsigned char Padding_FIB[] = { + 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +/****************************************************************************** + ************* Tables pour l'identification des fichiers mp2 **************** + *****************************************************************************/ +const unsigned short Bit_Rate_SpecifiedTable[16] = { + 0, 32, 48, 56, 64, 80, 96, 112, + 128, 160, 192, 224, 256, 320, 384, 0 +}; + + +const unsigned short Sub_Channel_SizeTable[64] = { + 16, 21, 24, 29, 35, 24, 29, 35, + 42, 52, 29, 35, 42, 52, 32, 42, + 48, 58, 70, 40, 52, 58, 70, 84, + 48, 58, 70, 84, 104, 58, 70, 84, + 104, 64, 84, 96, 116, 140, 80, 104, + 116, 140, 168, 96, 116, 140, 168, 208, + 116, 140, 168, 208, 232, 128, 168, 192, + 232, 280, 160, 208, 280, 192, 280, 416 +}; + + +const unsigned char ProtectionLevelTable[64] = { + 4, 3, 2, 1, 0, 4, 3, 2, + 1, 0, 4, 3, 2, 1, 4, 3, + 2, 1, 0, 4, 3, 2, 1, 0, + 4, 3, 2, 1, 0, 4, 3, 2, + 1, 4, 3, 2, 1, 0, 4, 3, + 2, 1, 0, 4, 3, 2, 1, 0, + 4, 3, 2, 1, 0, 4, 3, 2, + 1, 0, 4, 3, 1, 4, 2, 0 +}; + + +const unsigned short BitRateTable[64] = { + 32, 32, 32, 32, 32, 48, 48, 48, + 48, 48, 56, 56, 56, 56, 64, 64, + 64, 64, 64, 80, 80, 80, 80, 80, + 96, 96, 96, 96, 96, 112, 112, 112, + 112, 128, 128, 128, 128, 128, 160, 160, + 160, 160, 160, 192, 192, 192, 192, 192, + 224, 224, 224, 224, 224, 256, 256, 256, + 256, 256, 320, 320, 320, 384, 384, 384 +}; + + +unsigned short getSizeByte(dabSubchannel* subchannel) +{ + return subchannel->bitrate * 3; +} + + +unsigned short getSizeWord(dabSubchannel* subchannel) +{ + return (subchannel->bitrate * 3) >> 2; +} + + +unsigned short getSizeDWord(dabSubchannel* subchannel) +{ + return (subchannel->bitrate * 3) >> 3; +} + + +unsigned short getSizeCu(dabSubchannel* subchannel) +{ + if (subchannel->protection.form == 0) { + return Sub_Channel_SizeTable[subchannel-> + protection.shortForm.tableIndex]; + } else { + dabProtectionLong* protection = + &subchannel->protection.longForm; + switch (protection->option) { + case 0: + switch (subchannel->protection.level) { + case 0: + return (subchannel->bitrate * 12) >> 3; + break; + case 1: + return subchannel->bitrate; + break; + case 2: + return (subchannel->bitrate * 6) >> 3; + break; + case 3: + return (subchannel->bitrate >> 1); + break; + default: // Should not happens + etiLog.print(TcpLog::ERR, "Bad protection level on " + "subchannel\n"); + return 0; + } + break; + case 1: + switch (subchannel->protection.level) { + case 0: + return (subchannel->bitrate * 27) >> 5; + break; + case 1: + return (subchannel->bitrate * 21) >> 5; + break; + case 2: + return (subchannel->bitrate * 18) >> 5; + break; + case 3: + return (subchannel->bitrate * 15) >> 5; + break; + default: // Should not happens + etiLog.print(TcpLog::ERR, + "Bad protection level on subchannel\n"); + return 0; + } + break; + default: + etiLog.print(TcpLog::ERR, "Invalid protection option\n"); + return 0; + } + } + return 0; +} + + +time_t getDabTime() +{ + static time_t oldTime = 0; + static int offset = 0; + if (oldTime == 0) { + oldTime = time(NULL); + } else { + offset+= 24; + if (offset >= 1000) { + offset -= 1000; + ++oldTime; + } + } + return oldTime; +} + + +void printUsage(char *name, FILE* out = stderr) +{ + fprintf(out, "NAME\n"); + fprintf(out, " %s - A software DAB multiplexer\n", name); + fprintf(out, "\nSYNOPSYS\n"); + fprintf(out, " %s" + " [ensemble]" + " [subchannel1 subchannel2 ...]" + " [service1 component1 [component2 ...] service2 ...]" + " [output1 ...]" + " [-h]" + " [-m mode]" + " [-n nbFrames]" + " [-o]" + " [-s]" + " [-V]" + " [-z]" + "\n", + name); + fprintf(out, "\n Where ensemble =" + " [-i ensembleId]" + " [-L label]" + " [-l sLabel]" + "\n"); + fprintf(out, "\n Where subchannel =" + " -(A | B | D | E | F | M | P | T) inputName" + " [-b bitrate]" + " [-i subchannelId]" + " [-k]" + " [-p protection]" + "\n"); + fprintf(out, "\n Where service =" + " -S" + " [-g language]" + " [-i serviceId]" + " [-L label]" + " [-l sLabel]" + " [-y PTy]" + "\n"); + fprintf(out, "\n Where component =" + " -C" + " [-a address]" + " [-d]" + " [-f figType]" + " [-i subchannelId]" + " [-L label]" + " [-l sLabel]" + " [-t type]" + "\n"); + fprintf(out, "\nDESCRIPTION\n"); + fprintf(out, + " %s is a software multiplexer that generates an ETI stream from\n" + " audio and data streams. Because of its software based architecture,\n" + " many typical DAB services can be generated and multiplexed on a single\n" + " PC platform with live or pre-recorded sources.\n" + "\n" + " A DAB multiplex configuration is composed of one ensemble. An ensemble\n" + " is the entity that receivers tune to and process. An ensemble contains\n" + " several services. A service is the listener-selectable output. Each\n" + " service contains one mandatory service component which is called pri-\n" + " mary component. An audio primary component define a program service\n" + " while a data primary component define a data service. Service can con-\n" + " tain additional components which are called secondary components. Maxi-\n" + " mum total number of components is 12 for program services and 11 for\n" + " data services. A service component is a link to one subchannel (of Fast\n" + " Information Data Channel). A subchannel is the physical space used\n" + " within the common interleaved frame.\n" + "\n" + " __________________________________________________\n" + " | CRC-Ensemble | ENSEMBLE\n" + " |__________________________________________________|\n" + " | | |\n" + " | | |\n" + " _______V______ _______V______ _______V______\n" + " | CRC-Service1 | | CRC-Service2 | | CRC-Service3 | SERVICES\n" + " |______________| |______________| |______________|\n" + " | | | | |______ |\n" + " | | | | | |\n" + " __V__ __V__ __V__ __V__ __V__ __V__\n" + " | SC1 | | SC2 | | SC3 | | SC4 | | SC5 | | SC6 | SERVICE\n" + " |_____| |_____| |_____| |_____| |_____| |_____| COMPONENTS\n" + " | | _____| | | ____|\n" + " | | | | | |\n" + " __V________V__V______________V________V___V_______ COMMON\n" + " | SubCh1 | SubCh9 | ... | SubCh3 | SubCh60 | ... | INTERLEAVED\n" + " |________|________|_______|________|_________|_____| FRAME\n" + " Figure 1: An example of a DAB multiplex configuration\n", + name); + + fprintf(out, "\nGENERAL OPTIONS\n"); + fprintf(out, " -h : get this help\n"); + fprintf(out, " -m : DAB mode (default: 2)\n"); + fprintf(out, " -n nbFrames : number of frames to produce\n"); + fprintf(out, " -o : turn on TCP log on port 12222\n"); + fprintf(out, " -V : print version information and " + "exit\n"); + fprintf(out, " -z : write SCCA field for Factum ETI" + " analyzer\n"); + fprintf(out, "\nINPUT OPTIONS\n"); + fprintf(out, " -A : set audio service\n"); + fprintf(out, " -B : set CRC-Bridge data service\n"); + fprintf(out, " -D : set data service\n"); + fprintf(out, " -E : set enhanced packet service\n"); + fprintf(out, " -F : set DAB+ service\n"); + fprintf(out, " -M : set DMB service\n"); + fprintf(out, " -P : set packet service\n"); + fprintf(out, " -T : set test service\n"); + fprintf(out, " inputName<n> : name of file for audio and " + "packet service and Udp input address for data service " + "([address]:port)\n"); + fprintf(out, " -a : packet address (default: 0x%x " + "(%i))\n", DEFAULT_PACKET_ADDRESS, DEFAULT_PACKET_ADDRESS); + fprintf(out, " -b bitrate<n> : bitrate (in kbits/s) of the " + "subchannel (default: audio 1st frame, data %i, packet %i)\n", + DEFAULT_DATA_BITRATE, DEFAULT_PACKET_BITRATE); + fprintf(out, " -c : set the extendend country code ECC " + "(default: %u (0x%2x)\n"); + fprintf(out, " -d : turn on datagroups in packet " + "mode\n"); + fprintf(out, " -f figType : user application type in FIG " + "0/13 for packet mode\n"); + fprintf(out, " -g language : Primary service component " + "language: english=9, french=15\n"); + fprintf(out, " -i id<n> : service|subchannel|" + "serviceComponent id <n> (default: <n>)\n"); + fprintf(out, " -k : set non-blocking file input " + "(audio and packet only)\n"); + fprintf(out, " -L label<n> : label of service <n>" + " (default: CRC-Audio<n>)\n"); + fprintf(out, " -l sLabel<n> : short label flag of service <n>" + " (default: 0xf040)\n"); + fprintf(out, " -p protection<n> : protection level (default: 3)\n"); + fprintf(out, " -s : enable TIST, synchronized on 1PPS at level 2\n"); + fprintf(out, " -t type : audio/data service component type" + " (default: 0)\n"); + fprintf(out, " audio: foreground=0, " + "background=1, multi-channel=2\n"); + fprintf(out, " data: unspecified=0, TMC=1, " + "EWS=2, ITTS=3, paging=4, TDC=5, DMB=24, IP=59, MOT=60, " + "proprietary=61\n"); + fprintf(out, " -y PTy : Primary service component program" + " type international code\n"); + fprintf(out, "\nOUTPUT OPTIONS\n"); + fprintf(out, " -O output : name of the output in format " + "scheme://[address][:port][/name]\n" + " where scheme is (raw|udp|tcp|file|fifo|simul)\n" + ); +} + + +bool running = true; + +void signalHandler(int signum) +{ +#ifdef _WIN32 + etiLog.print(TcpLog::DBG, "\npid: %i\n", _getpid()); +#else + etiLog.print(TcpLog::DBG, "\npid: %i, ppid: %i\n", getpid(), getppid()); +#endif + etiLog.print(TcpLog::DBG, "Signal handler called with signal "); + switch (signum) { +#ifndef _WIN32 + case SIGHUP: + etiLog.print(TcpLog::DBG, "SIGHUP\n"); + break; + case SIGQUIT: + etiLog.print(TcpLog::DBG, "SIGQUIT\n"); + break; + case SIGPIPE: + etiLog.print(TcpLog::DBG, "SIGPIPE\n"); + return; + break; +#endif + case SIGINT: + etiLog.print(TcpLog::DBG, "SIGINT\n"); + break; + case SIGTERM: + etiLog.print(TcpLog::DBG, "SIGTERM\n"); + etiLog.print(TcpLog::DBG, "Exiting software\n"); + exit(0); + break; + default: + etiLog.print(TcpLog::DBG, "number %i\n", signum); + } +#ifndef _WIN32 + killpg(0, SIGPIPE); +#endif + running = false; +} + + +void printEnsemble(dabEnsemble* ensemble) +{ + char label[17]; + memcpy(label, ensemble->label.text, 16); + label[16] = 0; + + etiLog.printHeader(TcpLog::INFO, "Ensemble\n"); + etiLog.printHeader(TcpLog::INFO, " id: 0x%lx (%lu)\n", + ensemble->id, ensemble->id); + etiLog.printHeader(TcpLog::INFO, " ecc: 0x%x (%u)\n", + ensemble->ecc, ensemble->ecc); + etiLog.printHeader(TcpLog::INFO, " label: %s\n", label); + etiLog.printHeader(TcpLog::INFO, " short label: "); + for (int i = 0; i < 32; ++i) { + if (ensemble->label.flag & 0x8000 >> i) { + etiLog.printHeader(TcpLog::INFO, "%c", ensemble->label.text[i]); + } + } + etiLog.printHeader(TcpLog::INFO, " (0x%x)\n", ensemble->label.flag); + etiLog.printHeader(TcpLog::INFO, " mode: %u\n", ensemble->mode); +} + + +void printSubchannels(vector<dabSubchannel*>& subchannels) +{ + vector<dabSubchannel*>::iterator subchannel; + int index = 0; + + for (subchannel = subchannels.begin(); subchannel != subchannels.end(); + ++subchannel) { + dabProtection* protection = &(*subchannel)->protection; + etiLog.printHeader(TcpLog::INFO, "Subchannel %i\n", index); + etiLog.printHeader(TcpLog::INFO, " input\n"); + etiLog.printHeader(TcpLog::INFO, " protocol: %s\n", + (*subchannel)->inputProto); + etiLog.printHeader(TcpLog::INFO, " name: %s\n", + (*subchannel)->inputName); + etiLog.printHeader(TcpLog::INFO, " type: "); + switch ((*subchannel)->type) { + case 0: + etiLog.printHeader(TcpLog::INFO, "audio\n"); + break; + case 1: + etiLog.printHeader(TcpLog::INFO, "data\n"); + break; + case 2: + etiLog.printHeader(TcpLog::INFO, "fidc\n"); + break; + case 3: + etiLog.printHeader(TcpLog::INFO, "packet\n"); + break; + default: + etiLog.printHeader(TcpLog::INFO, "Unknown data type " + "(service->type)\n"); + break; + } + etiLog.printHeader(TcpLog::INFO, " id: %i\n", + (*subchannel)->id); + etiLog.printHeader(TcpLog::INFO, " bitrate: %i\n", + (*subchannel)->bitrate); + etiLog.printHeader(TcpLog::INFO, " protection: "); + if (protection->form == 0) { + etiLog.printHeader(TcpLog::INFO, "UEP %i\n", protection->level + 1); + } else { + etiLog.printHeader(TcpLog::INFO, "EEP %i-%c\n", + protection->level + 1, + protection->longForm.option == 0 ? 'A' : 'B'); + } + if (protection->form == 0) { + etiLog.printHeader(TcpLog::INFO, + " form: short\n switch: %i\n index: %i\n", + protection->shortForm.tableSwitch, + protection->shortForm.tableIndex); + } else { + etiLog.printHeader(TcpLog::INFO, + " form: long\n option: %i\n level: %i\n", + protection->longForm.option, + (*subchannel)->protection.level); + } + etiLog.printHeader(TcpLog::INFO, " SAD: %i\n", + (*subchannel)->startAddress); + etiLog.printHeader(TcpLog::INFO, " size (CU): %i\n", + getSizeCu(*subchannel)); + ++index; + } +} + + +void printComponent(dabComponent* component) +{ + char label[17]; + memcpy(label, component->label.text, 16); + label[16] = 0; + if (label[0] == 0) { + sprintf(label, "<none>"); + } + + etiLog.printHeader(TcpLog::INFO, " service id: %i\n", + component->serviceId); + etiLog.printHeader(TcpLog::INFO, " subchannel id: %i\n", + component->subchId); + etiLog.printHeader(TcpLog::INFO, " label: %s\n", + label); + etiLog.printHeader(TcpLog::INFO, " short label: "); + for (int i = 0; i < 32; ++i) { + if (component->label.flag & 0x8000 >> i) { + etiLog.printHeader(TcpLog::INFO, "%c", component->label.text[i]); + } + } + etiLog.printHeader(TcpLog::INFO, " (0x%x)\n", component->label.flag); + etiLog.printHeader(TcpLog::INFO, " service component type: 0x%x (%u)\n", + component->type, component->type); + etiLog.printHeader(TcpLog::INFO, " (packet) id: %u\n", + component->packet.id); + etiLog.printHeader(TcpLog::INFO, " (packet) address: %u\n", + component->packet.address); + etiLog.printHeader(TcpLog::INFO, " (packet) app type: %u\n", + component->packet.appType); + etiLog.printHeader(TcpLog::INFO, " (packet) datagroup: %u\n", + component->packet.datagroup); +} + + +void printComponents(vector<dabComponent*>& components) +{ + vector<dabComponent*>::const_iterator current; + unsigned int index = 0; + + for (current = components.begin(); current != components.end(); ++current) { + etiLog.printHeader(TcpLog::INFO, "Component %i\n", index); + printComponent(*current); + ++index; + } +} + + +void printServices(vector<dabService*>& services) +{ + vector<dabService*>::const_iterator current; + int index = 0; + + for (current = services.begin(); current != services.end(); ++current) { + char label[17]; + memcpy(label, (*current)->label.text, 16); + label[16] = 0; + + etiLog.printHeader(TcpLog::INFO, "Service %i\n", index); + etiLog.printHeader(TcpLog::INFO, " label: %s\n", label); + etiLog.printHeader(TcpLog::INFO, " short label: "); + for (int i = 0; i < 32; ++i) { + if ((*current)->label.flag & 0x8000 >> i) { + etiLog.printHeader(TcpLog::INFO, "%c", (*current)->label.text[i]); + } + } + etiLog.printHeader(TcpLog::INFO, " (0x%x)\n", (*current)->label.flag); + etiLog.printHeader(TcpLog::INFO, " id: 0x%lx (%lu)\n", + (*current)->id, (*current)->id); + etiLog.printHeader(TcpLog::INFO, " pty: 0x%x (%u)\n", + (*current)->pty, (*current)->pty); + etiLog.printHeader(TcpLog::INFO, " language: 0x%x (%u)\n", + (*current)->language, (*current)->language); + ++index; + } +} + + +void printOutputs(vector<dabOutput*>& outputs) +{ + vector<dabOutput*>::const_iterator output; + int index = 0; + + for (output = outputs.begin(); output != outputs.end(); ++output) { + etiLog.printHeader(TcpLog::INFO, "Output %i\n", index); + etiLog.printHeader(TcpLog::INFO, " protocol: %s\n", + (*output)->outputProto); + etiLog.printHeader(TcpLog::INFO, " name: %s\n", + (*output)->outputName); + ++index; + } +} + + +int main(int argc, char *argv[]) +{ + etiLog.printHeader(TcpLog::INFO, + "Welcome to %s %s, compiled at %s, %s\n\n", + PACKAGE_NAME, PACKAGE_VERSION, __DATE__, __TIME__); + etiLog.printHeader(TcpLog::INFO, + "Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011\n" + "Her Majesty the Queen in Right of Canada,\n" + "(Communications Research Centre Canada) All rights reserved.\n\n"); + etiLog.printHeader(TcpLog::INFO, "Input URLs supported:"); +#if defined(HAVE_INPUT_PRBS) + etiLog.printHeader(TcpLog::INFO, " prbs"); +#endif +#if defined(HAVE_INPUT_TEST) + etiLog.printHeader(TcpLog::INFO, " test"); +#endif +#if defined(HAVE_INPUT_SLIP) + etiLog.printHeader(TcpLog::INFO, " slip"); +#endif +#if defined(HAVE_INPUT_UDP) + etiLog.printHeader(TcpLog::INFO, " udp"); +#endif +#if defined(HAVE_INPUT_FIFO) + etiLog.printHeader(TcpLog::INFO, " fifo"); +#endif +#if defined(HAVE_INPUT_FILE) + etiLog.printHeader(TcpLog::INFO, " file"); +#endif + etiLog.printHeader(TcpLog::INFO, "\n"); + + etiLog.printHeader(TcpLog::INFO, "Inputs format supported:"); +#if defined(HAVE_FORMAT_RAW) + etiLog.printHeader(TcpLog::INFO, " raw"); +#endif +#if defined(HAVE_FORMAT_BRIDGE) + etiLog.printHeader(TcpLog::INFO, " bridge"); +#endif +#if defined(HAVE_FORMAT_MPEG) + etiLog.printHeader(TcpLog::INFO, " mpeg"); +#endif +#if defined(HAVE_FORMAT_PACKET) + etiLog.printHeader(TcpLog::INFO, " packet"); +#endif +#if defined(HAVE_FORMAT_DMB) + etiLog.printHeader(TcpLog::INFO, " dmb"); +#endif +#if defined(HAVE_FORMAT_EPM) + etiLog.printHeader(TcpLog::INFO, " epm"); +#endif + etiLog.printHeader(TcpLog::INFO, "\n"); + + etiLog.printHeader(TcpLog::INFO, "Output URLs supported:"); +#if defined(HAVE_OUTPUT_FILE) + etiLog.printHeader(TcpLog::INFO, " file"); +#endif +#if defined(HAVE_OUTPUT_FIFO) + etiLog.printHeader(TcpLog::INFO, " fifo"); +#endif +#if defined(HAVE_OUTPUT_UDP) + etiLog.printHeader(TcpLog::INFO, " udp"); +#endif +#if defined(HAVE_OUTPUT_TCP) + etiLog.printHeader(TcpLog::INFO, " tcp"); +#endif +#if defined(HAVE_OUTPUT_RAW) + etiLog.printHeader(TcpLog::INFO, " raw"); +#endif +#if defined(HAVE_OUTPUT_SIMUL) + etiLog.printHeader(TcpLog::INFO, " simul"); +#endif + etiLog.printHeader(TcpLog::INFO, "\n\n"); + + /* for (int signum = 1; signum < 16; ++signum) { + signal(signum, signalHandler); + }*/ +#ifndef _WIN32 + signal(SIGHUP, signalHandler); + signal(SIGQUIT, signalHandler); +#endif + signal(SIGINT, signalHandler); + signal(SIGTERM, signalHandler); + //signal(SIGPIPE, signalHandler); + +#ifdef _WIN32 + if (SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST) == 0) { + etiLog.printHeader(TcpLog::WARNING, "Can't increase priority: %s\n", + strerror(errno)); + } +#else + if (setpriority(PRIO_PROCESS, 0, -20) == -1) { + etiLog.printHeader(TcpLog::WARNING, "Can't increase priority: %s\n", + strerror(errno)); + } +#endif + /*sched_param scheduler; + scheduler.sched_priority = 99; // sched_get_priority_max(SCHED_RR) + if (sched_setscheduler(0, SCHED_RR, &scheduler) == -1) { + etiLog.print(TcpLog::WARNING, "Can't increased priority: %s\n", + strerror(errno)); + }*/ + + uint8_t watermarkData[128]; + size_t watermarkSize = 0; + size_t watermarkPos = 0; + { + uint8_t buffer[sizeof(watermarkData) / 2]; + snprintf((char*)buffer, sizeof(buffer), + "%s %s, compiled at %s, %s", + PACKAGE_NAME, PACKAGE_VERSION, __DATE__, __TIME__); + memset(watermarkData, 0, sizeof(watermarkData)); + watermarkData[0] = 0x55; // Sync + watermarkData[1] = 0x55; + watermarkSize = 16; + for (unsigned i = 0; i < strlen((char*)buffer); ++i) { + for (int j = 0; j < 8; ++j) { + uint8_t bit = (buffer[watermarkPos >> 3] >> (7 - (watermarkPos & 0x07))) & 1; + watermarkData[watermarkSize >> 3] |= bit << (7 - (watermarkSize & 0x07)); + ++watermarkSize; + bit = 1; + watermarkData[watermarkSize >> 3] |= bit << (7 - (watermarkSize & 0x07)); + ++watermarkSize; + ++watermarkPos; + } + } + } + watermarkPos = 0; + + + dabEnsemble* ensemble = new dabEnsemble; + strncpy(ensemble->label.text, DEFAULT_ENSEMBLE_LABEL, 16); + ensemble->mode = DEFAULT_DAB_MODE; + ensemble->label.flag = DEFAULT_ENSEMBLE_SHORT_LABEL; + ensemble->id = DEFAULT_ENSEMBLE_ID; + ensemble->ecc = DEFAULT_ENSEMBLE_ECC; + + vector<dabOutput*> outputs; + vector<dabService*>::iterator service = ensemble->services.end(); + vector<dabService*>::iterator serviceProgramInd; + vector<dabService*>::iterator serviceDataInd; + vector<dabService*>::iterator servicePty; + vector<dabComponent*>::iterator component = ensemble->components.end(); + vector<dabComponent*>::iterator componentIndicatorProgram; + vector<dabComponent*>::iterator componentIndicatorData; + vector<dabSubchannel*>::iterator subchannel = ensemble->subchannels.end(); + vector<dabSubchannel*>::iterator subchannelIndicator; + vector<dabOutput*>::iterator output; + dabProtection* protection = NULL; + + unsigned int currentFrame; + int returnCode = 0; + int result; + int cur; + unsigned char etiFrame[6144]; + unsigned short index = 0; + //FIC Length, DAB Mode I, II, IV -> FICL = 24, DAB Mode III -> FICL = 32 + unsigned FICL = (ensemble->mode == 3 ? 32 : 24); + + unsigned long sync = 0x49C5F8; + unsigned short FLtmp = 0; + unsigned short nbBytesCRC = 0; + unsigned short CRCtmp = 0xFFFF; + unsigned short MSTsize = 0; + + unsigned int insertFIG = 0; + unsigned int alterneFIB = 0; + + bool factumAnalyzer = false; + unsigned long limit = 0; + time_t date; + unsigned timestamp = 0xffffff; + + + char* progName = strrchr(argv[0], '/'); + if (progName == NULL) { + progName = argv[0]; + } else { + ++progName; + } + + + while (1) { + int c = getopt(argc, argv, + "A:B:CD:E:F:L:M:O:P:STVa:b:c:de:f:g:hi:kl:m:n:op:st:y:z"); + if (c == -1) { + break; + } + switch (c) { + case 'O': + outputs.push_back(new dabOutput); + output = outputs.end() - 1; + + memset(*output, 0, sizeof(dabOutput)); + (*output)->outputProto = NULL; + (*output)->outputName = NULL; + (*output)->data = NULL; + (*output)->operations = dabOutputDefaultOperations; + + char* proto; + + proto = strstr(optarg, "://"); + if (proto == NULL) { + etiLog.printHeader(TcpLog::ERR, + "No protocol defined for output\n"); + returnCode = -1; + goto EXIT; + } else { + (*output)->outputProto = optarg; + (*output)->outputName = proto + 3; + *proto = 0; + } + subchannel = ensemble->subchannels.end(); + protection = NULL; + component = ensemble->components.end(); + service = ensemble->services.end(); + break; + case 'S': + ensemble->services.push_back(new dabService); + + subchannel = ensemble->subchannels.end(); + protection = NULL; + component = ensemble->components.end(); + service = ensemble->services.end() - 1; + output = outputs.end(); + + memset((*service)->label.text, 0, 16); + sprintf((*service)->label.text, "CRC-Service%i", + (int)ensemble->services.size()); + (*service)->label.flag = 0xe01f; + (*service)->id = DEFAULT_SERVICE_ID + ensemble->services.size(); + (*service)->pty = 0; + (*service)->language = 0; + currentFrame = 0; // Will be used temporaly for SCIdS + + break; + case 'C': + if (service == ensemble->services.end()) { + etiLog.printHeader(TcpLog::ERR, "You must define a service" + " before using option -%c\n", c); + printUsage(progName); + returnCode = -1; + goto EXIT; + } + + ensemble->components.push_back(new dabComponent); + + component = ensemble->components.end() - 1; + subchannel = ensemble->subchannels.end(); + protection = NULL; + output = outputs.end(); + + memset(*component, 0, sizeof(dabComponent)); + memset((*component)->label.text, 0, 16); + (*component)->label.flag = 0xffff; + (*component)->serviceId = (*service)->id; + (*component)->subchId = (*(ensemble->subchannels.end() - 1))->id; + (*component)->SCIdS = currentFrame++; + break; + case 'A': + case 'B': + case 'D': + case 'E': + case 'F': + case 'M': + case 'P': + case 'T': + if (optarg == NULL && c != 'T') { + etiLog.printHeader(TcpLog::ERR, + "Missing parameter for option -%c\n", c); + printUsage(progName); + returnCode = -1; + goto EXIT; + } + + ensemble->subchannels.push_back(new dabSubchannel); + + subchannel = ensemble->subchannels.end() - 1; + protection = &(*subchannel)->protection; + component = ensemble->components.end(); + service = ensemble->services.end(); + output = outputs.end(); + + if (c != 'T') { + (*subchannel)->inputName = optarg; + } else { + (*subchannel)->inputName = NULL; + } + if (0) { +#if defined(HAVE_INPUT_FILE) && defined(HAVE_FORMAT_MPEG) + } else if (c == 'A') { + (*subchannel)->inputProto = "file"; + (*subchannel)->type = 0; + (*subchannel)->bitrate = 0; + (*subchannel)->operations = dabInputMpegFileOperations; +#endif // defined(HAVE_INPUT_FILE) && defined(HAVE_FORMAT_MPEG) +#if defined(HAVE_FORMAT_DABPLUS) + } else if (c == 'F') { + (*subchannel)->type = 0; + (*subchannel)->bitrate = 32; + + char* proto; + + proto = strstr(optarg, "://"); + if (proto == NULL) { + (*subchannel)->inputProto = "file"; + } else { + (*subchannel)->inputProto = optarg; + (*subchannel)->inputName = proto + 3; + *proto = 0; + } + + if (0) { +#if defined(HAVE_INPUT_FILE) + } else if (strcmp((*subchannel)->inputProto, "file") == 0) { + (*subchannel)->operations = dabInputDabplusFileOperations; +#endif // defined(HAVE_INPUT_FILE) + } else { + etiLog.printHeader(TcpLog::ERR, + "Invalid protocol for DAB+ input (%s)\n", + (*subchannel)->inputProto); + printUsage(progName); + returnCode = -1; + goto EXIT; + } +#endif // defined(HAVE_FORMAT_DABPLUS) + } else if (c == 'B') { + char* proto; + + proto = strstr(optarg, "://"); + if (proto == NULL) { + (*subchannel)->inputProto = "udp"; + } else { + (*subchannel)->inputProto = optarg; + (*subchannel)->inputName = proto + 3; + *proto = 0; + } + if (0) { +#if defined(HAVE_FORMAT_BRIDGE) +#if defined(HAVE_INPUT_UDP) + } else if (strcmp((*subchannel)->inputProto, "udp") == 0) { + (*subchannel)->operations = dabInputBridgeUdpOperations; +#endif // defined(HAVE_INPUT_UDP) +#if defined(HAVE_INPUT_SLIP) + } else if (strcmp((*subchannel)->inputProto, "slip") == 0) { + (*subchannel)->operations = dabInputSlipOperations; +#endif // defined(HAVE_INPUT_SLIP) +#endif // defined(HAVE_FORMAT_BRIDGE) + } + } else if (c == 'D') { + char* proto; + + proto = strstr(optarg, "://"); + if (proto == NULL) { + (*subchannel)->inputProto = "udp"; + } else { + (*subchannel)->inputProto = optarg; + (*subchannel)->inputName = proto + 3; + *proto = 0; + } + if (0) { +#if defined(HAVE_INPUT_UDP) + } else if (strcmp((*subchannel)->inputProto, "udp") == 0) { + (*subchannel)->operations = dabInputUdpOperations; +#endif +#if defined(HAVE_INPUT_PRBS) && defined(HAVE_FORMAT_RAW) + } else if (strcmp((*subchannel)->inputProto, "prbs") == 0) { + (*subchannel)->operations = dabInputPrbsOperations; +#endif +#if defined(HAVE_INPUT_FILE) && defined(HAVE_FORMAT_RAW) + } else if (strcmp((*subchannel)->inputProto, "file") == 0) { + (*subchannel)->operations = dabInputRawFileOperations; +#endif + } else if (strcmp((*subchannel)->inputProto, "fifo") == 0) { + (*subchannel)->operations = dabInputRawFifoOperations; + } else { + etiLog.printHeader(TcpLog::ERR, + "Invalid protocol for data input (%s)\n", + (*subchannel)->inputProto); + printUsage(progName); + returnCode = -1; + goto EXIT; + } + + (*subchannel)->type = 1; + (*subchannel)->bitrate = DEFAULT_DATA_BITRATE; +#if defined(HAVE_INPUT_TEST) && defined(HAVE_FORMAT_RAW) + } else if (c == 'T') { + (*subchannel)->inputProto = "test"; + (*subchannel)->type = 1; + (*subchannel)->bitrate = DEFAULT_DATA_BITRATE; + (*subchannel)->operations = dabInputTestOperations; +#endif // defined(HAVE_INPUT_TEST)) && defined(HAVE_FORMAT_RAW) +#ifdef HAVE_FORMAT_PACKET + } else if (c == 'P') { + (*subchannel)->inputProto = "file"; + (*subchannel)->type = 3; + (*subchannel)->bitrate = DEFAULT_PACKET_BITRATE; +#ifdef HAVE_INPUT_FILE + (*subchannel)->operations = dabInputPacketFileOperations; +#elif defined(HAVE_INPUT_FIFO) + (*subchannel)->operations = dabInputFifoOperations; +#else +# pragma error("Must defined at least one packet input") +#endif // defined(HAVE_INPUT_FILE) +#ifdef HAVE_FORMAT_EPM + } else if (c == 'E') { + (*subchannel)->inputProto = "file"; + (*subchannel)->type = 3; + (*subchannel)->bitrate = DEFAULT_PACKET_BITRATE; + (*subchannel)->operations = dabInputEnhancedPacketFileOperations; +#endif // defined(HAVE_FORMAT_EPM) +#endif // defined(HAVE_FORMAT_PACKET) +#ifdef HAVE_FORMAT_DMB + } else if (c == 'M') { + char* proto; + + proto = strstr(optarg, "://"); + if (proto == NULL) { + (*subchannel)->inputProto = "udp"; + } else { + (*subchannel)->inputProto = optarg; + (*subchannel)->inputName = proto + 3; + *proto = 0; + } + if (strcmp((*subchannel)->inputProto, "udp") == 0) { + (*subchannel)->operations = dabInputDmbUdpOperations; + } else if (strcmp((*subchannel)->inputProto, "file") == 0) { + (*subchannel)->operations = dabInputDmbFileOperations; + } else { + etiLog.printHeader(TcpLog::ERR, + "Invalid protocol for DMB input (%s)\n", + (*subchannel)->inputProto); + printUsage(progName); + returnCode = -1; + goto EXIT; + } + + (*subchannel)->type = 1; + (*subchannel)->bitrate = DEFAULT_DATA_BITRATE; +#endif + } else { + etiLog.printHeader(TcpLog::ERR, + "Service '%c' not yet coded!\n", c); + returnCode = -1; + goto EXIT; + } + (*subchannel)->operations.init(&(*subchannel)->data); + for (int i = 0; i < 64; ++i) { // Find first free subchannel + subchannel = getSubchannel(ensemble->subchannels, i); + if (subchannel == ensemble->subchannels.end()) { + subchannel = ensemble->subchannels.end() - 1; + (*subchannel)->id = i; + break; + } + } + (*subchannel)->startAddress = 0; + + if (c == 'A') { + protection->form = 0; + protection->level = 2; + protection->shortForm.tableSwitch = 0; + protection->shortForm.tableIndex = 0; + } else { + protection->level = 2; + protection->form = 1; + protection->longForm.option = 0; + } + break; + case 'L': + if (optarg == NULL) { + etiLog.printHeader(TcpLog::ERR, + "Missing parameter for option -L\n"); + printUsage(progName); + returnCode = -1; + goto EXIT; + } + if (service == ensemble->services.end()) { + memset(ensemble->label.text, 0, 16); + strncpy(ensemble->label.text, optarg, 16); + ensemble->label.flag = 0xff00; + } else if (component != ensemble->components.end()) { + memset((*component)->label.text, 0, 16); + strncpy((*component)->label.text, optarg, 16); + (*component)->label.flag = 0xff00; + } else { // Service + memset((*service)->label.text, 0, 16); + strncpy((*service)->label.text, optarg, 16); + (*service)->label.flag = 0xff00; + } + // TODO Check strlen before doing short label + // TODO Check if short label already set + break; + case 'V': + goto EXIT; + case 'l': + if (optarg == NULL) { + etiLog.printHeader(TcpLog::ERR, + "Missing parameter for option -l\n"); + printUsage(progName); + returnCode = -1; + goto EXIT; + } + if (service == ensemble->services.end()) { + char* end; + ensemble->label.flag = strtoul(optarg, &end, 0); + if (*end != 0) { + end = optarg; + ensemble->label.flag = 0; + for (int i = 0; i < 32; ++i) { + if (*end == ensemble->label.text[i]) { + ensemble->label.flag |= 0x8000 >> i; + if (*(++end) == 0) { + break; + } + } + } + if (*end != 0) { + etiLog.printHeader(TcpLog::ERR, + "Error at '%c' in ensemble short label '%s'!\n" + "Not in label '%s'!\n", + *end, optarg, ensemble->label.text); + returnCode = -1; + goto EXIT; + } + } + int count = 0; + for (int i = 0; i < 16; ++i) { + if (ensemble->label.flag & (1 << i)) { + ++count; + } + } + if (count > 8) { + etiLog.printHeader(TcpLog::ERR, + "Ensemble short label too long!\n" + "Must be < 8 characters.\n"); + returnCode = -1; + goto EXIT; + } + } else if (component != ensemble->components.end()) { + char* end; + (*component)->label.flag = strtoul(optarg, &end, 0); + if (*end != 0) { + end = optarg; + (*component)->label.flag = 0; + for (int i = 0; i < 32; ++i) { + if (*end == (*component)->label.text[i]) { + (*component)->label.flag |= 0x8000 >> i; + if (*(++end) == 0) { + break; + } + } + } + if (*end != 0) { + etiLog.printHeader(TcpLog::ERR, + "Error at '%c' in component short label '%s'!\n" + "Not in label '%s'!\n", + *end, optarg, (*component)->label.text); + returnCode = -1; + goto EXIT; + } + } + int count = 0; + for (int i = 0; i < 16; ++i) { + if ((*component)->label.flag & (1 << i)) { + ++count; + } + } + if (count > 8) { + etiLog.printHeader(TcpLog::ERR, + "Service '%s' short label too long!\n" + "Must be < 8 characters.\n", (*component)->label.text); + returnCode = -1; + goto EXIT; + } + } else { + char* end; + (*service)->label.flag = strtoul(optarg, &end, 0); + if (*end != 0) { + end = optarg; + (*service)->label.flag = 0; + for (int i = 0; i < 32; ++i) { + if (*end == (*service)->label.text[i]) { + (*service)->label.flag |= 0x8000 >> i; + if (*(++end) == 0) { + break; + } + } + } + if (*end != 0) { + etiLog.printHeader(TcpLog::ERR, + "Error at '%c' in service short label '%s'!\n" + "Not in label '%s'!\n", + *end, optarg, (*service)->label.text); + returnCode = -1; + goto EXIT; + } + } + int count = 0; + for (int i = 0; i < 16; ++i) { + if ((*service)->label.flag & (1 << i)) { + ++count; + } + } + if (count > 8) { + etiLog.printHeader(TcpLog::ERR, + "Service '%s' short label too long!\n" + "Must be < 8 characters.\n", (*service)->label.text); + returnCode = -1; + goto EXIT; + } + } + break; + case 'i': + if (optarg == NULL) { + etiLog.printHeader(TcpLog::ERR, + "Missing parameter for option -i\n"); + printUsage(progName); + returnCode = -1; + goto EXIT; + } + if (component != ensemble->components.end()) { + (*component)->subchId = strtoul(optarg, NULL, 0); + } else if (subchannel != ensemble->subchannels.end()) { + (*subchannel)->id = strtoul(optarg, NULL, 0); + } else if (service != ensemble->services.end()) { + (*service)->id = strtoul(optarg, NULL, 0); + if ((*service)->id == 0) { + etiLog.printHeader(TcpLog::ERR, + "Service id 0 is invalid\n"); + returnCode = -1; + goto EXIT; + } + } else { + ensemble->id = strtoul(optarg, NULL, 0); + } + break; + case 'b': + if (optarg == NULL) { + etiLog.printHeader(TcpLog::ERR, + "Missing parameter for option -b\n"); + printUsage(progName); + returnCode = -1; + goto EXIT; + } + if (subchannel == ensemble->subchannels.end()) { + etiLog.printHeader(TcpLog::ERR, + "You must define a subchannel first!\n"); + printUsage(progName); + returnCode = -1; + goto EXIT; + } + (*subchannel)->bitrate = strtoul(optarg, NULL, 0); + if (((*subchannel)->bitrate & 0x7) != 0) { + (*subchannel)->bitrate += 8; + (*subchannel)->bitrate &= ~0x7; + etiLog.printHeader(TcpLog::WARNING, + "bitrate must be multiple of 8 -> ceiling to %i\n", + (*subchannel)->bitrate); + } + break; + case 'c': + if (optarg == NULL) { + etiLog.printHeader(TcpLog::ERR, + "Missing parameter for option -c\n"); + printUsage(progName); + returnCode = -1; + goto EXIT; + } + ensemble->ecc = strtoul(optarg, NULL, 0); + break; +#if defined(HAVE_INPUT_FIFO) && defined(HAVE_INPUT_FILE) + case 'k': + if (subchannel == ensemble->subchannels.end()) { + etiLog.printHeader(TcpLog::ERR, + "You must define a subchannel first!\n"); + printUsage(progName); + returnCode = -1; + goto EXIT; + } + switch ((*subchannel)->type) { +#ifdef HAVE_FORMAT_PACKET + case 3: + (*subchannel)->operations.clean(&(*subchannel)->data); + if ((*subchannel)->operations == dabInputPacketFileOperations) { + (*subchannel)->operations = dabInputFifoOperations; +#ifdef HAVE_FORMAT_EPM + } else if ((*subchannel)->operations == dabInputEnhancedPacketFileOperations) { + (*subchannel)->operations = dabInputEnhancedFifoOperations; +#endif // defined(HAVE_FORMAT_EPM) + } else { + etiLog.printHeader(TcpLog::ERR, + "Error, wrong packet subchannel operations!\n"); + returnCode = -1; + goto EXIT; + } + (*subchannel)->operations.init(&(*subchannel)->data); + (*subchannel)->inputProto = "fifo"; + break; +#endif // defined(HAVE_FORMAT_PACKET) +#ifdef HAVE_FORMAT_MPEG + case 0: + (*subchannel)->operations.clean(&(*subchannel)->data); + if ((*subchannel)->operations == dabInputMpegFileOperations) { + (*subchannel)->operations = dabInputMpegFifoOperations; + } else if ((*subchannel)->operations == + dabInputDabplusFileOperations) { + (*subchannel)->operations = dabInputDabplusFifoOperations; + } else { + etiLog.printHeader(TcpLog::ERR, + "Error, wrong audio subchannel operations!\n"); + returnCode = -1; + goto EXIT; + } + (*subchannel)->operations.init(&(*subchannel)->data); + (*subchannel)->inputProto = "fifo"; + break; +#endif // defined(HAVE_FORMAT_MPEG) + default: + etiLog.printHeader(TcpLog::ERR, + "sorry, non-blocking input file is " + "only valid with audio or packet services\n"); + returnCode = -1; + goto EXIT; + } + break; +#endif // defined(HAVE_INPUT_FIFO) && defined(HAVE_INPUT_FILE) + case 'p': + int level; + if (optarg == NULL) { + etiLog.printHeader(TcpLog::ERR, + "Missing parameter for option -P\n"); + printUsage(progName); + returnCode = -1; + goto EXIT; + } + if (subchannel == ensemble->subchannels.end()) { + etiLog.printHeader(TcpLog::ERR, + "You must define a subchannel first!\n"); + printUsage(progName); + returnCode = -1; + goto EXIT; + } + level = strtoul(optarg, NULL, 0) - 1; + if (protection->form == 0) { + if ((level < 0) || (level > 4)) { + etiLog.printHeader(TcpLog::ERR, + "protection level must be between " + "1 to 5 inclusively (current = %i)\n", level); + returnCode = -1; + goto EXIT; + } + } else { + if ((level < 0) || (level > 3)) { + etiLog.printHeader(TcpLog::ERR, + "protection level must be between " + "1 to 4 inclusively (current = %i)\n", level); + returnCode = -1; + goto EXIT; + } + } + protection->level = level; + break; + case 'm': + if (optarg) { + ensemble->mode = strtoul(optarg, NULL, 0); + if ((ensemble->mode < 1) || (ensemble->mode > 4)) { + etiLog.printHeader(TcpLog::ERR, + "Mode must be between 1-4\n"); + returnCode = -1; + goto EXIT; + } + if (ensemble->mode == 4) + ensemble->mode = 0; + if (ensemble->mode == 3) { + FICL = 32; + } else { + FICL = 24; + } + } else { + etiLog.printHeader(TcpLog::ERR, + "Missing parameter for option -m\n"); + printUsage(progName); + returnCode = -1; + goto EXIT; + } + break; + case 'n': + if (optarg) { + limit = strtoul(optarg, NULL, 0); + } else { + etiLog.printHeader(TcpLog::ERR, + "Missing parameter for option -n\n"); + printUsage(progName); + returnCode = -1; + goto EXIT; + } + break; + case 'o': + etiLog.open("createETI", 0, 12222); + break; + case 't': + if (optarg == NULL) { + etiLog.printHeader(TcpLog::ERR, + "Missing parameter for option -t\n"); + printUsage(progName); + returnCode = -1; + goto EXIT; + } + if (component == ensemble->components.end()) { + etiLog.printHeader(TcpLog::ERR, + "You must define a component before setting " + "service type!\n"); + printUsage(progName); + returnCode = -1; + goto EXIT; + } + (*component)->type = strtoul(optarg, NULL, 0); + break; + case 'a': + if (component == ensemble->components.end()) { + etiLog.printHeader(TcpLog::ERR, + "You must define a component before setting " + "packet address!\n"); + printUsage(progName); + returnCode = -1; + goto EXIT; + } + if (!(*component)->isPacketComponent(ensemble->subchannels)) { + etiLog.printHeader(TcpLog::ERR, "address\n"); + printUsage(progName); + returnCode = -1; + goto EXIT; + } + (*component)->packet.address = strtoul(optarg, NULL, 0); + break; + case 'd': + if (component == ensemble->components.end()) { + etiLog.printHeader(TcpLog::ERR, + "You must define a component before setting " + "datagroup!\n"); + printUsage(progName); + returnCode = -1; + goto EXIT; + } + if (!(*component)->isPacketComponent(ensemble->subchannels)) { + etiLog.printHeader(TcpLog::ERR, "datagroup\n"); + printUsage(progName); + returnCode = -1; + goto EXIT; + } + (*component)->packet.datagroup = true; + break; + case 'f': + if (component == ensemble->components.end()) { + etiLog.printHeader(TcpLog::ERR, + "You must define a component first!\n"); + printUsage(progName); + returnCode = -1; + goto EXIT; + } + if (!(*component)->isPacketComponent(ensemble->subchannels)) { + etiLog.printHeader(TcpLog::ERR, "application type\n"); + printUsage(progName); + returnCode = -1; + goto EXIT; + } + (*component)->packet.appType = strtoul(optarg, NULL, 0); + break; + case 'g': + if (service == ensemble->services.end()) { + etiLog.printHeader(TcpLog::ERR, "You must define a service" + " before using option -%c\n", c); + printUsage(progName); + returnCode = -1; + goto EXIT; + } + (*service)->language = strtoul(optarg, NULL, 0); + break; + case 's': + { + struct timeval tv; + gettimeofday(&tv, NULL); + unsigned _8ms = (tv.tv_usec / 1000) / 8; + unsigned _1ms = (tv.tv_usec - (_8ms * 8000)) / 1000; + unsigned _4us = 20; + unsigned _488ns = 0; + unsigned _61ns = 0; + timestamp = (((((((_8ms << 3) | _1ms) << 8) | _4us) << 3) | _488ns) << 8) | _61ns; + } + break; + case 'y': + if (service == ensemble->services.end()) { + etiLog.printHeader(TcpLog::ERR, "You must define a service" + " before using option -%c\n", c); + printUsage(progName); + returnCode = -1; + goto EXIT; + } + (*service)->pty = strtoul(optarg, NULL, 0); + break; + case 'z': + factumAnalyzer = true; + break; + case '?': + returnCode = -1; + case 'h': + printUsage(progName, stdout); + goto EXIT; + default: + etiLog.printHeader(TcpLog::ERR, "Option '%c' not coded yet\n", c); + returnCode = -1; + goto EXIT; + } + } + if (optind < argc) { + etiLog.printHeader(TcpLog::ERR, "Too much parameters:"); + while (optind < argc) { + etiLog.printHeader(TcpLog::ERR, " %s", argv[optind++]); + } + etiLog.printHeader(TcpLog::ERR, "\n"); + printUsage(progName); + returnCode = -1; + goto EXIT; + } + + if (outputs.size() == 0) { + etiLog.printHeader(TcpLog::WARNING, "no output defined\n"); + + outputs.push_back(new dabOutput); + output = outputs.end() - 1; + + memset(*output, 0, sizeof(dabOutput)); + (*output)->outputProto = "simul"; + (*output)->outputName = NULL; + (*output)->data = NULL; + (*output)->operations = dabOutputDefaultOperations; + + printf("Press enter to continue\n"); + getchar(); + } + + // Check and adjust subchannels + { + set<unsigned char> ids; + for (subchannel = ensemble->subchannels.begin(); + subchannel != ensemble->subchannels.end(); + ++subchannel) { + if (ids.find((*subchannel)->id) != ids.end()) { + etiLog.printHeader(TcpLog::ERR, + "Subchannel %u is set more than once!\n", + (*subchannel)->id); + returnCode = -1; + goto EXIT; + } + } + } + + // Check and adjust services and components + { + set<uint32_t> ids; + for (service = ensemble->services.begin(); + service != ensemble->services.end(); + ++service) { + if (ids.find((*service)->id) != ids.end()) { + etiLog.printHeader(TcpLog::ERR, + "Service id 0x%x (%u) is set more than once!\n", + (*service)->id, (*service)->id); + returnCode = -1; + goto EXIT; + } + + // Get first component of this service + component = getComponent(ensemble->components, (*service)->id); + if (component == ensemble->components.end()) { + etiLog.printHeader(TcpLog::ERR, + "Service %u includes no component!\n"); + returnCode = -1; + goto EXIT; + } + + // Adjust service type from this first component + switch ((*service)->getType(ensemble)) { + case 0: // Audio + (*service)->program = true; + break; + case 1: + case 2: + case 3: + (*service)->program = false; + break; + default: + etiLog.printHeader(TcpLog::ERR, + "Error, unknown service type: %u\n", (*service)->getType(ensemble)); + returnCode = -1; + goto EXIT; + } + + // Adjust components type for DAB+ + while (component != ensemble->components.end()) { + subchannel = + getSubchannel(ensemble->subchannels, (*component)->subchId); + if (subchannel == ensemble->subchannels.end()) { + etiLog.printHeader(TcpLog::ERR, "Error, service %u component " + "links to the invalid subchannel %u\n", + (*component)->serviceId, (*component)->subchId); + returnCode = -1; + goto EXIT; + } + + protection = &(*subchannel)->protection; + switch ((*subchannel)->type) { + case 0: // Audio + { + if (protection->form != 0) { + (*component)->type = 0x3f; // DAB+ + } + } + break; + case 1: + case 2: + case 3: + break; + default: + etiLog.printHeader(TcpLog::ERR, + "Error, unknown subchannel type\n"); + returnCode = -1; + goto EXIT; + } + component = getComponent(ensemble->components, + (*service)->id, component); + } + } + } + + + for (output = outputs.begin(); output != outputs.end() ; ++output) { +#if defined(HAVE_OUTPUT_FILE) + if (strcmp((*output)->outputProto, "file") == 0) { + (*output)->operations = dabOutputFileOperations; +#else // !defined(HAVE_OUTPUT_FILE) + if (0) { +#endif // defined(HAVE_OUTPUT_FILE) +#if defined(HAVE_OUTPUT_FIFO) + } else if (strcmp((*output)->outputProto, "fifo") == 0) { + (*output)->operations = dabOutputFifoOperations; +#endif // !defined(HAVE_OUTPUT_FIFO) +#if defined(HAVE_OUTPUT_RAW) + } else if (strcmp((*output)->outputProto, "raw") == 0) { + (*output)->operations = dabOutputRawOperations; +#endif // defined(HAVE_OUTPUT_RAW) +#if defined(HAVE_OUTPUT_UDP) + } else if (strcmp((*output)->outputProto, "udp") == 0) { + (*output)->operations = dabOutputUdpOperations; +#endif // defined(HAVE_OUTPUT_UDP) +#if defined(HAVE_OUTPUT_TCP) + } else if (strcmp((*output)->outputProto, "tcp") == 0) { + (*output)->operations = dabOutputTcpOperations; +#endif // defined(HAVE_OUTPUT_TCP) +#if defined(HAVE_OUTPUT_SIMUL) + } else if (strcmp((*output)->outputProto, "simul") == 0) { + (*output)->operations = dabOutputSimulOperations; +#endif // defined(HAVE_OUTPUT_SIMUL) + } else { + etiLog.printHeader(TcpLog::ERR, "Output protcol unknown: %s\n", + (*output)->outputProto); + goto EXIT; + } + + if ((*output)->operations.init(&(*output)->data) == -1) { + etiLog.printHeader(TcpLog::ERR, "Unable to init output %s://%s\n", + (*output)->outputProto, (*output)->outputName); + return -1; + } + if ((*output)->operations.open((*output)->data, (*output)->outputName) + == -1) { + etiLog.printHeader(TcpLog::ERR, "Unable to open output %s://%s\n", + (*output)->outputProto, (*output)->outputName); + return -1; + } + } + + //Relatif aux fichiers d'entre + for (subchannel = ensemble->subchannels.begin(); + subchannel != ensemble->subchannels.end(); + ++subchannel) { + protection = &(*subchannel)->protection; + if (subchannel == ensemble->subchannels.begin()) { + (*subchannel)->startAddress = 0; + } else { + (*subchannel)->startAddress = (*(subchannel - 1))->startAddress + + getSizeCu(*(subchannel - 1)); + } + if ((*subchannel)->operations.open((*subchannel)->data, + (*subchannel)->inputName) == -1) { + perror((*subchannel)->inputName); + returnCode = -1; + goto EXIT; + } + + // TODO Check errors + int result = (*subchannel)->operations.setBitrate( + &(*subchannel)->operations, (*subchannel)->data, + (*subchannel)->bitrate); + if (result <= 0) { + etiLog.printHeader(TcpLog::ERR, "can't set bitrate for source %s\n", + (*subchannel)->inputName); + returnCode = -1; + goto EXIT; + } + (*subchannel)->bitrate = result; + + if (protection->form == 0) { + protection->form = 1; + for (int i = 0; i < 64; i++) { + if ((*subchannel)->bitrate == BitRateTable[i]) { + if (protection->level == ProtectionLevelTable[i]) { + protection->form = 0; + protection->shortForm.tableIndex = i; + } + } + } + } + } + + if (ensemble->subchannels.size() == 0) { + etiLog.printHeader(TcpLog::ERR, "can't multiplexed no subchannel!\n"); + returnCode = -1; + goto EXIT; + } + + subchannel = ensemble->subchannels.end() - 1; + if ((*subchannel)->startAddress + getSizeCu((*subchannel)) > 864) { + etiLog.printHeader(TcpLog::ERR, "Total size in CU exceeds 864\n"); + printSubchannels(ensemble->subchannels); + returnCode = -1; + goto EXIT; + } + + // Init packet components SCId + cur = 0; + for (component = ensemble->components.begin(); + component != ensemble->components.end(); + ++component) { + subchannel = getSubchannel(ensemble->subchannels, + (*component)->subchId); + if (subchannel == ensemble->subchannels.end()) { + etiLog.printHeader(TcpLog::ERR, + "Subchannel %i does not exist for component " + "of service %i\n", + (*component)->subchId, (*component)->serviceId); + returnCode = -1; + goto EXIT; + } + if ((*subchannel)->type != 3) continue; + + (*component)->packet.id = cur++; + } + + //Initialisation a 0 des cases de la trame ETI + memset(etiFrame, 0, 6144); + + // Print settings before starting + etiLog.printHeader(TcpLog::INFO, "\n--- Multiplex configuration ---\n"); + printEnsemble(ensemble); + + etiLog.printHeader(TcpLog::INFO, "\n--- Subchannels list ---\n"); + printSubchannels(ensemble->subchannels); + + etiLog.printHeader(TcpLog::INFO, "\n--- Services list ---\n"); + printServices(ensemble->services); + + etiLog.printHeader(TcpLog::INFO, "\n--- Components list ---\n"); + printComponents(ensemble->components); + + etiLog.printHeader(TcpLog::INFO, "\n--- Output list ---\n"); + printOutputs(outputs); + + etiLog.printHeader(TcpLog::INFO, "\n"); + + + /*************************************************************************** + ********** Boucle principale, chaque passage cree une trame ************ + **************************************************************************/ + serviceProgramInd = ensemble->services.end(); + serviceDataInd = ensemble->services.end(); + componentIndicatorProgram = ensemble->components.end(); + componentIndicatorData = ensemble->components.end(); + servicePty = ensemble->services.end(); + subchannelIndicator = ensemble->subchannels.end(); + + + for (currentFrame = 0; running; currentFrame++) { + if ((limit > 0) && (currentFrame >= limit)) { + break; + } + date = getDabTime(); + + //Initialisation a 0 des cases de la trame + memset(etiFrame, 0, 6144); + + /********************************************************************** + ********** Section SYNC du ETI(NI, G703) ************************* + **********************************************************************/ + + //declare une instance d'une structure eti_SYNC + eti_SYNC *etiSync = (eti_SYNC *) etiFrame; + //****** Section ERR ******// + // 1 octet + etiSync->ERR = 0xFF; //Indique qu'il n'y a pas d'erreur + //****** Section FSYNC *****// + // 3 octets, pour la synchronisation, alterne a chaque trame entre les + // deux symboles + sync ^= 0xffffff; + etiSync->FSYNC = sync; + + /********************************************************************** + *********** Section LIDATA du ETI(NI, G703) ********************** + **********************************************************************/ + + //****** Section FC ***************************************************/ + // 4 octets + // declare une instance d une structure eti_FC et la place dans la trame + eti_FC *fc = (eti_FC *) & etiFrame[4]; + + //****** FCT **********************// + //Incremente a chaque trame, de 0 a 249, 1 octet + fc->FCT = currentFrame % 250; + + //****** FICF ******// + //Fast Information Channel Flag, 1 bit, =1 si le FIC est present + fc->FICF = 1; + + //****** NST ******// + //Number of Stream, 7 bits, 0-64, 0 si reconfiguration du multiplex + fc->NST = ensemble->subchannels.size(); + + //****** FP ******// + // Frame Phase, 3 bits, compteur sur 3 bits, permet au COFDM generator + // de savoir quand inserer le TII utilise egalement par le MNST + fc->FP = currentFrame & 0x7; + + //****** MID ******// + //Mode Identity, 2 bits, 01 ModeI, 10 modeII, 11 ModeIII, 00 ModeIV + fc->MID = ensemble->mode; //mode 2 demande 3 FIB, 3*32octets = 96octets + + //****** FL ******// + //Frame Length, 11 bits, nb of words(4 bytes) in STC, EOH and MST + // si NST=0, FL=1+FICL words, FICL=24 ou 32 selon le mode + //en word ( 4 bytes), +1 pour la partie EOH + FLtmp = 1 + FICL + (fc->NST); + + for (subchannel = ensemble->subchannels.begin(); + subchannel != ensemble->subchannels.end(); + ++subchannel) { + //Taille d'une trame audio mp2 en paquet de 64 bits + FLtmp += getSizeWord(*subchannel); + } + + fc->setFrameLength(FLtmp); + index = 8; + + /******* Section STC **************************************************/ + // Stream Characterization, + // number of channel * 4 octets = nb octets total + for (subchannel = ensemble->subchannels.begin(); + subchannel != ensemble->subchannels.end(); + ++subchannel) { + protection = &(*subchannel)->protection; + eti_STC *sstc = (eti_STC *) & etiFrame[index]; + + sstc->SCID = (*subchannel)->id; + sstc->startAddress_high = (*subchannel)->startAddress / 256; + sstc->startAddress_low = (*subchannel)->startAddress % 256; + //devrait changer selon le mode de protection desire + if (protection->form == 0) { + sstc->TPL = 0x10 | + ProtectionLevelTable[protection->shortForm.tableIndex]; + } else { + sstc->TPL = 0x20 | + (protection->longForm.option << 2) | + (protection->level); + } + //Sub-channel Stream Length, multiple de 64 bits + sstc->STL_high = getSizeDWord(*subchannel) / 256; + sstc->STL_low = getSizeDWord(*subchannel) % 256; + index += 4; + } + + /******* Section EOH **************************************************/ + // End of Header 4 octets + eti_EOH *eoh = (eti_EOH *) & etiFrame[index]; + + //MNSC Multiplex Network Signalling Channel, 2 octets + eoh->MNSC = 0; + + //CRC Cyclic Redundancy Checksum du FC, STC et MNSC, 2 octets + nbBytesCRC = 4 + ((fc->NST) * 4) + 2; + + CRCtmp = 0xffff; + CRCtmp = crc16(CRCtmp, &etiFrame[4], nbBytesCRC); + CRCtmp ^= 0xffff; + eoh->CRC = htons(CRCtmp); + + /******* Section MST **************************************************/ + // Main Stream Data, si FICF=1 alors les 96 ou 128 premiers octets + // transportent le FIC selon le mode + index = ((fc->NST) + 2 + 1) * 4; + + //Insertion du FIC + FIGtype0* fig0; + FIGtype0_0 *fig0_0; + FIGtype0_1 *figtype0_1; + + FIG_01_SubChannel_ShortF *fig0_1subchShort; + FIG_01_SubChannel_LongF *fig0_1subchLong1; + + FIGtype0_2 *fig0_2; + + FIGtype0_2_Service *fig0_2serviceAudio; + FIGtype0_2_Service_data *fig0_2serviceData; + FIGtype0_2_audio_component* audio_description; + FIGtype0_2_data_component* data_description; + FIGtype0_2_packet_component* packet_description; + + FIGtype0_3_header *fig0_3_header; + FIGtype0_3_data *fig0_3_data; + FIGtype0_9 *fig0_9; + FIGtype0_10 *fig0_10; + FIGtype0_17_programme *programme; + + FIGtype1_0 *fig1_0; + FIGtype1_1 *fig1_1; + FIGtype1_5 *fig1_5; + + tm* timeData; + + unsigned char figSize = 0; + + //Insertion du FIB 0 + switch (insertFIG) { + + case 0: + case 4: + // FIG type 0/0, Multiplex Configuration Info (MCI), + // Ensemble information + fig0_0 = (FIGtype0_0 *) & etiFrame[index]; + + fig0_0->FIGtypeNumber = 0; + fig0_0->Length = 5; + fig0_0->CN = 0; + fig0_0->OE = 0; + fig0_0->PD = 0; + fig0_0->Extension = 0; + + fig0_0->EId = htons(ensemble->id); + fig0_0->Change = 0; + fig0_0->Al = 0; + fig0_0->CIFcnt_hight = (currentFrame / 250) % 20; + fig0_0->CIFcnt_low = (currentFrame % 250); + index = index + 6; + figSize += 6; + + break; + + case 1: + // FIG type 0/1, MIC, Sub-Channel Organization, une instance de la + // sous-partie par sous-canal + figtype0_1 = (FIGtype0_1 *) & etiFrame[index]; + + figtype0_1->FIGtypeNumber = 0; + figtype0_1->Length = 1; + figtype0_1->CN = 0; + figtype0_1->OE = 0; + figtype0_1->PD = 0; + figtype0_1->Extension = 1; + index = index + 2; + figSize += 2; + + //Sous-partie du FIG type 0/1 + if (subchannelIndicator == ensemble->subchannels.end()) { + subchannelIndicator = ensemble->subchannels.begin(); + } + for (; subchannelIndicator != ensemble->subchannels.end(); + ++subchannelIndicator) { + protection = &(*subchannelIndicator)->protection; + + if ((protection->form == 0 && figSize > 27) || + (protection->form != 0 && figSize > 26)) { + break; + } + + if (protection->form == 0) { + fig0_1subchShort = + (FIG_01_SubChannel_ShortF*) &etiFrame[index]; + fig0_1subchShort->SubChId = (*subchannelIndicator)->id; + fig0_1subchShort->StartAdress_high = + (*subchannelIndicator)->startAddress / 256; + fig0_1subchShort->StartAdress_low = + (*subchannelIndicator)->startAddress % 256; + fig0_1subchShort->Short_Long_form = 0; + fig0_1subchShort->TableSwitch = 0; + fig0_1subchShort->TableIndex = + protection->shortForm.tableIndex; + + index = index + 3; + figSize += 3; + figtype0_1->Length += 3; + } else { + fig0_1subchLong1 = + (FIG_01_SubChannel_LongF*) &etiFrame[index]; + fig0_1subchLong1->SubChId = (*subchannelIndicator)->id; + fig0_1subchLong1->StartAdress_high = + (*subchannelIndicator)->startAddress / 256; + fig0_1subchLong1->StartAdress_low = + (*subchannelIndicator)->startAddress % 256; + fig0_1subchLong1->Short_Long_form = 1; + fig0_1subchLong1->Option = protection->longForm.option; + fig0_1subchLong1->ProtectionLevel = + protection->level; + fig0_1subchLong1->Sub_ChannelSize_high = + getSizeCu(*subchannelIndicator) / 256; + fig0_1subchLong1->Sub_ChannelSize_low = + getSizeCu(*subchannelIndicator) % 256; + + index = index + 4; + figSize += 4; + figtype0_1->Length += 4; + } + } + break; + + case 2: + // FIG type 0/2, MCI, Service Organization, une instance de + // FIGtype0_2_Service par sous-canal + fig0_2 = NULL; + cur = 0; + + if (serviceProgramInd == ensemble->services.end()) { + serviceProgramInd = ensemble->services.begin(); + } + for (; serviceProgramInd != ensemble->services.end(); + ++serviceProgramInd) { + if (!(*serviceProgramInd)->nbComponent(ensemble->components)) { + continue; + } + if ((*serviceProgramInd)->getType(ensemble) != 0) { + continue; + } + + ++cur; + + if (fig0_2 == NULL) { + fig0_2 = (FIGtype0_2 *) & etiFrame[index]; + + fig0_2->FIGtypeNumber = 0; + fig0_2->Length = 1; + fig0_2->CN = 0; + fig0_2->OE = 0; + fig0_2->PD = 0; + fig0_2->Extension = 2; + index = index + 2; + figSize += 2; + } + + if (figSize + 3 + + (*serviceProgramInd)->nbComponent(ensemble->components) + * 2 > 30) { + break; + } + + fig0_2serviceAudio = (FIGtype0_2_Service*) &etiFrame[index]; + + fig0_2serviceAudio->SId = htons((*serviceProgramInd)->id); + fig0_2serviceAudio->Local_flag = 0; + fig0_2serviceAudio->CAId = 0; + fig0_2serviceAudio->NbServiceComp = + (*serviceProgramInd)->nbComponent(ensemble->components); + index += 3; + fig0_2->Length += 3; + figSize += 3; + + int curCpnt = 0; + for (component = getComponent(ensemble->components, + (*serviceProgramInd)->id); + component != ensemble->components.end(); + component = getComponent(ensemble->components, + (*serviceProgramInd)->id, component)) { + subchannel = getSubchannel(ensemble->subchannels, + (*component)->subchId); + if (subchannel == ensemble->subchannels.end()) { + etiLog.printHeader(TcpLog::ERR, + "Subchannel %i does not exist for component " + "of service %i\n", + (*component)->subchId, (*component)->serviceId); + returnCode = -1; + goto EXIT; + } + + switch ((*subchannel)->type) { + case 0: // Audio + audio_description = + (FIGtype0_2_audio_component*)&etiFrame[index]; + audio_description->TMid = 0; + audio_description->ASCTy = (*component)->type; + audio_description->SubChId = (*subchannel)->id; + audio_description->PS = ((curCpnt == 0) ? 1 : 0); + audio_description->CA_flag = 0; + break; + case 1: // Data + data_description = + (FIGtype0_2_data_component*)&etiFrame[index]; + data_description->TMid = 1; + data_description->DSCTy = (*component)->type; + data_description->SubChId = (*subchannel)->id; + data_description->PS = ((curCpnt == 0) ? 1 : 0); + data_description->CA_flag = 0; + break; + case 3: // Packet + packet_description = + (FIGtype0_2_packet_component*)&etiFrame[index]; + packet_description->TMid = 3; + packet_description->setSCId((*component)->packet.id); + packet_description->PS = ((curCpnt == 0) ? 1 : 0); + packet_description->CA_flag = 0; + break; + default: + etiLog.printHeader(TcpLog::ERR, + "Component type not supported\n"); + returnCode = -1; + goto EXIT; + } + index += 2; + fig0_2->Length += 2; + figSize += 2; + if (figSize > 30) { + etiLog.printHeader(TcpLog::ERR, + "Sorry, no place left in FIG 0/2 to insert " + "component %i of program service %i.\n", + curCpnt, cur); + returnCode = -1; + goto EXIT; + } + ++curCpnt; + } + } + break; + + case 3: + fig0_2 = NULL; + cur = 0; + + if (serviceDataInd == ensemble->services.end()) { + serviceDataInd = ensemble->services.begin(); + } + for (; serviceDataInd != ensemble->services.end(); + ++serviceDataInd) { + if (!(*serviceDataInd)->nbComponent(ensemble->components)) { + continue; + } + unsigned char type = (*serviceDataInd)->getType(ensemble); + if ((type == 0) || (type == 2)) { + continue; + } + + ++cur; + + if (fig0_2 == NULL) { + fig0_2 = (FIGtype0_2 *) & etiFrame[index]; + + fig0_2->FIGtypeNumber = 0; + fig0_2->Length = 1; + fig0_2->CN = 0; + fig0_2->OE = 0; + fig0_2->PD = 1; + fig0_2->Extension = 2; + index = index + 2; + figSize += 2; + } + + if (figSize + 5 + + (*serviceDataInd)->nbComponent(ensemble->components) + * 2 > 30) { + break; + } + + fig0_2serviceData = + (FIGtype0_2_Service_data*) &etiFrame[index]; + + fig0_2serviceData->SId = htonl((*serviceDataInd)->id); + fig0_2serviceData->Local_flag = 0; + fig0_2serviceData->CAId = 0; + fig0_2serviceData->NbServiceComp = + (*serviceDataInd)->nbComponent(ensemble->components); + fig0_2->Length += 5; + index += 5; + figSize += 5; + + int curCpnt = 0; + for (component = getComponent(ensemble->components, + (*serviceDataInd)->id); + component != ensemble->components.end(); + component = getComponent(ensemble->components, + (*serviceDataInd)->id, component)) { + subchannel = getSubchannel(ensemble->subchannels, + (*component)->subchId); + if (subchannel == ensemble->subchannels.end()) { + etiLog.printHeader(TcpLog::ERR, + "Subchannel %i does not exist for component " + "of service %i\n", + (*component)->subchId, (*component)->serviceId); + returnCode = -1; + goto EXIT; + } + + switch ((*subchannel)->type) { + case 0: // Audio + audio_description = + (FIGtype0_2_audio_component*)&etiFrame[index]; + audio_description->TMid = 0; + audio_description->ASCTy = (*component)->type; + audio_description->SubChId = (*subchannel)->id; + audio_description->PS = ((curCpnt == 0) ? 1 : 0); + audio_description->CA_flag = 0; + break; + case 1: // Data + data_description = + (FIGtype0_2_data_component*)&etiFrame[index]; + data_description->TMid = 1; + data_description->DSCTy = (*component)->type; + data_description->SubChId = (*subchannel)->id; + data_description->PS = ((curCpnt == 0) ? 1 : 0); + data_description->CA_flag = 0; + break; + case 3: // Packet + packet_description = + (FIGtype0_2_packet_component*)&etiFrame[index]; + packet_description->TMid = 3; + packet_description->setSCId((*component)->packet.id); + packet_description->PS = ((curCpnt == 0) ? 1 : 0); + packet_description->CA_flag = 0; + break; + default: + etiLog.printHeader(TcpLog::ERR, + "Component type not supported\n"); + returnCode = -1; + goto EXIT; + } + index += 2; + fig0_2->Length += 2; + figSize += 2; + if (figSize > 30) { + etiLog.printHeader(TcpLog::ERR, + "Sorry, no place left in FIG 0/2 to insert " + "component %i of data service %i.\n", + curCpnt, cur); + returnCode = -1; + goto EXIT; + } + ++curCpnt; + } + } + break; + + case 5: + fig0_3_header = NULL; + + for (component = ensemble->components.begin(); + component != ensemble->components.end(); + ++component) { + subchannel = getSubchannel(ensemble->subchannels, + (*component)->subchId); + if (subchannel == ensemble->subchannels.end()) { + etiLog.printHeader(TcpLog::ERR, + "Subchannel %i does not exist for component " + "of service %i\n", + (*component)->subchId, (*component)->serviceId); + returnCode = -1; + goto EXIT; + } + + if ((*subchannel)->type != 3) continue; + + if (fig0_3_header == NULL) { + fig0_3_header = (FIGtype0_3_header*)&etiFrame[index]; + fig0_3_header->FIGtypeNumber = 0; + fig0_3_header->Length = 1; + fig0_3_header->CN = 0; + fig0_3_header->OE = 0; + fig0_3_header->PD = 0; + fig0_3_header->Extension = 3; + + index += 2; + figSize += 2; + } + + /* Warning: When bit SCCA_flag is unset(0), the multiplexer + * R&S does not send the SCCA field. But, in the Factum ETI + * analyzer, if this field is not there, it is an error. + */ + fig0_3_data = (FIGtype0_3_data*)&etiFrame[index]; + fig0_3_data->setSCId((*component)->packet.id); + fig0_3_data->rfa = 0; + fig0_3_data->SCCA_flag = 0; + // if 0, datagroups are used + fig0_3_data->DG_flag = !(*component)->packet.datagroup; + fig0_3_data->rfu = 0; + fig0_3_data->DSCTy = (*component)->type; + fig0_3_data->SubChId = (*subchannel)->id; + fig0_3_data->setPacketAddress((*component)->packet.address); + if (factumAnalyzer) { + fig0_3_data->SCCA = 0; + } + + fig0_3_header->Length += 5; + index += 5; + figSize += 5; + if (factumAnalyzer) { + fig0_3_header->Length += 2; + index += 2; + figSize += 2; + } + + if (figSize > 30) { + etiLog.printHeader(TcpLog::ERR, + "can't add to Fic Fig 0/3, " + "too much packet service\n"); + returnCode = -1; + goto EXIT; + } + } + break; + + case 7: + fig0 = NULL; + if (servicePty == ensemble->services.end()) { + servicePty = ensemble->services.begin(); + } + for (; servicePty != ensemble->services.end(); + ++servicePty) { + if ((*servicePty)->pty == 0 && (*servicePty)->language == 0) { + continue; + } + if (fig0 == NULL) { + fig0 = (FIGtype0*)&etiFrame[index]; + fig0->FIGtypeNumber = 0; + fig0->Length = 1; + fig0->CN = 0; + fig0->OE = 0; + fig0->PD = 0; + fig0->Extension = 17; + index += 2; + figSize += 2; + } + + if ((*servicePty)->language == 0) { + if (figSize + 4 > 30) { + break; + } + } else { + if (figSize + 5 > 30) { + break; + } + } + + programme = + (FIGtype0_17_programme*)&etiFrame[index]; + programme->SId = htons((*servicePty)->id); + programme->SD = 1; + programme->PS = 0; + programme->L = (*servicePty)->language != 0; + programme->CC = 0; + programme->Rfa = 0; + programme->NFC = 0; + if ((*servicePty)->language == 0) { + etiFrame[index + 3] = (*servicePty)->pty; + fig0->Length += 4; + index += 4; + figSize += 4; + } else { + etiFrame[index + 3] = (*servicePty)->language; + etiFrame[index + 4] = (*servicePty)->pty; + fig0->Length += 5; + index += 5; + figSize += 5; + } + } + break; + } + + if (figSize > 30) { + etiLog.printHeader(TcpLog::ERR, + "FIG too big (%i > 30)\n", figSize); + returnCode = -1; + goto EXIT; + } + + memcpy(&etiFrame[index], Padding_FIB, 30 - figSize); + index += 30 - figSize; + + CRCtmp = 0xffff; + CRCtmp = crc16(CRCtmp, &etiFrame[(index - 30)], 30); + CRCtmp ^= 0xffff; + etiFrame[index++] = ((char *) &CRCtmp)[1]; + etiFrame[index++] = ((char *) &CRCtmp)[0]; + + figSize = 0; + // Insertion du FIB 1 + switch (alterneFIB) { + case 0: // FIG 0/8 program + fig0 = NULL; + + if (componentIndicatorProgram == ensemble->components.end()) { + componentIndicatorProgram = ensemble->components.begin(); + } + for (; componentIndicatorProgram != ensemble->components.end(); + ++componentIndicatorProgram) { + service = getService(*componentIndicatorProgram, + ensemble->services); + subchannel = getSubchannel(ensemble->subchannels, + (*componentIndicatorProgram)->subchId); + if (subchannel == ensemble->subchannels.end()) { + etiLog.printHeader(TcpLog::ERR, + "Subchannel %i does not exist for component " + "of service %i\n", + (*componentIndicatorProgram)->subchId, + (*componentIndicatorProgram)->serviceId); + returnCode = -1; + goto EXIT; + } + + if (!(*service)->program) continue; + + if (fig0 == NULL) { + fig0 = (FIGtype0*)&etiFrame[index]; + fig0->FIGtypeNumber = 0; + fig0->Length = 1; + fig0->CN = 0; + fig0->OE = 0; + fig0->PD = 0; + fig0->Extension = 8; + index += 2; + figSize += 2; + } + + if ((*subchannel)->type == 3) { // Data packet + if (figSize > 30 - 5) { + break; + } + *((uint16_t*)&etiFrame[index]) = + htons((*componentIndicatorProgram)->serviceId); + fig0->Length += 2; + index += 2; + figSize += 2; + + FIGtype0_8_long* definition = + (FIGtype0_8_long*)&etiFrame[index]; + memset(definition, 0, 3); + definition->ext = 0; // no rfa + definition->SCIdS = (*componentIndicatorProgram)->SCIdS; + definition->LS = 1; + definition->setSCId((*componentIndicatorProgram)->packet.id); + fig0->Length += 3; + index += 3; // 8 minus rfa + figSize += 3; + } else { // Audio, data stream or FIDC + if (figSize > 30 - 4) { + break; + } + *((uint16_t*)&etiFrame[index]) = + htons((*componentIndicatorProgram)->serviceId); + fig0->Length += 2; + index += 2; + figSize += 2; + + FIGtype0_8_short* definition = + (FIGtype0_8_short*)&etiFrame[index]; + memset(definition, 0, 2); + definition->ext = 0; // no rfa + definition->SCIdS = (*componentIndicatorProgram)->SCIdS; + definition->LS = 0; + definition->MscFic = 0; + definition->Id = (*componentIndicatorProgram)->subchId; + fig0->Length += 2; + index += 2; // 4 minus rfa + figSize += 2; + } + } + break; + + case 1: // FIG 0/8 data + fig0 = NULL; + + if (componentIndicatorData == ensemble->components.end()) { + componentIndicatorData = ensemble->components.begin(); + } + for (; componentIndicatorData != ensemble->components.end(); + ++componentIndicatorData) { + service = getService(*componentIndicatorData, + ensemble->services); + subchannel = getSubchannel(ensemble->subchannels, + (*componentIndicatorData)->subchId); + if (subchannel == ensemble->subchannels.end()) { + etiLog.printHeader(TcpLog::ERR, + "Subchannel %i does not exist for component " + "of service %i\n", + (*componentIndicatorData)->subchId, + (*componentIndicatorData)->serviceId); + returnCode = -1; + goto EXIT; + } + + if ((*service)->program) continue; + + if (fig0 == NULL) { + fig0 = (FIGtype0*)&etiFrame[index]; + fig0->FIGtypeNumber = 0; + fig0->Length = 1; + fig0->CN = 0; + fig0->OE = 0; + fig0->PD = 1; + fig0->Extension = 8; + index += 2; + figSize += 2; + } + + if ((*subchannel)->type == 3) { // Data packet + if (figSize > 30 - 7) { + break; + } + *((uint32_t*)&etiFrame[index]) = + htonl((*componentIndicatorData)->serviceId); + fig0->Length += 4; + index += 4; + figSize += 4; + + FIGtype0_8_long* definition = + (FIGtype0_8_long*)&etiFrame[index]; + memset(definition, 0, 3); + definition->ext = 0; // no rfa + definition->SCIdS = (*componentIndicatorData)->SCIdS; + definition->LS = 1; + definition->setSCId((*componentIndicatorData)->packet.id); + fig0->Length += 3; + index += 3; // 8 minus rfa + figSize += 3; + } else { // Audio, data stream or FIDC + if (figSize > 30 - 6) { + break; + } + *((uint32_t*)&etiFrame[index]) = + htonl((*componentIndicatorData)->serviceId); + fig0->Length += 4; + index += 4; + figSize += 4; + + FIGtype0_8_short* definition = + (FIGtype0_8_short*)&etiFrame[index]; + memset(definition, 0, 2); + definition->ext = 0; // no rfa + definition->SCIdS = (*componentIndicatorData)->SCIdS; + definition->LS = 0; + definition->MscFic = 0; + definition->Id = (*componentIndicatorData)->subchId; + fig0->Length += 2; + index += 2; // 4 minus rfa + figSize += 2; + } + } + break; + + case 3: + // FIG type 1/0, Service Information (SI), Ensemble Label + fig1_0 = (FIGtype1_0 *) & etiFrame[index]; + + fig1_0->Length = 21; + fig1_0->FIGtypeNumber = 1; + fig1_0->Extension = 0; + fig1_0->OE = 0; + fig1_0->Charset = 0; + fig1_0->EId = htons(ensemble->id); + index = index + 4; + + memcpy(&etiFrame[index], ensemble->label.text, 16); + index = index + 16; + + etiFrame[index++] = ((char *) &ensemble->label.flag)[1]; + etiFrame[index++] = ((char *) &ensemble->label.flag)[0]; + + figSize += 22; + break; + case 5: + // FIG 0 / 13 + fig0 = NULL; + + for (component = ensemble->components.begin(); + component != ensemble->components.end(); + ++component) { + subchannel = getSubchannel(ensemble->subchannels, + (*component)->subchId); + if (subchannel == ensemble->subchannels.end()) { + etiLog.printHeader(TcpLog::ERR, + "Subchannel %i does not exist for component " + "of service %i\n", + (*component)->subchId, (*component)->serviceId); + returnCode = -1; + goto EXIT; + } + + if ((*subchannel)->type != 3) continue; + + if ((*component)->packet.appType != 0xffff) { + if (fig0 == NULL) { + fig0 = (FIGtype0*)&etiFrame[index]; + fig0->FIGtypeNumber = 0; + fig0->Length = 1; + fig0->CN = 0; + fig0->OE = 0; + fig0->PD = 1; + fig0->Extension = 13; + index += 2; + figSize += 2; + } + + FIG0_13_longAppInfo* info = + (FIG0_13_longAppInfo*)&etiFrame[index]; + info->SId = htonl((*component)->serviceId); + info->SCIdS = (*component)->SCIdS; + info->No = 1; + index += 5; + figSize += 5; + fig0->Length += 5; + + FIG0_13_app* app = (FIG0_13_app*)&etiFrame[index]; + app->setType((*component)->packet.appType); + app->length = 0; + index += 2; + figSize += 2; + fig0->Length += 2; + + if (figSize > 30) { + etiLog.printHeader(TcpLog::ERR, + "can't add to Fic Fig 0/13, " + "too much packet service\n"); + returnCode = -1; + goto EXIT; + } + } + } + break; + case 7: + //Time and country identifier + fig0_10 = (FIGtype0_10 *) & etiFrame[index]; + + fig0_10->FIGtypeNumber = 0; + fig0_10->Length = 5; + fig0_10->CN = 0; + fig0_10->OE = 0; + fig0_10->PD = 0; + fig0_10->Extension = 10; + index = index + 2; + + timeData = localtime(&date); + + fig0_10->RFU = 0; + fig0_10->setMJD(gregorian2mjd(timeData->tm_year + 1900, + timeData->tm_mon + 1, + timeData->tm_mday)); + fig0_10->LSI = 0; + fig0_10->ConfInd = (watermarkData[watermarkPos >> 3] >> + (7 - (watermarkPos & 0x07))) & 1; + if (++watermarkPos == watermarkSize) { + watermarkPos = 0; + } + fig0_10->UTC = 0; + fig0_10->setHours(timeData->tm_hour); + fig0_10->Minutes = timeData->tm_min; + index = index + 4; + figSize += 6; + + fig0_9 = (FIGtype0_9*)&etiFrame[index]; + fig0_9->FIGtypeNumber = 0; + fig0_9->Length = 4; + fig0_9->CN = 0; + fig0_9->OE = 0; + fig0_9->PD = 0; + fig0_9->Extension = 9; + + fig0_9->ext = 0; + fig0_9->lto = 0; + fig0_9->ensembleLto = 0; + fig0_9->ensembleEcc = ensemble->ecc; + fig0_9->tableId = 0x2; + index += 5; + figSize += 5; + + break; + } + + memcpy(&etiFrame[index], Padding_FIB, 30 - figSize); + index += 30 - figSize; + + CRCtmp = 0xffff; + CRCtmp = crc16(CRCtmp, &etiFrame[(index - 30)], 30); + CRCtmp ^= 0xffff; + etiFrame[index++] = ((char *) &CRCtmp)[1]; + etiFrame[index++] = ((char *) &CRCtmp)[0]; + + + figSize = 0; + // Insertion FIB 2 + if (alterneFIB < ensemble->services.size()) { + service = ensemble->services.begin() + alterneFIB; + + // FIG type 1/1, SI, Service label, une instance par sous-canal + if ((*service)->getType(ensemble) == 0) { + fig1_1 = (FIGtype1_1 *) & etiFrame[index]; + + fig1_1->FIGtypeNumber = 1; + fig1_1->Length = 21; + fig1_1->Charset = 0; + fig1_1->OE = 0; + fig1_1->Extension = 1; + + fig1_1->Sld = htons((*service)->id); + index += 4; + figSize += 4; + } else { + fig1_5 = (FIGtype1_5 *) & etiFrame[index]; + fig1_5->FIGtypeNumber = 1; + fig1_5->Length = 23; + fig1_5->Charset = 0; + fig1_5->OE = 0; + fig1_5->Extension = 5; + + fig1_5->SId = htonl((*service)->id); + index += 6; + figSize += 6; + } + memcpy(&etiFrame[index], (*service)->label.text, 16); + index += 16; + figSize += 16; + + etiFrame[index++] = ((char *) &(*service)->label.flag)[1]; + etiFrame[index++] = ((char *) &(*service)->label.flag)[0]; + figSize += 2; + } else if (alterneFIB < + ensemble->services.size() + ensemble->components.size()) { + component = ensemble->components.begin() + + (alterneFIB - ensemble->services.size()); + service = getService(*component, ensemble->services); + subchannel = + getSubchannel(ensemble->subchannels, (*component)->subchId); + + if ((*component)->label.text[0] != 0) { + if ((*service)->getType(ensemble) == 0) { // Programme + FIGtype1_4_programme *fig1_4; + fig1_4 = (FIGtype1_4_programme*)&etiFrame[index]; + + fig1_4->FIGtypeNumber = 1; + fig1_4->Length = 22; + fig1_4->Charset = 0; + fig1_4->OE = 0; + fig1_4->Extension = 4; + fig1_4->PD = 0; + fig1_4->rfa = 0; + fig1_4->SCIdS = (*component)->SCIdS; + + fig1_4->SId = htons((*service)->id); + index += 5; + figSize += 5; + } else { // Data + FIGtype1_4_data *fig1_4; + fig1_4 = (FIGtype1_4_data *) & etiFrame[index]; + fig1_4->FIGtypeNumber = 1; + fig1_4->Length = 24; + fig1_4->Charset = 0; + fig1_4->OE = 0; + fig1_4->Extension = 4; + fig1_4->PD = 1; + fig1_4->rfa = 0; + fig1_4->SCIdS = (*component)->SCIdS; + + fig1_4->SId = htonl((*service)->id); + index += 7; + figSize += 7; + } + memcpy(&etiFrame[index], (*component)->label.text, 16); + index += 16; + figSize += 16; + + etiFrame[index++] = ((char *) &(*component)->label.flag)[1]; + etiFrame[index++] = ((char *) &(*component)->label.flag)[0]; + figSize += 2; + } + } + memcpy(&etiFrame[index], Padding_FIB, 30 - figSize); + index += 30 - figSize; + + CRCtmp = 0xffff; + CRCtmp = crc16(CRCtmp, &etiFrame[(index - 30)], 30); + CRCtmp ^= 0xffff; + etiFrame[index++] = ((char *) &CRCtmp)[1]; + etiFrame[index++] = ((char *) &CRCtmp)[0]; + + if (ensemble->mode == 3) { + memcpy(&etiFrame[index], Padding_FIB, 30); + index += 30; + + CRCtmp = 0xffff; + CRCtmp = crc16(CRCtmp, &etiFrame[(index - 30)], 30); + CRCtmp ^= 0xffff; + etiFrame[index++] = ((char *) &CRCtmp)[1]; + etiFrame[index++] = ((char *) &CRCtmp)[0]; + } + + if (ensemble->services.size() > 30) { + etiLog.printHeader(TcpLog::ERR, + "Sorry, but this software currently can't write " + "Service Label of more than 30 services.\n"); + returnCode = -1; + goto EXIT; + } + + // compteur pour FIG 0/0 + insertFIG = (insertFIG + 1) % 8; + + // compteur pour inserer FIB a toutes les 30 trames + alterneFIB = (alterneFIB + 1) % 30; + + /********************************************************************** + ****** Section de lecture de donnees ******************************* + **********************************************************************/ + + //Lecture des donnees dans les fichiers d'entree + for (subchannel = ensemble->subchannels.begin(); + subchannel != ensemble->subchannels.end(); + ++subchannel) { + int sizeSubchannel = getSizeByte(*subchannel); + if ((*subchannel)->operations.lock != NULL) { + (*subchannel)->operations.lock((*subchannel)->data); + } + result = (*subchannel)->operations.readFrame( + &(*subchannel)->operations, + (*subchannel)->data, &etiFrame[index], sizeSubchannel); + if ((*subchannel)->operations.unlock != NULL) { + (*subchannel)->operations.unlock((*subchannel)->data); + } + if (result < 0) { + etiLog.print(TcpLog::INFO, "ETI frame number: %i\n", currentFrame); + } + index += sizeSubchannel; + } + + + index = (3 + fc->NST + FICL) * 4; + for (subchannel = ensemble->subchannels.begin(); + subchannel != ensemble->subchannels.end(); + ++subchannel) { + index += getSizeByte(*subchannel); + } + + /******* Section EOF **************************************************/ + // End of Frame, 4 octets + index = (FLtmp + 1 + 1) * 4; + eti_EOF *eof = (eti_EOF *) & etiFrame[index]; + + //CRC sur le Main Stream data (MST), sur 16 bits + index = ((fc->NST) + 2 + 1) * 4; //position du MST + MSTsize = ((FLtmp) - 1 - (fc->NST)) * 4; //nb d'octets de donnees + + CRCtmp = 0xffff; + CRCtmp = crc16(CRCtmp, &etiFrame[index], MSTsize); + CRCtmp ^= 0xffff; + eof->CRC = htons(CRCtmp); + + //RFU, Reserved for future use, 2 bytes, should be 0xFFFF + eof->RFU = htons(0xFFFF); + + /******* Section TIST *************************************************/ + // TimeStamps, 24 bits + 1 octet + index = (FLtmp + 2 + 1) * 4; + eti_TIST *tist = (eti_TIST *) & etiFrame[index]; + + tist->TIST = htonl(timestamp) | 0xff; + if (timestamp != 0xffffff) { + timestamp += 3 << 17; + if (timestamp > 0xf9ffff) { + timestamp -= 0xfa0000; + } + } + + /********************************************************************** + *********** Section FRPD ***************************************** + **********************************************************************/ + + //Donne le nombre total d'octets utils dans la trame + index = (FLtmp + 1 + 1 + 1 + 1) * 4; + + for (output = outputs.begin() ; output != outputs.end(); ++output) { + if ((*output)->operations.write((*output)->data, etiFrame, index) + == -1) { + etiLog.print(TcpLog::ERR, "Can't write to output %s://%s\n", + (*output)->outputProto, (*output)->outputName); + } + } + +#ifdef DUMP_BRIDGE + dumpBytes(dumpData, sizeSubChannel, stderr); +#endif // DUMP_BRIDGE + + if (currentFrame % 100 == 0) { + etiLog.print(TcpLog::INFO, "ETI frame number %i \n", currentFrame); + } + } + +EXIT: + etiLog.print(TcpLog::DBG, "exiting...\n"); + //fermeture des fichiers + for (subchannel = ensemble->subchannels.begin(); + subchannel != ensemble->subchannels.end(); + ++subchannel) { + (*subchannel)->operations.close((*subchannel)->data); + (*subchannel)->operations.clean(&(*subchannel)->data); + } + for (output = outputs.begin() ; output != outputs.end(); ++output) { + (*output)->operations.close((*output)->data); + (*output)->operations.clean(&(*output)->data); + } + + for_each(ensemble->components.begin(), ensemble->components.end(), free); + for_each(ensemble->services.begin(), ensemble->services.end(), free); + for_each(ensemble->subchannels.begin(), ensemble->subchannels.end(), free); + for_each(outputs.begin(), outputs.end(), free); + ensemble->components.clear(); + ensemble->services.clear(); + ensemble->subchannels.clear(); + free(ensemble); + outputs.clear(); + + UdpSocket::clean(); + + if (returnCode < 0) { + etiLog.print(TcpLog::EMERG, "...aborting\n"); + } else { + etiLog.print(TcpLog::DBG, "...done\n"); + } + + return returnCode; +} diff --git a/src/Dmb.cpp b/src/Dmb.cpp new file mode 100644 index 0000000..95742d0 --- /dev/null +++ b/src/Dmb.cpp @@ -0,0 +1,280 @@ +/* + Copyright (C) 2005, 2006, 2007, 2008, 2009 Her Majesty the Queen in Right + of Canada (Communications Research Center Canada) + */ +/* + This file is part of CRC-DabMux. + + CRC-DabMux is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + CRC-DabMux is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CRC-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "Dmb.h" + +#include <string.h> + + +#ifdef _WIN32 +# define bzero(a, b) memset((a), 0, (b)) +#endif // _WIN32 + + +DmbStats::DmbStats() +{ + reset(); +} + + +void DmbStats::reset() +{ + memset(this, 0, sizeof(*this)); +} + + +Dmb::Dmb(bool reverse) : +interleaver(12, 17), +encoder(204, 188) +{ + buffer = NULL; + bufferSize = 0; + setReverse(reverse); +} + + +Dmb::~Dmb() +{ + if (buffer != NULL) { + delete[] buffer; + } +} + + +void Dmb::setReverse(bool state) +{ + reverse = state; + reset(); + + interleaver.setReverse(state); + encoder.setReverse(state); + stats.reset(); +} + + +void Dmb::reset() +{ + bufferOffset = 0; + bufferLength = 0; + inputOffset = 0; + outputOffset = 0; +// padding = 0; +} + + +#include <stdio.h> +int Dmb::encode( + void* dataIn, + unsigned long sizeIn, + void* dataOut, + unsigned long sizeOut + ) +{ + int ret = 0; + char* input = reinterpret_cast<char*>(dataIn); + char* output = reinterpret_cast<char*>(dataOut); + + if (bufferSize < sizeIn + 204) { + if (buffer != NULL) { + delete[] buffer; + } + unsigned char* oldBuffer = buffer; + bufferSize = sizeIn + 204; + buffer = new unsigned char[bufferSize]; + memcpy(buffer, oldBuffer, bufferLength); + } + + if (reverse) { +// fprintf(stderr, "*** Decode ***\n"); +// fprintf(stderr, " sizeIn: %i\n", sizeIn); +// fprintf(stderr, " inputOffset: %i\n", inputOffset); +// fprintf(stderr, " bufferLength: %i\n", bufferLength); +// fprintf(stderr, " bufferOffset: %i\n", bufferOffset); +// fprintf(stderr, " outputOffset: %i\n", outputOffset); + + if (inputOffset == 0) { + ++stats.dmbFrame; + stats.rcvBytes += sizeIn; + } + + memcpy(&buffer[bufferLength], &input[inputOffset], + sizeIn - inputOffset); + interleaver.encode(&buffer[bufferLength], sizeIn - inputOffset); + bufferLength += sizeIn - inputOffset; + inputOffset += sizeIn - inputOffset; + while (bufferLength - bufferOffset >= 204) { + if (buffer[bufferOffset] != 0x47) { + int offset = sync(&buffer[bufferOffset], + bufferLength - bufferOffset); + if (offset == 0) { + bufferLength = 0; + bufferOffset = 0; + } else { + bufferOffset += offset; + } + } else { + if (outputOffset + 188 <= sizeOut) { // If enough place + int error = encoder.encode(&buffer[bufferOffset], 204); + if (error != -1) { +// if (true) { + if (error > 0) { + stats.corBytes += error; + } + memcpy(&output[outputOffset], &buffer[bufferOffset], + 188); + if (((buffer[bufferOffset + 1] & 0x1f) == 0x1f) && + (buffer[bufferOffset + 2] == 0xff)) { + stats.nulBytes += 188; + } else { + ret += 188; + stats.sndBytes += 188; + outputOffset += 188; + } + bufferOffset += 204; + ++stats.mpgFrame; + } else { +// interleaver.reset(); +// padding = 0; +// bufferLength = 0; +// inputOffset = 0; +// stats.errBytes += 188; + bufferOffset += 12; + stats.errBytes += 12; + ++stats.synFrame; + int offset = sync (&buffer[bufferOffset], + bufferLength - bufferOffset); + if (offset == 0) { + stats.errBytes += bufferLength - bufferOffset; + bufferOffset = 0; + bufferLength = 0; + } else { + stats.errBytes += offset; + bufferOffset += offset; + } + } + } else { + outputOffset = 0; + goto ENCODE_END; + } + } + } + memmove(buffer, &buffer[bufferOffset], bufferLength - bufferOffset); + bufferLength -= bufferOffset; + bufferOffset = 0; + if (ret == 0) { + inputOffset = 0; + } else { + outputOffset = 0; + } +// fprintf(stderr, " ret: %i\n\n", ret); + } else { + if (sizeIn == 0) { + bzero(&output[outputOffset], sizeOut - outputOffset); + interleaver.encode(&output[outputOffset], sizeOut - outputOffset); + outputOffset = 0; + ++stats.dmbFrame; + stats.sndBytes += sizeOut; + goto ENCODE_END; + } + + if (bufferLength == 204) { // If buffer is not empty + // If there's more data in buffer than place in output + if (204 - bufferOffset > sizeOut - outputOffset) { + memcpy(&output[outputOffset], &buffer[bufferOffset], + sizeOut - outputOffset); + bufferOffset += sizeOut - outputOffset; + outputOffset = 0; + ++stats.dmbFrame; + stats.sndBytes += sizeOut; + goto ENCODE_END; + } + memcpy(&output[outputOffset], &buffer[bufferOffset], + 204 - bufferOffset); + outputOffset += 204 - bufferOffset; + bufferOffset = 0; + bufferLength = 0; + } + + while (true) { + // If there's not enought input data + if (sizeIn - inputOffset < 188 - bufferLength) { + memcpy(&buffer[bufferLength], &input[inputOffset], + sizeIn - inputOffset); + bufferLength += sizeIn - inputOffset; + ret = outputOffset; + inputOffset = 0; + goto ENCODE_END; + } + if (buffer[bufferLength] == 0x47) { + ++stats.mpgFrame; + } +// fprintf(stderr, "++mpg: %i, sizeIn: %i, inputOffset: %i\n", +// stats.mpgFrame, sizeIn, inputOffset); + stats.rcvBytes += 188; + + memcpy(&buffer[bufferLength], &input[inputOffset], + 188 - bufferLength); + inputOffset += 188 - bufferLength; + + encoder.encode(buffer, 188); + interleaver.encode(buffer, 204); + bufferLength = 204; + + if (sizeOut - outputOffset < 204) { + memcpy(&output[outputOffset], buffer, sizeOut - outputOffset); + bufferOffset += sizeOut - outputOffset; + outputOffset = 0; + ++stats.dmbFrame; + stats.sndBytes += sizeOut; + goto ENCODE_END; + } + memcpy(&output[outputOffset], buffer, 204); + outputOffset += 204; + bufferLength = 0; + } + } + +ENCODE_END: + return ret; +} + + +int Dmb::sync(void* dataIn, unsigned long sizeIn) +{ + char* input = reinterpret_cast<char*>(dataIn); + char* sync = input; + unsigned long size = sizeIn; + + while (sync != NULL) { + sync = (char*)memchr(sync, 0x47, size); + if (sync != NULL) { + int offset = sync - input; + if (offset % 12 != 0) { + offset = ((offset / 12) * 12) + 12; + sync = &input[offset]; + size = sizeIn - offset; + } else { + return offset; + } + } + } + return 0; +} diff --git a/src/Dmb.h b/src/Dmb.h new file mode 100644 index 0000000..13ce340 --- /dev/null +++ b/src/Dmb.h @@ -0,0 +1,81 @@ +/* + Copyright (C) 2005, 2006, 2007, 2008, 2009 Her Majesty the Queen in Right + of Canada (Communications Research Center Canada) + */ +/* + This file is part of CRC-DabMux. + + CRC-DabMux is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + CRC-DabMux is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CRC-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _DMB +#define _DMB + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "Interleaver.h" +#include "ReedSolomon.h" + + +class DmbStats +{ +public: + DmbStats(); + void reset(); + + unsigned dmbFrame; + unsigned mpgFrame; + unsigned synFrame; + unsigned rcvBytes; + unsigned nulBytes; + unsigned sndBytes; + unsigned errBytes; + unsigned corBytes; +}; + + +class Dmb +{ +public: + Dmb(bool reverse = false); + Dmb(const Dmb& clone); + virtual ~Dmb(); + + void setReverse(bool state); + int encode(void* dataIn, unsigned long sizeIn, void* dataOut, unsigned long sizeOut); + void reset(); + DmbStats getStats() { return stats; }; + +private: + int sync(void* dataIn, unsigned long sizeIn); + + Interleaver interleaver; + ReedSolomon encoder; + unsigned char* buffer; + unsigned bufferSize; + unsigned bufferOffset; // Encoded data written to output + unsigned bufferLength; // Encoded data + unsigned inputOffset; + unsigned outputOffset; +// unsigned padding; // Padding data written + + bool reverse; + + DmbStats stats; +}; + + +#endif // _DMB diff --git a/src/Eti.cpp b/src/Eti.cpp new file mode 100644 index 0000000..3dd11e2 --- /dev/null +++ b/src/Eti.cpp @@ -0,0 +1,70 @@ +/* + Copyright (C) 2005, 2006, 2007, 2008, 2009 Her Majesty the Queen in Right + of Canada (Communications Research Center Canada) + */ +/* + This file is part of CRC-DabMux. + + CRC-DabMux is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + CRC-DabMux is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CRC-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifdef _WIN32 +# pragma warning ( disable : 4103 ) +# include "Eti.h" +# pragma warning ( default : 4103 ) +#else +# include "Eti.h" +#endif + + +//definitions des structures des champs du ETI(NI, G703) + + +unsigned short eti_FC::getFrameLength() +{ + return (unsigned short)((FL_high << 8) | FL_low); +} + + +void eti_FC::setFrameLength(uint16_t length) +{ + FL_high = (length >> 8) & 0x07; + FL_low = length & 0xff; +} + + +void eti_STC::setSTL(uint16_t length) +{ + STL_high = length >> 8; + STL_low = length & 0xff; +} + + +uint16_t eti_STC::getSTL() +{ + return (uint16_t)((STL_high << 8) + STL_low); +} + + +void eti_STC::setStartAddress(uint16_t address) +{ + startAddress_high = address >> 8; + startAddress_low = address & 0xff; +} + + +uint16_t eti_STC::getStartAddress() +{ + return (uint16_t)((startAddress_high << 8) + startAddress_low); +} diff --git a/src/Eti.h b/src/Eti.h new file mode 100644 index 0000000..5580aaf --- /dev/null +++ b/src/Eti.h @@ -0,0 +1,96 @@ +/* + Copyright (C) 2005, 2006, 2007, 2008, 2009 Her Majesty the Queen in Right + of Canada (Communications Research Center Canada) + */ +/* + This file is part of CRC-DabMux. + + CRC-DabMux is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + CRC-DabMux is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CRC-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef ETI_ +#define ETI_ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#ifdef _WIN32 +# include <winsock2.h> // For types... +typedef WORD uint16_t; +typedef DWORD32 uint32_t; + +# define PACKED +# pragma pack(push, 1) +#else +# include <stdint.h> + +# define PACKED __attribute__ ((packed)) +#endif + + +//definitions des structures des champs du ETI(NI, G703) + + +struct eti_SYNC { + uint32_t ERR:8; + uint32_t FSYNC:24; +} PACKED; + + +struct eti_FC { + uint32_t FCT:8; + uint32_t NST:7; + uint32_t FICF:1; + uint32_t FL_high:3; + uint32_t MID:2; + uint32_t FP:3; + uint32_t FL_low:8; + uint16_t getFrameLength(); + void setFrameLength(uint16_t length); +} PACKED; + + +struct eti_STC { + uint32_t startAddress_high:2; + uint32_t SCID:6; + uint32_t startAddress_low:8; + uint32_t STL_high:2; + uint32_t TPL:6; + uint32_t STL_low:8; + void setSTL(uint16_t length); + uint16_t getSTL(); + void setStartAddress(uint16_t address); + uint16_t getStartAddress(); +} PACKED; + + +struct eti_EOH { + uint16_t MNSC; + uint16_t CRC; +} PACKED; + + +struct eti_EOF { + uint16_t CRC; + uint16_t RFU; +} PACKED; + + +struct eti_TIST { + uint32_t TIST; +} PACKED; + + +#endif // ETI_ diff --git a/src/InetAddress.cpp b/src/InetAddress.cpp new file mode 100644 index 0000000..8915285 --- /dev/null +++ b/src/InetAddress.cpp @@ -0,0 +1,259 @@ +/* + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Her Majesty the + Queen in Right of Canada (Communications Research Center Canada) + */ +/* + This file is part of CRC-DabMux. + + CRC-DabMux is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + CRC-DabMux is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CRC-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "InetAddress.h" +#include <iostream> +#include <stdio.h> + +#ifdef _WIN32 +#else +# include <errno.h> +# include <string.h> +#endif + +#ifdef TRACE_ON +# ifndef TRACE_CLASS +# define TRACE_CLASS(clas, func) cout <<"-" <<(clas) <<"\t(" <<this <<")::" <<(func) <<endl +# define TRACE_STATIC(clas, func) cout <<"-" <<(clas) <<"\t(static)::" <<(func) <<endl +# endif +#else +# ifndef TRACE_CLASS +# define TRACE_CLASS(clas, func) +# define TRACE_STATIC(clas, func) +# endif +#endif + + +int inetErrNo = 0; +const char *inetErrMsg = NULL; +const char *inetErrDesc = NULL; + + +/** + * Constructs an IP address. + * @param port The port of this address + * @param name The name of this address + */ +InetAddress::InetAddress(int port, const char* name) { + TRACE_CLASS("InetAddress", "InetAddress(int, char)"); + addr.sin_family = PF_INET; + addr.sin_addr.s_addr = htons(INADDR_ANY); + addr.sin_port = htons(port); + if (name) + setAddress(name); +} + + +/** + * Constructs a copy of inet + * @param inet The address to be copied + */ +InetAddress::InetAddress(const InetAddress &inet) { + TRACE_CLASS("InetAddress", "InetAddress(InetAddress)"); + memcpy(&addr, &inet.addr, sizeof(addr)); +} + + +/// Destructor +InetAddress::~InetAddress() { + TRACE_CLASS("InetAddress" ,"~InetAddress()"); +} + + +/// Returns the raw IP address of this InetAddress object. +sockaddr *InetAddress::getAddress() { + TRACE_CLASS("InetAddress", "getAddress()"); + return (sockaddr *)&addr; +} + + +/// Return the port of this address. +int InetAddress::getPort() +{ + TRACE_CLASS("InetAddress", "getPort()"); + return ntohs(addr.sin_port); +} + + +/** + * Returns the IP address string "%d.%d.%d.%d". + * @return IP address + */ +const char *InetAddress::getHostAddress() { + TRACE_CLASS("InetAddress", "getHostAddress()"); + return inet_ntoa(addr.sin_addr); +} + + +/// Returns true if this address is multicast +bool InetAddress::isMulticastAddress() { + TRACE_CLASS("InetAddress", "isMulticastAddress()"); + return IN_MULTICAST(ntohl(addr.sin_addr.s_addr)); // a modifier +} + + +/** + * Set the port number + * @param port The new port number + */ +void InetAddress::setPort(int port) +{ + TRACE_CLASS("InetAddress", "setPort(int)"); + addr.sin_port = htons(port); +} + + +/** + * Set the address + * @param name The new address name + * @return 0 if ok + * -1 if error + */ +int InetAddress::setAddress(const char *name) +{ + TRACE_CLASS("InetAddress", "setAddress(char*)"); + if (name) { + if (atoi(name)) { // If it start with a number + if ((addr.sin_addr.s_addr = inet_addr(name)) == INADDR_NONE) { + addr.sin_addr.s_addr = htons(INADDR_ANY); + inetErrNo = 0; + inetErrMsg = "Invalid address"; + inetErrDesc = name; + return -1; + } + } else { // Assume it's a real name + hostent *host = gethostbyname(name); + if (host) { + addr.sin_addr = *(in_addr *)(host->h_addr); + } else { + addr.sin_addr.s_addr = htons(INADDR_ANY); + inetErrNo = 0; + inetErrMsg = "Could not find address"; + inetErrDesc = name; + return -1; + } + } + } else { + addr.sin_addr.s_addr = INADDR_ANY; + } + return 0; +} + + +void setInetError(const char* description) +{ + inetErrNo = 0; +#ifdef _WIN32 + inetErrNo = WSAGetLastError(); + switch (inetErrNo) { + case WSANOTINITIALISED: + inetErrMsg = "WSANOTINITIALISED A successful WSAStartup must occur before using this function."; + break; + case WSAENETDOWN: + inetErrMsg = "WSAENETDOWN The network subsystem has failed."; + break; + case WSAEFAULT: + inetErrMsg = "WSAEFAULT The buf or from parameters are not part of the user address space, or the fromlen parameter is too small to accommodate the peer address."; + break; + case WSAEINTR: + inetErrMsg = "WSAEINTR The (blocking) call was canceled through WSACancelBlockingCall."; + break; + case WSAEINPROGRESS: + inetErrMsg = "WSAEINPROGRESS A blocking Windows Sockets 1.1 call is in progress, or the service provider is still processing a callback function."; + break; + case WSAEINVAL: + inetErrMsg = "WSAEINVAL The socket has not been bound with bind, or an unknown flag was specified, or MSG_OOB was specified for a socket with SO_OOBINLINE enabled, or (for byte stream-style sockets only) len was zero or negative."; + break; + case WSAEISCONN: + inetErrMsg = "WSAEISCONN The socket is connected. This function is not permitted with a connected socket, whether the socket is connection-oriented or connectionless."; + break; + case WSAENETRESET: + inetErrMsg = "WSAENETRESET The connection has been broken due to the \"keep-alive\" activity detecting a failure while the operation was in progress."; + break; + case WSAENOTSOCK: + inetErrMsg = "WSAENOTSOCK The descriptor is not a socket."; + break; + case WSAEOPNOTSUPP: + inetErrMsg = "WSAEOPNOTSUPP MSG_OOB was specified, but the socket is not stream-style such as type SOCK_STREAM, out-of-band data is not supported in the communication domain associated with this socket, or the socket is unidirectional and supports only send operations."; + break; + case WSAESHUTDOWN: + inetErrMsg = "WSAESHUTDOWN The socket has been shut down; it is not possible to recvfrom on a socket after shutdown has been invoked with how set to SD_RECEIVE or SD_BOTH."; + break; + case WSAEWOULDBLOCK: + inetErrMsg = "WSAEWOULDBLOCK The socket is marked as nonblocking and the recvfrom operation would block."; + break; + case WSAEMSGSIZE: + inetErrMsg = "WSAEMSGSIZE The message was too large to fit into the specified buffer and was truncated."; + break; + case WSAETIMEDOUT: + inetErrMsg = "WSAETIMEDOUT The connection has been dropped, because of a network failure or because the system on the other end went down without notice."; + break; + case WSAECONNRESET: + inetErrMsg = "WSAECONNRESET"; + break; + case WSAEACCES: + inetErrMsg = "WSAEACCES The requested address is a broadcast address, but the appropriate flag was not set. Call setsockopt with the SO_BROADCAST parameter to allow the use of the broadcast address."; + break; + case WSAENOBUFS: + inetErrMsg = "WSAENOBUFS No buffer space is available."; + break; + case WSAENOTCONN: + inetErrMsg = "WSAENOTCONN The socket is not connected (connection-oriented sockets only)"; + break; + case WSAEHOSTUNREACH: + inetErrMsg = "WSAEHOSTUNREACH The remote host cannot be reached from this host at this time."; + break; + case WSAECONNABORTED: + inetErrMsg = "WSAECONNABORTED The virtual circuit was terminated due to a time-out or other failure. The application should close the socket as it is no longer usable."; + break; + case WSAEADDRNOTAVAIL: + inetErrMsg = "WSAEADDRNOTAVAIL The remote address is not a valid address, for example, ADDR_ANY."; + break; + case WSAEAFNOSUPPORT: + inetErrMsg = "WSAEAFNOSUPPORT Addresses in the specified family cannot be used with this socket."; + break; + case WSAEDESTADDRREQ: + inetErrMsg = "WSAEDESTADDRREQ A destination address is required."; + break; + case WSAENETUNREACH: + inetErrMsg = "WSAENETUNREACH The network cannot be reached from this host at this time."; + break; + case WSAEMFILE: + inetErrMsg = "No more socket descriptors are available."; + break; + case WSAEPROTONOSUPPORT: + inetErrMsg = "The specified protocol is not supported."; + break; + case WSAEPROTOTYPE: + inetErrMsg = "The specified protocol is the wrong type for this socket."; + break; + case WSAESOCKTNOSUPPORT: + inetErrMsg = "The specified socket type is not supported in this address family."; + break; + default: + inetErrMsg = "Unknown"; + }; +#else + inetErrNo = errno; + inetErrMsg = strerror(inetErrNo); +#endif + inetErrDesc = description; +} diff --git a/src/InetAddress.h b/src/InetAddress.h new file mode 100644 index 0000000..f818cbf --- /dev/null +++ b/src/InetAddress.h @@ -0,0 +1,91 @@ +/* + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Her Majesty the + Queen in Right of Canada (Communications Research Center Canada) + */ +/* + This file is part of CRC-DabMux. + + CRC-DabMux is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + CRC-DabMux is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CRC-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _InetAddress +#define _InetAddress + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +// General libraries +#include <stdlib.h> +// Linux librairies +#ifndef _WIN32 +// # include <sys/types.h> +# include <sys/socket.h> +# include <netinet/in.h> +# include <unistd.h> +# include <netdb.h> +# include <arpa/inet.h> +# include <pthread.h> +# define SOCKET int +# define INVALID_SOCKET -1 +# define closesocket ::close +// Windows librairies +#else +# include <winsock.h> +# ifdef _MSC_VER +# pragma comment(lib, "wsock32.lib") +# elif defined(__BORLANDC__) +# pragma(lib, "mswsock.lib") +# endif +# ifndef IN_MULTICAST +# define IN_MULTICAST(a) ((((unsigned long) (a)) & 0xf0000000) == 0xe0000000) +# endif +#endif +// General definitions +#define INVALID_PORT -1 + + +/// The last error number +extern int inetErrNo; +/// The last error message +extern const char *inetErrMsg; +/// The description of the last error +extern const char *inetErrDesc; +/// Set the number, message and description of the last error +void setInetError(const char* description); + + +/** + * This class represents an Internet Protocol (IP) address. + * @author Pascal Charest pascal.charest@crc.ca + */ +class InetAddress { + public: + InetAddress(int port = 0, const char* name = NULL); + InetAddress(const InetAddress &addr); + ~InetAddress(); + + sockaddr *getAddress(); + const char *getHostAddress(); + int getPort(); + int setAddress(const char *name); + void setPort(int port); + bool isMulticastAddress(); + + private: + sockaddr_in addr; +}; + + +#endif diff --git a/src/Interleaver.cpp b/src/Interleaver.cpp new file mode 100644 index 0000000..0b23b8d --- /dev/null +++ b/src/Interleaver.cpp @@ -0,0 +1,143 @@ +/* + Copyright (C) 2005, 2006, 2007, 2008, 2009 Her Majesty the Queen in Right + of Canada (Communications Research Center Canada) + */ +/* + This file is part of CRC-DabMux. + + CRC-DabMux is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + CRC-DabMux is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CRC-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "Interleaver.h" + +#include <string.h> + +#ifdef _WIN32 +# define bzero(a, b) memset((a), 0, (b)) +#endif // _WIN32 + + +Interleaver::Interleaver(unsigned short I, unsigned short M, bool reverse) +{ + this->I = I; + this->M = M; + this->N = I * M; + this->memSize = (this->N * I) - 1; + this->mem = new char[memSize]; + setReverse(reverse); +} + + +Interleaver::~Interleaver() +{ + delete []mem; +} + + +void Interleaver::setReverse(bool state) +{ + reverse = state; + reset(); +} + + +void Interleaver::reset() +{ + j = 0; + index = 0; + bzero(mem, memSize); +} + + +void Interleaver::encode(void* data, unsigned long size) +{ + encode(data, data, size); +} + + +void Interleaver::encode(const void* inData, void* outData, unsigned long size) +{ + const char* input = reinterpret_cast<const char *>(inData); + char* output = reinterpret_cast<char *>(outData); + unsigned long i; + + if (reverse) { + for (i = 0; i < size; ++i) { + mem[(index + ((I - 1 - j) * N)) % memSize] = *input; + *output = mem[index]; + ++input; + ++output; + if (++j == I) { + j = 0; + } + if (++index == memSize) { + index = 0; + } + } + } else { + for (i = 0; i < size; ++i) { + if (j) { + mem[(index + (j * N)) % memSize] = *input; + *output = mem[index]; + } else { + *output = *input; + } + ++input; + ++output; + if (++j == I) { + j = 0; + } + if (++index == memSize) { + index = 0; + } + } + } +} + + +unsigned long Interleaver::sync(void* data, unsigned long size, char padding) +{ + char* input = reinterpret_cast<char *>(data); + unsigned long index; + + if (reverse) { + for (index = 0; index < size; ++index) { + mem[(index + ((I - 1 - j) * N)) % memSize] = padding; + *input = mem[index]; + ++input; + if (++index == memSize) { + index = 0; + } + if (++j == I) { + j = 0; + break; + } + } + } else { + for (index = 0; index < size; ++index) { + mem[(index + (j * N)) % memSize] = padding; + *input = mem[index]; + ++input; + if (++index == memSize) { + index = 0; + } + if (++j == I) { + j = 0; + break; + } + } + } + + return index; +} diff --git a/src/Interleaver.h b/src/Interleaver.h new file mode 100644 index 0000000..ad5cccf --- /dev/null +++ b/src/Interleaver.h @@ -0,0 +1,56 @@ +/* + Copyright (C) 2005, 2006, 2007, 2008, 2009 Her Majesty the Queen in Right + of Canada (Communications Research Center Canada) + */ +/* + This file is part of CRC-DabMux. + + CRC-DabMux is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + CRC-DabMux is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CRC-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _INTERLEAVER +#define _INTERLEAVER + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + + +class Interleaver +{ +public: + Interleaver(unsigned short I, unsigned short M, bool reverse = false); + Interleaver(Interleaver& clone); + virtual ~Interleaver(); + + void setReverse(bool state); + void encode(void* data, unsigned long size); + void encode(const void* inData, void* outData, unsigned long size); + unsigned long sync(void* data, unsigned long size, char padding = 0); + void reset(); + void flush(char padding = 0); + +private: + unsigned short I; + unsigned short M; + unsigned long N; + unsigned long j; + unsigned long index; + unsigned long memSize; + char* mem; + bool reverse; +}; + + +#endif // _INTERLEAVER diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..956e0f4 --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,66 @@ +# Copyright (C) 2008, 2009 Her Majesty the Queen in Right of Canada +# (Communications Research Center Canada) + +# This file is part of CRC-DabMux. +# +# CRC-DabMux is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# CRC-DabMux is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with CRC-DabMux. If not, see <http://www.gnu.org/licenses/>. + +bin_PROGRAMS =CRC-DabMux CRC-BridgeTest + +FEC_FLAGS = +FEC_LIBS =-lfec + +CRC_DabMux_CPPFLAGS =-I$(FARSYNC_DIR) +CRC_DabMux_LDADD =$(FEC_LIBS) -lpthread +CRC_DabMux_SOURCES =DabMux.cpp \ + dabInput.h dabInput.cpp \ + dabInputBridgeUdp.h dabInputBridgeUdp.cpp \ + dabInputDabplusFifo.h dabInputDabplusFifo.cpp \ + dabInputDabplusFile.h dabInputDabplusFile.cpp \ + dabInputDmbFile.h dabInputDmbFile.cpp \ + dabInputDmbUdp.h dabInputDmbUdp.cpp \ + dabInputEnhancedFifo.h dabInputEnhancedFifo.cpp \ + dabInputEnhancedPacketFile.h dabInputEnhancedPacketFile.cpp \ + dabInputFifo.h dabInputFifo.cpp \ + dabInputFile.h dabInputFile.cpp \ + dabInputMpegFifo.h dabInputMpegFifo.cpp \ + dabInputMpegFile.h dabInputMpegFile.cpp \ + dabInputPacketFile.h dabInputPacketFile.cpp \ + dabInputPrbs.h dabInputPrbs.cpp \ + dabInputRawFile.h dabInputRawFile.cpp \ + dabInputRawFifo.h dabInputRawFifo.cpp \ + dabInputSlip.h dabInputSlip.cpp \ + dabInputTest.h dabInputTest.cpp \ + dabInputUdp.h dabInputUdp.cpp \ + dabOutput.h dabOutput.cpp \ + bridge.h bridge.c \ + \ + Eti.h Eti.cpp \ + TcpLog.h TcpLog.cpp \ + UdpSocket.h UdpSocket.cpp \ + InetAddress.h InetAddress.cpp \ + prbs.h prbs.c \ + crc.h crc.c \ + dabUtils.h dabUtils.cpp \ + PcDebug.h \ + Dmb.h Dmb.cpp \ + Interleaver.h Interleaver.cpp \ + ReedSolomon.h ReedSolomon.cpp \ + mpeg.h mpeg.c \ + TcpServer.h TcpServer.cpp \ + TcpSocket.h TcpSocket.cpp + +CRC_BridgeTest_CFLAGS =-DBRIDGE_TEST +CRC_BridgeTest_SOURCES =bridge.c \ + crc.c crc.h diff --git a/src/Makefile.in b/src/Makefile.in new file mode 100644 index 0000000..e3689b0 --- /dev/null +++ b/src/Makefile.in @@ -0,0 +1,1146 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Copyright (C) 2008, 2009 Her Majesty the Queen in Right of Canada +# (Communications Research Center Canada) + +# This file is part of CRC-DabMux. +# +# CRC-DabMux is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# CRC-DabMux is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with CRC-DabMux. If not, see <http://www.gnu.org/licenses/>. + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +bin_PROGRAMS = CRC-DabMux$(EXEEXT) CRC-BridgeTest$(EXEEXT) +subdir = src +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__installdirs = "$(DESTDIR)$(bindir)" +PROGRAMS = $(bin_PROGRAMS) +am_CRC_BridgeTest_OBJECTS = CRC_BridgeTest-bridge.$(OBJEXT) \ + CRC_BridgeTest-crc.$(OBJEXT) +CRC_BridgeTest_OBJECTS = $(am_CRC_BridgeTest_OBJECTS) +CRC_BridgeTest_LDADD = $(LDADD) +CRC_BridgeTest_LINK = $(CCLD) $(CRC_BridgeTest_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +am_CRC_DabMux_OBJECTS = CRC_DabMux-DabMux.$(OBJEXT) \ + CRC_DabMux-dabInput.$(OBJEXT) \ + CRC_DabMux-dabInputBridgeUdp.$(OBJEXT) \ + CRC_DabMux-dabInputDabplusFifo.$(OBJEXT) \ + CRC_DabMux-dabInputDabplusFile.$(OBJEXT) \ + CRC_DabMux-dabInputDmbFile.$(OBJEXT) \ + CRC_DabMux-dabInputDmbUdp.$(OBJEXT) \ + CRC_DabMux-dabInputEnhancedFifo.$(OBJEXT) \ + CRC_DabMux-dabInputEnhancedPacketFile.$(OBJEXT) \ + CRC_DabMux-dabInputFifo.$(OBJEXT) \ + CRC_DabMux-dabInputFile.$(OBJEXT) \ + CRC_DabMux-dabInputMpegFifo.$(OBJEXT) \ + CRC_DabMux-dabInputMpegFile.$(OBJEXT) \ + CRC_DabMux-dabInputPacketFile.$(OBJEXT) \ + CRC_DabMux-dabInputPrbs.$(OBJEXT) \ + CRC_DabMux-dabInputRawFile.$(OBJEXT) \ + CRC_DabMux-dabInputRawFifo.$(OBJEXT) \ + CRC_DabMux-dabInputSlip.$(OBJEXT) \ + CRC_DabMux-dabInputTest.$(OBJEXT) \ + CRC_DabMux-dabInputUdp.$(OBJEXT) \ + CRC_DabMux-dabOutput.$(OBJEXT) CRC_DabMux-bridge.$(OBJEXT) \ + CRC_DabMux-Eti.$(OBJEXT) CRC_DabMux-TcpLog.$(OBJEXT) \ + CRC_DabMux-UdpSocket.$(OBJEXT) \ + CRC_DabMux-InetAddress.$(OBJEXT) CRC_DabMux-prbs.$(OBJEXT) \ + CRC_DabMux-crc.$(OBJEXT) CRC_DabMux-dabUtils.$(OBJEXT) \ + CRC_DabMux-Dmb.$(OBJEXT) CRC_DabMux-Interleaver.$(OBJEXT) \ + CRC_DabMux-ReedSolomon.$(OBJEXT) CRC_DabMux-mpeg.$(OBJEXT) \ + CRC_DabMux-TcpServer.$(OBJEXT) CRC_DabMux-TcpSocket.$(OBJEXT) +CRC_DabMux_OBJECTS = $(am_CRC_DabMux_OBJECTS) +am__DEPENDENCIES_1 = +CRC_DabMux_DEPENDENCIES = $(am__DEPENDENCIES_1) +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +CXXLD = $(CXX) +CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ + -o $@ +SOURCES = $(CRC_BridgeTest_SOURCES) $(CRC_DabMux_SOURCES) +DIST_SOURCES = $(CRC_BridgeTest_SOURCES) $(CRC_DabMux_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BUILD_HOST = @BUILD_HOST@ +BUILD_TARGET = @BUILD_TARGET@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FARSYNC_DIR = @FARSYNC_DIR@ +GETOPT = @GETOPT@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +WSOCK32 = @WSOCK32@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +FEC_FLAGS = +FEC_LIBS = -lfec +CRC_DabMux_CPPFLAGS = -I$(FARSYNC_DIR) +CRC_DabMux_LDADD = $(FEC_LIBS) -lpthread +CRC_DabMux_SOURCES = DabMux.cpp \ + dabInput.h dabInput.cpp \ + dabInputBridgeUdp.h dabInputBridgeUdp.cpp \ + dabInputDabplusFifo.h dabInputDabplusFifo.cpp \ + dabInputDabplusFile.h dabInputDabplusFile.cpp \ + dabInputDmbFile.h dabInputDmbFile.cpp \ + dabInputDmbUdp.h dabInputDmbUdp.cpp \ + dabInputEnhancedFifo.h dabInputEnhancedFifo.cpp \ + dabInputEnhancedPacketFile.h dabInputEnhancedPacketFile.cpp \ + dabInputFifo.h dabInputFifo.cpp \ + dabInputFile.h dabInputFile.cpp \ + dabInputMpegFifo.h dabInputMpegFifo.cpp \ + dabInputMpegFile.h dabInputMpegFile.cpp \ + dabInputPacketFile.h dabInputPacketFile.cpp \ + dabInputPrbs.h dabInputPrbs.cpp \ + dabInputRawFile.h dabInputRawFile.cpp \ + dabInputRawFifo.h dabInputRawFifo.cpp \ + dabInputSlip.h dabInputSlip.cpp \ + dabInputTest.h dabInputTest.cpp \ + dabInputUdp.h dabInputUdp.cpp \ + dabOutput.h dabOutput.cpp \ + bridge.h bridge.c \ + \ + Eti.h Eti.cpp \ + TcpLog.h TcpLog.cpp \ + UdpSocket.h UdpSocket.cpp \ + InetAddress.h InetAddress.cpp \ + prbs.h prbs.c \ + crc.h crc.c \ + dabUtils.h dabUtils.cpp \ + PcDebug.h \ + Dmb.h Dmb.cpp \ + Interleaver.h Interleaver.cpp \ + ReedSolomon.h ReedSolomon.cpp \ + mpeg.h mpeg.c \ + TcpServer.h TcpServer.cpp \ + TcpSocket.h TcpSocket.cpp + +CRC_BridgeTest_CFLAGS = -DBRIDGE_TEST +CRC_BridgeTest_SOURCES = bridge.c \ + crc.c crc.h + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .cpp .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)" + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p; \ + then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(bindir)" && rm -f $$files + +clean-binPROGRAMS: + -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS) +CRC-BridgeTest$(EXEEXT): $(CRC_BridgeTest_OBJECTS) $(CRC_BridgeTest_DEPENDENCIES) + @rm -f CRC-BridgeTest$(EXEEXT) + $(CRC_BridgeTest_LINK) $(CRC_BridgeTest_OBJECTS) $(CRC_BridgeTest_LDADD) $(LIBS) +CRC-DabMux$(EXEEXT): $(CRC_DabMux_OBJECTS) $(CRC_DabMux_DEPENDENCIES) + @rm -f CRC-DabMux$(EXEEXT) + $(CXXLINK) $(CRC_DabMux_OBJECTS) $(CRC_DabMux_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CRC_BridgeTest-bridge.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CRC_BridgeTest-crc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CRC_DabMux-DabMux.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CRC_DabMux-Dmb.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CRC_DabMux-Eti.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CRC_DabMux-InetAddress.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CRC_DabMux-Interleaver.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CRC_DabMux-ReedSolomon.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CRC_DabMux-TcpLog.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CRC_DabMux-TcpServer.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CRC_DabMux-TcpSocket.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CRC_DabMux-UdpSocket.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CRC_DabMux-bridge.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CRC_DabMux-crc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CRC_DabMux-dabInput.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CRC_DabMux-dabInputBridgeUdp.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CRC_DabMux-dabInputDabplusFifo.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CRC_DabMux-dabInputDabplusFile.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CRC_DabMux-dabInputDmbFile.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CRC_DabMux-dabInputDmbUdp.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CRC_DabMux-dabInputEnhancedFifo.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CRC_DabMux-dabInputEnhancedPacketFile.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CRC_DabMux-dabInputFifo.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CRC_DabMux-dabInputFile.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CRC_DabMux-dabInputMpegFifo.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CRC_DabMux-dabInputMpegFile.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CRC_DabMux-dabInputPacketFile.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CRC_DabMux-dabInputPrbs.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CRC_DabMux-dabInputRawFifo.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CRC_DabMux-dabInputRawFile.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CRC_DabMux-dabInputSlip.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CRC_DabMux-dabInputTest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CRC_DabMux-dabInputUdp.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CRC_DabMux-dabOutput.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CRC_DabMux-dabUtils.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CRC_DabMux-mpeg.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CRC_DabMux-prbs.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +CRC_BridgeTest-bridge.o: bridge.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(CRC_BridgeTest_CFLAGS) $(CFLAGS) -MT CRC_BridgeTest-bridge.o -MD -MP -MF $(DEPDIR)/CRC_BridgeTest-bridge.Tpo -c -o CRC_BridgeTest-bridge.o `test -f 'bridge.c' || echo '$(srcdir)/'`bridge.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/CRC_BridgeTest-bridge.Tpo $(DEPDIR)/CRC_BridgeTest-bridge.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='bridge.c' object='CRC_BridgeTest-bridge.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(CRC_BridgeTest_CFLAGS) $(CFLAGS) -c -o CRC_BridgeTest-bridge.o `test -f 'bridge.c' || echo '$(srcdir)/'`bridge.c + +CRC_BridgeTest-bridge.obj: bridge.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(CRC_BridgeTest_CFLAGS) $(CFLAGS) -MT CRC_BridgeTest-bridge.obj -MD -MP -MF $(DEPDIR)/CRC_BridgeTest-bridge.Tpo -c -o CRC_BridgeTest-bridge.obj `if test -f 'bridge.c'; then $(CYGPATH_W) 'bridge.c'; else $(CYGPATH_W) '$(srcdir)/bridge.c'; fi` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/CRC_BridgeTest-bridge.Tpo $(DEPDIR)/CRC_BridgeTest-bridge.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='bridge.c' object='CRC_BridgeTest-bridge.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(CRC_BridgeTest_CFLAGS) $(CFLAGS) -c -o CRC_BridgeTest-bridge.obj `if test -f 'bridge.c'; then $(CYGPATH_W) 'bridge.c'; else $(CYGPATH_W) '$(srcdir)/bridge.c'; fi` + +CRC_BridgeTest-crc.o: crc.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(CRC_BridgeTest_CFLAGS) $(CFLAGS) -MT CRC_BridgeTest-crc.o -MD -MP -MF $(DEPDIR)/CRC_BridgeTest-crc.Tpo -c -o CRC_BridgeTest-crc.o `test -f 'crc.c' || echo '$(srcdir)/'`crc.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/CRC_BridgeTest-crc.Tpo $(DEPDIR)/CRC_BridgeTest-crc.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='crc.c' object='CRC_BridgeTest-crc.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(CRC_BridgeTest_CFLAGS) $(CFLAGS) -c -o CRC_BridgeTest-crc.o `test -f 'crc.c' || echo '$(srcdir)/'`crc.c + +CRC_BridgeTest-crc.obj: crc.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(CRC_BridgeTest_CFLAGS) $(CFLAGS) -MT CRC_BridgeTest-crc.obj -MD -MP -MF $(DEPDIR)/CRC_BridgeTest-crc.Tpo -c -o CRC_BridgeTest-crc.obj `if test -f 'crc.c'; then $(CYGPATH_W) 'crc.c'; else $(CYGPATH_W) '$(srcdir)/crc.c'; fi` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/CRC_BridgeTest-crc.Tpo $(DEPDIR)/CRC_BridgeTest-crc.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='crc.c' object='CRC_BridgeTest-crc.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(CRC_BridgeTest_CFLAGS) $(CFLAGS) -c -o CRC_BridgeTest-crc.obj `if test -f 'crc.c'; then $(CYGPATH_W) 'crc.c'; else $(CYGPATH_W) '$(srcdir)/crc.c'; fi` + +CRC_DabMux-bridge.o: bridge.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT CRC_DabMux-bridge.o -MD -MP -MF $(DEPDIR)/CRC_DabMux-bridge.Tpo -c -o CRC_DabMux-bridge.o `test -f 'bridge.c' || echo '$(srcdir)/'`bridge.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/CRC_DabMux-bridge.Tpo $(DEPDIR)/CRC_DabMux-bridge.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='bridge.c' object='CRC_DabMux-bridge.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o CRC_DabMux-bridge.o `test -f 'bridge.c' || echo '$(srcdir)/'`bridge.c + +CRC_DabMux-bridge.obj: bridge.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT CRC_DabMux-bridge.obj -MD -MP -MF $(DEPDIR)/CRC_DabMux-bridge.Tpo -c -o CRC_DabMux-bridge.obj `if test -f 'bridge.c'; then $(CYGPATH_W) 'bridge.c'; else $(CYGPATH_W) '$(srcdir)/bridge.c'; fi` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/CRC_DabMux-bridge.Tpo $(DEPDIR)/CRC_DabMux-bridge.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='bridge.c' object='CRC_DabMux-bridge.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o CRC_DabMux-bridge.obj `if test -f 'bridge.c'; then $(CYGPATH_W) 'bridge.c'; else $(CYGPATH_W) '$(srcdir)/bridge.c'; fi` + +CRC_DabMux-prbs.o: prbs.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT CRC_DabMux-prbs.o -MD -MP -MF $(DEPDIR)/CRC_DabMux-prbs.Tpo -c -o CRC_DabMux-prbs.o `test -f 'prbs.c' || echo '$(srcdir)/'`prbs.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/CRC_DabMux-prbs.Tpo $(DEPDIR)/CRC_DabMux-prbs.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='prbs.c' object='CRC_DabMux-prbs.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o CRC_DabMux-prbs.o `test -f 'prbs.c' || echo '$(srcdir)/'`prbs.c + +CRC_DabMux-prbs.obj: prbs.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT CRC_DabMux-prbs.obj -MD -MP -MF $(DEPDIR)/CRC_DabMux-prbs.Tpo -c -o CRC_DabMux-prbs.obj `if test -f 'prbs.c'; then $(CYGPATH_W) 'prbs.c'; else $(CYGPATH_W) '$(srcdir)/prbs.c'; fi` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/CRC_DabMux-prbs.Tpo $(DEPDIR)/CRC_DabMux-prbs.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='prbs.c' object='CRC_DabMux-prbs.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o CRC_DabMux-prbs.obj `if test -f 'prbs.c'; then $(CYGPATH_W) 'prbs.c'; else $(CYGPATH_W) '$(srcdir)/prbs.c'; fi` + +CRC_DabMux-crc.o: crc.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT CRC_DabMux-crc.o -MD -MP -MF $(DEPDIR)/CRC_DabMux-crc.Tpo -c -o CRC_DabMux-crc.o `test -f 'crc.c' || echo '$(srcdir)/'`crc.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/CRC_DabMux-crc.Tpo $(DEPDIR)/CRC_DabMux-crc.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='crc.c' object='CRC_DabMux-crc.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o CRC_DabMux-crc.o `test -f 'crc.c' || echo '$(srcdir)/'`crc.c + +CRC_DabMux-crc.obj: crc.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT CRC_DabMux-crc.obj -MD -MP -MF $(DEPDIR)/CRC_DabMux-crc.Tpo -c -o CRC_DabMux-crc.obj `if test -f 'crc.c'; then $(CYGPATH_W) 'crc.c'; else $(CYGPATH_W) '$(srcdir)/crc.c'; fi` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/CRC_DabMux-crc.Tpo $(DEPDIR)/CRC_DabMux-crc.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='crc.c' object='CRC_DabMux-crc.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o CRC_DabMux-crc.obj `if test -f 'crc.c'; then $(CYGPATH_W) 'crc.c'; else $(CYGPATH_W) '$(srcdir)/crc.c'; fi` + +CRC_DabMux-mpeg.o: mpeg.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT CRC_DabMux-mpeg.o -MD -MP -MF $(DEPDIR)/CRC_DabMux-mpeg.Tpo -c -o CRC_DabMux-mpeg.o `test -f 'mpeg.c' || echo '$(srcdir)/'`mpeg.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/CRC_DabMux-mpeg.Tpo $(DEPDIR)/CRC_DabMux-mpeg.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='mpeg.c' object='CRC_DabMux-mpeg.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o CRC_DabMux-mpeg.o `test -f 'mpeg.c' || echo '$(srcdir)/'`mpeg.c + +CRC_DabMux-mpeg.obj: mpeg.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT CRC_DabMux-mpeg.obj -MD -MP -MF $(DEPDIR)/CRC_DabMux-mpeg.Tpo -c -o CRC_DabMux-mpeg.obj `if test -f 'mpeg.c'; then $(CYGPATH_W) 'mpeg.c'; else $(CYGPATH_W) '$(srcdir)/mpeg.c'; fi` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/CRC_DabMux-mpeg.Tpo $(DEPDIR)/CRC_DabMux-mpeg.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='mpeg.c' object='CRC_DabMux-mpeg.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o CRC_DabMux-mpeg.obj `if test -f 'mpeg.c'; then $(CYGPATH_W) 'mpeg.c'; else $(CYGPATH_W) '$(srcdir)/mpeg.c'; fi` + +.cpp.o: +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $< + +.cpp.obj: +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +CRC_DabMux-DabMux.o: DabMux.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT CRC_DabMux-DabMux.o -MD -MP -MF $(DEPDIR)/CRC_DabMux-DabMux.Tpo -c -o CRC_DabMux-DabMux.o `test -f 'DabMux.cpp' || echo '$(srcdir)/'`DabMux.cpp +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/CRC_DabMux-DabMux.Tpo $(DEPDIR)/CRC_DabMux-DabMux.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='DabMux.cpp' object='CRC_DabMux-DabMux.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o CRC_DabMux-DabMux.o `test -f 'DabMux.cpp' || echo '$(srcdir)/'`DabMux.cpp + +CRC_DabMux-DabMux.obj: DabMux.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT CRC_DabMux-DabMux.obj -MD -MP -MF $(DEPDIR)/CRC_DabMux-DabMux.Tpo -c -o CRC_DabMux-DabMux.obj `if test -f 'DabMux.cpp'; then $(CYGPATH_W) 'DabMux.cpp'; else $(CYGPATH_W) '$(srcdir)/DabMux.cpp'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/CRC_DabMux-DabMux.Tpo $(DEPDIR)/CRC_DabMux-DabMux.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='DabMux.cpp' object='CRC_DabMux-DabMux.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o CRC_DabMux-DabMux.obj `if test -f 'DabMux.cpp'; then $(CYGPATH_W) 'DabMux.cpp'; else $(CYGPATH_W) '$(srcdir)/DabMux.cpp'; fi` + +CRC_DabMux-dabInput.o: dabInput.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT CRC_DabMux-dabInput.o -MD -MP -MF $(DEPDIR)/CRC_DabMux-dabInput.Tpo -c -o CRC_DabMux-dabInput.o `test -f 'dabInput.cpp' || echo '$(srcdir)/'`dabInput.cpp +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/CRC_DabMux-dabInput.Tpo $(DEPDIR)/CRC_DabMux-dabInput.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='dabInput.cpp' object='CRC_DabMux-dabInput.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o CRC_DabMux-dabInput.o `test -f 'dabInput.cpp' || echo '$(srcdir)/'`dabInput.cpp + +CRC_DabMux-dabInput.obj: dabInput.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT CRC_DabMux-dabInput.obj -MD -MP -MF $(DEPDIR)/CRC_DabMux-dabInput.Tpo -c -o CRC_DabMux-dabInput.obj `if test -f 'dabInput.cpp'; then $(CYGPATH_W) 'dabInput.cpp'; else $(CYGPATH_W) '$(srcdir)/dabInput.cpp'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/CRC_DabMux-dabInput.Tpo $(DEPDIR)/CRC_DabMux-dabInput.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='dabInput.cpp' object='CRC_DabMux-dabInput.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o CRC_DabMux-dabInput.obj `if test -f 'dabInput.cpp'; then $(CYGPATH_W) 'dabInput.cpp'; else $(CYGPATH_W) '$(srcdir)/dabInput.cpp'; fi` + +CRC_DabMux-dabInputBridgeUdp.o: dabInputBridgeUdp.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT CRC_DabMux-dabInputBridgeUdp.o -MD -MP -MF $(DEPDIR)/CRC_DabMux-dabInputBridgeUdp.Tpo -c -o CRC_DabMux-dabInputBridgeUdp.o `test -f 'dabInputBridgeUdp.cpp' || echo '$(srcdir)/'`dabInputBridgeUdp.cpp +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/CRC_DabMux-dabInputBridgeUdp.Tpo $(DEPDIR)/CRC_DabMux-dabInputBridgeUdp.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='dabInputBridgeUdp.cpp' object='CRC_DabMux-dabInputBridgeUdp.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o CRC_DabMux-dabInputBridgeUdp.o `test -f 'dabInputBridgeUdp.cpp' || echo '$(srcdir)/'`dabInputBridgeUdp.cpp + +CRC_DabMux-dabInputBridgeUdp.obj: dabInputBridgeUdp.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT CRC_DabMux-dabInputBridgeUdp.obj -MD -MP -MF $(DEPDIR)/CRC_DabMux-dabInputBridgeUdp.Tpo -c -o CRC_DabMux-dabInputBridgeUdp.obj `if test -f 'dabInputBridgeUdp.cpp'; then $(CYGPATH_W) 'dabInputBridgeUdp.cpp'; else $(CYGPATH_W) '$(srcdir)/dabInputBridgeUdp.cpp'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/CRC_DabMux-dabInputBridgeUdp.Tpo $(DEPDIR)/CRC_DabMux-dabInputBridgeUdp.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='dabInputBridgeUdp.cpp' object='CRC_DabMux-dabInputBridgeUdp.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o CRC_DabMux-dabInputBridgeUdp.obj `if test -f 'dabInputBridgeUdp.cpp'; then $(CYGPATH_W) 'dabInputBridgeUdp.cpp'; else $(CYGPATH_W) '$(srcdir)/dabInputBridgeUdp.cpp'; fi` + +CRC_DabMux-dabInputDabplusFifo.o: dabInputDabplusFifo.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT CRC_DabMux-dabInputDabplusFifo.o -MD -MP -MF $(DEPDIR)/CRC_DabMux-dabInputDabplusFifo.Tpo -c -o CRC_DabMux-dabInputDabplusFifo.o `test -f 'dabInputDabplusFifo.cpp' || echo '$(srcdir)/'`dabInputDabplusFifo.cpp +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/CRC_DabMux-dabInputDabplusFifo.Tpo $(DEPDIR)/CRC_DabMux-dabInputDabplusFifo.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='dabInputDabplusFifo.cpp' object='CRC_DabMux-dabInputDabplusFifo.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o CRC_DabMux-dabInputDabplusFifo.o `test -f 'dabInputDabplusFifo.cpp' || echo '$(srcdir)/'`dabInputDabplusFifo.cpp + +CRC_DabMux-dabInputDabplusFifo.obj: dabInputDabplusFifo.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT CRC_DabMux-dabInputDabplusFifo.obj -MD -MP -MF $(DEPDIR)/CRC_DabMux-dabInputDabplusFifo.Tpo -c -o CRC_DabMux-dabInputDabplusFifo.obj `if test -f 'dabInputDabplusFifo.cpp'; then $(CYGPATH_W) 'dabInputDabplusFifo.cpp'; else $(CYGPATH_W) '$(srcdir)/dabInputDabplusFifo.cpp'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/CRC_DabMux-dabInputDabplusFifo.Tpo $(DEPDIR)/CRC_DabMux-dabInputDabplusFifo.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='dabInputDabplusFifo.cpp' object='CRC_DabMux-dabInputDabplusFifo.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o CRC_DabMux-dabInputDabplusFifo.obj `if test -f 'dabInputDabplusFifo.cpp'; then $(CYGPATH_W) 'dabInputDabplusFifo.cpp'; else $(CYGPATH_W) '$(srcdir)/dabInputDabplusFifo.cpp'; fi` + +CRC_DabMux-dabInputDabplusFile.o: dabInputDabplusFile.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT CRC_DabMux-dabInputDabplusFile.o -MD -MP -MF $(DEPDIR)/CRC_DabMux-dabInputDabplusFile.Tpo -c -o CRC_DabMux-dabInputDabplusFile.o `test -f 'dabInputDabplusFile.cpp' || echo '$(srcdir)/'`dabInputDabplusFile.cpp +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/CRC_DabMux-dabInputDabplusFile.Tpo $(DEPDIR)/CRC_DabMux-dabInputDabplusFile.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='dabInputDabplusFile.cpp' object='CRC_DabMux-dabInputDabplusFile.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o CRC_DabMux-dabInputDabplusFile.o `test -f 'dabInputDabplusFile.cpp' || echo '$(srcdir)/'`dabInputDabplusFile.cpp + +CRC_DabMux-dabInputDabplusFile.obj: dabInputDabplusFile.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT CRC_DabMux-dabInputDabplusFile.obj -MD -MP -MF $(DEPDIR)/CRC_DabMux-dabInputDabplusFile.Tpo -c -o CRC_DabMux-dabInputDabplusFile.obj `if test -f 'dabInputDabplusFile.cpp'; then $(CYGPATH_W) 'dabInputDabplusFile.cpp'; else $(CYGPATH_W) '$(srcdir)/dabInputDabplusFile.cpp'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/CRC_DabMux-dabInputDabplusFile.Tpo $(DEPDIR)/CRC_DabMux-dabInputDabplusFile.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='dabInputDabplusFile.cpp' object='CRC_DabMux-dabInputDabplusFile.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o CRC_DabMux-dabInputDabplusFile.obj `if test -f 'dabInputDabplusFile.cpp'; then $(CYGPATH_W) 'dabInputDabplusFile.cpp'; else $(CYGPATH_W) '$(srcdir)/dabInputDabplusFile.cpp'; fi` + +CRC_DabMux-dabInputDmbFile.o: dabInputDmbFile.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT CRC_DabMux-dabInputDmbFile.o -MD -MP -MF $(DEPDIR)/CRC_DabMux-dabInputDmbFile.Tpo -c -o CRC_DabMux-dabInputDmbFile.o `test -f 'dabInputDmbFile.cpp' || echo '$(srcdir)/'`dabInputDmbFile.cpp +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/CRC_DabMux-dabInputDmbFile.Tpo $(DEPDIR)/CRC_DabMux-dabInputDmbFile.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='dabInputDmbFile.cpp' object='CRC_DabMux-dabInputDmbFile.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o CRC_DabMux-dabInputDmbFile.o `test -f 'dabInputDmbFile.cpp' || echo '$(srcdir)/'`dabInputDmbFile.cpp + +CRC_DabMux-dabInputDmbFile.obj: dabInputDmbFile.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT CRC_DabMux-dabInputDmbFile.obj -MD -MP -MF $(DEPDIR)/CRC_DabMux-dabInputDmbFile.Tpo -c -o CRC_DabMux-dabInputDmbFile.obj `if test -f 'dabInputDmbFile.cpp'; then $(CYGPATH_W) 'dabInputDmbFile.cpp'; else $(CYGPATH_W) '$(srcdir)/dabInputDmbFile.cpp'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/CRC_DabMux-dabInputDmbFile.Tpo $(DEPDIR)/CRC_DabMux-dabInputDmbFile.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='dabInputDmbFile.cpp' object='CRC_DabMux-dabInputDmbFile.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o CRC_DabMux-dabInputDmbFile.obj `if test -f 'dabInputDmbFile.cpp'; then $(CYGPATH_W) 'dabInputDmbFile.cpp'; else $(CYGPATH_W) '$(srcdir)/dabInputDmbFile.cpp'; fi` + +CRC_DabMux-dabInputDmbUdp.o: dabInputDmbUdp.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT CRC_DabMux-dabInputDmbUdp.o -MD -MP -MF $(DEPDIR)/CRC_DabMux-dabInputDmbUdp.Tpo -c -o CRC_DabMux-dabInputDmbUdp.o `test -f 'dabInputDmbUdp.cpp' || echo '$(srcdir)/'`dabInputDmbUdp.cpp +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/CRC_DabMux-dabInputDmbUdp.Tpo $(DEPDIR)/CRC_DabMux-dabInputDmbUdp.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='dabInputDmbUdp.cpp' object='CRC_DabMux-dabInputDmbUdp.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o CRC_DabMux-dabInputDmbUdp.o `test -f 'dabInputDmbUdp.cpp' || echo '$(srcdir)/'`dabInputDmbUdp.cpp + +CRC_DabMux-dabInputDmbUdp.obj: dabInputDmbUdp.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT CRC_DabMux-dabInputDmbUdp.obj -MD -MP -MF $(DEPDIR)/CRC_DabMux-dabInputDmbUdp.Tpo -c -o CRC_DabMux-dabInputDmbUdp.obj `if test -f 'dabInputDmbUdp.cpp'; then $(CYGPATH_W) 'dabInputDmbUdp.cpp'; else $(CYGPATH_W) '$(srcdir)/dabInputDmbUdp.cpp'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/CRC_DabMux-dabInputDmbUdp.Tpo $(DEPDIR)/CRC_DabMux-dabInputDmbUdp.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='dabInputDmbUdp.cpp' object='CRC_DabMux-dabInputDmbUdp.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o CRC_DabMux-dabInputDmbUdp.obj `if test -f 'dabInputDmbUdp.cpp'; then $(CYGPATH_W) 'dabInputDmbUdp.cpp'; else $(CYGPATH_W) '$(srcdir)/dabInputDmbUdp.cpp'; fi` + +CRC_DabMux-dabInputEnhancedFifo.o: dabInputEnhancedFifo.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT CRC_DabMux-dabInputEnhancedFifo.o -MD -MP -MF $(DEPDIR)/CRC_DabMux-dabInputEnhancedFifo.Tpo -c -o CRC_DabMux-dabInputEnhancedFifo.o `test -f 'dabInputEnhancedFifo.cpp' || echo '$(srcdir)/'`dabInputEnhancedFifo.cpp +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/CRC_DabMux-dabInputEnhancedFifo.Tpo $(DEPDIR)/CRC_DabMux-dabInputEnhancedFifo.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='dabInputEnhancedFifo.cpp' object='CRC_DabMux-dabInputEnhancedFifo.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o CRC_DabMux-dabInputEnhancedFifo.o `test -f 'dabInputEnhancedFifo.cpp' || echo '$(srcdir)/'`dabInputEnhancedFifo.cpp + +CRC_DabMux-dabInputEnhancedFifo.obj: dabInputEnhancedFifo.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT CRC_DabMux-dabInputEnhancedFifo.obj -MD -MP -MF $(DEPDIR)/CRC_DabMux-dabInputEnhancedFifo.Tpo -c -o CRC_DabMux-dabInputEnhancedFifo.obj `if test -f 'dabInputEnhancedFifo.cpp'; then $(CYGPATH_W) 'dabInputEnhancedFifo.cpp'; else $(CYGPATH_W) '$(srcdir)/dabInputEnhancedFifo.cpp'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/CRC_DabMux-dabInputEnhancedFifo.Tpo $(DEPDIR)/CRC_DabMux-dabInputEnhancedFifo.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='dabInputEnhancedFifo.cpp' object='CRC_DabMux-dabInputEnhancedFifo.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o CRC_DabMux-dabInputEnhancedFifo.obj `if test -f 'dabInputEnhancedFifo.cpp'; then $(CYGPATH_W) 'dabInputEnhancedFifo.cpp'; else $(CYGPATH_W) '$(srcdir)/dabInputEnhancedFifo.cpp'; fi` + +CRC_DabMux-dabInputEnhancedPacketFile.o: dabInputEnhancedPacketFile.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT CRC_DabMux-dabInputEnhancedPacketFile.o -MD -MP -MF $(DEPDIR)/CRC_DabMux-dabInputEnhancedPacketFile.Tpo -c -o CRC_DabMux-dabInputEnhancedPacketFile.o `test -f 'dabInputEnhancedPacketFile.cpp' || echo '$(srcdir)/'`dabInputEnhancedPacketFile.cpp +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/CRC_DabMux-dabInputEnhancedPacketFile.Tpo $(DEPDIR)/CRC_DabMux-dabInputEnhancedPacketFile.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='dabInputEnhancedPacketFile.cpp' object='CRC_DabMux-dabInputEnhancedPacketFile.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o CRC_DabMux-dabInputEnhancedPacketFile.o `test -f 'dabInputEnhancedPacketFile.cpp' || echo '$(srcdir)/'`dabInputEnhancedPacketFile.cpp + +CRC_DabMux-dabInputEnhancedPacketFile.obj: dabInputEnhancedPacketFile.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT CRC_DabMux-dabInputEnhancedPacketFile.obj -MD -MP -MF $(DEPDIR)/CRC_DabMux-dabInputEnhancedPacketFile.Tpo -c -o CRC_DabMux-dabInputEnhancedPacketFile.obj `if test -f 'dabInputEnhancedPacketFile.cpp'; then $(CYGPATH_W) 'dabInputEnhancedPacketFile.cpp'; else $(CYGPATH_W) '$(srcdir)/dabInputEnhancedPacketFile.cpp'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/CRC_DabMux-dabInputEnhancedPacketFile.Tpo $(DEPDIR)/CRC_DabMux-dabInputEnhancedPacketFile.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='dabInputEnhancedPacketFile.cpp' object='CRC_DabMux-dabInputEnhancedPacketFile.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o CRC_DabMux-dabInputEnhancedPacketFile.obj `if test -f 'dabInputEnhancedPacketFile.cpp'; then $(CYGPATH_W) 'dabInputEnhancedPacketFile.cpp'; else $(CYGPATH_W) '$(srcdir)/dabInputEnhancedPacketFile.cpp'; fi` + +CRC_DabMux-dabInputFifo.o: dabInputFifo.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT CRC_DabMux-dabInputFifo.o -MD -MP -MF $(DEPDIR)/CRC_DabMux-dabInputFifo.Tpo -c -o CRC_DabMux-dabInputFifo.o `test -f 'dabInputFifo.cpp' || echo '$(srcdir)/'`dabInputFifo.cpp +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/CRC_DabMux-dabInputFifo.Tpo $(DEPDIR)/CRC_DabMux-dabInputFifo.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='dabInputFifo.cpp' object='CRC_DabMux-dabInputFifo.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o CRC_DabMux-dabInputFifo.o `test -f 'dabInputFifo.cpp' || echo '$(srcdir)/'`dabInputFifo.cpp + +CRC_DabMux-dabInputFifo.obj: dabInputFifo.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT CRC_DabMux-dabInputFifo.obj -MD -MP -MF $(DEPDIR)/CRC_DabMux-dabInputFifo.Tpo -c -o CRC_DabMux-dabInputFifo.obj `if test -f 'dabInputFifo.cpp'; then $(CYGPATH_W) 'dabInputFifo.cpp'; else $(CYGPATH_W) '$(srcdir)/dabInputFifo.cpp'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/CRC_DabMux-dabInputFifo.Tpo $(DEPDIR)/CRC_DabMux-dabInputFifo.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='dabInputFifo.cpp' object='CRC_DabMux-dabInputFifo.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o CRC_DabMux-dabInputFifo.obj `if test -f 'dabInputFifo.cpp'; then $(CYGPATH_W) 'dabInputFifo.cpp'; else $(CYGPATH_W) '$(srcdir)/dabInputFifo.cpp'; fi` + +CRC_DabMux-dabInputFile.o: dabInputFile.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT CRC_DabMux-dabInputFile.o -MD -MP -MF $(DEPDIR)/CRC_DabMux-dabInputFile.Tpo -c -o CRC_DabMux-dabInputFile.o `test -f 'dabInputFile.cpp' || echo '$(srcdir)/'`dabInputFile.cpp +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/CRC_DabMux-dabInputFile.Tpo $(DEPDIR)/CRC_DabMux-dabInputFile.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='dabInputFile.cpp' object='CRC_DabMux-dabInputFile.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o CRC_DabMux-dabInputFile.o `test -f 'dabInputFile.cpp' || echo '$(srcdir)/'`dabInputFile.cpp + +CRC_DabMux-dabInputFile.obj: dabInputFile.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT CRC_DabMux-dabInputFile.obj -MD -MP -MF $(DEPDIR)/CRC_DabMux-dabInputFile.Tpo -c -o CRC_DabMux-dabInputFile.obj `if test -f 'dabInputFile.cpp'; then $(CYGPATH_W) 'dabInputFile.cpp'; else $(CYGPATH_W) '$(srcdir)/dabInputFile.cpp'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/CRC_DabMux-dabInputFile.Tpo $(DEPDIR)/CRC_DabMux-dabInputFile.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='dabInputFile.cpp' object='CRC_DabMux-dabInputFile.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o CRC_DabMux-dabInputFile.obj `if test -f 'dabInputFile.cpp'; then $(CYGPATH_W) 'dabInputFile.cpp'; else $(CYGPATH_W) '$(srcdir)/dabInputFile.cpp'; fi` + +CRC_DabMux-dabInputMpegFifo.o: dabInputMpegFifo.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT CRC_DabMux-dabInputMpegFifo.o -MD -MP -MF $(DEPDIR)/CRC_DabMux-dabInputMpegFifo.Tpo -c -o CRC_DabMux-dabInputMpegFifo.o `test -f 'dabInputMpegFifo.cpp' || echo '$(srcdir)/'`dabInputMpegFifo.cpp +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/CRC_DabMux-dabInputMpegFifo.Tpo $(DEPDIR)/CRC_DabMux-dabInputMpegFifo.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='dabInputMpegFifo.cpp' object='CRC_DabMux-dabInputMpegFifo.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o CRC_DabMux-dabInputMpegFifo.o `test -f 'dabInputMpegFifo.cpp' || echo '$(srcdir)/'`dabInputMpegFifo.cpp + +CRC_DabMux-dabInputMpegFifo.obj: dabInputMpegFifo.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT CRC_DabMux-dabInputMpegFifo.obj -MD -MP -MF $(DEPDIR)/CRC_DabMux-dabInputMpegFifo.Tpo -c -o CRC_DabMux-dabInputMpegFifo.obj `if test -f 'dabInputMpegFifo.cpp'; then $(CYGPATH_W) 'dabInputMpegFifo.cpp'; else $(CYGPATH_W) '$(srcdir)/dabInputMpegFifo.cpp'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/CRC_DabMux-dabInputMpegFifo.Tpo $(DEPDIR)/CRC_DabMux-dabInputMpegFifo.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='dabInputMpegFifo.cpp' object='CRC_DabMux-dabInputMpegFifo.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o CRC_DabMux-dabInputMpegFifo.obj `if test -f 'dabInputMpegFifo.cpp'; then $(CYGPATH_W) 'dabInputMpegFifo.cpp'; else $(CYGPATH_W) '$(srcdir)/dabInputMpegFifo.cpp'; fi` + +CRC_DabMux-dabInputMpegFile.o: dabInputMpegFile.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT CRC_DabMux-dabInputMpegFile.o -MD -MP -MF $(DEPDIR)/CRC_DabMux-dabInputMpegFile.Tpo -c -o CRC_DabMux-dabInputMpegFile.o `test -f 'dabInputMpegFile.cpp' || echo '$(srcdir)/'`dabInputMpegFile.cpp +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/CRC_DabMux-dabInputMpegFile.Tpo $(DEPDIR)/CRC_DabMux-dabInputMpegFile.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='dabInputMpegFile.cpp' object='CRC_DabMux-dabInputMpegFile.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o CRC_DabMux-dabInputMpegFile.o `test -f 'dabInputMpegFile.cpp' || echo '$(srcdir)/'`dabInputMpegFile.cpp + +CRC_DabMux-dabInputMpegFile.obj: dabInputMpegFile.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT CRC_DabMux-dabInputMpegFile.obj -MD -MP -MF $(DEPDIR)/CRC_DabMux-dabInputMpegFile.Tpo -c -o CRC_DabMux-dabInputMpegFile.obj `if test -f 'dabInputMpegFile.cpp'; then $(CYGPATH_W) 'dabInputMpegFile.cpp'; else $(CYGPATH_W) '$(srcdir)/dabInputMpegFile.cpp'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/CRC_DabMux-dabInputMpegFile.Tpo $(DEPDIR)/CRC_DabMux-dabInputMpegFile.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='dabInputMpegFile.cpp' object='CRC_DabMux-dabInputMpegFile.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o CRC_DabMux-dabInputMpegFile.obj `if test -f 'dabInputMpegFile.cpp'; then $(CYGPATH_W) 'dabInputMpegFile.cpp'; else $(CYGPATH_W) '$(srcdir)/dabInputMpegFile.cpp'; fi` + +CRC_DabMux-dabInputPacketFile.o: dabInputPacketFile.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT CRC_DabMux-dabInputPacketFile.o -MD -MP -MF $(DEPDIR)/CRC_DabMux-dabInputPacketFile.Tpo -c -o CRC_DabMux-dabInputPacketFile.o `test -f 'dabInputPacketFile.cpp' || echo '$(srcdir)/'`dabInputPacketFile.cpp +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/CRC_DabMux-dabInputPacketFile.Tpo $(DEPDIR)/CRC_DabMux-dabInputPacketFile.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='dabInputPacketFile.cpp' object='CRC_DabMux-dabInputPacketFile.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o CRC_DabMux-dabInputPacketFile.o `test -f 'dabInputPacketFile.cpp' || echo '$(srcdir)/'`dabInputPacketFile.cpp + +CRC_DabMux-dabInputPacketFile.obj: dabInputPacketFile.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT CRC_DabMux-dabInputPacketFile.obj -MD -MP -MF $(DEPDIR)/CRC_DabMux-dabInputPacketFile.Tpo -c -o CRC_DabMux-dabInputPacketFile.obj `if test -f 'dabInputPacketFile.cpp'; then $(CYGPATH_W) 'dabInputPacketFile.cpp'; else $(CYGPATH_W) '$(srcdir)/dabInputPacketFile.cpp'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/CRC_DabMux-dabInputPacketFile.Tpo $(DEPDIR)/CRC_DabMux-dabInputPacketFile.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='dabInputPacketFile.cpp' object='CRC_DabMux-dabInputPacketFile.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o CRC_DabMux-dabInputPacketFile.obj `if test -f 'dabInputPacketFile.cpp'; then $(CYGPATH_W) 'dabInputPacketFile.cpp'; else $(CYGPATH_W) '$(srcdir)/dabInputPacketFile.cpp'; fi` + +CRC_DabMux-dabInputPrbs.o: dabInputPrbs.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT CRC_DabMux-dabInputPrbs.o -MD -MP -MF $(DEPDIR)/CRC_DabMux-dabInputPrbs.Tpo -c -o CRC_DabMux-dabInputPrbs.o `test -f 'dabInputPrbs.cpp' || echo '$(srcdir)/'`dabInputPrbs.cpp +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/CRC_DabMux-dabInputPrbs.Tpo $(DEPDIR)/CRC_DabMux-dabInputPrbs.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='dabInputPrbs.cpp' object='CRC_DabMux-dabInputPrbs.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o CRC_DabMux-dabInputPrbs.o `test -f 'dabInputPrbs.cpp' || echo '$(srcdir)/'`dabInputPrbs.cpp + +CRC_DabMux-dabInputPrbs.obj: dabInputPrbs.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT CRC_DabMux-dabInputPrbs.obj -MD -MP -MF $(DEPDIR)/CRC_DabMux-dabInputPrbs.Tpo -c -o CRC_DabMux-dabInputPrbs.obj `if test -f 'dabInputPrbs.cpp'; then $(CYGPATH_W) 'dabInputPrbs.cpp'; else $(CYGPATH_W) '$(srcdir)/dabInputPrbs.cpp'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/CRC_DabMux-dabInputPrbs.Tpo $(DEPDIR)/CRC_DabMux-dabInputPrbs.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='dabInputPrbs.cpp' object='CRC_DabMux-dabInputPrbs.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o CRC_DabMux-dabInputPrbs.obj `if test -f 'dabInputPrbs.cpp'; then $(CYGPATH_W) 'dabInputPrbs.cpp'; else $(CYGPATH_W) '$(srcdir)/dabInputPrbs.cpp'; fi` + +CRC_DabMux-dabInputRawFile.o: dabInputRawFile.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT CRC_DabMux-dabInputRawFile.o -MD -MP -MF $(DEPDIR)/CRC_DabMux-dabInputRawFile.Tpo -c -o CRC_DabMux-dabInputRawFile.o `test -f 'dabInputRawFile.cpp' || echo '$(srcdir)/'`dabInputRawFile.cpp +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/CRC_DabMux-dabInputRawFile.Tpo $(DEPDIR)/CRC_DabMux-dabInputRawFile.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='dabInputRawFile.cpp' object='CRC_DabMux-dabInputRawFile.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o CRC_DabMux-dabInputRawFile.o `test -f 'dabInputRawFile.cpp' || echo '$(srcdir)/'`dabInputRawFile.cpp + +CRC_DabMux-dabInputRawFile.obj: dabInputRawFile.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT CRC_DabMux-dabInputRawFile.obj -MD -MP -MF $(DEPDIR)/CRC_DabMux-dabInputRawFile.Tpo -c -o CRC_DabMux-dabInputRawFile.obj `if test -f 'dabInputRawFile.cpp'; then $(CYGPATH_W) 'dabInputRawFile.cpp'; else $(CYGPATH_W) '$(srcdir)/dabInputRawFile.cpp'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/CRC_DabMux-dabInputRawFile.Tpo $(DEPDIR)/CRC_DabMux-dabInputRawFile.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='dabInputRawFile.cpp' object='CRC_DabMux-dabInputRawFile.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o CRC_DabMux-dabInputRawFile.obj `if test -f 'dabInputRawFile.cpp'; then $(CYGPATH_W) 'dabInputRawFile.cpp'; else $(CYGPATH_W) '$(srcdir)/dabInputRawFile.cpp'; fi` + +CRC_DabMux-dabInputRawFifo.o: dabInputRawFifo.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT CRC_DabMux-dabInputRawFifo.o -MD -MP -MF $(DEPDIR)/CRC_DabMux-dabInputRawFifo.Tpo -c -o CRC_DabMux-dabInputRawFifo.o `test -f 'dabInputRawFifo.cpp' || echo '$(srcdir)/'`dabInputRawFifo.cpp +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/CRC_DabMux-dabInputRawFifo.Tpo $(DEPDIR)/CRC_DabMux-dabInputRawFifo.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='dabInputRawFifo.cpp' object='CRC_DabMux-dabInputRawFifo.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o CRC_DabMux-dabInputRawFifo.o `test -f 'dabInputRawFifo.cpp' || echo '$(srcdir)/'`dabInputRawFifo.cpp + +CRC_DabMux-dabInputRawFifo.obj: dabInputRawFifo.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT CRC_DabMux-dabInputRawFifo.obj -MD -MP -MF $(DEPDIR)/CRC_DabMux-dabInputRawFifo.Tpo -c -o CRC_DabMux-dabInputRawFifo.obj `if test -f 'dabInputRawFifo.cpp'; then $(CYGPATH_W) 'dabInputRawFifo.cpp'; else $(CYGPATH_W) '$(srcdir)/dabInputRawFifo.cpp'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/CRC_DabMux-dabInputRawFifo.Tpo $(DEPDIR)/CRC_DabMux-dabInputRawFifo.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='dabInputRawFifo.cpp' object='CRC_DabMux-dabInputRawFifo.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o CRC_DabMux-dabInputRawFifo.obj `if test -f 'dabInputRawFifo.cpp'; then $(CYGPATH_W) 'dabInputRawFifo.cpp'; else $(CYGPATH_W) '$(srcdir)/dabInputRawFifo.cpp'; fi` + +CRC_DabMux-dabInputSlip.o: dabInputSlip.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT CRC_DabMux-dabInputSlip.o -MD -MP -MF $(DEPDIR)/CRC_DabMux-dabInputSlip.Tpo -c -o CRC_DabMux-dabInputSlip.o `test -f 'dabInputSlip.cpp' || echo '$(srcdir)/'`dabInputSlip.cpp +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/CRC_DabMux-dabInputSlip.Tpo $(DEPDIR)/CRC_DabMux-dabInputSlip.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='dabInputSlip.cpp' object='CRC_DabMux-dabInputSlip.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o CRC_DabMux-dabInputSlip.o `test -f 'dabInputSlip.cpp' || echo '$(srcdir)/'`dabInputSlip.cpp + +CRC_DabMux-dabInputSlip.obj: dabInputSlip.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT CRC_DabMux-dabInputSlip.obj -MD -MP -MF $(DEPDIR)/CRC_DabMux-dabInputSlip.Tpo -c -o CRC_DabMux-dabInputSlip.obj `if test -f 'dabInputSlip.cpp'; then $(CYGPATH_W) 'dabInputSlip.cpp'; else $(CYGPATH_W) '$(srcdir)/dabInputSlip.cpp'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/CRC_DabMux-dabInputSlip.Tpo $(DEPDIR)/CRC_DabMux-dabInputSlip.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='dabInputSlip.cpp' object='CRC_DabMux-dabInputSlip.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o CRC_DabMux-dabInputSlip.obj `if test -f 'dabInputSlip.cpp'; then $(CYGPATH_W) 'dabInputSlip.cpp'; else $(CYGPATH_W) '$(srcdir)/dabInputSlip.cpp'; fi` + +CRC_DabMux-dabInputTest.o: dabInputTest.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT CRC_DabMux-dabInputTest.o -MD -MP -MF $(DEPDIR)/CRC_DabMux-dabInputTest.Tpo -c -o CRC_DabMux-dabInputTest.o `test -f 'dabInputTest.cpp' || echo '$(srcdir)/'`dabInputTest.cpp +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/CRC_DabMux-dabInputTest.Tpo $(DEPDIR)/CRC_DabMux-dabInputTest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='dabInputTest.cpp' object='CRC_DabMux-dabInputTest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o CRC_DabMux-dabInputTest.o `test -f 'dabInputTest.cpp' || echo '$(srcdir)/'`dabInputTest.cpp + +CRC_DabMux-dabInputTest.obj: dabInputTest.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT CRC_DabMux-dabInputTest.obj -MD -MP -MF $(DEPDIR)/CRC_DabMux-dabInputTest.Tpo -c -o CRC_DabMux-dabInputTest.obj `if test -f 'dabInputTest.cpp'; then $(CYGPATH_W) 'dabInputTest.cpp'; else $(CYGPATH_W) '$(srcdir)/dabInputTest.cpp'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/CRC_DabMux-dabInputTest.Tpo $(DEPDIR)/CRC_DabMux-dabInputTest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='dabInputTest.cpp' object='CRC_DabMux-dabInputTest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o CRC_DabMux-dabInputTest.obj `if test -f 'dabInputTest.cpp'; then $(CYGPATH_W) 'dabInputTest.cpp'; else $(CYGPATH_W) '$(srcdir)/dabInputTest.cpp'; fi` + +CRC_DabMux-dabInputUdp.o: dabInputUdp.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT CRC_DabMux-dabInputUdp.o -MD -MP -MF $(DEPDIR)/CRC_DabMux-dabInputUdp.Tpo -c -o CRC_DabMux-dabInputUdp.o `test -f 'dabInputUdp.cpp' || echo '$(srcdir)/'`dabInputUdp.cpp +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/CRC_DabMux-dabInputUdp.Tpo $(DEPDIR)/CRC_DabMux-dabInputUdp.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='dabInputUdp.cpp' object='CRC_DabMux-dabInputUdp.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o CRC_DabMux-dabInputUdp.o `test -f 'dabInputUdp.cpp' || echo '$(srcdir)/'`dabInputUdp.cpp + +CRC_DabMux-dabInputUdp.obj: dabInputUdp.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT CRC_DabMux-dabInputUdp.obj -MD -MP -MF $(DEPDIR)/CRC_DabMux-dabInputUdp.Tpo -c -o CRC_DabMux-dabInputUdp.obj `if test -f 'dabInputUdp.cpp'; then $(CYGPATH_W) 'dabInputUdp.cpp'; else $(CYGPATH_W) '$(srcdir)/dabInputUdp.cpp'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/CRC_DabMux-dabInputUdp.Tpo $(DEPDIR)/CRC_DabMux-dabInputUdp.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='dabInputUdp.cpp' object='CRC_DabMux-dabInputUdp.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o CRC_DabMux-dabInputUdp.obj `if test -f 'dabInputUdp.cpp'; then $(CYGPATH_W) 'dabInputUdp.cpp'; else $(CYGPATH_W) '$(srcdir)/dabInputUdp.cpp'; fi` + +CRC_DabMux-dabOutput.o: dabOutput.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT CRC_DabMux-dabOutput.o -MD -MP -MF $(DEPDIR)/CRC_DabMux-dabOutput.Tpo -c -o CRC_DabMux-dabOutput.o `test -f 'dabOutput.cpp' || echo '$(srcdir)/'`dabOutput.cpp +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/CRC_DabMux-dabOutput.Tpo $(DEPDIR)/CRC_DabMux-dabOutput.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='dabOutput.cpp' object='CRC_DabMux-dabOutput.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o CRC_DabMux-dabOutput.o `test -f 'dabOutput.cpp' || echo '$(srcdir)/'`dabOutput.cpp + +CRC_DabMux-dabOutput.obj: dabOutput.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT CRC_DabMux-dabOutput.obj -MD -MP -MF $(DEPDIR)/CRC_DabMux-dabOutput.Tpo -c -o CRC_DabMux-dabOutput.obj `if test -f 'dabOutput.cpp'; then $(CYGPATH_W) 'dabOutput.cpp'; else $(CYGPATH_W) '$(srcdir)/dabOutput.cpp'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/CRC_DabMux-dabOutput.Tpo $(DEPDIR)/CRC_DabMux-dabOutput.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='dabOutput.cpp' object='CRC_DabMux-dabOutput.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o CRC_DabMux-dabOutput.obj `if test -f 'dabOutput.cpp'; then $(CYGPATH_W) 'dabOutput.cpp'; else $(CYGPATH_W) '$(srcdir)/dabOutput.cpp'; fi` + +CRC_DabMux-Eti.o: Eti.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT CRC_DabMux-Eti.o -MD -MP -MF $(DEPDIR)/CRC_DabMux-Eti.Tpo -c -o CRC_DabMux-Eti.o `test -f 'Eti.cpp' || echo '$(srcdir)/'`Eti.cpp +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/CRC_DabMux-Eti.Tpo $(DEPDIR)/CRC_DabMux-Eti.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='Eti.cpp' object='CRC_DabMux-Eti.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o CRC_DabMux-Eti.o `test -f 'Eti.cpp' || echo '$(srcdir)/'`Eti.cpp + +CRC_DabMux-Eti.obj: Eti.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT CRC_DabMux-Eti.obj -MD -MP -MF $(DEPDIR)/CRC_DabMux-Eti.Tpo -c -o CRC_DabMux-Eti.obj `if test -f 'Eti.cpp'; then $(CYGPATH_W) 'Eti.cpp'; else $(CYGPATH_W) '$(srcdir)/Eti.cpp'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/CRC_DabMux-Eti.Tpo $(DEPDIR)/CRC_DabMux-Eti.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='Eti.cpp' object='CRC_DabMux-Eti.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o CRC_DabMux-Eti.obj `if test -f 'Eti.cpp'; then $(CYGPATH_W) 'Eti.cpp'; else $(CYGPATH_W) '$(srcdir)/Eti.cpp'; fi` + +CRC_DabMux-TcpLog.o: TcpLog.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT CRC_DabMux-TcpLog.o -MD -MP -MF $(DEPDIR)/CRC_DabMux-TcpLog.Tpo -c -o CRC_DabMux-TcpLog.o `test -f 'TcpLog.cpp' || echo '$(srcdir)/'`TcpLog.cpp +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/CRC_DabMux-TcpLog.Tpo $(DEPDIR)/CRC_DabMux-TcpLog.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='TcpLog.cpp' object='CRC_DabMux-TcpLog.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o CRC_DabMux-TcpLog.o `test -f 'TcpLog.cpp' || echo '$(srcdir)/'`TcpLog.cpp + +CRC_DabMux-TcpLog.obj: TcpLog.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT CRC_DabMux-TcpLog.obj -MD -MP -MF $(DEPDIR)/CRC_DabMux-TcpLog.Tpo -c -o CRC_DabMux-TcpLog.obj `if test -f 'TcpLog.cpp'; then $(CYGPATH_W) 'TcpLog.cpp'; else $(CYGPATH_W) '$(srcdir)/TcpLog.cpp'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/CRC_DabMux-TcpLog.Tpo $(DEPDIR)/CRC_DabMux-TcpLog.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='TcpLog.cpp' object='CRC_DabMux-TcpLog.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o CRC_DabMux-TcpLog.obj `if test -f 'TcpLog.cpp'; then $(CYGPATH_W) 'TcpLog.cpp'; else $(CYGPATH_W) '$(srcdir)/TcpLog.cpp'; fi` + +CRC_DabMux-UdpSocket.o: UdpSocket.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT CRC_DabMux-UdpSocket.o -MD -MP -MF $(DEPDIR)/CRC_DabMux-UdpSocket.Tpo -c -o CRC_DabMux-UdpSocket.o `test -f 'UdpSocket.cpp' || echo '$(srcdir)/'`UdpSocket.cpp +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/CRC_DabMux-UdpSocket.Tpo $(DEPDIR)/CRC_DabMux-UdpSocket.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='UdpSocket.cpp' object='CRC_DabMux-UdpSocket.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o CRC_DabMux-UdpSocket.o `test -f 'UdpSocket.cpp' || echo '$(srcdir)/'`UdpSocket.cpp + +CRC_DabMux-UdpSocket.obj: UdpSocket.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT CRC_DabMux-UdpSocket.obj -MD -MP -MF $(DEPDIR)/CRC_DabMux-UdpSocket.Tpo -c -o CRC_DabMux-UdpSocket.obj `if test -f 'UdpSocket.cpp'; then $(CYGPATH_W) 'UdpSocket.cpp'; else $(CYGPATH_W) '$(srcdir)/UdpSocket.cpp'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/CRC_DabMux-UdpSocket.Tpo $(DEPDIR)/CRC_DabMux-UdpSocket.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='UdpSocket.cpp' object='CRC_DabMux-UdpSocket.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o CRC_DabMux-UdpSocket.obj `if test -f 'UdpSocket.cpp'; then $(CYGPATH_W) 'UdpSocket.cpp'; else $(CYGPATH_W) '$(srcdir)/UdpSocket.cpp'; fi` + +CRC_DabMux-InetAddress.o: InetAddress.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT CRC_DabMux-InetAddress.o -MD -MP -MF $(DEPDIR)/CRC_DabMux-InetAddress.Tpo -c -o CRC_DabMux-InetAddress.o `test -f 'InetAddress.cpp' || echo '$(srcdir)/'`InetAddress.cpp +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/CRC_DabMux-InetAddress.Tpo $(DEPDIR)/CRC_DabMux-InetAddress.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='InetAddress.cpp' object='CRC_DabMux-InetAddress.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o CRC_DabMux-InetAddress.o `test -f 'InetAddress.cpp' || echo '$(srcdir)/'`InetAddress.cpp + +CRC_DabMux-InetAddress.obj: InetAddress.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT CRC_DabMux-InetAddress.obj -MD -MP -MF $(DEPDIR)/CRC_DabMux-InetAddress.Tpo -c -o CRC_DabMux-InetAddress.obj `if test -f 'InetAddress.cpp'; then $(CYGPATH_W) 'InetAddress.cpp'; else $(CYGPATH_W) '$(srcdir)/InetAddress.cpp'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/CRC_DabMux-InetAddress.Tpo $(DEPDIR)/CRC_DabMux-InetAddress.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='InetAddress.cpp' object='CRC_DabMux-InetAddress.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o CRC_DabMux-InetAddress.obj `if test -f 'InetAddress.cpp'; then $(CYGPATH_W) 'InetAddress.cpp'; else $(CYGPATH_W) '$(srcdir)/InetAddress.cpp'; fi` + +CRC_DabMux-dabUtils.o: dabUtils.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT CRC_DabMux-dabUtils.o -MD -MP -MF $(DEPDIR)/CRC_DabMux-dabUtils.Tpo -c -o CRC_DabMux-dabUtils.o `test -f 'dabUtils.cpp' || echo '$(srcdir)/'`dabUtils.cpp +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/CRC_DabMux-dabUtils.Tpo $(DEPDIR)/CRC_DabMux-dabUtils.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='dabUtils.cpp' object='CRC_DabMux-dabUtils.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o CRC_DabMux-dabUtils.o `test -f 'dabUtils.cpp' || echo '$(srcdir)/'`dabUtils.cpp + +CRC_DabMux-dabUtils.obj: dabUtils.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT CRC_DabMux-dabUtils.obj -MD -MP -MF $(DEPDIR)/CRC_DabMux-dabUtils.Tpo -c -o CRC_DabMux-dabUtils.obj `if test -f 'dabUtils.cpp'; then $(CYGPATH_W) 'dabUtils.cpp'; else $(CYGPATH_W) '$(srcdir)/dabUtils.cpp'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/CRC_DabMux-dabUtils.Tpo $(DEPDIR)/CRC_DabMux-dabUtils.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='dabUtils.cpp' object='CRC_DabMux-dabUtils.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o CRC_DabMux-dabUtils.obj `if test -f 'dabUtils.cpp'; then $(CYGPATH_W) 'dabUtils.cpp'; else $(CYGPATH_W) '$(srcdir)/dabUtils.cpp'; fi` + +CRC_DabMux-Dmb.o: Dmb.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT CRC_DabMux-Dmb.o -MD -MP -MF $(DEPDIR)/CRC_DabMux-Dmb.Tpo -c -o CRC_DabMux-Dmb.o `test -f 'Dmb.cpp' || echo '$(srcdir)/'`Dmb.cpp +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/CRC_DabMux-Dmb.Tpo $(DEPDIR)/CRC_DabMux-Dmb.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='Dmb.cpp' object='CRC_DabMux-Dmb.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o CRC_DabMux-Dmb.o `test -f 'Dmb.cpp' || echo '$(srcdir)/'`Dmb.cpp + +CRC_DabMux-Dmb.obj: Dmb.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT CRC_DabMux-Dmb.obj -MD -MP -MF $(DEPDIR)/CRC_DabMux-Dmb.Tpo -c -o CRC_DabMux-Dmb.obj `if test -f 'Dmb.cpp'; then $(CYGPATH_W) 'Dmb.cpp'; else $(CYGPATH_W) '$(srcdir)/Dmb.cpp'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/CRC_DabMux-Dmb.Tpo $(DEPDIR)/CRC_DabMux-Dmb.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='Dmb.cpp' object='CRC_DabMux-Dmb.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o CRC_DabMux-Dmb.obj `if test -f 'Dmb.cpp'; then $(CYGPATH_W) 'Dmb.cpp'; else $(CYGPATH_W) '$(srcdir)/Dmb.cpp'; fi` + +CRC_DabMux-Interleaver.o: Interleaver.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT CRC_DabMux-Interleaver.o -MD -MP -MF $(DEPDIR)/CRC_DabMux-Interleaver.Tpo -c -o CRC_DabMux-Interleaver.o `test -f 'Interleaver.cpp' || echo '$(srcdir)/'`Interleaver.cpp +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/CRC_DabMux-Interleaver.Tpo $(DEPDIR)/CRC_DabMux-Interleaver.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='Interleaver.cpp' object='CRC_DabMux-Interleaver.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o CRC_DabMux-Interleaver.o `test -f 'Interleaver.cpp' || echo '$(srcdir)/'`Interleaver.cpp + +CRC_DabMux-Interleaver.obj: Interleaver.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT CRC_DabMux-Interleaver.obj -MD -MP -MF $(DEPDIR)/CRC_DabMux-Interleaver.Tpo -c -o CRC_DabMux-Interleaver.obj `if test -f 'Interleaver.cpp'; then $(CYGPATH_W) 'Interleaver.cpp'; else $(CYGPATH_W) '$(srcdir)/Interleaver.cpp'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/CRC_DabMux-Interleaver.Tpo $(DEPDIR)/CRC_DabMux-Interleaver.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='Interleaver.cpp' object='CRC_DabMux-Interleaver.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o CRC_DabMux-Interleaver.obj `if test -f 'Interleaver.cpp'; then $(CYGPATH_W) 'Interleaver.cpp'; else $(CYGPATH_W) '$(srcdir)/Interleaver.cpp'; fi` + +CRC_DabMux-ReedSolomon.o: ReedSolomon.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT CRC_DabMux-ReedSolomon.o -MD -MP -MF $(DEPDIR)/CRC_DabMux-ReedSolomon.Tpo -c -o CRC_DabMux-ReedSolomon.o `test -f 'ReedSolomon.cpp' || echo '$(srcdir)/'`ReedSolomon.cpp +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/CRC_DabMux-ReedSolomon.Tpo $(DEPDIR)/CRC_DabMux-ReedSolomon.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='ReedSolomon.cpp' object='CRC_DabMux-ReedSolomon.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o CRC_DabMux-ReedSolomon.o `test -f 'ReedSolomon.cpp' || echo '$(srcdir)/'`ReedSolomon.cpp + +CRC_DabMux-ReedSolomon.obj: ReedSolomon.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT CRC_DabMux-ReedSolomon.obj -MD -MP -MF $(DEPDIR)/CRC_DabMux-ReedSolomon.Tpo -c -o CRC_DabMux-ReedSolomon.obj `if test -f 'ReedSolomon.cpp'; then $(CYGPATH_W) 'ReedSolomon.cpp'; else $(CYGPATH_W) '$(srcdir)/ReedSolomon.cpp'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/CRC_DabMux-ReedSolomon.Tpo $(DEPDIR)/CRC_DabMux-ReedSolomon.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='ReedSolomon.cpp' object='CRC_DabMux-ReedSolomon.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o CRC_DabMux-ReedSolomon.obj `if test -f 'ReedSolomon.cpp'; then $(CYGPATH_W) 'ReedSolomon.cpp'; else $(CYGPATH_W) '$(srcdir)/ReedSolomon.cpp'; fi` + +CRC_DabMux-TcpServer.o: TcpServer.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT CRC_DabMux-TcpServer.o -MD -MP -MF $(DEPDIR)/CRC_DabMux-TcpServer.Tpo -c -o CRC_DabMux-TcpServer.o `test -f 'TcpServer.cpp' || echo '$(srcdir)/'`TcpServer.cpp +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/CRC_DabMux-TcpServer.Tpo $(DEPDIR)/CRC_DabMux-TcpServer.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='TcpServer.cpp' object='CRC_DabMux-TcpServer.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o CRC_DabMux-TcpServer.o `test -f 'TcpServer.cpp' || echo '$(srcdir)/'`TcpServer.cpp + +CRC_DabMux-TcpServer.obj: TcpServer.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT CRC_DabMux-TcpServer.obj -MD -MP -MF $(DEPDIR)/CRC_DabMux-TcpServer.Tpo -c -o CRC_DabMux-TcpServer.obj `if test -f 'TcpServer.cpp'; then $(CYGPATH_W) 'TcpServer.cpp'; else $(CYGPATH_W) '$(srcdir)/TcpServer.cpp'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/CRC_DabMux-TcpServer.Tpo $(DEPDIR)/CRC_DabMux-TcpServer.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='TcpServer.cpp' object='CRC_DabMux-TcpServer.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o CRC_DabMux-TcpServer.obj `if test -f 'TcpServer.cpp'; then $(CYGPATH_W) 'TcpServer.cpp'; else $(CYGPATH_W) '$(srcdir)/TcpServer.cpp'; fi` + +CRC_DabMux-TcpSocket.o: TcpSocket.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT CRC_DabMux-TcpSocket.o -MD -MP -MF $(DEPDIR)/CRC_DabMux-TcpSocket.Tpo -c -o CRC_DabMux-TcpSocket.o `test -f 'TcpSocket.cpp' || echo '$(srcdir)/'`TcpSocket.cpp +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/CRC_DabMux-TcpSocket.Tpo $(DEPDIR)/CRC_DabMux-TcpSocket.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='TcpSocket.cpp' object='CRC_DabMux-TcpSocket.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o CRC_DabMux-TcpSocket.o `test -f 'TcpSocket.cpp' || echo '$(srcdir)/'`TcpSocket.cpp + +CRC_DabMux-TcpSocket.obj: TcpSocket.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT CRC_DabMux-TcpSocket.obj -MD -MP -MF $(DEPDIR)/CRC_DabMux-TcpSocket.Tpo -c -o CRC_DabMux-TcpSocket.obj `if test -f 'TcpSocket.cpp'; then $(CYGPATH_W) 'TcpSocket.cpp'; else $(CYGPATH_W) '$(srcdir)/TcpSocket.cpp'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/CRC_DabMux-TcpSocket.Tpo $(DEPDIR)/CRC_DabMux-TcpSocket.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='TcpSocket.cpp' object='CRC_DabMux-TcpSocket.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CRC_DabMux_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o CRC_DabMux-TcpSocket.obj `if test -f 'TcpSocket.cpp'; then $(CYGPATH_W) 'TcpSocket.cpp'; else $(CYGPATH_W) '$(srcdir)/TcpSocket.cpp'; fi` + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) +installdirs: + for dir in "$(DESTDIR)$(bindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-binPROGRAMS clean-generic mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-binPROGRAMS + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-binPROGRAMS + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \ + clean-generic ctags distclean distclean-compile \ + distclean-generic distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-binPROGRAMS \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \ + uninstall-am uninstall-binPROGRAMS + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/PcDebug.h b/src/PcDebug.h new file mode 100644 index 0000000..4e966d3 --- /dev/null +++ b/src/PcDebug.h @@ -0,0 +1,76 @@ +/* + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Her Majesty the + Queen in Right of Canada (Communications Research Center Canada) + */ +/* + This file is part of CRC-DabMux. + + CRC-DabMux is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + CRC-DabMux is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CRC-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef PC_DEBUG_ +#define PC_DEBUG_ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <stdio.h> + +#define LOG stderr + +#if !defined(_WIN32) || defined(__MINGW32__) +# ifndef PDEBUG +# ifdef DEBUG +# define PDEBUG(fmt, args...) fprintf (LOG, fmt , ## args) +# else +# define PDEBUG(fmt, args...) +# endif +# endif +# ifdef DEBUG +# define PDEBUG_VERBOSE(level, verbosity, fmt, args...) if (level <= verbosity) { fprintf(LOG, fmt, ## args); fflush(LOG); } +# define PDEBUG0_VERBOSE(level, verbosity, txt) if (level <= verbosity) { fprintf(LOG, txt); fflush(LOG); } +# define PDEBUG1_VERBOSE(level, verbosity, txt, arg0) if (level <= verbosity) { fprintf(LOG, txt, arg0); fflush(LOG); } +# define PDEBUG2_VERBOSE(level, verbosity, txt, arg0, arg1) if (level <= verbosity) { fprintf(LOG, txt, arg0, arg1); fflush(LOG); } +# define PDEBUG3_VERBOSE(level, verbosity, txt, arg0, arg1, arg2) if (level <= verbosity) { fprintf(LOG, txt, arg0, arg1, arg2); fflush(LOG); } +# define PDEBUG4_VERBOSE(level, verbosity, txt, arg0, arg1, arg2, arg3) if (level <= verbosity) { fprintf(LOG, txt, arg0, arg1, arg2, arg3); fflush(LOG); } +# else +# define PDEBUG_VERBOSE(level, verbosity, fmt, args...) +# define PDEBUG0_VERBOSE(level, verbosity, txt) +# define PDEBUG1_VERBOSE(level, verbosity, txt, arg0) +# define PDEBUG2_VERBOSE(level, verbosity, txt, arg0, arg1) +# define PDEBUG3_VERBOSE(level, verbosity, txt, arg0, arg1, arg2) +# define PDEBUG4_VERBOSE(level, verbosity, txt, arg0, arg1, arg2, arg3) +# endif // DEBUG +#else // _WIN32 +# ifdef _DEBUG +# define PDEBUG +# define PDEBUG_VERBOSE +# define PDEBUG0_VERBOSE(level, verbosity, txt) if (level <= verbosity) { fprintf(LOG, txt); fflush(LOG); } +# define PDEBUG1_VERBOSE(level, verbosity, txt, arg0) if (level <= verbosity) { fprintf(LOG, txt, arg0); fflush(LOG); } +# define PDEBUG2_VERBOSE(level, verbosity, txt, arg0, arg1) if (level <= verbosity) { fprintf(LOG, txt, arg0, arg1); fflush(LOG); } +# define PDEBUG3_VERBOSE(level, verbosity, txt, arg0, arg1, arg2) if (level <= verbosity) { fprintf(LOG, txt, arg0, arg1, arg2); fflush(LOG); } +# define PDEBUG4_VERBOSE(level, verbosity, txt, arg0, arg1, arg2, arg3) if (level <= verbosity) { fprintf(LOG, txt, arg0, arg1, arg2, arg3); fflush(LOG); } +# else +# define PDEBUG +# define PDEBUG_VERBOSE +# define PDEBUG0_VERBOSE(level, verbosity, txt) +# define PDEBUG1_VERBOSE(level, verbosity, txt, arg0) +# define PDEBUG2_VERBOSE(level, verbosity, txt, arg0, arg1) +# define PDEBUG3_VERBOSE(level, verbosity, txt, arg0, arg1, arg2) +# define PDEBUG4_VERBOSE(level, verbosity, txt, arg0, arg1, arg2, arg3) +# endif +#endif + +#endif // PC_DEBUG_ diff --git a/src/ReedSolomon.cpp b/src/ReedSolomon.cpp new file mode 100644 index 0000000..31d5021 --- /dev/null +++ b/src/ReedSolomon.cpp @@ -0,0 +1,105 @@ +/* + Copyright (C) 2005, 2006, 2007, 2008, 2009 Her Majesty the Queen in Right + of Canada (Communications Research Center Canada) + */ +/* + This file is part of CRC-DabMux. + + CRC-DabMux is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + CRC-DabMux is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CRC-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "ReedSolomon.h" +#include <stdio.h> // For galois.h ... +#include <string.h> // For memcpy + +extern "C" { +#include <fec.h> +} +#include <assert.h> +#include <stdlib.h> + +#define SYMSIZE 8 + + +ReedSolomon::ReedSolomon(int N, int K, bool reverse, int gfpoly, int firstRoot, int primElem) +{ + setReverse(reverse); + + myN = N; + myK = K; + + int symsize = SYMSIZE; + int nroots = N - K; + int pad = ((1 << symsize) - 1) - N; + + rsData = init_rs_char(symsize, gfpoly, firstRoot, primElem, nroots, pad); + + if (rsData == NULL) { + fprintf(stderr, "ERROR: Invalid Reed Solomon parameters!\n"); + abort(); + } +} + + +ReedSolomon::~ReedSolomon() +{ + free_rs_char(rsData); +} + + +void ReedSolomon::setReverse(bool state) +{ + reverse = state; +} + + +int ReedSolomon::encode(void* data, void* fec, unsigned long size) +{ + unsigned char* input = reinterpret_cast<unsigned char*>(data); + unsigned char* output = reinterpret_cast<unsigned char*>(fec); + int ret = 0; + + if (reverse) { + unsigned char* buffer = new unsigned char[myN]; + memcpy(buffer, input, myK); + memcpy(&buffer[myK], output, myN - myK); + + ret = decode_rs_char(rsData, buffer, NULL, 0); + if ((ret != 0) && (ret != -1)) { + memcpy(input, buffer, myK); + memcpy(output, &buffer[myK], myN - myK); + } + + delete[] buffer; + } else { + encode_rs_char(rsData, input, output); + } + + return ret; +} + + +int ReedSolomon::encode(void* data, unsigned long size) +{ + unsigned char* input = reinterpret_cast<unsigned char*>(data); + int ret = 0; + + if (reverse) { + ret = decode_rs_char(rsData, input, NULL, 0); + } else { + encode_rs_char(rsData, input, &input[188]); + } + + return ret; +} diff --git a/src/ReedSolomon.h b/src/ReedSolomon.h new file mode 100644 index 0000000..2a94542 --- /dev/null +++ b/src/ReedSolomon.h @@ -0,0 +1,52 @@ +/* + Copyright (C) 2005, 2006, 2007, 2008, 2009 Her Majesty the Queen in Right + of Canada (Communications Research Center Canada) + */ +/* + This file is part of CRC-DabMux. + + CRC-DabMux is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + CRC-DabMux is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CRC-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _REEDSOLOMON +#define _REEDSOLOMON + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + + +class ReedSolomon +{ +public: + ReedSolomon(int N, int K, bool reverse = false, + int gfpoly = 0x11d, int firstRoot = 0, int primElem = 1); + ReedSolomon(const ReedSolomon& clone); + virtual ~ReedSolomon(); + + void setReverse(bool state); + int encode(void* data, void* fec, unsigned long size); + int encode(void* data, unsigned long size); + +protected: + int myN; + int myK; + +private: + void* rsData; + bool reverse; +}; + + +#endif // _REEDSOLOMON diff --git a/src/TcpLog.cpp b/src/TcpLog.cpp new file mode 100644 index 0000000..7161c92 --- /dev/null +++ b/src/TcpLog.cpp @@ -0,0 +1,330 @@ +/* + Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Her Majesty the Queen in + Right of Canada (Communications Research Center Canada) + */ +/* + This file is part of CRC-DabMux. + + CRC-DabMux is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + CRC-DabMux is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CRC-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "TcpLog.h" +#include "InetAddress.h" +#include <string.h> +#include <stdlib.h> +#include <stdio.h> +#include <stdarg.h> + +#ifdef _WIN32 +# include <io.h> +# +# define vsnprintf _vsnprintf +# define MSG_NOSIGNAL 0 +# define socklen_t int +#else +# include <sys/socket.h> +# include <netinet/in.h> +# include <arpa/inet.h> +# include <unistd.h> +#endif + +#include <sstream> + + +const int TcpLog::EMERG = 0; // system is unusable +const int TcpLog::ALERT = 1; // action must be taken immediately +const int TcpLog::CRIT = 2; // critical conditions +const int TcpLog::ERR = 3; // error conditions +const int TcpLog::WARNING = 4; // warning conditions +const int TcpLog::NOTICE = 5; // normal but significant condition +const int TcpLog::INFO = 6; // informational +const int TcpLog::DBG = 7; // debug-level messages + + +TcpLog::TcpLog() : listenPort(0), client(-1), name(NULL), serverThread(0), running(false) +{ + buffer = (char*)malloc(512); + bufferSize = 512; + headers = (char**)malloc(sizeof(char**)); + headers[0] = NULL; +} + + +TcpLog::~TcpLog() +{ + if (running) { + running = false; + } + if (client != -1) { + ::close(client); + } + if (headers != NULL) { + for (int count = 0; headers[count] != NULL; ++count) { + free(headers[count]); + } + free(headers); + } +} + + +//TcpLog::TcpLog(int port); + + +void TcpLog::open(const char *ident, const int option, const int port) +{ + listenPort = port; + + if (name != NULL) { + free(name); + } + name = strdup(ident); + + if (running) { + running = false; +#ifdef WIN32 + DWORD status; + for (int i = 0; i < 5; ++i) { + if (GetExitCodeThread(serverThread, &status)) { + break; + } + Sleep(100); + } + TerminateThread(serverThread, 1); +#else + pthread_join(serverThread, NULL); +#endif + } + running = true; +#ifdef _WIN32 + serverThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)listen, this, 0, NULL); + if (serverThread == NULL) { + fprintf(stderr, "Can't create TCP listen thread\n"); + } +#else + pthread_create(&serverThread, NULL, (void*(*)(void*))listen, this); +#endif +} + + +void TcpLog::printHeader(const int priority, const char *format, ...) +{ + static char last = '\n'; + std::string beginning; + std::string message; + int ret; + + + beginning = "<"; + beginning += '0' + (priority % 10); + beginning += "> "; + + va_list argp; + va_start(argp, format); + for (ret = vsnprintf(buffer, bufferSize, format, argp); + ret >= bufferSize || ret == -1; + ret = vsprintf(buffer, format, argp)) { + if (ret == -1) { + buffer = (char*)realloc(buffer, bufferSize * 2); + bufferSize *= 2; + } else { + buffer = (char*)realloc(buffer, ret + 1); + bufferSize = ret + 1; + } + } + va_end(argp); + + if (last == '\n') { + message += beginning; + } + message += buffer; + + last = buffer[ret - 1]; + + for (unsigned long pos = message.find('\n'); + pos != std::string::npos && ++pos != message.size(); + pos = message.find('\n', pos)) { + message.insert(pos, beginning); + } + + fprintf(stderr, message.c_str()); + if (client != -1) { + if (write(client, message.c_str(), message.size()) + != (int)message.size()) { + fprintf(stderr, "<6> Client closed\n"); + ::close(client); + client = -1; + } + } + + int count = 0; + while (headers[count++] != NULL) { + } + headers = (char**)realloc(headers, sizeof(char**) * (count + 1)); + headers[count - 1] = strdup(message.c_str()); + headers[count] = NULL; +} + + +void TcpLog::print(const int priority, const char *format, ...) +{ + static char last = '\n'; + std::string beginning; + std::string message; + int ret; + + + beginning = "<"; + beginning += '0' + (priority % 10); + beginning += "> "; + + va_list argp; + va_start(argp, format); + for (ret = vsnprintf(buffer, bufferSize, format, argp); + ret >= bufferSize || ret == -1; + ret = vsprintf(buffer, format, argp)) { + if (ret == -1) { + buffer = (char*)realloc(buffer, bufferSize * 2); + bufferSize *= 2; + } else { + buffer = (char*)realloc(buffer, ret + 1); + bufferSize = ret + 1; + } + } + va_end(argp); + + if (last == '\n') { + message += beginning; + } + message += buffer; + + last = buffer[ret - 1]; + + for (unsigned long pos = message.find('\n'); + pos != std::string::npos && ++pos != message.size(); + pos = message.find('\n', pos)) { + message.insert(pos, beginning); + } + + fprintf(stderr, message.c_str()); + if (client != -1) { + if (send(client, message.c_str(), message.size(), MSG_NOSIGNAL) + != (int)message.size()) { + fprintf(stderr, "<6> Client closed\n"); + ::close(client); + client = -1; + } + } +} + + +void TcpLog::close(void) +{ +} + + +void* TcpLog::listen(TcpLog* obj) +{ + int server; + struct sockaddr_in server_addr; + struct sockaddr_in client_addr; + socklen_t addrlen = sizeof(client_addr); + +#ifdef _WIN32 + WSADATA wsaData; + WORD wVersionRequested = wVersionRequested = MAKEWORD( 2, 2 ); + + int res = WSAStartup( wVersionRequested, &wsaData ); + if (res) { + fprintf(stderr, "Can't initialize winsock\n"); + ExitThread(1); + } +#endif + server = socket(PF_INET, SOCK_STREAM, 0); + if (server == INVALID_SOCKET) { +#ifdef _WIN32 + fprintf(stderr, "Can't create socket\n"); + ExitThread(1); +#else + perror("Can't create socket"); + pthread_exit(NULL); +#endif + } + + int reuse = 1; + if (setsockopt(server, SOL_SOCKET, SO_REUSEADDR, (char*)&reuse, sizeof(reuse)) + == -1) { + perror("Can't set socket reusable"); + } + + server_addr.sin_family = AF_INET; + server_addr.sin_port = htons(obj->listenPort); + server_addr.sin_addr.s_addr = INADDR_ANY; + + if (bind(server, (struct sockaddr*)&server_addr, sizeof(server_addr)) + == -1) { + perror("Can't bind socket"); + fprintf(stderr, " port: %i\n", obj->listenPort); +#ifdef _WIN32 + ExitThread(1); +#else + pthread_exit(NULL); +#endif + } + + if (::listen(server, 1) == -1) { + perror("Can't listen on socket"); +#ifdef _WIN32 + ExitThread(1); +#else + pthread_exit(NULL); +#endif + } + + while (obj->running) { + int client = accept(server, (struct sockaddr*)&client_addr, &addrlen); + if (client == INVALID_SOCKET) { +#ifdef _WIN32 + if (WSAGetLastError() != WSAEINTR) { + setInetError("Can't accept client"); + fprintf(stderr, "%s: %s\n", inetErrDesc, inetErrMsg); + ExitThread(1); + } +#else + perror("Can't accept client"); + pthread_exit(NULL); +#endif + } + obj->print(INFO, "%s:%d connected\n", + inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port)); + if (obj->client != -1) { + ::close(obj->client); + } + obj->client = client; + for (int i = 0; obj->headers[i] != NULL; ++i) { + send(client, obj->headers[i], strlen(obj->headers[i]), MSG_NOSIGNAL); + } + } + if (obj->client != -1) { + ::close(obj->client); + obj->client = -1; + } + ::close(server); + +#ifdef _WIN32 + ExitThread(1); +#else + pthread_exit(NULL); +#endif + return NULL; +} diff --git a/src/TcpLog.h b/src/TcpLog.h new file mode 100644 index 0000000..c9abd70 --- /dev/null +++ b/src/TcpLog.h @@ -0,0 +1,69 @@ +/* + Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Her Majesty the Queen in + Right of Canada (Communications Research Center Canada) + */ +/* + This file is part of CRC-DabMux. + + CRC-DabMux is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + CRC-DabMux is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CRC-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _TCP_LOG +#define _TCP_LOG + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifndef _WIN32 +# include <pthread.h> +#else +# include <winsock2.h> +# define pthread_t HANDLE +#endif + +class TcpLog { +public: + TcpLog(); + ~TcpLog(); + + void open(const char *ident, const int option, const int port); + void printHeader(const int priority, const char *format, ...); + void print(const int priority, const char *format, ...); + void close(void); + + const static int EMERG; // system is unusable + const static int ALERT; // action must be taken immediately + const static int CRIT; // critical conditions + const static int ERR; // error conditions + const static int WARNING; // warning conditions + const static int NOTICE; // normal but significant condition + const static int INFO; // informational + const static int DBG; // debug-level messages + +private: + static void* listen(TcpLog* obj); + + int listenPort; + int client; + char* name; + pthread_t serverThread; + bool running; + char* buffer; + int bufferSize; + char** headers; +}; + + +#endif // _TCP_LOG diff --git a/src/TcpServer.cpp b/src/TcpServer.cpp new file mode 100644 index 0000000..00a50e9 --- /dev/null +++ b/src/TcpServer.cpp @@ -0,0 +1,243 @@ +/* + Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Her Majesty the Queen in + Right of Canada (Communications Research Center Canada) + */ +/* + This file is part of CRC-DabMux. + + CRC-DabMux is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + CRC-DabMux is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CRC-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "TcpServer.h" +#include <iostream> +#include <stdio.h> +#include <errno.h> + +#ifdef _WIN32 +#else +# include <sys/socket.h> +#endif + +#ifdef TRACE_ON +# ifndef TRACE_CLASS +# define TRACE_CLASS(class, func) cout <<"-" <<(class) <<"\t(" <<this <<")::" <<(func) <<endl +# define TRACE_STATIC(class, func) cout <<"-" <<(class) <<"\t(static)::" <<(func) <<endl +# endif +#else +# ifndef TRACE_CLASS +# define TRACE_CLASS(class, func) +# define TRACE_STATIC(class, func) +# endif +#endif + + +/// Must be call once before doing any operation on sockets +int TcpServer::init() +{ +#ifdef _WIN32 + WSADATA wsaData; + WORD wVersionRequested = wVersionRequested = MAKEWORD( 2, 2 ); + + int res = WSAStartup( wVersionRequested, &wsaData ); + if (res) { + setInetError("Can't initialize winsock"); + return -1; + } +#endif + return 0; +} + + +/// Must be call once before leaving application +int TcpServer::clean() +{ +#ifdef _WIN32 + int res = WSACleanup(); + if (res) { + setInetError("Can't initialize winsock"); + return -1; + } +#endif + return 0; +} + + +/** + * Two step constructor. Create must be called prior to use this + * socket. + */ +TcpServer::TcpServer() : + listenSocket(INVALID_SOCKET) +{ + TRACE_CLASS("TcpServer", "TcpServer()"); +} + + +/** + * One step constructor. + * @param port The port number on which the socket will be bind + * @param name The IP address on which the socket will be bind. + * It is used to bind the socket on a specific interface if + * the computer have many NICs. + */ +TcpServer::TcpServer(int port, const char *name) : + listenSocket(INVALID_SOCKET) +{ + TRACE_CLASS("TcpServer", "TcpServer(int, char*)"); + create(port, name); +} + + +/** + * Two step initializer. This function must be called after the constructor + * without argument as been called. + * @param port The port number on which the socket will be bind + * @param name The IP address on which the socket will be bind. + * It is used to bind the socket on a specific interface if + * the computer have many NICs. + * @return 0 if ok + * -1 if error + */ +int TcpServer::create(int port, const char *name) +{ + TRACE_CLASS("TcpServer", "create(int, char*)"); + if (listenSocket != INVALID_SOCKET) + closesocket(listenSocket); + address.setAddress(name); + address.setPort(port); + if ((listenSocket = socket(PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) { + setInetError("Can't create socket"); + return -1; + } + reuseopt_t reuse = 1; + if (setsockopt(listenSocket, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) + == SOCKET_ERROR) { + setInetError("Can't reuse address"); + return -1; + } + if (bind(listenSocket, address.getAddress(), sizeof(sockaddr_in)) == SOCKET_ERROR) { + setInetError("Can't bind socket"); + closesocket(listenSocket); + listenSocket = INVALID_SOCKET; + return -1; + } + return 0; +} + + +/** + * Close the underlying socket. + * @return 0 if ok + * -1 if error + */ +int TcpServer::close() +{ + TRACE_CLASS("TcpServer", "close()"); + if (listenSocket != INVALID_SOCKET) { + int res = closesocket(listenSocket); + if (res != 0) { + setInetError("Can't close socket"); + return -1; + } + listenSocket = INVALID_SOCKET; + } + return 0; +} + + +/// Destructor +TcpServer::~TcpServer() +{ + TRACE_CLASS("TcpServer", "~TcpServer()"); + close(); +} + + +int TcpServer::listen() +{ + TRACE_CLASS("TcpServer", "listen()"); + if (::listen(listenSocket, 1) == SOCKET_ERROR) { + setInetError("Can't listen on socket"); + return -1; + } + return 0; +} + + +TcpSocket* TcpServer::accept() +{ + SOCKET socket; + TcpSocket* client = NULL; + InetAddress addr; + socklen_t addrLen = sizeof(sockaddr_in); + + socket = ::accept(listenSocket, addr.getAddress(), &addrLen); + if (socket == SOCKET_ERROR) { + setInetError("Can't accept connection on socket"); + } else { + client = new TcpSocket(); + client->setSocket(socket, addr); + } + return client; +} + +/* +WSAEINTR +WSAEBADF +WSAEACCES +WSAEFAULT +WSAEINVAL +WSAEMFILE +WSAEWOULDBLOCK +WSAEINPROGRESS +WSAEALREADY +WSAENOTSOCK +WSAEDESTADDRREQ +WSAEMSGSIZE +WSAEPROTOTYPE +WSAENOPROTOOPT +WSAEPROTONOSUPPORT +WSAESOCKTNOSUPPORT +WSAEOPNOTSUPP +WSAEPFNOSUPPORT +WSAEAFNOSUPPORT +WSAEADDRINUSE +WSAEADDRNOTAVAIL +WSAENETDOWN +WSAENETUNREACH +WSAENETRESET +WSAECONNABORTED +WSAECONNRESET +WSAENOBUFS +WSAEISCONN +WSAENOTCONN +WSAESHUTDOWN +WSAETOOMANYREFS +WSAETIMEDOUT +WSAECONNREFUSED +WSAELOOP +WSAENAMETOOLONG +WSAEHOSTDOWN +WSAEHOSTUNREACH +WSAENOTEMPTY +WSAEPROCLIM +WSAEUSERS +WSAEDQUOT +WSAESTALE +WSAEREMOTE +WSAEDISCON +WSASYSNOTREADY +WSAVERNOTSUPPORTED +WSANOTINITIALISED +*/ diff --git a/src/TcpServer.h b/src/TcpServer.h new file mode 100644 index 0000000..c4d9a4d --- /dev/null +++ b/src/TcpServer.h @@ -0,0 +1,84 @@ +/* + Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Her Majesty the Queen in + Right of Canada (Communications Research Center Canada) + */ +/* + This file is part of CRC-DabMux. + + CRC-DabMux is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + CRC-DabMux is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CRC-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _TCPSERVER +#define _TCPSERVER + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "InetAddress.h" +#ifdef _WIN32 +# include <winsock.h> +# define socklen_t int +# define reuseopt_t char +#else +# include <sys/socket.h> +# include <netinet/in.h> +# include <unistd.h> +# include <netdb.h> +# include <arpa/inet.h> +# include <pthread.h> +# define SOCKET int +# define INVALID_SOCKET -1 +# define SOCKET_ERROR -1 +# define reuseopt_t int +#endif +//#define INVALID_PORT -1 + +#include <iostream> +#include "TcpSocket.h" +//#include "SocketSelector.h" + +/** + * This class represents a socket for sending and receiving UDP packets. + * + * A UDP socket is the sending or receiving point for a packet delivery service. + * Each packet sent or received on a datagram socket is individually + * addressed and routed. Multiple packets sent from one machine to another may + * be routed differently, and may arrive in any order. + * @author Pascal Charest pascal.charest@crc.ca + */ +class TcpServer { + friend class SocketSelector; +public: + TcpServer(); + TcpServer(int port, const char *name = NULL); + ~TcpServer(); + + static int init(); + static int clean(); + + int create(int port, const char *name = NULL); + int close(); + int listen(); + TcpSocket* accept(); + + + protected: + /// The address on which the socket is binded. + InetAddress address; + /// The low-level socket used by system functions. + SOCKET listenSocket; +}; + +#endif // _TCPSERVER diff --git a/src/TcpSocket.cpp b/src/TcpSocket.cpp new file mode 100644 index 0000000..723d06b --- /dev/null +++ b/src/TcpSocket.cpp @@ -0,0 +1,366 @@ +/* + Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Her Majesty the Queen in + Right of Canada (Communications Research Center Canada) + */ +/* + This file is part of CRC-DabMux. + + CRC-DabMux is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + CRC-DabMux is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CRC-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "TcpSocket.h" +#include <iostream> +#include <stdio.h> +#include <errno.h> +#include <string.h> +#include <signal.h> + +#ifdef _WIN32 +#else +# include <unistd.h> +#endif + +#ifdef TRACE_ON +# ifndef TRACE_CLASS +# define TRACE_CLASS(class, func) cout <<"-" <<(class) <<"\t(" <<this <<")::" <<(func) <<endl +# define TRACE_STATIC(class, func) cout <<"-" <<(class) <<"\t(static)::" <<(func) <<endl +# endif +#else +# ifndef TRACE_CLASS +# define TRACE_CLASS(class, func) +# define TRACE_STATIC(class, func) +# endif +#endif + + +/// Must be call once before doing any operation on sockets +int TcpSocket::init() +{ +#ifdef _WIN32 + WSADATA wsaData; + WORD wVersionRequested = wVersionRequested = MAKEWORD( 2, 2 ); + + int res = WSAStartup( wVersionRequested, &wsaData ); + if (res) { + setInetError("Can't initialize winsock"); + return -1; + } +#endif + return 0; +} + + +/// Must be call once before leaving application +int TcpSocket::clean() +{ +#ifdef _WIN32 + int res = WSACleanup(); + if (res) { + setInetError("Can't initialize winsock"); + return -1; + } +#endif + return 0; +} + + +/** + * Two step constructor. Create must be called prior to use this + * socket. + */ +TcpSocket::TcpSocket() : + listenSocket(INVALID_SOCKET) +{ + TRACE_CLASS("TcpSocket", "TcpSocket()"); +} + + +/** + * One step constructor. + * @param port The port number on which the socket will be bind + * @param name The IP address on which the socket will be bind. + * It is used to bind the socket on a specific interface if + * the computer have many NICs. + */ +TcpSocket::TcpSocket(int port, char *name) : + listenSocket(INVALID_SOCKET) +{ + TRACE_CLASS("TcpSocket", "TcpSocket(int, char*)"); + create(port, name); +} + + +/** + * Close the underlying socket. + * @return 0 if ok + * -1 if error + */ +int TcpSocket::close() +{ + TRACE_CLASS("TcpSocket", "close()"); + if (listenSocket != INVALID_SOCKET) { + int res = closesocket(listenSocket); + if (res != 0) { + setInetError("Can't close socket"); + return -1; + } + listenSocket = INVALID_SOCKET; + } + return 0; +} + + +/** + * Two step initializer. This function must be called after the constructor + * without argument as been called. + * @param port The port number on which the socket will be bind + * @param name The IP address on which the socket will be bind. + * It is used to bind the socket on a specific interface if + * the computer have many NICs. + * @return 0 if ok + * -1 if error + */ +int TcpSocket::create(int port, char *name) +{ + TRACE_CLASS("TcpSocket", "create(int, char*)"); + if (listenSocket != INVALID_SOCKET) + closesocket(listenSocket); + address.setAddress(name); + address.setPort(port); + if ((listenSocket = socket(PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) { + setInetError("Can't create socket"); + return -1; + } + reuseopt_t reuse = 1; + if (setsockopt(listenSocket, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) + == SOCKET_ERROR) { + setInetError("Can't reuse address"); + return -1; + } + if (bind(listenSocket, address.getAddress(), sizeof(sockaddr_in)) == SOCKET_ERROR) { + setInetError("Can't bind socket"); + closesocket(listenSocket); + listenSocket = INVALID_SOCKET; + return -1; + } + return 0; +} + + +/// Destructor +TcpSocket::~TcpSocket() { + TRACE_CLASS("TcpSocket", "~TcpSocket()"); + close(); +} + + +/** + * Receive an telnet packet, i.e a TCP stream ending with carriage return. + * @param data The buffer that will receive data. + * @param size The buffer size. + * @return > 0 if ok, -1 (SOCKET_ERROR) if error + */ +int TcpSocket::telnetRead(void* data, int size) +{ + TRACE_CLASS("TcpSocket", "read(void*, size)"); + int ret; + + printf("selectCall\n"); + + printf("readread 1\n"); + char *line=GetLine(listenSocket); + ret=strlen(line); + printf("readread 2\n"); + if (ret <= size) + { + strcpy((char*)data, line); + } + else + { +// size_t n = size; + strcpy((char*)data, line); + ret = size; + } + printf("TELNET READ returned %d\n", ret); + return ret; +} + +/** + * Receive a TCP stream. + * @param data The buffer that will receive data. + * @param size The buffer size. + * @return > 0 if ok, -1 (SOCKET_ERROR) if error + */ +int TcpSocket::read(void* data, int size) +{ + TRACE_CLASS("TcpSocket", "read(void*, size)"); + + int ret = recv(listenSocket, (char*)data, size, 0); + if (ret == SOCKET_ERROR) { + setInetError("Can't receive TCP packet"); + return -1; + } + return ret; +} + + +#define MAX 512 +char* TcpSocket::GetLine(int fd) +{ + static char line[MAX]; + static char netread[MAX] = ""; + int n, len; + char *p; + + len = strlen(netread); + + /* look for \r\n in netread buffer */ + p = strstr(netread, "\r\n"); + if (p == NULL) { + /* fill buff - no \r\n found */ + //n = ::read(fd, (void*)(netread+len), (size_t)(MAX-len)); + n = recv(fd, (netread+len), MAX-len, 0); + if (n == SOCKET_ERROR) { + setInetError("Can't receive TCP packet"); + return NULL; + } + len += n; + netread[len] = '\0'; + if (n>0) + return GetLine(fd); + } + if (p!=NULL) + { + *p = '\0'; + strcpy(line, netread); + /* copy rest of buf down */ + memmove(netread, p+2, strlen(p+2)+1); + } + return line; +} + + +/** + * Send an TCP packet. + * @param data The buffer taht will be sent. + * @param size Number of bytes to send. + * return 0 if ok, -1 if error + */ +int TcpSocket::write(const void* data, int size) +{ +#ifdef DUMP + TRACE_CLASS("TcpSocket", "write(const void*, int)"); +#endif + + // ignore BROKENPIPE signal (we handle it instead) +// void* old_sigpipe = signal ( SIGPIPE, SIG_IGN ); + // try to send data + int ret = send(listenSocket, (char*)data, size, 0 /*MSG_NOSIGNAL*/ ); + // restore the BROKENPIPE handling +// signal ( SIGPIPE, (__sighandler_t)old_sigpipe ); + if (ret == SOCKET_ERROR) { + setInetError("Can't send TCP packet"); + return -1; + } + return ret; +} + + +int TcpSocket::setDestination(InetAddress &addr) +{ + address = addr; + int ret = connect(listenSocket, addr.getAddress(), sizeof(*addr.getAddress())); + // A etre verifier: code de retour differend entre Linux et Windows + return ret; +} + + +void TcpSocket::setSocket(SOCKET socket, InetAddress &addr) +{ + if (listenSocket != INVALID_SOCKET) + closesocket(listenSocket); + listenSocket = socket; + address = addr; +} + + +InetAddress TcpSocket::getAddress() +{ + return address; +} + + +int TcpSocket::PeekCount() +{ + int count; + char tempBuffer[3]; + int size=3; + + count = recv(listenSocket, tempBuffer, size, MSG_PEEK); + if (count == -1) + { + printf("ERROR WHEN PEEKING SOCKET\n"); + } + return count; +} + +/* +WSAEINTR +WSAEBADF +WSAEACCES +WSAEFAULT +WSAEINVAL +WSAEMFILE +WSAEWOULDBLOCK +WSAEINPROGRESS +WSAEALREADY +WSAENOTSOCK +WSAEDESTADDRREQ +WSAEMSGSIZE +WSAEPROTOTYPE +WSAENOPROTOOPT +WSAEPROTONOSUPPORT +WSAESOCKTNOSUPPORT +WSAEOPNOTSUPP +WSAEPFNOSUPPORT +WSAEAFNOSUPPORT +WSAEADDRINUSE +WSAEADDRNOTAVAIL +WSAENETDOWN +WSAENETUNREACH +WSAENETRESET +WSAECONNABORTED +WSAECONNRESET +WSAENOBUFS +WSAEISCONN +WSAENOTCONN +WSAESHUTDOWN +WSAETOOMANYREFS +WSAETIMEDOUT +WSAECONNREFUSED +WSAELOOP +WSAENAMETOOLONG +WSAEHOSTDOWN +WSAEHOSTUNREACH +WSAENOTEMPTY +WSAEPROCLIM +WSAEUSERS +WSAEDQUOT +WSAESTALE +WSAEREMOTE +WSAEDISCON +WSASYSNOTREADY +WSAVERNOTSUPPORTED +WSANOTINITIALISED +*/ diff --git a/src/TcpSocket.h b/src/TcpSocket.h new file mode 100644 index 0000000..7c92af0 --- /dev/null +++ b/src/TcpSocket.h @@ -0,0 +1,97 @@ +/* + Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Her Majesty the Queen in + Right of Canada (Communications Research Center Canada) + */ +/* + This file is part of CRC-DabMux. + + CRC-DabMux is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + CRC-DabMux is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CRC-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _TCPSOCKET +#define _TCPSOCKET + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "InetAddress.h" +#ifdef _WIN32 +# include <winsock.h> +# define socklen_t int +# define reuseopt_t char +#else +# include <sys/socket.h> +# include <netinet/in.h> +# include <unistd.h> +# include <netdb.h> +# include <arpa/inet.h> +# include <pthread.h> +# define SOCKET int +# define INVALID_SOCKET -1 +# define SOCKET_ERROR -1 +# define reuseopt_t int +#endif +//#define INVALID_PORT -1 + +//# include "SocketSelector.h" + +#include <iostream> + +/** + * This class represents a socket for sending and receiving UDP packets. + * + * A UDP socket is the sending or receiving point for a packet delivery service. + * Each packet sent or received on a datagram socket is individually + * addressed and routed. Multiple packets sent from one machine to another may + * be routed differently, and may arrive in any order. + * @author Pascal Charest pascal.charest@crc.ca + */ +class TcpSocket { + friend class SocketSelector; + public: + TcpSocket(); + TcpSocket(int port, char *name = NULL); + ~TcpSocket(); + + static int init(); + static int clean(); + + int create(int port = 0, char *name = NULL); + int close(); + + int write(const void* data, int size); + int read(void* data, int size); + int telnetRead(void* data, int size); + /** + * Connects the socket on a specific address. Only data from this address + * will be received. + * @param addr The address to connect the socket + * @warning Not implemented yet. + */ + int setDestination(InetAddress &addr); + InetAddress getAddress(); + void setSocket(SOCKET socket, InetAddress &addr); + char* GetLine(int fd); + + int PeekCount(); + + protected: + /// The address on which the socket is binded. + InetAddress address; + /// The low-level socket used by system functions. + SOCKET listenSocket; +}; + +#endif // _TCPSOCKET diff --git a/src/UdpSocket.cpp b/src/UdpSocket.cpp new file mode 100644 index 0000000..f3b2ca0 --- /dev/null +++ b/src/UdpSocket.cpp @@ -0,0 +1,455 @@ +/* + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Her Majesty the + Queen in Right of Canada (Communications Research Center Canada) + */ +/* + This file is part of CRC-DabMux. + + CRC-DabMux is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + CRC-DabMux is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CRC-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "UdpSocket.h" + +#include <iostream> +#include <stdio.h> +#include <errno.h> +#include <fcntl.h> +#include <string.h> + +#ifdef TRACE_ON +# ifndef TRACE_CLASS +# define TRACE_CLASS(class, func) cout <<"-" <<(class) <<"\t(" <<this <<")::" <<(func) <<endl +# define TRACE_STATIC(class, func) cout <<"-" <<(class) <<"\t(static)::" <<(func) <<endl +# endif +#else +# ifndef TRACE_CLASS +# define TRACE_CLASS(class, func) +# define TRACE_STATIC(class, func) +# endif +#endif + + +/// Must be call once before doing any operation on sockets +int UdpSocket::init() +{ +#ifdef _WIN32 + WSADATA wsaData; + WORD wVersionRequested = wVersionRequested = MAKEWORD( 2, 2 ); + + int res = WSAStartup( wVersionRequested, &wsaData ); + if (res) { + setInetError("Can't initialize winsock"); + return -1; + } +#endif + return 0; +} + + +/// Must be call once before leaving application +int UdpSocket::clean() +{ +#ifdef _WIN32 + int res = WSACleanup(); + if (res) { + setInetError("Can't initialize winsock"); + return -1; + } +#endif + return 0; +} + + +/** + * Two step constructor. Create must be called prior to use this + * socket. + */ +UdpSocket::UdpSocket() : + listenSocket(INVALID_SOCKET) +{ + TRACE_CLASS("UdpSocket", "UdpSocket()"); +} + + +/** + * One step constructor. + * @param port The port number on which the socket will be bind + * @param name The IP address on which the socket will be bind. + * It is used to bind the socket on a specific interface if + * the computer have many NICs. + */ +UdpSocket::UdpSocket(int port, char *name) : + listenSocket(INVALID_SOCKET) +{ + TRACE_CLASS("UdpSocket", "UdpSocket(int, char*)"); + create(port, name); +} + + +/** + * This functin set blocking mode. The socket can be blocking or not, + * depending of the parametre. By default, the socket is blocking. + * @param block If true, set the socket blocking, otherwise set non-blocking + * @return 0 if ok + * -1 if error + */ +int UdpSocket::setBlocking(bool block) +{ +#ifdef _WIN32 + unsigned long res = block ? 0 : 1; + if (ioctlsocket(listenSocket, FIONBIO, &res) != 0) { + setInetError("Can't change blocking state of socket"); + return -1; + } + return 0; +#else + int res; + if (block) + res = fcntl(listenSocket, F_SETFL, 0); + else + res = fcntl(listenSocket, F_SETFL, O_NONBLOCK); + if (res == SOCKET_ERROR) { + setInetError("Can't change blocking state of socket"); + return -1; + } + return 0; +#endif +} + + +/** + * Two step initializer. This function must be called after the constructor + * without argument as been called. + * @param port The port number on which the socket will be bind + * @param name The IP address on which the socket will be bind. + * It is used to bind the socket on a specific interface if + * the computer have many NICs. + * @return 0 if ok + * -1 if error + */ +int UdpSocket::create(int port, char *name) +{ + TRACE_CLASS("UdpSocket", "create(int, char*)"); + if (listenSocket != INVALID_SOCKET) + closesocket(listenSocket); + address.setAddress(name); + address.setPort(port); + if ((listenSocket = socket(PF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET) { + setInetError("Can't create socket"); + return -1; + } + reuseopt_t reuse = 1; + if (setsockopt(listenSocket, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) + == SOCKET_ERROR) { + setInetError("Can't reuse address"); + return -1; + } + if (bind(listenSocket, address.getAddress(), sizeof(sockaddr_in)) == SOCKET_ERROR) { + setInetError("Can't bind socket"); + closesocket(listenSocket); + listenSocket = INVALID_SOCKET; + return -1; + } + return 0; +} + + +/// Destructor +UdpSocket::~UdpSocket() { + TRACE_CLASS("UdpSocket", "~UdpSocket()"); + if (listenSocket != INVALID_SOCKET) + closesocket(listenSocket); +} + + +/** + * Receive an UDP packet. + * @param packet The packet that will receive data. The address will be set + * to the source address. + * @return 0 if ok, -1 if error + */ +int UdpSocket::receive(UdpPacket &packet) +{ + TRACE_CLASS("UdpSocket", "receive(UdpPacket)"); + socklen_t addrSize; + addrSize = sizeof(*packet.getAddress().getAddress()); + int ret = recvfrom(listenSocket, packet.getData(), packet.getSize() - packet.getOffset(), 0, + packet.getAddress().getAddress(), &addrSize); + if (ret == SOCKET_ERROR) { + packet.setLength(0); +#ifndef _WIN32 + if (errno == EAGAIN) + return 0; +#endif + setInetError("Can't receive UDP packet"); + return -1; + } + packet.setLength(ret); + if (ret == (long)packet.getSize()) { + packet.setSize(packet.getSize() << 1); + } + return 0; +} + + +/** + * Send an UDP packet. + * @param packet The UDP packet to be sent. It includes the data and the + * destination address + * return 0 if ok, -1 if error + */ +int UdpSocket::send(UdpPacket &packet) +{ +#ifdef DUMP + TRACE_CLASS("UdpSocket", "send(UdpPacket)"); +#endif + int ret = sendto(listenSocket, packet.getData(), packet.getLength(), 0, + packet.getAddress().getAddress(), sizeof(*packet.getAddress().getAddress())); + if (ret == SOCKET_ERROR +#ifndef _WIN32 + && errno != ECONNREFUSED +#endif + ) { + setInetError("Can't send UDP packet"); + return -1; + } + return 0; +} + + +/** + * Must be called to receive data on a multicast address. + * @param groupname The multica +st address to join. + * @return 0 if ok, -1 if error + */ +int UdpSocket::joinGroup(char* groupname) +{ + TRACE_CLASS("UdpSocket", "joinGroup(char*)"); +#ifdef _WIN32 + ip_mreq group; +#else + ip_mreqn group; +#endif + if ((group.imr_multiaddr.s_addr = inet_addr(groupname)) == INADDR_NONE) { + setInetError(groupname); + return -1; + } + if (!IN_MULTICAST(ntohl(group.imr_multiaddr.s_addr))) { + setInetError("Not a multicast address"); + return -1; + } +#ifdef _WIN32 + group.imr_interface.s_addr = 0; + if (setsockopt(listenSocket, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&group, sizeof(group)) + == SOCKET_ERROR) { + setInetError("Can't join multicast group"); + return -1; + } +#else + group.imr_address.s_addr = htons(INADDR_ANY);; + group.imr_ifindex = 0; + if (setsockopt(listenSocket, SOL_IP, IP_ADD_MEMBERSHIP, &group, sizeof(group)) + == SOCKET_ERROR) { + setInetError("Can't join multicast group"); + } +#endif + return 0; +} + + +/** + * Constructs an UDP packet. + * @param initSize The initial size of the data buffer + */ +UdpPacket::UdpPacket(unsigned int initSize) : + dataBuf(new char[initSize]), + length(0), + size(initSize), + offset(0) +{ + TRACE_CLASS("UdpPacket", "UdpPacket(unsigned int)"); + if (dataBuf == NULL) + size = 0; +} + + +/// Destructor +UdpPacket::~UdpPacket() +{ + TRACE_CLASS("UdpPacket", "~UdpPacket()"); + if (dataBuf != NULL) { + delete []dataBuf; + dataBuf = NULL; + } +} + + +/** + * Changes size of the data buffer size. \a Length + \a offset data will be copied + * in the new buffer. + * @warning The pointer to data will be changed + * @param newSize The new data buffer size + */ +void UdpPacket::setSize(unsigned newSize) +{ + TRACE_CLASS("UdpPacket", "setSize(unsigned)"); + char *tmp = new char[newSize]; + if (length > newSize) + length = newSize; + if (tmp) { + memcpy(tmp, dataBuf, length); + delete []dataBuf; + dataBuf = tmp; + size = newSize; + } +} + + +/** + * Give the pointer to data. It is ajusted with the \a offset. + * @warning This pointer change. when the \a size of the buffer and the \a offset change. + * @return The pointer + */ +char *UdpPacket::getData() +{ + return dataBuf + offset; +} + + +/** + * Add some data at the end of data buffer and adjust size. + * @param data Pointer to the data to add + * @param size Size in bytes of new data + */ +void UdpPacket::addData(void *data, unsigned size) +{ + if (length + size > this->size) { + setSize(this->size << 1); + } + memcpy(dataBuf + length, data, size); + length += size; +} + + +/** + * Returns the length of useful data. Data before the \a offset are ignored. + * @return The data length + */ +unsigned long UdpPacket::getLength() +{ + return length - offset; +} + + +/** + * Returns the size of the data buffer. + * @return The data buffer size + */ +unsigned long UdpPacket::getSize() +{ + return size; +} + + +/** + * Returns the offset value. + * @return The offset value + */ +unsigned long UdpPacket::getOffset() +{ + return offset; +} + + +/** + * Sets the data length value. Data before the \a offset are ignored. + * @param len The new length of data + */ +void UdpPacket::setLength(unsigned long len) +{ + length = len + offset; +} + + +/** + * Sets the data offset. Data length is ajusted to ignore data before the \a offset. + * @param val The new data offset. + */ +void UdpPacket::setOffset(unsigned long val) +{ + offset = val; + if (offset > length) + length = offset; +} + + +/** + * Returns the UDP address of the data. + * @return The UDP address + */ +InetAddress &UdpPacket::getAddress() +{ + return address; +} + +/* +WSAEINTR +WSAEBADF +WSAEACCES +WSAEFAULT +WSAEINVAL +WSAEMFILE +WSAEWOULDBLOCK +WSAEINPROGRESS +WSAEALREADY +WSAENOTSOCK +WSAEDESTADDRREQ +WSAEMSGSIZE +WSAEPROTOTYPE +WSAENOPROTOOPT +WSAEPROTONOSUPPORT +WSAESOCKTNOSUPPORT +WSAEOPNOTSUPP +WSAEPFNOSUPPORT +WSAEAFNOSUPPORT +WSAEADDRINUSE +WSAEADDRNOTAVAIL +WSAENETDOWN +WSAENETUNREACH +WSAENETRESET +WSAECONNABORTED +WSAECONNRESET +WSAENOBUFS +WSAEISCONN +WSAENOTCONN +WSAESHUTDOWN +WSAETOOMANYREFS +WSAETIMEDOUT +WSAECONNREFUSED +WSAELOOP +WSAENAMETOOLONG +WSAEHOSTDOWN +WSAEHOSTUNREACH +WSAENOTEMPTY +WSAEPROCLIM +WSAEUSERS +WSAEDQUOT +WSAESTALE +WSAEREMOTE +WSAEDISCON +WSASYSNOTREADY +WSAVERNOTSUPPORTED +WSANOTINITIALISED +*/ diff --git a/src/UdpSocket.h b/src/UdpSocket.h new file mode 100644 index 0000000..a500606 --- /dev/null +++ b/src/UdpSocket.h @@ -0,0 +1,126 @@ +/* + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Her Majesty the + Queen in Right of Canada (Communications Research Center Canada) + */ +/* + This file is part of CRC-DabMux. + + CRC-DabMux is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + CRC-DabMux is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CRC-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _UDPSOCKET +#define _UDPSOCKET + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "InetAddress.h" +#ifdef _WIN32 +# include <winsock.h> +# define socklen_t int +# define reuseopt_t char +#else +# include <sys/socket.h> +# include <netinet/in.h> +# include <unistd.h> +# include <netdb.h> +# include <arpa/inet.h> +# include <pthread.h> +# define SOCKET int +# define INVALID_SOCKET -1 +# define SOCKET_ERROR -1 +# define reuseopt_t int +#endif +//#define INVALID_PORT -1 + +#include <stdlib.h> +#include <iostream> +class UdpPacket; + + +/** + * This class represents a socket for sending and receiving UDP packets. + * + * A UDP socket is the sending or receiving point for a packet delivery service. + * Each packet sent or received on a datagram socket is individually + * addressed and routed. Multiple packets sent from one machine to another may + * be routed differently, and may arrive in any order. + * @author Pascal Charest pascal.charest@crc.ca + */ +class UdpSocket { + public: + UdpSocket(); + UdpSocket(int port, char *name = NULL); + ~UdpSocket(); + + static int init(); + static int clean(); + + int create(int port = 0, char *name = NULL); + + int send(UdpPacket &packet); + int receive(UdpPacket &packet); + int joinGroup(char* groupname); + /** + * Connects the socket on a specific address. Only data from this address + * will be received. + * @param addr The address to connect the socket + * @warning Not implemented yet. + */ + void connect(InetAddress &addr); + int setBlocking(bool block); + + protected: + /// The address on which the socket is binded. + InetAddress address; + /// The low-level socket used by system functions. + SOCKET listenSocket; +}; + +/** + * This class represents a UDP packet. + * + * UDP packets are used to implement a connectionless packet delivery service. + * Each message is routed from one machine to another based solely on + * information contained within that packet. Multiple packets sent from one + * machine to another might be routed differently, and might arrive in any order. + * @author Pascal Charest pascal.charest@crc.ca + */ +class UdpPacket { + public: + UdpPacket(unsigned int initSize = 1024); + // Not implemented + UdpPacket(const UdpPacket& packet); + ~UdpPacket(); + + char *getData(); + void addData(void *data, unsigned size); + unsigned long getLength(); + unsigned long getSize(); + unsigned long getOffset(); + void setLength(unsigned long len); + void setOffset(unsigned long val); + void setSize(unsigned newSize); + InetAddress &getAddress(); + // Not implemented + const UdpPacket &operator=(const UdpPacket&); + + private: + char *dataBuf; + unsigned long length, size, offset; + InetAddress address; +}; + +#endif // _UDPSOCKET diff --git a/src/bridge.c b/src/bridge.c new file mode 100644 index 0000000..5a9de23 --- /dev/null +++ b/src/bridge.c @@ -0,0 +1,515 @@ +/* + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Her Majesty the + Queen in Right of Canada (Communications Research Center Canada) + */ +/* + This file is part of CRC-DabMux. + + CRC-DabMux is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + CRC-DabMux is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CRC-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdio.h> +#ifdef _WIN32 +# include <winsock2.h> +#else +# include <netinet/in.h> +#endif // _WIN32 +#include <string.h> +#include "bridge.h" +#include "crc.h" + +#include <assert.h> +#include "PcDebug.h" + +#ifdef _WIN32 +# ifdef _DEBUG + int bridgeVerbosity = 0; +# endif +#else +# ifdef DEBUG + int bridgeVerbosity = 0; +# endif +#endif + +void printStats(struct bridgeInfo* info, FILE* out) +{ + struct bridgeStats stats = getStats(info); + fprintf(out, "frames : %lu\n", stats.frames); + fprintf(out, " valids : %lu\n", stats.valids); + fprintf(out, " invalids : %lu\n", stats.invalids); + fprintf(out, " bytes : %lu\n", stats.bytes); + fprintf(out, " packets : %lu\n", stats.packets); + fprintf(out, " errors : %lu\n", stats.errors); + fprintf(out, " missings : %lu\n", stats.missings); + fprintf(out, " dropped : %lu\n", stats.dropped); + fprintf(out, " crc : %lu\n", stats.crc); + fprintf(out, " overruns : %lu\n", stats.overruns); +} + + +void resetStats(struct bridgeInfo* info) +{ + memset(&info->stats, 0, sizeof(info->stats)); +} + + +struct bridgeStats getStats(struct bridgeInfo* info) +{ + return info->stats; +} + + +void bridgeInitInfo(struct bridgeInfo* info) +{ + memset(info, 0, sizeof(*info)); + info->transmitted = -8; +}; + + +int writePacket(void* dataIn, int sizeIn, void* dataOut, int sizeOut, + struct bridgeInfo* info) +{ + static struct bridgeHdr header = { 0 }; + + PDEBUG4_VERBOSE(1, bridgeVerbosity, "writePacket\n sizeIn: %i, sizeOut: %i, " + "offset: %i, transmitted: %i\n", + sizeIn, sizeOut, info->offset, info->transmitted); + + assert(info->transmitted < sizeIn); + + if ((info->offset == 0) && (sizeIn > 0)) { + ((unsigned short*)dataOut)[0] = 0xb486; + info->offset = 2; + } + if (sizeIn == 0) { + memset((unsigned char*)dataOut + info->offset, 0, sizeOut - info->offset); + info->offset = 0; + info->transmitted = -8; + PDEBUG1_VERBOSE(1, bridgeVerbosity, " return %i (sizeIn == 0)\n", + sizeOut); + return 0; + } + + while (info->offset < sizeOut) { + switch (info->transmitted) { + case (-8): + ((unsigned char*)dataOut)[info->offset++] = 0xcb; + ++info->transmitted; + break; + case (-7): + ((unsigned char*)dataOut)[info->offset++] = 0x28; + ++info->transmitted; + break; + case (-6): + header.size = htons((unsigned short)sizeIn); + header.crc = htons((unsigned short)(crc16(0xffff, &header, 4) ^ 0xffff)); + ((unsigned char*)dataOut)[info->offset++] = ((char*)&header)[0]; + ++info->transmitted; + break; + case (-5): + ((unsigned char*)dataOut)[info->offset++] = ((char*)&header)[1]; + ++info->transmitted; + break; + case (-4): + ((unsigned char*)dataOut)[info->offset++] = ((char*)&header)[2]; + ++info->transmitted; + break; + case (-3): + ((unsigned char*)dataOut)[info->offset++] = ((char*)&header)[3]; + ++info->transmitted; + break; + case (-2): + ((unsigned char*)dataOut)[info->offset++] = ((char*)&header)[4]; + ++info->transmitted; + break; + case (-1): + ((unsigned char*)dataOut)[info->offset++] = ((char*)&header)[5]; + ++info->transmitted; + header.seqNb = htons((unsigned short)(ntohs(header.seqNb) + 1)); + break; + default: + ((unsigned char*)dataOut)[info->offset++] = + ((unsigned char*)dataIn)[info->transmitted++]; + if (info->transmitted == sizeIn) { + PDEBUG2_VERBOSE(1, bridgeVerbosity, + " Packet done, %i bytes at offset %i\n", + info->transmitted, info->offset); + PDEBUG1_VERBOSE(1, bridgeVerbosity, + " return %i (sizeIn == transmitted)\n", info->offset); + info->transmitted = -8; + return info->offset; + } + } + } + + PDEBUG1_VERBOSE(1, bridgeVerbosity, " return %i (offset >= sizeOut)\n", + info->offset); + info->offset = 0; + return 0; +} + + +int getPacket(void* dataIn, int sizeIn, void* dataOut, int sizeOut, + struct bridgeInfo* info, char async) +{ + unsigned char* in = (unsigned char*)dataIn; + unsigned char* out = (unsigned char*)dataOut; + unsigned char ch; + unsigned short crc; + unsigned short diff; + + PDEBUG3_VERBOSE(1, bridgeVerbosity, + "getPacket\n pos\t%i\n state\t%i\n received\t%i\n", + info->pos, info->state, info->received); + + if (info->pos == 0) { + ++info->stats.frames; + if (((unsigned short*)dataIn)[0] != 0xb486) { + if (((unsigned short*)dataIn)[0] != 0) { + ++info->stats.invalids; + printf("WARNING: processing frame with invalid magic " + "number!\n"); + } else { + PDEBUG0_VERBOSE(1, bridgeVerbosity, + "getPacket: not a valid frame\n"); + return 0; + } + } else { + PDEBUG0_VERBOSE(2, bridgeVerbosity, "Valid frame\n"); + info->pos += 2; + ++info->stats.valids; + } + info->stats.bytes += sizeIn; + } + while (info->pos < sizeIn) { + ch = in[info->pos++]; + switch (info->state) { + case 0: // sync search + info->sync <<= 8; + info->sync |= ch; + if (info->sync == 0xcb28) { + PDEBUG0_VERBOSE(2, bridgeVerbosity, "Sync found\n"); + ++info->stats.packets; + info->received = 0; + info->state = 1; + } + if (info->sync == 0) { // Padding + info->pos = 0; + return 0; + } + break; + case 1: // header search + ((char*)&info->header)[info->received++] = ch; + if (info->received == sizeof(struct bridgeHdr)) { + PDEBUG0_VERBOSE(2, bridgeVerbosity, "Header found\n"); + out = (unsigned char*)dataOut; + info->received = 0; + info->state = 2; + crc = crc16(0xffff, &info->header, 4); + crc ^= 0xffff; + info->header.size = ntohs(info->header.size); + info->header.seqNb = ntohs(info->header.seqNb); + info->header.crc = ntohs(info->header.crc); + PDEBUG4_VERBOSE(2, bridgeVerbosity, + " size\t%i\n seq\t%i\n crc\t0x%.4x (0x%.4x)\n", + info->header.size, info->header.seqNb, + info->header.crc, crc); + if (crc != info->header.crc) { + PDEBUG0_VERBOSE(2, bridgeVerbosity, "CRC error\n"); + ++info->stats.errors; + ++info->stats.crc; + info->state = 0; + if (info->pos < sizeof(struct bridgeHdr) + 2 + 2) { + info->pos = 2; + } + } else { + if (!info->initSeq) { + info->lastSeq = info->header.seqNb; + info->initSeq = 1; + } else { + if (info->header.seqNb > info->lastSeq) { + diff = (info->header.seqNb - info->lastSeq) - 1; + } else { + diff = ((short)info->lastSeq - + (short)info->header.seqNb) - 1; + } + info->stats.errors += diff; + info->stats.missings += diff; + info->lastSeq = info->header.seqNb; + } + } + } + break; + case 2: // data + out[info->received++] = ch; + if (info->received == info->header.size) { + PDEBUG0_VERBOSE(2, bridgeVerbosity, "data found\n"); + info->state = 0; + return info->received; + } + if (info->received == sizeOut) { + PDEBUG1_VERBOSE(1, bridgeVerbosity, "To much data: %i\n", + info->received); + ++info->stats.errors; + ++info->stats.overruns; + info->sync = 0; + info->state = 0; + return -1; + } + break; + case 3: // Padding or sync + if (ch == 0) { // Padding + info->pos = 0; + return 0; + } + if (ch != 0xcb) { // error + info->sync = ch; + info->state = 0; + } else { + info->state = 4; + } + break; + case 4: // Low byte sync + if (ch != 28) { // error + info->sync <<= 8; + info->sync |= ch; + info->state = 0; + } else { + info->state = 2; + } + break; + } + } + info->pos = 0; + return 0; +} + + +void dump(void* data, int size, FILE* stream) +{ + int i; + fprintf(stream, "%i bytes\n", size); + for (i = 0; i < size; ++i) { + fprintf(stream, " 0x%.2x", ((unsigned char*)data)[i]); + if (i % 8 == 7) + fprintf(stream, "\n"); + } + fprintf(stream, "\n"); +} + + +#ifdef BRIDGE_TEST +#include <stdlib.h> + + +int test(const unsigned char* data) +{ + unsigned char bridgeSize = data[0]; + unsigned char nbInput = data[1]; + unsigned char nbBridge = 1; + struct bridgeInfo info; + + int i, j; + int index = 0; + int max = 0; + int nbBytes; + + unsigned char** inputData; + unsigned char** bridgeData; + unsigned char* outputData; + + inputData = malloc(nbInput * 4); + bridgeData = malloc(nbBridge * 4); + for (i = 0; i < nbInput; ++i) { + if (data[i + 2] > 0) + inputData[i] = malloc(data[i + 2]); + if (data[i + 2] > max) { + max = data[i + 2]; + } + for (j = 0; j < data[i + 2]; ++j) { + inputData[i][j] = index++; + } + } + bridgeData[0] = malloc(bridgeSize); + memset(bridgeData[0], 0, bridgeSize); + outputData = malloc(max); + bridgeInitInfo(&info); + + // Write packets + index = 0; + while (1) { + if (data[index + 2] == 0) { + if (++index == nbInput) + break; + } + while ((nbBytes = writePacket(inputData[index], data[index + 2], + bridgeData[nbBridge - 1], bridgeSize, &info)) + != 0) { + if (++index == nbInput) { + break; + } + } + if (index == nbInput) + break; + // TODO check null + bridgeData = realloc(bridgeData, (++nbBridge) * 4); + bridgeData[nbBridge - 1] = malloc(bridgeSize); + memset(bridgeData[nbBridge - 1], 0, bridgeSize); + } +// if (nbBytes != bridgeSize) { + writePacket(NULL, 0, bridgeData[nbBridge - 1], bridgeSize, &info); +// } + + // read packets + index = 0; + for (i = 0; i < nbBridge; ++i) { + while ((nbBytes = getPacket(bridgeData[i], bridgeSize, outputData, max, + &info, 0)) != 0) { + while (data[index + 2] == 0) { + ++index; + } + if (nbBytes != data[index + 2]) { + printf("FAILED\n"); + printf("Invalid size at bridge %i, data %i: %i != %i\n", + i, index, nbBytes, data[index + 2]); + for (i = 0; i < nbInput; ++i) { + printf("Input %i: ", i); + dump(inputData[i], data[i + 2], stdout); + } + for (i = 0; i < nbBridge; ++i) { + printf("Bridge %i: ", i); + dump(bridgeData[i], bridgeSize, stdout); + } + printf("Output %i: ", index); + dump(outputData, nbBytes, stdout); + return -1; + } + if (memcmp(outputData, inputData[index], data[index + 2]) != 0) { + printf("FAILED\n"); + printf("output != input\n"); + for (i = 0; i < nbInput; ++i) { + printf("Input %i: ", i); + dump(inputData[i], data[i + 2], stdout); + } + for (i = 0; i < nbBridge; ++i) { + printf("Bridge %i: ", i); + dump(bridgeData[i], bridgeSize, stdout); + } + printf("Output %i: ", index); + dump(outputData, nbBytes, stdout); + } + ++index; + } + } + + printf("SUCCESS\n"); + + for (i = 0; i < nbInput; ++i) { + if (data[i + 2] > 0) + free(inputData[i]); + } + free(inputData); + free(outputData); + for (i = 0; i < nbBridge; ++i) { + free(bridgeData[i]); + } + free(bridgeData); + + return -1; +} + + +int main(int argc, char* argv[]) +{ + int i; + // test: bridgesize, nbinput [, input1, input2, ... ] + const unsigned char complete[] = { 32, 1, 16 }; + const unsigned char split[] = { 32, 1, 48 }; + const unsigned char twice[] = {32, 2, 8, 4 }; + const unsigned char secondSplit[] = { 32, 2, 16, 16 }; + const unsigned char headerSplit[][4] = { + { 32, 2, 23, 16 }, + { 32, 2, 22, 16 }, + { 32, 2, 21, 16 }, + { 32, 2, 20, 16 }, + { 32, 2, 19, 16 }, + { 32, 2, 18, 16 }, + { 32, 2, 17, 16 } + }; + const unsigned char two[] = { 32, 3, 16, 0, 16 }; + const unsigned char doubleSplit[] = { 32, 2, 32, 32 }; + const unsigned char full[] = { 32, 2, 24, 12 }; + const unsigned char empty[] = { 32, 3, 0, 0, 5 }; + +#ifdef _WIN32 + #ifdef _DEBUG + bridgeVerbosity = argc - 1; + #endif // DEBUG +#else + #ifdef DEBUG + bridgeVerbosity = argc - 1; + #endif // DEBUG +#endif // _WIN32 + + printf("Complete: "); + test(complete); + // printStats(stdout); + fflush(stdout); + + printf("split: "); + test(split); + // printStats(stdout); + fflush(stdout); + + printf("twice: "); + test(twice); + // printStats(stdout); + fflush(stdout); + + printf("second split: "); + test(secondSplit); + // printStats(stdout); + fflush(stdout); + + for (i = 0; i < sizeof(headerSplit) / sizeof(headerSplit[0]); ++i) { + printf("headerSplit%i: ", i); + test(headerSplit[i]); + // printStats(stdout); + fflush(stdout); + } + + printf("two: "); + test(two); + // printStats(stdout); + fflush(stdout); + + printf("doubleSplit: "); + test(doubleSplit); + // printStats(stdout); + fflush(stdout); + + printf("full: "); + test(full); + // printStats(stdout); + fflush(stdout); + + printf("empty: "); + test(empty); + // printStats(stdout); + fflush(stdout); + + return 0; +} + +#endif // BRIDGE_TEST diff --git a/src/bridge.h b/src/bridge.h new file mode 100644 index 0000000..f7d3f41 --- /dev/null +++ b/src/bridge.h @@ -0,0 +1,112 @@ +/* + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Her Majesty the + Queen in Right of Canada (Communications Research Center Canada) + */ +/* + This file is part of CRC-DabMux. + + CRC-DabMux is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + CRC-DabMux is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CRC-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _BRIDGE +#define _BRIDGE + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <stdio.h> + + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef _WIN32 +# ifdef _DEBUG + extern int bridgeVerbosity; +# endif // _DEBUG +#else +# ifndef DEBUG +# ifndef NDEBUG +# define NDEBUG +# endif +# else + extern int bridgeVerbosity; +# endif // DEBUG +#endif // _WIN32 + +struct bridgeStats { + unsigned long frames; // Number of frames analyzed + unsigned long valids; // Nb of frames with a good magic number + unsigned long invalids; // Nb of frames with a good magic number + unsigned long bytes; // Nb of data bytes + unsigned long packets; // Nb of packets found + unsigned long errors; + unsigned long missings; + unsigned long dropped; + unsigned long crc; // Nb of crc errors + unsigned long overruns; // Nb of packet too big +}; + + +struct bridgeHdr { + unsigned short size; + unsigned short seqNb; + unsigned short crc; +}; + + +struct bridgeInfo { + // Tx + int transmitted; // Nb bytes written + int offset; // Offset of the next byte to write + // Rx + int received; + int pos; + int state; + unsigned short lastSeq; + unsigned short sync; + char initSeq; + // General + struct bridgeHdr header; + struct bridgeStats stats; +}; + + + +void dump(void* data, int size, FILE* stream); + +/* + * Example of usae: + * if (data.length == 0) + * read(data) + * while (writePacket() != 0) + * read(read) + * ... + */ +int writePacket(void* dataIn, int sizeIn, void* dataOut, int sizeOut, struct bridgeInfo* info); + +int getPacket(void* dataIn, int sizeIn, void* dataOut, int sizeOut, struct bridgeInfo* info, char async); + +void bridgeInitInfo(struct bridgeInfo* info); +struct bridgeStats getStats(struct bridgeInfo* info); +void resetStats(struct bridgeInfo* info); +void printStats(struct bridgeInfo* info, FILE* out); + +#ifdef __cplusplus +} +#endif + +#endif // _BRIDGE diff --git a/src/crc.c b/src/crc.c new file mode 100644 index 0000000..8dc9966 --- /dev/null +++ b/src/crc.c @@ -0,0 +1,266 @@ +/* + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Her Majesty the + Queen in Right of Canada (Communications Research Center Canada) + */ +/* + This file is part of CRC-DabMux. + + CRC-DabMux is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + CRC-DabMux is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CRC-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "crc.h" +#ifndef _WIN32 +# include <unistd.h> +# include <netinet/in.h> +#endif +#include <stdio.h> +#include <fcntl.h> + +//#define CCITT 0x1021 + +uint8_t crc8tab[256] = { + 0x00, 0x07, 0x0e, 0x09, 0x1c, 0x1b, 0x12, 0x15, + 0x38, 0x3f, 0x36, 0x31, 0x24, 0x23, 0x2a, 0x2d, + 0x70, 0x77, 0x7e, 0x79, 0x6c, 0x6b, 0x62, 0x65, + 0x48, 0x4f, 0x46, 0x41, 0x54, 0x53, 0x5a, 0x5d, + 0xe0, 0xe7, 0xee, 0xe9, 0xfc, 0xfb, 0xf2, 0xf5, + 0xd8, 0xdf, 0xd6, 0xd1, 0xc4, 0xc3, 0xca, 0xcd, + 0x90, 0x97, 0x9e, 0x99, 0x8c, 0x8b, 0x82, 0x85, + 0xa8, 0xaf, 0xa6, 0xa1, 0xb4, 0xb3, 0xba, 0xbd, + 0xc7, 0xc0, 0xc9, 0xce, 0xdb, 0xdc, 0xd5, 0xd2, + 0xff, 0xf8, 0xf1, 0xf6, 0xe3, 0xe4, 0xed, 0xea, + 0xb7, 0xb0, 0xb9, 0xbe, 0xab, 0xac, 0xa5, 0xa2, + 0x8f, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9d, 0x9a, + 0x27, 0x20, 0x29, 0x2e, 0x3b, 0x3c, 0x35, 0x32, + 0x1f, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0d, 0x0a, + 0x57, 0x50, 0x59, 0x5e, 0x4b, 0x4c, 0x45, 0x42, + 0x6f, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7d, 0x7a, + 0x89, 0x8e, 0x87, 0x80, 0x95, 0x92, 0x9b, 0x9c, + 0xb1, 0xb6, 0xbf, 0xb8, 0xad, 0xaa, 0xa3, 0xa4, + 0xf9, 0xfe, 0xf7, 0xf0, 0xe5, 0xe2, 0xeb, 0xec, + 0xc1, 0xc6, 0xcf, 0xc8, 0xdd, 0xda, 0xd3, 0xd4, + 0x69, 0x6e, 0x67, 0x60, 0x75, 0x72, 0x7b, 0x7c, + 0x51, 0x56, 0x5f, 0x58, 0x4d, 0x4a, 0x43, 0x44, + 0x19, 0x1e, 0x17, 0x10, 0x05, 0x02, 0x0b, 0x0c, + 0x21, 0x26, 0x2f, 0x28, 0x3d, 0x3a, 0x33, 0x34, + 0x4e, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5c, 0x5b, + 0x76, 0x71, 0x78, 0x7f, 0x6a, 0x6d, 0x64, 0x63, + 0x3e, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2c, 0x2b, + 0x06, 0x01, 0x08, 0x0f, 0x1a, 0x1d, 0x14, 0x13, + 0xae, 0xa9, 0xa0, 0xa7, 0xb2, 0xb5, 0xbc, 0xbb, + 0x96, 0x91, 0x98, 0x9f, 0x8a, 0x8d, 0x84, 0x83, + 0xde, 0xd9, 0xd0, 0xd7, 0xc2, 0xc5, 0xcc, 0xcb, + 0xe6, 0xe1, 0xe8, 0xef, 0xfa, 0xfd, 0xf4, 0xf3 +}; + + +uint16_t crc16tab[256] = { + 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, + 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, + 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, + 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, + 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, + 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, + 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, + 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, + 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, + 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, + 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, + 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, + 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, + 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, + 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, + 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, + 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, + 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, + 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, + 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, + 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, + 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, + 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, + 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, + 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, + 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, + 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, + 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, + 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, + 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, + 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, + 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0 +}; + + +uint32_t crc32tab[256] = { + 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, + 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005, + 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, + 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, + 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, + 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75, + 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, + 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd, + 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, + 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, + 0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81, + 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d, + 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, + 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95, + 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, + 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, + 0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae, + 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072, + 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, + 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca, + 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde, + 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, + 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066, + 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba, + 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, + 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692, + 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6, + 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, + 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e, + 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, + 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, + 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a, + 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637, + 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, + 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, + 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53, + 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, + 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b, + 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, + 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, + 0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, + 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b, + 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, + 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3, + 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, + 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, + 0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f, + 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3, + 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, + 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c, + 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8, + 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, + 0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30, + 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec, + 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, + 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654, + 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0, + 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, + 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18, + 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, + 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, + 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c, + 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668, + 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4 +}; + +// This function can be used to create a new table with a different polynom +void init_crc8tab(uint8_t l_code, uint8_t l_init) +{ + unsigned i, j, msb; + uint8_t nb; + uint8_t crc; + + for (i = 0; i < 256; ++i) { + crc = l_init; + nb = i ^ 0xff; + for (j = 0; j < 8; ++j) { + msb = (nb & (0x80 >> j)) && 1; + msb ^= (crc >> 7); + crc <<= 1; + if (msb) + crc ^= l_code; + } + crc8tab[i] = crc; + } +} + + +void init_crc16tab(uint16_t l_code, uint16_t l_init) +{ + unsigned i, j, msb; + uint8_t nb; + uint16_t crc; + + for (i = 0; i < 256; ++i) { + crc = l_init; + nb = i ^ 0xff; + for (j = 0; j < 8; ++j) { + msb = (nb & (0x80 >> j)) && 1; + msb ^= (crc >> 15); + crc <<= 1; + if (msb) + crc ^= l_code; + } + crc ^= 0xff00; + crc16tab[i] = crc; + } +} + + +void init_crc32tab(uint32_t l_code, uint32_t l_init) +{ + unsigned i, j, msb; + uint8_t nb; + uint32_t crc; + + for (i = 0; i < 256; ++i) { + crc = l_init; + nb = i ^ 0xff; + for (j = 0; j < 8; ++j) { + msb = (nb & (0x80 >> j)) && 1; + msb ^= (crc >> 31); + crc <<= 1; + if (msb) + crc ^= l_code; + } + crc ^= 0xffffff00; + crc32tab[i] = crc; + } +} + + +uint8_t crc8(uint8_t l_crc, const void *lp_data, unsigned l_nb) +{ + uint8_t* data = (uint8_t*)lp_data; + while (l_nb--) { + l_crc = crc8tab[l_crc ^ *(data++)]; + } + return (l_crc); +} + + +uint16_t crc16(uint16_t l_crc, const void *lp_data, unsigned l_nb) +{ + uint8_t* data = (uint8_t*)lp_data; + while (l_nb--) { + l_crc = + (l_crc << 8) ^ crc16tab[(l_crc >> 8) ^ *(data++)]; + } + return (l_crc); +} + + +uint32_t crc32(uint32_t l_crc, const void *lp_data, unsigned l_nb) +{ + uint8_t* data = (uint8_t*)lp_data; + while (l_nb--) { + l_crc = + (l_crc << 8) ^ crc32tab[((l_crc >> 24) ^ *(data++)) & 0xff]; + } + return (l_crc); +} diff --git a/src/crc.h b/src/crc.h new file mode 100644 index 0000000..f0da0f5 --- /dev/null +++ b/src/crc.h @@ -0,0 +1,59 @@ +/* + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Her Majesty the + Queen in Right of Canada (Communications Research Center Canada) + */ +/* + This file is part of CRC-DabMux. + + CRC-DabMux is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + CRC-DabMux is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CRC-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _CRC +#define _CRC + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifndef _WIN32 + #include <stdint.h> +#else + #include <winsock2.h> // For types... + typedef BYTE uint8_t; + typedef WORD uint16_t; + typedef DWORD32 uint32_t; +#endif + + +#ifdef __cplusplus +extern "C" { // } +#endif + +void init_crc8tab(uint8_t l_code, uint8_t l_init); +uint8_t crc8(uint8_t l_crc, const void *lp_data, unsigned l_nb); +extern uint8_t crc8tab[]; + +void init_crc16tab(uint16_t l_code, uint16_t l_init); +uint16_t crc16(uint16_t l_crc, const void *lp_data, unsigned l_nb); +extern uint16_t crc16tab[]; + +void init_crc32tab(uint32_t l_code, uint32_t l_init); +uint32_t crc32(uint32_t l_crc, const void *lp_data, unsigned l_nb); +extern uint32_t crc32tab[]; + +#ifdef __cplusplus +} +#endif + +#endif //_CRC diff --git a/src/dabInput.cpp b/src/dabInput.cpp new file mode 100644 index 0000000..e937008 --- /dev/null +++ b/src/dabInput.cpp @@ -0,0 +1,51 @@ +/* + Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Her Majesty the Queen in + Right of Canada (Communications Research Center Canada) + */ +/* + This file is part of CRC-DabMux. + + CRC-DabMux is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + CRC-DabMux is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CRC-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "dabInput.h" + +#include <string.h> + +TcpLog etiLog; + + +bool dabInputOperations::operator==(const dabInputOperations& ops) +{ + return memcmp(this, &ops, sizeof(*this)) == 0; +} + + +int dabInputSetbuf(void* args, int size) +{ + return 0; +} + + +int dabInputSetbitrate(dabInputOperations* ops, void* args, int bitrate) +{ + if (bitrate <= 0) { + etiLog.print(TcpLog::ERR, "Invalid bitrate (%i)\n", bitrate); + return -1; + } + if (ops->setbuf(args, bitrate * 3) == 0) { + return bitrate; + } + return -1; +} diff --git a/src/dabInput.h b/src/dabInput.h new file mode 100644 index 0000000..245a162 --- /dev/null +++ b/src/dabInput.h @@ -0,0 +1,52 @@ +/* + Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Her Majesty the Queen in + Right of Canada (Communications Research Center Canada) + */ +/* + This file is part of CRC-DabMux. + + CRC-DabMux is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + CRC-DabMux is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CRC-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef DAB_INPUT_H +#define DAB_INPUT_H + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#include "TcpLog.h" +extern TcpLog etiLog; + + +struct dabInputOperations { + int (*init)(void** args); + int (*open)(void* args, const char* name); + int (*setbuf)(void* args, int size); + int (*read)(void* args, void* buffer, int size); + int (*lock)(void* args); + int (*unlock)(void* args); + int (*readFrame)(dabInputOperations* ops, void* args, void* buffer, int size); + int (*setBitrate)(dabInputOperations* ops, void* args, int bitrate); + int (*close)(void* args); + int (*clean)(void** args); + int (*rewind)(void* args); + bool operator==(const dabInputOperations&); +}; + + +int dabInputSetbuf(void* args, int size); +int dabInputSetbitrate(dabInputOperations* ops, void* args, int bitrate); + + +#endif // DAB_INPUT_H diff --git a/src/dabInputBridgeUdp.cpp b/src/dabInputBridgeUdp.cpp new file mode 100644 index 0000000..a2ccf85 --- /dev/null +++ b/src/dabInputBridgeUdp.cpp @@ -0,0 +1,124 @@ +/* + Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications + Research Center Canada) + */ +/* + This file is part of CRC-DabMux. + + CRC-DabMux is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + CRC-DabMux is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CRC-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "dabInputBridgeUdp.h" +#include "dabInputUdp.h" +#include "bridge.h" + + +struct dabInputBridgeUdpData { + dabInputUdpData* udpData; + bridgeInfo* info; +}; + + +struct dabInputOperations dabInputBridgeUdpOperations = { + dabInputBridgeUdpInit, + dabInputBridgeUdpOpen, + dabInputSetbuf, + NULL, + NULL, + NULL, + dabInputBridgeUdpRead, + dabInputSetbitrate, + dabInputBridgeUdpClose, + dabInputBridgeUdpClean, + NULL +}; + + +int dabInputBridgeUdpInit(void** args) +{ + dabInputBridgeUdpData* input = new dabInputBridgeUdpData; + dabInputUdpInit((void**)&input->udpData); + input->info = new bridgeInfo; + bridgeInitInfo(input->info); + *args = input; + + return 0; +} + + +int dabInputBridgeUdpOpen(void* args, const char* inputName) +{ + dabInputBridgeUdpData* input = (dabInputBridgeUdpData*)args; + + return dabInputUdpOpen(input->udpData, inputName); +} + + +int dabInputBridgeUdpRead(dabInputOperations* ops, void* args, void* buffer, int size) +{ + int nbBytes = 0; + dabInputBridgeUdpData* input = (dabInputBridgeUdpData*)args; + dabInputFifoStats* stats = (dabInputFifoStats*)&input->udpData->stats; + + stats->frameRecords[stats->frameCount].curSize = 0; + stats->frameRecords[stats->frameCount].maxSize = size; + + if (input->udpData->packet->getLength() == 0) { + input->udpData->socket->receive(*input->udpData->packet); + } + while ((nbBytes = writePacket(input->udpData->packet->getData(), + input->udpData->packet->getLength(), buffer, size, + input->info)) + != 0) { + stats->frameRecords[stats->frameCount].curSize = nbBytes; + input->udpData->socket->receive(*input->udpData->packet); + } + + if (input->udpData->packet->getLength() != 0) { + stats->frameRecords[stats->frameCount].curSize = size; + } + + if (++stats->frameCount == NB_RECORDS) { + etiLog.print(TcpLog::INFO, "Data subchannel usage: (%i)", + stats->id); + for (int i = 0; i < stats->frameCount; ++i) { + etiLog.print(TcpLog::INFO, " %i/%i", + stats->frameRecords[i].curSize, + stats->frameRecords[i].maxSize); + } + etiLog.print(TcpLog::INFO, "\n"); + stats->frameCount = 0; + } + return size; +} + + +int dabInputBridgeUdpClose(void* args) +{ + dabInputBridgeUdpData* input = (dabInputBridgeUdpData*)args; + + return dabInputUdpClose(input->udpData); +} + + +int dabInputBridgeUdpClean(void** args) +{ + dabInputBridgeUdpData* input = (dabInputBridgeUdpData*)(*args); + dabInputUdpClean((void**)&input->udpData); + delete input->info; + delete input; + return 0; +} + + diff --git a/src/dabInputBridgeUdp.h b/src/dabInputBridgeUdp.h new file mode 100644 index 0000000..c75f838 --- /dev/null +++ b/src/dabInputBridgeUdp.h @@ -0,0 +1,49 @@ +/* + Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications + Research Center Canada) + */ +/* + This file is part of CRC-DabMux. + + CRC-DabMux is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + CRC-DabMux is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CRC-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef DAB_INPUT_BRIDGE_UDP_H +#define DAB_INPUT_BRIDGE_UDP_H + + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#include "dabInput.h" + + +#ifdef HAVE_FORMAT_BRIDGE +# ifdef HAVE_INPUT_UDP + + +extern struct dabInputOperations dabInputBridgeUdpOperations; + +int dabInputBridgeUdpInit(void** args); +int dabInputBridgeUdpOpen(void* args, const char* inputName); +int dabInputBridgeUdpRead(dabInputOperations* ops, void* args, void* buffer, int size); +int dabInputBridgeUdpClose(void* args); +int dabInputBridgeUdpClean(void** args); + + +# endif +#endif + + +#endif // DAB_INPUT_BRIDGE_UDP_H diff --git a/src/dabInputDabplusFifo.cpp b/src/dabInputDabplusFifo.cpp new file mode 100644 index 0000000..fdff5ad --- /dev/null +++ b/src/dabInputDabplusFifo.cpp @@ -0,0 +1,186 @@ +/* + Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications + Research Center Canada) + */ +/* + This file is part of CRC-DabMux. + + CRC-DabMux is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + CRC-DabMux is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CRC-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "dabInputDabplusFifo.h" +#include "dabInputDabplusFile.h" +#include "dabInputFifo.h" +#include "dabInput.h" + +#include <stdint.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <fcntl.h> + +#ifndef _WIN32 +# define O_BINARY 0 +#endif + + +#ifdef HAVE_FORMAT_DABPLUS +# ifdef HAVE_INPUT_FILE + + +struct dabInputDabplusFifoData { + void* fifoData; + uint8_t* buffer; + size_t bufferSize; + size_t bufferIndex; + size_t bufferOffset; +}; + + +struct dabInputOperations dabInputDabplusFifoOperations = { + dabInputDabplusFifoInit, + dabInputDabplusFifoOpen, + dabInputDabplusFifoSetbuf, + dabInputDabplusFifoRead, + dabInputDabplusFifoLock, + dabInputDabplusFifoUnlock, + dabInputDabplusFileReadFrame, + dabInputSetbitrate, + dabInputDabplusFifoClose, + dabInputDabplusFifoClean, + dabInputDabplusFifoRewind +}; + + +int dabInputDabplusFifoInit(void** args) +{ + dabInputDabplusFifoData* data = new dabInputDabplusFifoData; + + dabInputFifoInit(&data->fifoData); + data->buffer = NULL; + data->bufferSize = 0; + data->bufferIndex = 0; + data->bufferOffset = 0; + + *args = data; +} + + +int dabInputDabplusFifoOpen(void* args, const char* filename) +{ + dabInputDabplusFifoData* data = (dabInputDabplusFifoData*)args; + + return dabInputFifoOpen(data->fifoData, filename); +} + + +int dabInputDabplusFifoSetbuf(void* args, int size) +{ + dabInputDabplusFifoData* data = (dabInputDabplusFifoData*)args; + + return dabInputFifoSetbuf(data->fifoData, size); +} + + +int dabInputDabplusFifoRead(void* args, void* buffer, int size) +{ + dabInputDabplusFifoData* data = (dabInputDabplusFifoData*)args; + + if (data->bufferSize != size * 5) { + if (data->buffer != NULL) { + delete[] data->buffer; + } + data->buffer = new uint8_t[size * 5]; + data->bufferSize = size * 5; + data->bufferIndex = 0; + } + + if (data->bufferOffset < data->bufferSize) { + int ret = dabInputFifoRead(data->fifoData, + &data->buffer[data->bufferOffset], + data->bufferSize - data->bufferOffset); + if (ret < 0) { + return ret; + } + data->bufferOffset += ret; + if (data->bufferOffset != data->bufferSize) { + etiLog.print(TcpLog::CRIT, "ERROR: Incomplete DAB+ frame!\n"); + return 0; + } + } + + memcpy(buffer, &data->buffer[data->bufferIndex], size); + data->bufferIndex += size; + if (data->bufferIndex >= data->bufferSize) { + data->bufferIndex = 0; + data->bufferOffset = 0; + } + return size; +} + + +int dabInputDabplusFifoLock(void* args) +{ + dabInputDabplusFifoData* data = (dabInputDabplusFifoData*)args; + + return dabInputFifoLock(data->fifoData); +} + + +int dabInputDabplusFifoUnlock(void* args) +{ + dabInputDabplusFifoData* data = (dabInputDabplusFifoData*)args; + + return dabInputFifoUnlock(data->fifoData); +} + + +int dabInputDabplusFifoReadFrame(dabInputOperations* ops, void* args, + void* buffer, int size) +{ + dabInputDabplusFifoData* data = (dabInputDabplusFifoData*)args; + + return ops->read(args, buffer, size); +} + + +int dabInputDabplusFifoClose(void* args) +{ + dabInputDabplusFifoData* data = (dabInputDabplusFifoData*)args; + + return dabInputFifoClose(data->fifoData); +} + + +int dabInputDabplusFifoClean(void** args) +{ + dabInputDabplusFifoData* data = (dabInputDabplusFifoData*)args; + + dabInputFifoClean(&data->fifoData); + delete data; + + return 0; +} + + +int dabInputDabplusFifoRewind(void* args) +{ + dabInputDabplusFifoData* data = (dabInputDabplusFifoData*)args; + + return dabInputFifoRewind(data->fifoData); +} + + +# endif +#endif diff --git a/src/dabInputDabplusFifo.h b/src/dabInputDabplusFifo.h new file mode 100644 index 0000000..a02513a --- /dev/null +++ b/src/dabInputDabplusFifo.h @@ -0,0 +1,54 @@ +/* + Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications + Research Center Canada) + */ +/* + This file is part of CRC-DabMux. + + CRC-DabMux is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + CRC-DabMux is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CRC-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef DAB_INPUT_DABPLUS_FIFO_H +#define DAB_INPUT_DABPLUS_FIFO_H + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + + +#ifdef HAVE_FORMAT_DABPLUS +# ifdef HAVE_INPUT_FIFO + + +extern struct dabInputOperations dabInputDabplusFifoOperations; + + +int dabInputDabplusFifoInit(void** args); +int dabInputDabplusFifoOpen(void* args, const char* filename); +int dabInputDabplusFifoSetbuf(void* args, int size); +int dabInputDabplusFifoRead(void* args, void* buffer, int size); +int dabInputDabplusFifoLock(void* args); +int dabInputDabplusFifoUnlock(void* args); +int dabInputDabplusFifoReadFrame(dabInputOperations* ops, void* args, + void* buffer, int size); +int dabInputDabplusFifoClose(void* args); +int dabInputDabplusFifoClean(void** args); +int dabInputDabplusFifoRewind(void* args); + + +# endif +#endif + + +#endif // DAB_INPUT_DABPLUS_FIFO_H diff --git a/src/dabInputDabplusFile.cpp b/src/dabInputDabplusFile.cpp new file mode 100644 index 0000000..8d46ea1 --- /dev/null +++ b/src/dabInputDabplusFile.cpp @@ -0,0 +1,176 @@ +/* + Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications + Research Center Canada) + */ +/* + This file is part of CRC-DabMux. + + CRC-DabMux is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + CRC-DabMux is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CRC-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "dabInputDabplusFile.h" +#include "dabInput.h" + +#include <stdio.h> +#include <string.h> +#include <fcntl.h> + +#ifndef _WIN32 +# define O_BINARY 0 +#endif + + +#ifdef HAVE_FORMAT_DABPLUS +# ifdef HAVE_INPUT_FILE + + +struct dabInputOperations dabInputDabplusFileOperations = { + dabInputDabplusFileInit, + dabInputDabplusFileOpen, + dabInputSetbuf, + dabInputDabplusFileRead, + NULL, + NULL, + dabInputDabplusFileReadFrame, + dabInputSetbitrate, + dabInputDabplusFileClose, + dabInputDabplusFileClean, + dabInputDabplusFileRewind +}; + + +int dabInputDabplusFileInit(void** args) +{ + dabInputDabplusFileData* data = new dabInputDabplusFileData; + data->file = -1; + data->buffer = NULL; + data->bufferSize = 0; + data->bufferIndex = 0; + + *args = data; + return 0; +} + + +int dabInputDabplusFileOpen(void* args, const char* filename) +{ + dabInputDabplusFileData* data = (dabInputDabplusFileData*)args; + data->file = open(filename, O_RDONLY | O_BINARY); + if (data->file == -1) { + perror(filename); + return -1; + } + + return 0; +} + + +int dabInputDabplusFileRead(void* args, void* buffer, int size) +{ + dabInputDabplusFileData* data = (dabInputDabplusFileData*)args; + if (data->bufferSize != size * 5) { + if (data->buffer == NULL) { + delete[] data->buffer; + } + data->buffer = new uint8_t[size * 5]; + data->bufferSize = size * 5; + data->bufferIndex = 0; + } + + if (data->bufferIndex + size > data->bufferSize) { + int ret = read(data->file, data->buffer, data->bufferSize); + if (ret != data->bufferSize) { + if (ret != 0) { + etiLog.print(TcpLog::CRIT, "ERROR: Incomplete DAB+ frame!\n"); + } + return 0; + } + data->bufferIndex = 0; + } + + memcpy(buffer, &data->buffer[data->bufferIndex], size); + data->bufferIndex += size; + + return size; +} + + +int dabInputDabplusFileReadFrame(dabInputOperations* ops, void* args, + void* buffer, int size) +{ + //dabInputDabplusFileData* data = (dabInputDabplusFileData*)args; + int result; + uint8_t* dataOut = reinterpret_cast<uint8_t*>(buffer); + + result = ops->read(args, dataOut, size); + if (result == -1) { + etiLog.print(TcpLog::CRIT, "ERROR: Can't read file\n"); + perror(""); + return -1; + } + if (result < size) { + int sizeOut = result; + etiLog.print(TcpLog::NOTICE, "reach end of file -> rewinding\n"); + if (ops->rewind(args) == -1) { + etiLog.print(TcpLog::CRIT, "ERROR: Can't rewind file\n"); + return -1; + } + + result = ops->read(args, dataOut + sizeOut, size - sizeOut); + if (result == -1) { + etiLog.print(TcpLog::CRIT, "ERROR: Can't read file\n"); + perror(""); + return -1; + } + + if (result < size) { + etiLog.print(TcpLog::CRIT, "ERROR: Not enought data in file\n"); + return -1; + } + } + + return size; +} + + +int dabInputDabplusFileClose(void* args) +{ + dabInputDabplusFileData* data = (dabInputDabplusFileData*)args; + if (data->file != -1) { + close(data->file); + } + return 0; +} + + +int dabInputDabplusFileClean(void** args) +{ + dabInputDabplusFileData* data = (dabInputDabplusFileData*)*args; + if (data->buffer != NULL) { + delete[] data->buffer; + } + delete data; + return 0; +} + + +int dabInputDabplusFileRewind(void* args) +{ + dabInputDabplusFileData* data = (dabInputDabplusFileData*)args; + return lseek(data->file, 0, SEEK_SET); +} + + +# endif +#endif diff --git a/src/dabInputDabplusFile.h b/src/dabInputDabplusFile.h new file mode 100644 index 0000000..26a67a5 --- /dev/null +++ b/src/dabInputDabplusFile.h @@ -0,0 +1,62 @@ +/* + Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications + Research Center Canada) + */ +/* + This file is part of CRC-DabMux. + + CRC-DabMux is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + CRC-DabMux is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CRC-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef DAB_INPUT_DABPLUS_FILE_H +#define DAB_INPUT_DABPLUS_FILE_H + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <stdint.h> +#include <unistd.h> + + +#ifdef HAVE_FORMAT_DABPLUS +# ifdef HAVE_INPUT_FILE + + +extern struct dabInputOperations dabInputDabplusFileOperations; + + +struct dabInputDabplusFileData { + int file; + uint8_t* buffer; + size_t bufferSize; + size_t bufferIndex; +}; + + +int dabInputDabplusFileInit(void** args); +int dabInputDabplusFileOpen(void* args, const char* filename); +int dabInputDabplusFileRead(void* args, void* buffer, int size); +int dabInputDabplusFileReadFrame(dabInputOperations* ops, void* args, + void* buffer, int size); +int dabInputDabplusFileClose(void* args); +int dabInputDabplusFileClean(void** args); +int dabInputDabplusFileRewind(void* args); + + +# endif +#endif + + +#endif // DAB_INPUT_DABPLUS_FILE_H diff --git a/src/dabInputDmbFile.cpp b/src/dabInputDmbFile.cpp new file mode 100644 index 0000000..a057764 --- /dev/null +++ b/src/dabInputDmbFile.cpp @@ -0,0 +1,161 @@ +/* + Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications + Research Center Canada) + */ +/* + This file is part of CRC-DabMux. + + CRC-DabMux is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + CRC-DabMux is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CRC-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "dabInputDmbFile.h" +#include "dabInputFifo.h" +#include "Dmb.h" +#include "UdpSocket.h" + +#include <string.h> +#include <stdio.h> + + +struct dabInputDmbFileData { + FILE* file; + Dmb* dmb; + dabInputFifoStats stats; + unsigned char buffer[188]; + unsigned bufferLength; +}; + + +struct dabInputOperations dabInputDmbFileOperations = { + dabInputDmbFileInit, + dabInputDmbFileOpen, + dabInputSetbuf, + NULL, + NULL, + NULL, + dabInputDmbFileRead, + dabInputSetbitrate, + dabInputDmbFileClose, + dabInputDmbFileClean, + NULL +}; + + +int dabInputDmbFileInit(void** args) +{ + dabInputDmbFileData* input = new dabInputDmbFileData; + memset(&input->stats, 0, sizeof(input->stats)); + input->stats.id = dabInputFifoData::nb++; + input->file = NULL; + input->bufferLength = 0; + input->dmb = new Dmb(); + *args = input; + + UdpSocket::init(); + return 0; +} + + +int dabInputDmbFileOpen(void* args, const char* inputName) +{ + int returnCode = 0; + dabInputDmbFileData* input = (dabInputDmbFileData*)args; + + input->file = fopen(inputName, "r"); + if (input->file == NULL) { + perror(inputName); + returnCode = -1; + } + + return returnCode;; +} + + +int dabInputDmbFileRead(dabInputOperations* ops, void* args, void* buffer, int size) +{ + int nbBytes = 0; + dabInputDmbFileData* input = (dabInputDmbFileData*)args; + dabInputFifoStats* stats = (dabInputFifoStats*)&input->stats; + + input->stats.frameRecords[input->stats.frameCount].curSize = 0; + input->stats.frameRecords[input->stats.frameCount].maxSize = size; + + if (input->bufferLength == 0) { + input->bufferLength = fread(input->buffer, 188, 1, input->file); + } +/* while ((nbBytes = writePacket(input->packet->getData(), + input->packet->getLength(), buffer, size, input->info)) + != 0) { + input->stats.frameRecords[input->stats.frameCount].curSize = nbBytes; + input->socket->receive(*input->packet); + }*/ + while ((nbBytes = input->dmb->encode(input->buffer, + input->bufferLength * 188, buffer, size)) + != 0) { + input->stats.frameRecords[input->stats.frameCount].curSize = nbBytes; + input->bufferLength = fread(input->buffer, 188, 1, input->file); + if (input->bufferLength == 0) { + etiLog.print(TcpLog::NOTICE, "reach end of file -> rewinding\n"); + if (fseek(input->file, 0, SEEK_SET) == 0) { + input->bufferLength = fread(input->buffer, 188, 1, input->file); + } + } + //++mpgFrameNb; + } + //++dmbFrameNb; + + if (input->bufferLength != 0) { + input->stats.frameRecords[input->stats.frameCount].curSize = size; + } + + if (++stats->frameCount == NB_RECORDS) { + etiLog.print(TcpLog::INFO, "Data subchannel usage: (%i)", + stats->id); + for (int i = 0; i < stats->frameCount; ++i) { + etiLog.print(TcpLog::INFO, " %i/%i", + stats->frameRecords[i].curSize, + stats->frameRecords[i].maxSize); + } + etiLog.print(TcpLog::INFO, "\n"); + stats->frameCount = 0; + } + return size; +} + + +int dabInputDmbFileClose(void* args) +{ + dabInputDmbFileData* input = (dabInputDmbFileData*)args; + + if (input->file != NULL) { + if (fclose(input->file)) { + perror(""); + return -1; + } + } + + return 0; +} + + +int dabInputDmbFileClean(void** args) +{ + dabInputDmbFileData* input = (dabInputDmbFileData*)(*args); + dabInputDmbFileClose(args); + delete input->dmb; + delete input; + return 0; +} + + diff --git a/src/dabInputDmbFile.h b/src/dabInputDmbFile.h new file mode 100644 index 0000000..f77ab77 --- /dev/null +++ b/src/dabInputDmbFile.h @@ -0,0 +1,49 @@ +/* + Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications + Research Center Canada) + */ +/* + This file is part of CRC-DabMux. + + CRC-DabMux is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + CRC-DabMux is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CRC-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef DAB_INPUT_DMB_FILE_H +#define DAB_INPUT_DMB_FILE_H + + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#include "dabInput.h" + + +#ifdef HAVE_FORMAT_DMB +# ifdef HAVE_INPUT_FILE + + +extern struct dabInputOperations dabInputDmbFileOperations; + +int dabInputDmbFileInit(void** args); +int dabInputDmbFileOpen(void* args, const char* inputName); +int dabInputDmbFileRead(dabInputOperations* ops, void* args, void* buffer, int size); +int dabInputDmbFileClose(void* args); +int dabInputDmbFileClean(void** args); + + +# endif +#endif + + +#endif // DAB_INPUT_DMB_FILE_H diff --git a/src/dabInputDmbUdp.cpp b/src/dabInputDmbUdp.cpp new file mode 100644 index 0000000..935e925 --- /dev/null +++ b/src/dabInputDmbUdp.cpp @@ -0,0 +1,191 @@ +/* + Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications + Research Center Canada) + */ +/* + This file is part of CRC-DabMux. + + CRC-DabMux is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + CRC-DabMux is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CRC-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "dabInputDmbUdp.h" +#include "dabInputFifo.h" +#include "Dmb.h" +#include "UdpSocket.h" + +#include <string.h> +#include <limits.h> + + +#ifdef HAVE_FORMAT_DMB +# ifdef HAVE_INPUT_UDP + + +struct dabInputDmbUdpData { + UdpSocket* socket; + UdpPacket* packet; + Dmb* dmb; + dabInputFifoStats stats; +}; + + +struct dabInputOperations dabInputDmbUdpOperations = { + dabInputDmbUdpInit, + dabInputDmbUdpOpen, + dabInputSetbuf, + NULL, + NULL, + NULL, + dabInputDmbUdpRead, + dabInputSetbitrate, + dabInputDmbUdpClose, + dabInputDmbUdpClean, + NULL +}; + + +int dabInputDmbUdpInit(void** args) +{ + dabInputDmbUdpData* input = new dabInputDmbUdpData; + memset(&input->stats, 0, sizeof(input->stats)); + input->stats.id = dabInputFifoData::nb++; + input->socket = new UdpSocket(); + input->packet = new UdpPacket(2048); + input->dmb = new Dmb(); + *args = input; + + UdpSocket::init(); + return 0; +} + + +int dabInputDmbUdpOpen(void* args, const char* inputName) +{ + int returnCode = 0; + char* address; + char* ptr; + long port; + address = strdup(inputName); + ptr = strchr(address, ':'); + if (ptr == NULL) { + etiLog.print(TcpLog::ERR, + "\"%s\" is an invalid format for udp address: " + "should be [address]:port - > aborting\n", address); + returnCode = -1; + } + *(ptr++) = 0; + port = strtol(ptr, (char **)NULL, 10); + if ((port == LONG_MIN) || (port == LONG_MAX)) { + etiLog.print(TcpLog::ERR, + "can't convert port number in udp address %s\n", + address); + returnCode = -1; + } + if (port == 0) { + etiLog.print(TcpLog::ERR, "can't use port number 0 in udp address\n"); + returnCode = -1; + } + dabInputDmbUdpData* input = (dabInputDmbUdpData*)args; + if (input->socket->create(port) == -1) { + etiLog.print(TcpLog::ERR, "can't set port %i on Dmb input (%s: %s)\n", + port, inetErrDesc, inetErrMsg); + returnCode = -1; + } + + if (*address != 0) { + if (input->socket->joinGroup(address) == -1) { + etiLog.print(TcpLog::ERR, + "can't join multicast group %s (%s: %s)\n", + address, inetErrDesc, inetErrMsg); + returnCode = -1; + } + } + + if (input->socket->setBlocking(false) == -1) { + etiLog.print(TcpLog::ERR, "can't set Dmb input socket in blocking mode " + "(%s: %s)\n", inetErrDesc, inetErrMsg); + returnCode = -1; + } + + free(address); + etiLog.print(TcpLog::DBG, "check return code of create\n"); + return returnCode;; +} + + +int dabInputDmbUdpRead(dabInputOperations* ops, void* args, void* buffer, int size) +{ + int nbBytes = 0; + dabInputDmbUdpData* input = (dabInputDmbUdpData*)args; + dabInputFifoStats* stats = (dabInputFifoStats*)&input->stats; + + input->stats.frameRecords[input->stats.frameCount].curSize = 0; + input->stats.frameRecords[input->stats.frameCount].maxSize = size; + + if (input->packet->getLength() == 0) { + input->socket->receive(*input->packet); + } +/* while ((nbBytes = writePacket(input->packet->getData(), + input->packet->getLength(), buffer, size, input->info)) + != 0) { + input->stats.frameRecords[input->stats.frameCount].curSize = nbBytes; + input->socket->receive(*input->packet); + }*/ + while ((nbBytes = input->dmb->encode(input->packet->getData(), + input->packet->getLength(), buffer, size)) + != 0) { + input->stats.frameRecords[input->stats.frameCount].curSize = nbBytes; + input->socket->receive(*input->packet); + //++mpgFrameNb; + } + //++dmbFrameNb; + + if (input->packet->getLength() != 0) { + input->stats.frameRecords[input->stats.frameCount].curSize = size; + } + + if (++stats->frameCount == NB_RECORDS) { + etiLog.print(TcpLog::INFO, "Data subchannel usage: (%i)", + stats->id); + for (int i = 0; i < stats->frameCount; ++i) { + etiLog.print(TcpLog::INFO, " %i/%i", + stats->frameRecords[i].curSize, + stats->frameRecords[i].maxSize); + } + etiLog.print(TcpLog::INFO, "\n"); + stats->frameCount = 0; + } + return size; +} + + +int dabInputDmbUdpClose(void* args) +{ + return 0; +} + + +int dabInputDmbUdpClean(void** args) +{ + dabInputDmbUdpData* input = (dabInputDmbUdpData*)(*args); + delete input->socket; + delete input->packet; + delete input->dmb; + delete input; + return 0; +} + + +# endif +#endif diff --git a/src/dabInputDmbUdp.h b/src/dabInputDmbUdp.h new file mode 100644 index 0000000..1dfcf35 --- /dev/null +++ b/src/dabInputDmbUdp.h @@ -0,0 +1,49 @@ +/* + Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications + Research Center Canada) + */ +/* + This file is part of CRC-DabMux. + + CRC-DabMux is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + CRC-DabMux is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CRC-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef DAB_INPUT_DMB_UDP_H +#define DAB_INPUT_DMB_UDP_H + + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#include "dabInput.h" + + +#ifdef HAVE_FORMAT_DMB +# ifdef HAVE_INPUT_UDP + + +extern struct dabInputOperations dabInputDmbUdpOperations; + +int dabInputDmbUdpInit(void** args); +int dabInputDmbUdpOpen(void* args, const char* inputName); +int dabInputDmbUdpRead(dabInputOperations* ops, void* args, void* buffer, int size); +int dabInputDmbUdpClose(void* args); +int dabInputDmbUdpClean(void** args); + + +# endif +#endif + + +#endif // DAB_INPUT_DMB_UDP_H diff --git a/src/dabInputEnhancedFifo.cpp b/src/dabInputEnhancedFifo.cpp new file mode 100644 index 0000000..b187aec --- /dev/null +++ b/src/dabInputEnhancedFifo.cpp @@ -0,0 +1,64 @@ +/* + Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications + Research Center Canada) + */ +/* + This file is part of CRC-DabMux. + + CRC-DabMux is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + CRC-DabMux is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CRC-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "dabInputEnhancedFifo.h" +#include "dabInputPacketFile.h" +#include "dabInputFifo.h" + + +#ifdef HAVE_FORMAT_PACKET +# ifdef HAVE_FORMAT_EPM +# ifdef HAVE_INPUT_FIFO + + +struct dabInputOperations dabInputEnhancedFifoOperations = { + dabInputEnhancedFifoInit, + dabInputFifoOpen, + dabInputFifoSetbuf, + dabInputFifoRead, + dabInputFifoLock, + dabInputFifoUnlock, + dabInputPacketFileRead, + dabInputSetbitrate, + dabInputFifoClose, + dabInputFifoClean, + dabInputFifoRewind +}; + + +int dabInputEnhancedFifoInit(void** args) +{ + dabInputFifoInit(args); + dabInputFifoData* data = (dabInputFifoData*)*args; + + data->packetData = new unsigned char[96]; + data->enhancedPacketData = new unsigned char*[12]; + for (int i = 0; i < 12; ++i) { + data->enhancedPacketData[i] = new unsigned char[204]; + } + + return 0; +} + + +# endif +# endif +#endif diff --git a/src/dabInputEnhancedFifo.h b/src/dabInputEnhancedFifo.h new file mode 100644 index 0000000..2479c88 --- /dev/null +++ b/src/dabInputEnhancedFifo.h @@ -0,0 +1,46 @@ +/* + Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications + Research Center Canada) + */ +/* + This file is part of CRC-DabMux. + + CRC-DabMux is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + CRC-DabMux is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CRC-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef DAB_INPUT_ENHANCED_FIFO_H +#define DAB_INPUT_ENHANCED_FIFO_H + + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#include "dabInput.h" + + +#ifdef HAVE_FORMAT_PACKET +# ifdef HAVE_FORMAT_EPM +# ifdef HAVE_INPUT_FIFO + + +extern struct dabInputOperations dabInputEnhancedFifoOperations; +int dabInputEnhancedFifoInit(void** args); + + +# endif +# endif +#endif + + +#endif // DAB_INPUT_ENHANCED_FIFO_H diff --git a/src/dabInputEnhancedPacketFile.cpp b/src/dabInputEnhancedPacketFile.cpp new file mode 100644 index 0000000..b3b48bf --- /dev/null +++ b/src/dabInputEnhancedPacketFile.cpp @@ -0,0 +1,53 @@ +/* + Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications + Research Center Canada) + */ +/* + This file is part of CRC-DabMux. + + CRC-DabMux is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + CRC-DabMux is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CRC-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "dabInputEnhancedPacketFile.h" +#include "dabInputPacketFile.h" +#include "dabInputFile.h" + + +struct dabInputOperations dabInputEnhancedPacketFileOperations = { + dabInputEnhancedFileInit, + dabInputFileOpen, + dabInputSetbuf, + dabInputFileRead, + NULL, + NULL, + dabInputPacketFileRead, + dabInputSetbitrate, + dabInputFileClose, + dabInputFileClean, + dabInputFileRewind +}; + + +int dabInputEnhancedFileInit(void** args) +{ + dabInputFileInit(args); + dabInputFileData* data = (dabInputFileData*)*args; + + data->enhancedPacketData = new unsigned char*[12]; + for (int i = 0; i < 12; ++i) { + data->enhancedPacketData[i] = new unsigned char[204]; + } + + return 0; +} diff --git a/src/dabInputEnhancedPacketFile.h b/src/dabInputEnhancedPacketFile.h new file mode 100644 index 0000000..0f419e0 --- /dev/null +++ b/src/dabInputEnhancedPacketFile.h @@ -0,0 +1,47 @@ +/* + Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications + Research Center Canada) + */ +/* + This file is part of CRC-DabMux. + + CRC-DabMux is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + CRC-DabMux is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CRC-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef DAB_INPUT_ENHANCED_PACKET_FILE_H +#define DAB_INPUT_ENHANCED_PACKET_FILE_H + + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#include "dabInput.h" + + +#ifdef HAVE_FORMAT_PACKET +# ifdef HAVE_FORMAT_EPM +# ifdef HAVE_INPUT_FILE + + +extern struct dabInputOperations dabInputEnhancedPacketFileOperations; + +int dabInputEnhancedFileInit(void** args); + + +# endif +# endif +#endif + + +#endif // DAB_INPUT_ENHANCED_PACKET_FILE_H diff --git a/src/dabInputFifo.cpp b/src/dabInputFifo.cpp new file mode 100644 index 0000000..a2c2ef7 --- /dev/null +++ b/src/dabInputFifo.cpp @@ -0,0 +1,513 @@ +/* + Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications + Research Center Canada) + */ +/* + This file is part of CRC-DabMux. + + CRC-DabMux is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + CRC-DabMux is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CRC-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "dabInputFifo.h" +#include "dabInputPacketFile.h" +#include "dabInput.h" + +#include <unistd.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <fcntl.h> + + +#ifdef HAVE_FORMAT_PACKET +# ifdef HAVE_INPUT_FIFO + + +int dabInputFifoData::nb = 0; + + +struct dabInputOperations dabInputFifoOperations = { + dabInputFifoInit, + dabInputFifoOpen, + dabInputFifoSetbuf, + dabInputFifoRead, + dabInputFifoLock, + dabInputFifoUnlock, + dabInputPacketFileRead, + dabInputSetbitrate, + dabInputFifoClose, + dabInputFifoClean, + dabInputFifoRewind +}; + + +int dabInputFifoInit(void** args) +{ + dabInputFifoData* data = new dabInputFifoData; + memset(data, 0, sizeof(*data)); + data->stats.id = dabInputFifoData::nb++; + data->maxSize = 0; + data->curSize = 0; + data->head = 0; + data->tail = 0; + data->buffer = NULL; + data->packetData = NULL; + data->enhancedPacketData = NULL; + data->packetLength = 0; + data->enhancedPacketLength = 0; + data->enhancedPacketWaiting = 0; + data->full = false; + data->running = true; + data->thread = (pthread_t)NULL; +#ifdef _WIN32 + char semName[32]; + sprintf(semName, "semInfo%i", data->stats.id); + data->semInfo = CreateSemaphore(NULL, 1, 1, semName); + if (data->semInfo == NULL) { + fprintf(stderr, "Can't init FIFO data semaphore %s\n", semName); + return -1; + } + sprintf(semName, "semBuffer%i", data->stats.id); + data->semBuffer = CreateSemaphore(NULL, 1, 1, semName); + if (data->semBuffer == NULL) { + fprintf(stderr, "Can't init FIFO buffer semaphore %s\n", semName); + return -1; + } + sprintf(semName, "semFull%i", data->stats.id); + data->semFull = CreateSemaphore(NULL, 1, 1, semName); + if (data->semFull == NULL) { + fprintf(stderr, "Can't init FIFO semaphore %s\n", semName); + return -1; + } +#else + if (sem_init(&data->semInfo, 0, 1) == -1) { + perror("Can't init FIFO data semaphore"); + return -1; + } + if (sem_init(&data->semBuffer, 0, 0) == -1) { + perror("Can't init fIFO buffer semaphore"); + return -1; + } + if (sem_init(&data->semFull, 0, 0) == -1) { + perror("Can't init FIFO semaphore"); + return -1; + } +#endif + + if (data->maxSize > 0) { +#ifdef _WIN32 + ReleaseSemaphore(data->semBuffer, 1, NULL); +#else + sem_post(&data->semBuffer); +#endif + } + *args = data; + return 0; +} + + +int dabInputFifoOpen(void* args, const char* filename) +{ + dabInputFifoData* data = (dabInputFifoData*)args; + data->file = open(filename, O_RDONLY | O_BINARY | O_NONBLOCK); + if (data->file == -1) { + perror(filename); + return -1; + } +#ifdef _WIN32 +#else + int flags = fcntl(data->file, F_GETFL); + if (flags == -1) { + perror(filename); + return -1; + } + if (fcntl(data->file, F_SETFL, flags & ~O_NONBLOCK) == -1) { + perror(filename); + return -1; + } +#endif + +#ifdef _WIN32 + data->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)dabInputFifoThread, data, 0, NULL); + if (data->thread == NULL) { + fprintf(stderr, "Can't create FIFO child\n"); + return -1; + } +#else + if (pthread_create(&data->thread, NULL, dabInputFifoThread, data)) { + perror("Can't create FIFO child"); + return -1; + } +#endif + + return 0; +} + + +int dabInputFifoSetbuf(void* args, int size) +{ + dabInputFifoData* data = (dabInputFifoData*)args; + + if (data->maxSize > 0) { +#ifdef _WIN32 + WaitForSingleObject(data->semBuffer, INFINITE); +#else + sem_wait(&data->semBuffer); +#endif + } + if (data->buffer != NULL) { + delete data->buffer; + } + if (size == 0) { + size = 1024; + } + data->buffer = new unsigned char[size * 16]; + data->maxSize = size * 16; +#ifdef _WIN32 + ReleaseSemaphore(data->semBuffer, 1, NULL); +#else + sem_post(&data->semBuffer); +#endif + + return 0; +} + + +int dabInputFifoRead(void* args, void* buffer, int size) +{ + //fprintf(stderr, "INFO: read %i bytes\n", size); + dabInputFifoData* data = (dabInputFifoData*)args; + dabInputFifoStats* stats = &data->stats; + int head; + int tail; + int curSize; + int maxSize; +#ifdef _WIN32 + WaitForSingleObject(data->semInfo, INFINITE); +#else + sem_wait(&data->semInfo); +#endif + head = data->head; + tail = data->tail; + curSize = data->curSize; + maxSize = data->maxSize; +#ifdef _WIN32 + ReleaseSemaphore(data->semInfo, 1, NULL); +#else + sem_post(&data->semInfo); +#endif + //fprintf(stderr, "head: %i, tail: %i, curSize: %i\n", head, tail, curSize); + if (size > curSize) { + if (curSize == 0) { + stats->empty = true; + } else { + etiLog.print(TcpLog::WARNING, "Not enough data in FIFO buffer: (%i) %i/%i\n", + data->stats.id, curSize, size); + } + return 0; + } + if (head > tail) { + memcpy(buffer, data->buffer + tail, size); +#ifdef _WIN32 + WaitForSingleObject(data->semInfo, INFINITE); +#else + sem_wait(&data->semInfo); +#endif + data->tail += size; + data->curSize -= size; +#ifdef _WIN32 + ReleaseSemaphore(data->semInfo, 1, NULL); +#else + sem_post(&data->semInfo); +#endif + return size; + } else { + if (maxSize - tail >= size) { + memcpy(buffer, data->buffer + tail, size); +#ifdef _WIN32 + WaitForSingleObject(data->semInfo, INFINITE); +#else + sem_wait(&data->semInfo); +#endif + data->tail += size; + data->curSize -= size; +#ifdef _WIN32 + ReleaseSemaphore(data->semInfo, 1, NULL); +#else + sem_post(&data->semInfo); +#endif + return size; + } else { + memcpy(buffer, data->buffer + tail, maxSize - tail); +#ifdef _WIN32 + WaitForSingleObject(data->semInfo, INFINITE); +#else + sem_wait(&data->semInfo); +#endif + data->tail = 0; + data->curSize -= maxSize - tail; +#ifdef _WIN32 + ReleaseSemaphore(data->semInfo, 1, NULL); +#else + sem_post(&data->semInfo); +#endif + return maxSize - tail + dabInputFifoRead(data, (char*)buffer + maxSize - tail, size - (maxSize - tail)); + } + } + return -1; +} + + +int dabInputFifoLock(void* args) { + dabInputFifoData* data = (dabInputFifoData*)args; + dabInputFifoStats* stats = &data->stats; + + int maxSize; + int curSize; +#ifdef _WIN32 + WaitForSingleObject(data->semInfo, INFINITE); +#else + sem_wait(&data->semInfo); +#endif + maxSize = data->maxSize; + curSize = data->curSize; +#ifdef _WIN32 + ReleaseSemaphore(data->semInfo, 1, NULL); +#else + sem_post(&data->semInfo); +#endif + + stats->bufferRecords[stats->bufferCount].curSize = curSize; + stats->bufferRecords[stats->bufferCount].maxSize = maxSize; + + if (++stats->bufferCount == NB_RECORDS) { + etiLog.print(TcpLog::INFO, "FIFO buffer state: (%i)", stats->id); + for (int i = 0; i < stats->bufferCount; ++i) { + etiLog.print(TcpLog::INFO, " %i/%i", + stats->bufferRecords[i].curSize, + stats->bufferRecords[i].maxSize); + } + etiLog.print(TcpLog::INFO, "\n"); + + if (stats->full) { + etiLog.print(TcpLog::WARNING, "FIFO buffer full: (%i)\n", + data->stats.id); + stats->full = false; + } + if (stats->empty) { + etiLog.print(TcpLog::WARNING, "FIFO buffer empty: (%i)\n", + data->stats.id); + stats->empty = false; + } + if (stats->error) { + etiLog.print(TcpLog::ERR, "FIFO input read error: (%i)\n", + data->stats.id); + stats->error = false; + } + if (stats->input) { + etiLog.print(TcpLog::ERR, "FIFO input not connected: (%i)\n", + data->stats.id); + stats->input = false; + } + + stats->bufferCount = 0; + } + return 0; +} + + +int dabInputFifoUnlock(void* args) { + dabInputFifoData* data = (dabInputFifoData*)args; + if (data->full) { +#ifdef _WIN32 + ReleaseSemaphore(data->semFull, 1, NULL); +#else + sem_post(&data->semFull); +#endif + } + return 0; +} + + +int dabInputFifoClose(void* args) +{ + dabInputFifoData* data = (dabInputFifoData*)args; + close(data->file); + return 0; +} + + +int dabInputFifoClean(void** args) +{ + dabInputFifoData* data = (dabInputFifoData*)*args; + data->running = false; + etiLog.print(TcpLog::DBG, "Wait FIFO child...\n"); +#ifdef WIN32 + DWORD status; + for (int i = 0; i < 5; ++i) { + if (GetExitCodeThread(data->thread, &status)) { + break; + } + Sleep(100); + } + TerminateThread(data->thread, 1); + if (CloseHandle(data->thread) == 0) { + etiLog.print(TcpLog::DBG, "ERROR: Failed to close FIFO child thread\n"); + } +#else + if (data->thread != (pthread_t)NULL) { + if (pthread_join(data->thread, NULL)) { + etiLog.print(TcpLog::DBG, "ERROR: FIFO child thread had not exit normally\n"); + } + } +#endif + etiLog.print(TcpLog::DBG, "Done\n"); +#ifdef _WIN32 + CloseHandle(data->semInfo); + CloseHandle(data->semFull); + CloseHandle(data->semBuffer); +#else + sem_destroy(&data->semInfo); + sem_destroy(&data->semFull); + sem_destroy(&data->semBuffer); +#endif + if (data->packetData != NULL) { + delete[] data->packetData; + } + if (data->enhancedPacketData != NULL) { + for (int i = 0; i < 12; ++i) { + if (data->enhancedPacketData[i] != NULL) { + delete[] data->enhancedPacketData[i]; + } + } + delete[] data->enhancedPacketData; + } + delete data->buffer; + delete data; + return 0; +} + + +int dabInputFifoRewind(void* args) +{ + return -1; +} + + +void* dabInputFifoThread(void* args) +{ + dabInputFifoData* data = (dabInputFifoData*)args; + int head; + int tail; + int curSize; + int maxSize; + int ret; + while (data->running) { +#ifdef _WIN32 + WaitForSingleObject(data->semBuffer, INFINITE); + WaitForSingleObject(data->semInfo, INFINITE); +#else + sem_wait(&data->semBuffer); + sem_wait(&data->semInfo); +#endif + head = data->head; + tail = data->tail; + curSize = data->curSize; + maxSize = data->maxSize; +#ifdef _WIN32 + ReleaseSemaphore(data->semInfo, 1, NULL); +#else + sem_post(&data->semInfo); +#endif + //fprintf(stderr, "thread, head: %i, tail: %i, curSize: %i\n", head, tail, curSize); + + if (curSize == maxSize) { + data->stats.full = true; + data->full = true; +#ifdef _WIN32 + WaitForSingleObject(data->semFull, INFINITE); +#else + sem_wait(&data->semFull); +#endif + } else if (head >= tail) { // 2 blocks + ret = read(data->file, data->buffer + head, maxSize - head); + if (ret == 0) { + data->stats.input = true; + data->full = true; +#ifdef _WIN32 + WaitForSingleObject(data->semFull, INFINITE); +#else + sem_wait(&data->semFull); +#endif + } else if (ret == -1) { + data->stats.error = true; + } else { +#ifdef _WIN32 + WaitForSingleObject(data->semInfo, INFINITE); +#else + sem_wait(&data->semInfo); +#endif + data->head += ret; + data->curSize += ret; + if (data->head == maxSize) { + data->head = 0; + } +#ifdef _WIN32 + ReleaseSemaphore(data->semInfo, 1, NULL); +#else + sem_post(&data->semInfo); +#endif + } + } else { // 1 block + ret = read(data->file, data->buffer + head, tail - head); + if (ret == 0) { + data->stats.input = true; + data->full = true; +#ifdef _WIN32 + WaitForSingleObject(data->semFull, INFINITE); +#else + sem_wait(&data->semFull); +#endif + } else if (ret == -1) { + data->stats.error = true; + } else { +#ifdef _WIN32 + WaitForSingleObject(data->semInfo, INFINITE); +#else + sem_wait(&data->semInfo); +#endif + data->head += ret; + data->curSize += ret; + if (data->head == maxSize) { + data->head = 0; + } +#ifdef _WIN32 + ReleaseSemaphore(data->semInfo, 1, NULL); +#else + sem_post(&data->semInfo); +#endif + } + } +#ifdef _WIN32 + ReleaseSemaphore(data->semBuffer, 1, NULL); +#else + sem_post(&data->semBuffer); +#endif + } + return NULL; +} + + +# endif +#endif diff --git a/src/dabInputFifo.h b/src/dabInputFifo.h new file mode 100644 index 0000000..1844d1e --- /dev/null +++ b/src/dabInputFifo.h @@ -0,0 +1,101 @@ +/* + Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications + Research Center Canada) + */ +/* + This file is part of CRC-DabMux. + + CRC-DabMux is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + CRC-DabMux is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CRC-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef DAB_INPUT_FIFO_H +#define DAB_INPUT_FIFO_H + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#include "dabInputFile.h" +#include "TcpLog.h" +extern TcpLog etiLog; + + +#ifdef _WIN32 +# include <io.h> + +# define sem_t HANDLE +# define O_NONBLOCK 0 +#else +# include <semaphore.h> +# define O_BINARY 0 +#endif + + +#ifdef HAVE_FORMAT_PACKET +# ifdef HAVE_INPUT_FIFO +extern struct dabInputOperations dabInputFifoOperations; + + +struct dabInputFifoStatRecord { + int curSize; + int maxSize; +}; + + +#define NB_RECORDS 10 +struct dabInputFifoStats { + int id; + bool full; + bool empty; + bool error; + bool input; + int bufferCount; + dabInputFifoStatRecord bufferRecords[NB_RECORDS]; + int frameCount; + dabInputFifoStatRecord frameRecords[NB_RECORDS]; +}; + + +struct dabInputFifoData : dabInputFileData { + static int nb; + int maxSize; + int curSize; + int head; + int tail; + dabInputFifoStats stats; + unsigned char* buffer; + pthread_t thread; + sem_t semInfo; + sem_t semBuffer; + sem_t semFull; + bool full; + bool running; +}; + + +int dabInputFifoInit(void** args); +int dabInputFifoOpen(void* args, const char* filename); +int dabInputFifoSetbuf(void* args, int size); +int dabInputFifoRead(void* args, void* buffer, int size); +int dabInputFifoLock(void* args); +int dabInputFifoUnlock(void* args); +int dabInputFifoClose(void* args); +int dabInputFifoClean(void** args); +int dabInputFifoRewind(void* args); +void* dabInputFifoThread(void* args); + + +# endif +#endif + +#endif // DAB_INPUT_FIFO_H diff --git a/src/dabInputFile.cpp b/src/dabInputFile.cpp new file mode 100644 index 0000000..330519a --- /dev/null +++ b/src/dabInputFile.cpp @@ -0,0 +1,104 @@ +/* + Copyright (C) 2009,2011 Her Majesty the Queen in Right of Canada + (Communications Research Center Canada) + */ +/* + This file is part of CRC-DabMux. + + CRC-DabMux is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + CRC-DabMux is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CRC-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "dabInputFile.h" + +#include <stdlib.h> +#include <stdio.h> +#include <fcntl.h> +#include <unistd.h> + +#ifndef _WIN32 +# define O_BINARY 0 +#endif + + +int dabInputFileInit(void** args) +{ + dabInputFileData* data = new dabInputFileData; + data->file = -1; + data->parity = false; + data->packetLength = 0; + data->packetData = new unsigned char[96]; + data->enhancedPacketData = NULL; + data->enhancedPacketLength = 0; + data->enhancedPacketWaiting = 0; + + *args = data; + return 0; +} + + +int dabInputFileOpen(void* args, const char* filename) +{ + dabInputFileData* data = (dabInputFileData*)args; + data->file = open(filename, O_RDONLY | O_BINARY); + if (data->file == -1) { + perror(filename); + return -1; + } + return 0; +} + + +int dabInputFileRead(void* args, void* buffer, int size) +{ + dabInputFileData* data = (dabInputFileData*)args; + return read(data->file, buffer, size); +} + + +int dabInputFileClose(void* args) +{ + dabInputFileData* data = (dabInputFileData*)args; + if (data->file != -1) { + close(data->file); + } + return 0; +} + + +int dabInputFileClean(void** args) +{ + dabInputFileData* data = (dabInputFileData*)*args; + if (data->packetData != NULL) { + delete[] data->packetData; + } + if (data->enhancedPacketData != NULL) { + for (int i = 0; i < 12; ++i) { + if (data->enhancedPacketData[i] != NULL) { + delete[] data->enhancedPacketData[i]; + } + } + delete[] data->enhancedPacketData; + } + delete data; + return 0; +} + + +int dabInputFileRewind(void* args) +{ + dabInputFileData* data = (dabInputFileData*)args; + return lseek(data->file, 0, SEEK_SET); +} + + diff --git a/src/dabInputFile.h b/src/dabInputFile.h new file mode 100644 index 0000000..af2798b --- /dev/null +++ b/src/dabInputFile.h @@ -0,0 +1,49 @@ +/* + Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications + Research Center Canada) + */ +/* + This file is part of CRC-DabMux. + + CRC-DabMux is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + CRC-DabMux is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CRC-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef DAB_INPUT_FILE_H +#define DAB_INPUT_FILE_H + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + + +struct dabInputFileData { + int file; + bool parity; + unsigned packetLength; + unsigned char* packetData; + unsigned char** enhancedPacketData; + unsigned enhancedPacketLength; + unsigned enhancedPacketWaiting; +}; + + +int dabInputFileInit(void** args); +int dabInputFileOpen(void* args, const char* filename); +int dabInputFileRead(void* args, void* buffer, int size); +int dabInputFileClose(void* args); +int dabInputFileClean(void** args); +int dabInputFileRewind(void* args); + + +#endif // DAB_INPUT_FILE_H diff --git a/src/dabInputMpegFifo.cpp b/src/dabInputMpegFifo.cpp new file mode 100644 index 0000000..b34ee76 --- /dev/null +++ b/src/dabInputMpegFifo.cpp @@ -0,0 +1,47 @@ +/* + Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications + Research Center Canada) + */ +/* + This file is part of CRC-DabMux. + + CRC-DabMux is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + CRC-DabMux is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CRC-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "dabInputMpegFifo.h" +#include "dabInputFifo.h" +#include "dabInputMpegFile.h" + + +#ifdef HAVE_FORMAT_MPEG +# ifdef HAVE_INPUT_FIFO + + +struct dabInputOperations dabInputMpegFifoOperations = { + dabInputFifoInit, + dabInputFifoOpen, + dabInputFifoSetbuf, + dabInputFifoRead, + dabInputFifoLock, + dabInputFifoUnlock, + dabInputMpegFileRead, + dabInputSetbitrate, + dabInputFifoClose, + dabInputFifoClean, + dabInputFifoRewind +}; + + +# endif +#endif diff --git a/src/dabInputMpegFifo.h b/src/dabInputMpegFifo.h new file mode 100644 index 0000000..e7b54dd --- /dev/null +++ b/src/dabInputMpegFifo.h @@ -0,0 +1,37 @@ +/* + Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications + Research Center Canada) + */ +/* + This file is part of CRC-DabMux. + + CRC-DabMux is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + CRC-DabMux is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CRC-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef DAB_INPUT_MPEG_FIFO_H +#define DAB_INPUT_MPEG_FIFO_H + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + + +#ifdef HAVE_FORMAT_MPEG +# ifdef HAVE_INPUT_FIFO +extern struct dabInputOperations dabInputMpegFifoOperations; +# endif +#endif + + +#endif // DAB_INPUT_MPEG_FIFO_H diff --git a/src/dabInputMpegFile.cpp b/src/dabInputMpegFile.cpp new file mode 100644 index 0000000..0a06b2f --- /dev/null +++ b/src/dabInputMpegFile.cpp @@ -0,0 +1,201 @@ +/* + Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications + Research Center Canada) + */ +/* + This file is part of CRC-DabMux. + + CRC-DabMux is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + CRC-DabMux is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CRC-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "dabInputMpegFile.h" +#include "dabInputFile.h" +#include "mpeg.h" + +#include <stdio.h> +#include <errno.h> +#include <string.h> + + +#ifdef HAVE_FORMAT_MPEG +# ifdef HAVE_INPUT_FILE + + +struct dabInputOperations dabInputMpegFileOperations = { + dabInputFileInit, + dabInputFileOpen, + dabInputSetbuf, + dabInputFileRead, + NULL, + NULL, + dabInputMpegFileRead, + dabInputMpegSetbitrate, + dabInputFileClose, + dabInputFileClean, + dabInputFileRewind +}; + + +#define MPEG_FREQUENCY -2 +#define MPEG_PADDING -3 +#define MPEG_COPYRIGHT -4 +#define MPEG_ORIGINAL -5 +#define MPEG_EMPHASIS -6 +int checkDabMpegFrame(void* data) { + mpegHeader* header = (mpegHeader*)data; + unsigned long* headerData = (unsigned long*)data; + if ((*headerData & 0x0f0ffcff) == 0x0004fcff) return 0; + if ((*headerData & 0x0f0ffcff) == 0x0004f4ff) return 0; + if (getMpegFrequency(header) != 48000) { + if (getMpegFrequency(header) != 24000) { + return MPEG_FREQUENCY; + } + } + if (header->padding != 0) { + return MPEG_PADDING; + } + if (header->copyright != 0) { + return MPEG_COPYRIGHT; + } + if (header->original != 0) { + return MPEG_ORIGINAL; + } + if (header->emphasis != 0) { + return MPEG_EMPHASIS; + } + return -1; +} + + +int dabInputMpegFileRead(dabInputOperations* ops, void* args, void* buffer, int size) +{ + dabInputFileData* data = (dabInputFileData*)args; + int result; + bool rewind = false; +READ_SUBCHANNEL: + if (data->parity) { + result = readData(data->file, buffer, size, 2); + data->parity = false; + return 0; + } else { + result = readMpegHeader(data->file, buffer, size); + if (result > 0) { + result = readMpegFrame(data->file, buffer, size); + if (result < 0 && getMpegFrequency(buffer) == 24000) { + data->parity = true; + result = size; + } + } + } + switch (result) { + case MPEG_BUFFER_UNDERFLOW: + etiLog.print(TcpLog::WARNING, "data underflow -> frame muted\n"); + goto MUTE_SUBCHANNEL; + case MPEG_BUFFER_OVERFLOW: + etiLog.print(TcpLog::WARNING, "bitrate too high -> frame muted\n"); + goto MUTE_SUBCHANNEL; + case MPEG_FILE_EMPTY: + if (rewind) { + etiLog.print(TcpLog::ERR, "file rewinded and still empty " + "-> frame muted\n"); + goto MUTE_SUBCHANNEL; + } else { + rewind = true; + etiLog.print(TcpLog::NOTICE, "reach end of file -> rewinding\n"); + lseek(data->file, 0, SEEK_SET); + goto READ_SUBCHANNEL; + } + case MPEG_FILE_ERROR: + etiLog.print(TcpLog::CRIT, "can't read file (%i) -> frame muted\n", errno); + perror(""); + goto MUTE_SUBCHANNEL; + case MPEG_SYNC_NOT_FOUND: + etiLog.print(TcpLog::CRIT, "mpeg sync not found, maybe is not a valid file " + "-> frame muted\n"); + goto MUTE_SUBCHANNEL; + case MPEG_INVALID_FRAME: + etiLog.print(TcpLog::CRIT, "file is not a valid mpeg file " + "-> frame muted\n"); + goto MUTE_SUBCHANNEL; + default: + if (result < 0) { + etiLog.print(TcpLog::CRIT, + "unknown error (code = %i) -> frame muted\n", + result); +MUTE_SUBCHANNEL: + memset(buffer, 0, size); + } else { + if (result < size) { + etiLog.print(TcpLog::WARNING, "bitrate too low from file " + "-> frame padded\n"); + memset((char*)buffer + result, 0, size - result); + } + result = checkDabMpegFrame(buffer); + switch (result) { + case MPEG_FREQUENCY: + etiLog.print(TcpLog::ERR, "file has a frame with an invalid " + "frequency: %i, should be 48000 or 24000\n", + getMpegFrequency(buffer)); + break; + case MPEG_PADDING: + etiLog.print(TcpLog::WARNING, + "file has a frame with padding bit set\n"); + break; + case MPEG_COPYRIGHT: + etiLog.print(TcpLog::WARNING, + "file has a frame with copyright bit set\n"); + break; + case MPEG_ORIGINAL: + etiLog.print(TcpLog::WARNING, + "file has a frame with original bit set\n"); + break; + case MPEG_EMPHASIS: + etiLog.print(TcpLog::WARNING, + "file has a frame with emphasis bits set\n"); + break; + default: + if (result < 0) { + etiLog.print(TcpLog::CRIT, "mpeg file has an invalid DAB " + "mpeg frame (unknown reason: %i)\n", result); + } + break; + } + } + } + return result; +} + + +int dabInputMpegSetbitrate(dabInputOperations* ops, void* args, int bitrate) +{ + //dabInputFileData* data = (dabInputFileData*)args; + if (bitrate == 0) { + char buffer[4]; + + if (ops->readFrame(ops, args, buffer, 4) == 0) { + bitrate = getMpegBitrate(buffer); + } else { + bitrate = -1; + } + ops->rewind(args); + } + if (ops->setbuf(args, bitrate * 3) != 0) { + bitrate = -1; + } + return bitrate; +} + + +# endif +#endif diff --git a/src/dabInputMpegFile.h b/src/dabInputMpegFile.h new file mode 100644 index 0000000..741a5f7 --- /dev/null +++ b/src/dabInputMpegFile.h @@ -0,0 +1,42 @@ +/* + Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications + Research Center Canada) + */ +/* + This file is part of CRC-DabMux. + + CRC-DabMux is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + CRC-DabMux is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CRC-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef DAB_INPUT_MPEG_FILE_H +#define DAB_INPUT_MPEG_FILE_H + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#include "dabInput.h" + + +#ifdef HAVE_FORMAT_MPEG +# ifdef HAVE_INPUT_FILE +extern struct dabInputOperations dabInputMpegFileOperations; + +int dabInputMpegFileRead(dabInputOperations* ops, void* args, void* buffer, int size); +int dabInputMpegSetbitrate(dabInputOperations* ops, void* args, int bitrate); +int checkDabMpegFrame(void* data); +# endif +#endif + + +#endif // DAB_INPUT_MPEG_FILE_H diff --git a/src/dabInputPacketFile.cpp b/src/dabInputPacketFile.cpp new file mode 100644 index 0000000..65b5ebe --- /dev/null +++ b/src/dabInputPacketFile.cpp @@ -0,0 +1,263 @@ +/* + Copyright (C) 2009, 2011 Her Majesty the Queen in Right of Canada + (Communications Research Center Canada) + */ +/* + This file is part of CRC-DabMux. + + CRC-DabMux is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + CRC-DabMux is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CRC-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "dabInputPacketFile.h" +#include "dabInputFile.h" +#include "dabInputFifo.h" +#include "ReedSolomon.h" + +#ifdef HAVE_FORMAT_PACKET +# ifdef HAVE_INPUT_FILE + + +#include <string.h> +#include <stdio.h> +#include <errno.h> + + +#ifdef _WIN32 +# pragma pack(push, 1) +#endif +struct packetHeader { + unsigned char addressHigh:2; + unsigned char last:1; + unsigned char first:1; + unsigned char continuityIndex:2; + unsigned char packetLength:2; + unsigned char addressLow; + unsigned char dataLength:7; + unsigned char command; +} +#ifdef _WIN32 +# pragma pack(pop) +#else +__attribute((packed)) +#endif +; + + +struct dabInputOperations dabInputPacketFileOperations = { + dabInputFileInit, + dabInputFileOpen, + dabInputSetbuf, + dabInputFileRead, + NULL, + NULL, + dabInputPacketFileRead, + dabInputSetbitrate, + dabInputFileClose, + dabInputFileClean, + dabInputFileRewind +}; + + +int dabInputPacketFileRead(dabInputOperations* ops, void* args, void* buffer, + int size) +{ + dabInputFileData* data = (dabInputFileData*)args; + unsigned char* dataBuffer = (unsigned char*)buffer; + int written = 0; + int length; + packetHeader* header; + int indexRow; + int indexCol; + + while (written < size) { + if (data->enhancedPacketWaiting > 0) { + *dataBuffer = 192 - data->enhancedPacketWaiting; + *dataBuffer /= 22; + *dataBuffer <<= 2; + *(dataBuffer++) |= 0x03; + *(dataBuffer++) = 0xfe; + indexCol = 188; + indexCol += (192 - data->enhancedPacketWaiting) / 12; + indexRow = 0; + indexRow += (192 - data->enhancedPacketWaiting) % 12; + for (int j = 0; j < 22; ++j) { + if (data->enhancedPacketWaiting == 0) { + *(dataBuffer++) = 0; + } else { + *(dataBuffer++) = data->enhancedPacketData[indexRow][indexCol]; + if (++indexRow == 12) { + indexRow = 0; + ++indexCol; + } + --data->enhancedPacketWaiting; + } + } + written += 24; + if (data->enhancedPacketWaiting == 0) { + data->enhancedPacketLength = 0; + } + } else if (data->packetLength != 0) { + header = (packetHeader*)data->packetData; + if (written + data->packetLength > (unsigned)size) { + memset(dataBuffer, 0, 22); + dataBuffer[22] = 0x60; + dataBuffer[23] = 0x4b; + length = 24; + } else if (data->enhancedPacketData != NULL) { + if (data->enhancedPacketLength + data->packetLength + > (12 * 188)) { + memset(dataBuffer, 0, 22); + dataBuffer[22] = 0x60; + dataBuffer[23] = 0x4b; + length = 24; + } else { + memcpy(dataBuffer, data->packetData, data->packetLength); + length = data->packetLength; + data->packetLength = 0; + } + } else { + memcpy(dataBuffer, data->packetData, data->packetLength); + length = data->packetLength; + data->packetLength = 0; + } + if (data->enhancedPacketData != NULL) { + indexCol = data->enhancedPacketLength / 12; + indexRow = data->enhancedPacketLength % 12; // TODO Check if always 0 + for (int j = 0; j < length; ++j) { + data->enhancedPacketData[indexRow][indexCol] = dataBuffer[j]; + if (++indexRow == 12) { + indexRow = 0; + ++indexCol; + } + } + data->enhancedPacketLength += length; + if (data->enhancedPacketLength >= (12 * 188)) { + data->enhancedPacketLength = (12 * 188); + ReedSolomon encoder(204, 188); + for (int j = 0; j < 12; ++j) { + encoder.encode(data->enhancedPacketData[j], 188); + } + data->enhancedPacketWaiting = 192; + } + } + written += length; + dataBuffer += length; + } else { + int nbBytes = ops->read(args, dataBuffer, 3); + header = (packetHeader*)dataBuffer; + if (nbBytes == -1) { + if (errno == EAGAIN) goto END_PACKET; + perror("Packet file"); + return -1; + } else if (nbBytes == 0) { + if (ops->rewind(args) == -1) { + goto END_PACKET; + } + continue; + } else if (nbBytes < 3) { + etiLog.print(TcpLog::ERR, + "Error while reading file for packet header; " + "read %i out of 3 bytes\n", nbBytes); + break; + } + + length = header->packetLength * 24 + 24; + if (written + length > size) { + memcpy(data->packetData, header, 3); + ops->read(args, &data->packetData[3], length - 3); + data->packetLength = length; + continue; + } + if (data->enhancedPacketData != NULL) { + if (data->enhancedPacketLength + length > (12 * 188)) { + memcpy(data->packetData, header, 3); + ops->read(args, &data->packetData[3], length - 3); + data->packetLength = length; + continue; + } + } + nbBytes = ops->read(args, dataBuffer + 3, length - 3); + if (nbBytes == -1) { + perror("Packet file"); + return -1; + } else if (nbBytes == 0) { + etiLog.print(TcpLog::NOTICE, + "Packet header read, but no data!\n"); + if (ops->rewind(args) == -1) { + goto END_PACKET; + } + continue; + } else if (nbBytes < length - 3) { + etiLog.print(TcpLog::ERR, "Error while reading packet file; " + "read %i out of %i bytes\n", nbBytes, length - 3); + break; + } + if (data->enhancedPacketData != NULL) { + indexCol = data->enhancedPacketLength / 12; + indexRow = data->enhancedPacketLength % 12; // TODO Check if always 0 + for (int j = 0; j < length; ++j) { + data->enhancedPacketData[indexRow][indexCol] = dataBuffer[j]; + if (++indexRow == 12) { + indexRow = 0; + ++indexCol; + } + } + data->enhancedPacketLength += length; + if (data->enhancedPacketLength >= (12 * 188)) { + if (data->enhancedPacketLength > (12 * 188)) { + etiLog.print(TcpLog::ERR, + "Error, too much enhanced packet data!\n"); + } + ReedSolomon encoder(204, 188); + for (int j = 0; j < 12; ++j) { + encoder.encode(data->enhancedPacketData[j], 188); + } + data->enhancedPacketWaiting = 192; + } + } + written += length; + dataBuffer += length; + } + } +END_PACKET: + if (ops->read == dabInputFifoRead) { + dabInputFifoData* fifoData = (dabInputFifoData*)args; + dabInputFifoStats* fifoStats = (dabInputFifoStats*)&fifoData->stats; + fifoStats->frameRecords[fifoStats->frameCount].curSize = written; + fifoStats->frameRecords[fifoStats->frameCount].maxSize = size; + if (++fifoStats->frameCount == NB_RECORDS) { + etiLog.print(TcpLog::INFO, "Packet subchannel usage: (%i)", + fifoStats->id); + for (int i = 0; i < fifoStats->frameCount; ++i) { + etiLog.print(TcpLog::INFO, " %i/%i", + fifoStats->frameRecords[i].curSize, + fifoStats->frameRecords[i].maxSize); + } + etiLog.print(TcpLog::INFO, "\n"); + fifoStats->frameCount = 0; + } + } + while (written < size) { + memset(dataBuffer, 0, 22); + dataBuffer[22] = 0x60; + dataBuffer[23] = 0x4b; + dataBuffer += 24; + written += 24; + } + return written; +} + + +# endif +#endif diff --git a/src/dabInputPacketFile.h b/src/dabInputPacketFile.h new file mode 100644 index 0000000..9559ac1 --- /dev/null +++ b/src/dabInputPacketFile.h @@ -0,0 +1,46 @@ +/* + Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications + Research Center Canada) + */ +/* + This file is part of CRC-DabMux. + + CRC-DabMux is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + CRC-DabMux is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CRC-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef DAB_INPUT_PACKET_FILE_H +#define DAB_INPUT_PACKET_FILE_H + + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#include "dabInput.h" + + +#ifdef HAVE_FORMAT_PACKET +# ifdef HAVE_INPUT_FILE + + +extern struct dabInputOperations dabInputPacketFileOperations; + +int dabInputPacketFileRead(dabInputOperations* ops, void* args, void* buffer, + int size); + + +# endif +#endif + + +#endif // DAB_INPUT_PACKET_FILE_H diff --git a/src/dabInputPrbs.cpp b/src/dabInputPrbs.cpp new file mode 100644 index 0000000..3b7a0dc --- /dev/null +++ b/src/dabInputPrbs.cpp @@ -0,0 +1,146 @@ +/* + Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications + Research Center Canada) + */ +/* + This file is part of CRC-DabMux. + + CRC-DabMux is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + CRC-DabMux is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CRC-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "dabInputPrbs.h" + +#include <string.h> +#include <limits.h> +#include <stdlib.h> + + +#ifdef HAVE_FORMAT_RAW +# ifdef HAVE_INPUT_PRBS + + +struct dabInputOperations dabInputPrbsOperations = { + dabInputPrbsInit, + dabInputPrbsOpen, + NULL, + dabInputPrbsRead, + NULL, + NULL, + dabInputPrbsReadFrame, + dabInputPrbsBitrate, + dabInputPrbsClose, + dabInputPrbsClean, + dabInputPrbsRewind, +}; + + +int dabInputPrbsInit(void** args) +{ + prbs_data* data = new prbs_data; + + memset(data, 0, sizeof(*data)); + + *args = data; + return 0; +} + + +int dabInputPrbsOpen(void* args, const char* name) +{ + prbs_data* data = (prbs_data*)args; + + if (*name != ':') { + etiLog.print(TcpLog::ERR, + "Sorry, PRBS address format is prbs://:polynomial.\n"); + errno = EINVAL; + return -1; + } + + long polynomial = strtol(++name, (char **)NULL, 10); + if ((polynomial == LONG_MIN) || (polynomial == LONG_MAX)) { + etiLog.print(TcpLog::ERR, "can't convert polynomial number %s\n", name); + errno = EINVAL; + return -1; + } + if (polynomial == 0) { + etiLog.print(TcpLog::ERR, "you must specify a polynomial number\n"); + errno = EINVAL; + return -1; + } + + data->polynomial = polynomial; + data->accum = 0; + gen_prbs_table(data); + gen_weight_table(data); + dabInputPrbsRewind(args); + + return 0; +} + + +int dabInputPrbsRead(void* args, void* buffer, int size) +{ + prbs_data* data = (prbs_data*)args; + unsigned char* cbuffer = reinterpret_cast<unsigned char*>(buffer); + + for(int i = 0; i < size; ++i) { + data->accum = update_prbs(args); + *(cbuffer++) = (unsigned char)(data->accum & 0xff); + } + + return size; +} + + +int dabInputPrbsReadFrame(dabInputOperations* ops, void* args, + void* buffer, int size) +{ + return ops->read(args, buffer, size); +} + + +int dabInputPrbsBitrate(dabInputOperations* ops, void* args, int bitrate) +{ + return bitrate; +} + + +int dabInputPrbsClose(void* args) +{ + return 0; +} + + +int dabInputPrbsClean(void** args) +{ + delete (prbs_data*)(*args); + return 0; +} + + +int dabInputPrbsRewind(void* args) +{ + prbs_data* data = (prbs_data*)args; + + while (data->accum < data->polynomial) { + data->accum <<= 1; + data->accum |= 1; + } + + return 0; +} + + +# endif +#endif diff --git a/src/dabInputPrbs.h b/src/dabInputPrbs.h new file mode 100644 index 0000000..e51b79f --- /dev/null +++ b/src/dabInputPrbs.h @@ -0,0 +1,56 @@ +/* + Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications + Research Center Canada) + */ +/* + This file is part of CRC-DabMux. + + CRC-DabMux is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + CRC-DabMux is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CRC-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef DAB_INPUT_PRBS_H +#define DAB_INPUT_PRBS_H + + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#include "dabInput.h" +#include "prbs.h" + +#include <errno.h> + + +#ifdef HAVE_FORMAT_RAW +# ifdef HAVE_INPUT_PRBS + + +extern struct dabInputOperations dabInputPrbsOperations; + +int dabInputPrbsInit(void** args); +int dabInputPrbsOpen(void* args, const char* name); +int dabInputPrbsRead(void* args, void* buffer, int size); +int dabInputPrbsReadFrame(dabInputOperations* ops, void* args, + void* buffer, int size); +int dabInputPrbsBitrate(dabInputOperations* ops, void* args, int bitrate); +int dabInputPrbsClose(void* args); +int dabInputPrbsClean(void** args); +int dabInputPrbsRewind(void* args); + + +# endif +#endif + + +#endif // DAB_INPUT_PRBS_H diff --git a/src/dabInputRawFifo.cpp b/src/dabInputRawFifo.cpp new file mode 100644 index 0000000..b40e14d --- /dev/null +++ b/src/dabInputRawFifo.cpp @@ -0,0 +1,193 @@ +/* + Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications + Research Center Canada) + */ +/* + This file is part of CRC-DabMux. + + CRC-DabMux is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + CRC-DabMux is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CRC-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "dabInputRawFifo.h" + +#include <unistd.h> +#include <stdio.h> +#include <fcntl.h> +#include <string.h> + +#ifndef _WIN32 +# define O_BINARY 0 +#endif + + +#ifdef HAVE_FORMAT_RAW +# ifdef HAVE_INPUT_FILE + + +struct dabInputOperations dabInputRawFifoOperations = { + dabInputRawFifoInit, + dabInputRawFifoOpen, + dabInputRawFifoSetbuf, + dabInputRawFifoRead, + NULL, + NULL, + dabInputRawFifoReadFrame, + dabInputSetbitrate, + dabInputRawFifoClose, + dabInputRawFifoClean, + dabInputRawFifoRewind +}; + + +int dabInputRawFifoInit(void** args) +{ + dabInputRawFifoData* data = new dabInputRawFifoData; + data->file = -1; + data->buffer = NULL; + data->bufferSize = 0; + data->bufferOffset = 0; + + *args = data; + return 0; +} + + +int dabInputRawFifoOpen(void* args, const char* filename) +{ + dabInputRawFifoData* data = (dabInputRawFifoData*)args; + data->file = open(filename, O_RDONLY | O_BINARY | O_NONBLOCK); + if (data->file == -1) { + perror(filename); + return -1; + } +#ifdef _WIN32 +#else + int flags = fcntl(data->file, F_GETFL); + if (flags == -1) { + perror(filename); + return -1; + } + if (fcntl(data->file, F_SETFL, flags & ~O_NONBLOCK) == -1) { + perror(filename); + return -1; + } +#endif + + return 0; +} + + +int dabInputRawFifoSetbuf(void* args, int size) +{ + dabInputRawFifoData* data = (dabInputRawFifoData*)args; + + if (size <= 0) { + return size; + } + + if (data->bufferSize != size) { + if (data->buffer != NULL) { + delete[] data->buffer; + } + data->buffer = new uint8_t[size]; + data->bufferSize = size; + data->bufferOffset = 0; + } + + return 0; +} + + +int dabInputRawFifoRead(void* args, void* buffer, int size) +{ + dabInputRawFifoData* data = (dabInputRawFifoData*)args; + + return read(data->file, buffer, size); +} + + +int dabInputRawFifoReadFrame(dabInputOperations* ops, void* args, + void* buffer, int size) +{ + dabInputRawFifoData* data = (dabInputRawFifoData*)args; + int result; + + result = ops->read(args, data->buffer + data->bufferOffset, size - data->bufferOffset); + if (result == -1) { + etiLog.print(TcpLog::CRIT, "ERROR: Can't read fifo\n"); + perror(""); + return -1; + } + + if (result + data->bufferOffset < size) { + data->bufferOffset += result; + + etiLog.print(TcpLog::NOTICE, "reach end of fifo -> rewinding\n"); + if (ops->rewind(args) == -1) { + etiLog.print(TcpLog::CRIT, "ERROR: Can't rewind fifo\n"); + return -1; + } + + result = ops->read(args, data->buffer + data->bufferOffset, size - data->bufferOffset); + if (result == -1) { + etiLog.print(TcpLog::CRIT, "ERROR: Can't read fifo\n"); + perror(""); + return -1; + } + + if (result < size) { + etiLog.print(TcpLog::CRIT, "ERROR: Not enought data in fifo\n"); + return 0; + } + } + + memcpy(buffer, data->buffer, size); + data->bufferOffset = 0; + + return size; +} + + +int dabInputRawFifoClose(void* args) +{ + dabInputRawFifoData* data = (dabInputRawFifoData*)args; + + if (data->file != -1) { + close(data->file); + data->file = -1; + } + return 0; +} + + +int dabInputRawFifoClean(void** args) +{ + dabInputRawFifoData* data = (dabInputRawFifoData*)*args; + if (data->buffer != NULL) { + delete[] data->buffer; + } + delete data; + return 0; +} + + +int dabInputRawFifoRewind(void* args) +{ + dabInputRawFifoData* data = (dabInputRawFifoData*)args; + return lseek(data->file, 0, SEEK_SET); +} + + +# endif +#endif diff --git a/src/dabInputRawFifo.h b/src/dabInputRawFifo.h new file mode 100644 index 0000000..4afe55d --- /dev/null +++ b/src/dabInputRawFifo.h @@ -0,0 +1,63 @@ +/* + Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications + Research Center Canada) + */ +/* + This file is part of CRC-DabMux. + + CRC-DabMux is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + CRC-DabMux is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CRC-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef DAB_INPUT_RAW_FIFO_H +#define DAB_INPUT_RAW_FIFO_H + + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "dabInput.h" + +#include <stdint.h> + + +#ifdef HAVE_FORMAT_RAW +# ifdef HAVE_INPUT_FILE + + +extern struct dabInputOperations dabInputRawFifoOperations; + +int dabInputRawFifoInit(void** args); +int dabInputRawFifoOpen(void* args, const char* filename); +int dabInputRawFifoSetbuf(void* args, int size); +int dabInputRawFifoRead(void* args, void* buffer, int size); +int dabInputRawFifoReadFrame(dabInputOperations* ops, void* args, + void* buffer, int size); +int dabInputRawFifoClose(void* args); +int dabInputRawFifoClean(void** args); +int dabInputRawFifoRewind(void* args); + + +struct dabInputRawFifoData { + int file; + uint8_t* buffer; + size_t bufferSize; + size_t bufferOffset; +}; + + +# endif +#endif + +#endif // DAB_INPUT_RAW_FIFO_H diff --git a/src/dabInputRawFile.cpp b/src/dabInputRawFile.cpp new file mode 100644 index 0000000..17be73c --- /dev/null +++ b/src/dabInputRawFile.cpp @@ -0,0 +1,59 @@ +/* + Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications + Research Center Canada) + */ +/* + This file is part of CRC-DabMux. + + CRC-DabMux is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + CRC-DabMux is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CRC-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "dabInputRawFile.h" +#include "dabInputFile.h" + + +#ifdef HAVE_FORMAT_RAW +# ifdef HAVE_INPUT_FILE + + +struct dabInputOperations dabInputRawFileOperations = { + dabInputFileInit, + dabInputFileOpen, + dabInputSetbuf, + dabInputFileRead, + NULL, + NULL, + dabInputRawFileRead, + dabInputSetbitrate, + dabInputFileClose, + dabInputFileClean, + dabInputFileRewind +}; + + +int dabInputRawFileRead(dabInputOperations* ops, void* args, void* buffer, + int size) +{ + int ret = ops->read(args, buffer, size); + if (ret == 0) { + etiLog.print(TcpLog::NOTICE, "reach end of raw file -> rewinding\n"); + ops->rewind(args); + ret = ops->read(args, buffer, size); + } + return ret; +} + + +# endif +#endif diff --git a/src/dabInputRawFile.h b/src/dabInputRawFile.h new file mode 100644 index 0000000..e75f962 --- /dev/null +++ b/src/dabInputRawFile.h @@ -0,0 +1,45 @@ +/* + Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications + Research Center Canada) + */ +/* + This file is part of CRC-DabMux. + + CRC-DabMux is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + CRC-DabMux is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CRC-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef DAB_INPUT_RAW_FILE_H +#define DAB_INPUT_RAW_FILE_H + + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#include "dabInput.h" + + +#ifdef HAVE_FORMAT_RAW +# ifdef HAVE_INPUT_FILE + + +extern struct dabInputOperations dabInputRawFileOperations; + +int dabInputRawFileRead(dabInputOperations* ops, void* args, void* buffer, + int size); + + +# endif +#endif + +#endif // DAB_INPUT_RAW_FILE_H diff --git a/src/dabInputSlip.cpp b/src/dabInputSlip.cpp new file mode 100644 index 0000000..7663d2c --- /dev/null +++ b/src/dabInputSlip.cpp @@ -0,0 +1,408 @@ +/* + Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications + Research Center Canada) + */ +/* + This file is part of CRC-DabMux. + + CRC-DabMux is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + CRC-DabMux is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CRC-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "dabInputSlip.h" +#include "dabInputFifo.h" +#include "TcpServer.h" +#include "UdpSocket.h" +#include "bridge.h" + +#include <signal.h> +#include <string.h> +#include <limits.h> + + +#ifdef _WIN32 +# include <io.h> + +# define sem_t HANDLE +# define O_NONBLOCK 0 +#else +# include <semaphore.h> +# define O_BINARY 0 +#endif + + +struct dabInputSlipData { + TcpServer* server; + UdpPacket** packets; + UdpPacket* buffer; + bridgeInfo* info; + dabInputFifoStats stats; + pthread_t thread; + sem_t semWrite; + sem_t semQueue; + bool reading; + volatile int nbPackets; + volatile int queueSize; + volatile int packetSize; +}; + + +struct dabInputOperations dabInputSlipOperations = { + dabInputSlipInit, + dabInputSlipOpen, + dabInputSlipSetbuf, + dabInputSlipRead, + NULL, + NULL, + dabInputSlipReadFrame, + dabInputSetbitrate, + dabInputSlipClose, + dabInputSlipClean, + NULL +}; + + +int dabInputSlipInit(void** args) +{ + dabInputSlipData* data = new dabInputSlipData; + memset(&data->stats, 0, sizeof(data->stats)); + data->stats.id = dabInputFifoData::nb++; + data->server = new TcpServer(); + data->packetSize = 1500; + data->queueSize = 10; + data->packets = new UdpPacket*[data->queueSize]; + for (int i = 0; i < data->queueSize; ++i) { + data->packets[i] = new UdpPacket(data->packetSize); + } + data->buffer = new UdpPacket(data->packetSize); + data->nbPackets = 0; + data->info = new bridgeInfo; + data->thread = (pthread_t)NULL; + bridgeInitInfo(data->info); + +#ifdef _WIN32 + char semName[32]; + sprintf(semName, "semWrite%i", data->stats.id); + data->semWrite = CreateSemaphore(NULL, 1, 1, semName); + if (data->semWrite == NULL) { + fprintf(stderr, "Can't init SLIP data write semaphore %s\n", semName); + return -1; + } + sprintf(semName, "semQueue%i", data->stats.id); + data->semQueue = CreateSemaphore(NULL, 1, 1, semName); + if (data->semQueue == NULL) { + fprintf(stderr, "Can't init SLIP data index semaphore %s\n", semName); + return -1; + } +#else + if (sem_init(&data->semWrite, 0, data->queueSize) == -1) { + perror("Can't init SLIP data write semaphore"); + return -1; + } + if (sem_init(&data->semQueue, 0, 1) == -1) { + perror("Can't init SLIP data index semaphore"); + return -1; + } +#endif + data->reading = false; + + *args = data; + return 0; +} + + +void* dabInputSlipThread(void* args) +{ + dabInputSlipData* data = (dabInputSlipData*)args; + TcpSocket* client; + + while ((client = data->server->accept()) != NULL) { + int size = 0; + etiLog.print(TcpLog::INFO, "SLIP server got a new client.\n"); + +#ifdef _WIN32 + WaitForSingleObject(data->semWrite, INFINITE); + WaitForSingleObject(data->semQueue, INFINITE); +#else + sem_wait(&data->semWrite); + sem_wait(&data->semQueue); +#endif + UdpPacket* packet = data->packets[data->nbPackets]; +#ifdef _WIN32 + ReleaseSemaphore(data->semQueue, 1, NULL); +#else + sem_post(&data->semQueue); +#endif + + while ((size = client->read(packet->getData(), packet->getSize())) + > 0) { + packet->setLength(size); +#ifdef _WIN32 + WaitForSingleObject(data->semQueue, INFINITE); +#else + sem_wait(&data->semQueue); +#endif + data->nbPackets++; +#ifdef _WIN32 + ReleaseSemaphore(data->semQueue, 1, NULL); +#else + sem_post(&data->semQueue); +#endif + +#ifdef _WIN32 + WaitForSingleObject(data->semWrite, INFINITE); + WaitForSingleObject(data->semQueue, INFINITE); +#else + sem_wait(&data->semWrite); + sem_wait(&data->semQueue); +#endif + packet = data->packets[data->nbPackets]; +#ifdef _WIN32 + ReleaseSemaphore(data->semQueue, 1, NULL); +#else + sem_post(&data->semQueue); +#endif + } + etiLog.print(TcpLog::INFO, "SLIP server client deconnected.\n"); + client->close(); + } + etiLog.print(TcpLog::ERR, "SLIP thread can't accept new client (%s)\n", + inetErrDesc, inetErrMsg); + + return NULL; +} + + +int dabInputSlipOpen(void* args, const char* inputName) +{ + const char* address; + long port; + address = strchr(inputName, ':'); + if (address == NULL) { + etiLog.print(TcpLog::ERR, "\"%s\" SLIP address format is invalid: " + "should be [address]:port - > aborting\n", inputName); + return -1; + } + ++address; + port = strtol(address, (char **)NULL, 10); + if ((port == LONG_MIN) || (port == LONG_MAX)) { + etiLog.print(TcpLog::ERR, "can't convert port number in SLIP address %s\n", + address); + return -1; + } + if (port == 0) { + etiLog.print(TcpLog::ERR, "can't use port number 0 in SLIP address\n"); + return -1; + } + dabInputSlipData* data = (dabInputSlipData*)args; + if (data->server->create(port) == -1) { + etiLog.print(TcpLog::ERR, "can't set port %i on SLIP input (%s: %s)\n", + port, inetErrDesc, inetErrMsg); + return -1; + } + + if (data->server->listen() == -1) { + etiLog.print(TcpLog::ERR, "can't listen on SLIP socket(%s: %s)\n", + inetErrDesc, inetErrMsg); + return -1; + } +#ifdef _WIN32 + data->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)dabInputSlipThread, data, 0, NULL); + if (data->thread == NULL) { + fprintf(stderr, "Can't create SLIP child"); + return -1; + } +#else + if (pthread_create(&data->thread, NULL, dabInputSlipThread, data)) { + perror("Can't create SLIP child"); + return -1; + } +#endif + + etiLog.print(TcpLog::DBG, "check return code of create\n"); + return 0; +} + + +int dabInputSlipSetbuf(void* args, int size) +{ + dabInputSlipData* data = (dabInputSlipData*)args; + + if (size <= 10) { + return -1; + } + + data->packetSize = size - 10; + if (data->packets == NULL) { + data->packets = new UdpPacket*[data->queueSize]; + } + for (int i = 0; i < data->queueSize; ++i) { + if (data->packets[i] == NULL) { + data->packets[i] = new UdpPacket(data->packetSize); + } else { + data->packets[i]->setSize(data->packetSize); + } + } + if (data->buffer == NULL) { + data->buffer = new UdpPacket(data->packetSize); + } else { + data->buffer->setSize(data->packetSize); + } + + return 0; +} + + +int dabInputSlipRead(void* args, void* buffer, int size) +{ + dabInputSlipData* data = (dabInputSlipData*)args; + + if (data->nbPackets > 0) { // data ready + UdpPacket* temp; + temp = data->buffer; + data->buffer = data->packets[0]; + +#ifdef _WIN32 + WaitForSingleObject(data->semQueue, INFINITE); +#else + sem_wait(&data->semQueue); +#endif + for (int i = 1; i < data->queueSize; ++i) { + data->packets[i - 1] = data->packets[i]; + } + data->packets[data->queueSize - 1] = temp; + --data->nbPackets; +#ifdef _WIN32 + ReleaseSemaphore(data->semQueue, 1, NULL); + ReleaseSemaphore(data->semWrite, 1, NULL); +#else + sem_post(&data->semQueue); + sem_post(&data->semWrite); +#endif + } else { + data->buffer->setLength(0); + } + + return data->buffer->getLength(); +} + + +int dabInputSlipReadFrame(dabInputOperations* ops, void* args, void* buffer, int size) +{ + int nbBytes = 0; + dabInputSlipData* data = (dabInputSlipData*)args; + dabInputFifoStats* stats = (dabInputFifoStats*)&data->stats; + +#ifdef _WIN32 + WaitForSingleObject(data->semQueue, INFINITE); +#else + sem_wait(&data->semQueue); +#endif + stats->bufferRecords[stats->bufferCount].curSize = data->nbPackets; + stats->bufferRecords[stats->bufferCount].maxSize = data->queueSize; +#ifdef _WIN32 + ReleaseSemaphore(data->semQueue, 1, NULL); +#else + sem_post(&data->semQueue); +#endif + if (++stats->bufferCount == NB_RECORDS) { + etiLog.print(TcpLog::INFO, "SLIP buffer state: (%i)", stats->id); + for (int i = 0; i < stats->bufferCount; ++i) { + etiLog.print(TcpLog::INFO, " %i/%i", + stats->bufferRecords[i].curSize, + stats->bufferRecords[i].maxSize); + } + etiLog.print(TcpLog::INFO, "\n"); + + stats->bufferCount = 0; + } + + data->stats.frameRecords[data->stats.frameCount].curSize = 0; + data->stats.frameRecords[data->stats.frameCount].maxSize = size; + + if (data->buffer->getLength() == 0) { + ops->read(args, NULL, 0); + } + while ((nbBytes = writePacket(data->buffer->getData(), + data->buffer->getLength(), buffer, size, data->info)) + != 0) { + data->stats.frameRecords[data->stats.frameCount].curSize = nbBytes; + ops->read(args, NULL, 0); + } + + if (data->buffer->getLength() != 0) { + data->stats.frameRecords[data->stats.frameCount].curSize = size; + } + + if (++stats->frameCount == NB_RECORDS) { + etiLog.print(TcpLog::INFO, "Data subchannel usage: (%i)", + stats->id); + for (int i = 0; i < stats->frameCount; ++i) { + etiLog.print(TcpLog::INFO, " %i/%i", + stats->frameRecords[i].curSize, + stats->frameRecords[i].maxSize); + } + etiLog.print(TcpLog::INFO, "\n"); + stats->frameCount = 0; + } + return size; +} + + +int dabInputSlipClose(void* args) +{ + dabInputSlipData* data = (dabInputSlipData*)args; + data->server->close(); +#ifdef WIN32 + DWORD status; + for (int i = 0; i < 5; ++i) { + if (GetExitCodeThread(data->thread, &status)) { + break; + } + Sleep(100); + } + TerminateThread(data->thread, 1); +#else + if (data->thread != (pthread_t)NULL) { + pthread_kill(data->thread, SIGPIPE); + } +#endif + return 0; +} + + +int dabInputSlipClean(void** args) +{ + dabInputSlipData* data = (dabInputSlipData*)(*args); +#ifdef _WIN32 + CloseHandle(data->thread); + CloseHandle(data->semWrite); + CloseHandle(data->semQueue); +#else + sem_destroy(&data->semWrite); + sem_destroy(&data->semQueue); +#endif + for (int i = 0; i < data->queueSize; ++i) { + if (data->packets[i] != NULL) { + delete data->packets[i]; + } + } + delete []data->packets; + delete data->buffer; + delete data->server; + delete data->info; + delete data; + return 0; +} + + diff --git a/src/dabInputSlip.h b/src/dabInputSlip.h new file mode 100644 index 0000000..bcaf0d1 --- /dev/null +++ b/src/dabInputSlip.h @@ -0,0 +1,52 @@ +/* + Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications + Research Center Canada) + */ +/* + This file is part of CRC-DabMux. + + CRC-DabMux is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + CRC-DabMux is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CRC-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef DAB_INPUT_SLIP_H +#define DAB_INPUT_SLIP_H + + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#include "dabInput.h" + + +#ifdef HAVE_FORMAT_BRIDGE +# ifdef HAVE_INPUT_SLIP + + +extern struct dabInputOperations dabInputSlipOperations; + +int dabInputSlipInit(void** args); +void* dabInputSlipThread(void* args); +int dabInputSlipOpen(void* args, const char* inputName); +int dabInputSlipSetbuf(void* args, int size); +int dabInputSlipRead(void* args, void* buffer, int size); +int dabInputSlipReadFrame(dabInputOperations* ops, void* args, void* buffer, int size); +int dabInputSlipClose(void* args); +int dabInputSlipClean(void** args); + + +# endif +#endif + + +#endif // DAB_INPUT_SLIP_H diff --git a/src/dabInputTest.cpp b/src/dabInputTest.cpp new file mode 100644 index 0000000..78adaa8 --- /dev/null +++ b/src/dabInputTest.cpp @@ -0,0 +1,105 @@ +/* + Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications + Research Center Canada) + */ +/* + This file is part of CRC-DabMux. + + CRC-DabMux is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + CRC-DabMux is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CRC-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "dabInputTest.h" + +#include <string.h> +#ifdef _WIN32 +#else +# include <arpa/inet.h> +#endif + + +#ifdef HAVE_FORMAT_RAW +# ifdef HAVE_INPUT_TEST + + +struct dabInputTestData { + unsigned long counter; +}; + + +struct dabInputOperations dabInputTestOperations = { + dabInputTestInit, + dabInputTestOpen, + NULL, + NULL, + NULL, + NULL, + dabInputTestRead, + dabInputTestSetbitrate, + dabInputTestClose, + dabInputTestClean, + NULL +}; + + +int dabInputTestInit(void** args) +{ + dabInputTestData* input = new dabInputTestData; + memset(input, 0, sizeof(*input)); + input->counter = 0; + *args = input; + return 0; +} + + +int dabInputTestOpen(void* args, const char* inputName) +{ + return 0; +} + + +int dabInputTestRead(dabInputOperations* ops, void* args, void* buffer, int size) +{ + dabInputTestData* input = (dabInputTestData*)args; + char* data = (char*)buffer; + + *((long*)buffer) = htonl(input->counter++); + for (int i = sizeof(input->counter); i < size; ++i) { + data[i] = i; + } + return size; +} + + +int dabInputTestSetbitrate(dabInputOperations* ops, void* args, int bitrate) +{ + return bitrate; +} + + +int dabInputTestClose(void* args) +{ + return 0; +} + + +int dabInputTestClean(void** args) +{ + dabInputTestData* input = (dabInputTestData*)(*args); + delete input; + return 0; +} + + +# endif +#endif diff --git a/src/dabInputTest.h b/src/dabInputTest.h new file mode 100644 index 0000000..5e21e80 --- /dev/null +++ b/src/dabInputTest.h @@ -0,0 +1,50 @@ +/* + Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications + Research Center Canada) + */ +/* + This file is part of CRC-DabMux. + + CRC-DabMux is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + CRC-DabMux is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CRC-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef DAB_INPUT_TEST_H +#define DAB_INPUT_TEST_H + + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#include "dabInput.h" + + +#ifdef HAVE_FORMAT_RAW +# ifdef HAVE_INPUT_TEST + + +extern struct dabInputOperations dabInputTestOperations; + +int dabInputTestInit(void** args); +int dabInputTestOpen(void* args, const char* inputName); +int dabInputTestRead(dabInputOperations* ops, void* args, void* buffer, int size); +int dabInputTestSetbitrate(dabInputOperations* ops, void* args, int bitrate); +int dabInputTestClose(void* args); +int dabInputTestClean(void** args); + + +# endif +#endif + + +#endif // DAB_INPUT_TEST_H diff --git a/src/dabInputUdp.cpp b/src/dabInputUdp.cpp new file mode 100644 index 0000000..b128584 --- /dev/null +++ b/src/dabInputUdp.cpp @@ -0,0 +1,189 @@ +/* + Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications + Research Center Canada) + */ +/* + This file is part of CRC-DabMux. + + CRC-DabMux is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + CRC-DabMux is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CRC-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "dabInputUdp.h" + +#include <string.h> +#include <limits.h> + + +#ifdef __MINGW32__ +# define bzero(s, n) memset(s, 0, n) +#endif + +#ifdef HAVE_FORMAT_RAW +# ifdef HAVE_INPUT_UDP + + +struct dabInputOperations dabInputUdpOperations = { + dabInputUdpInit, + dabInputUdpOpen, + dabInputSetbuf, + NULL, + NULL, + NULL, + dabInputUdpRead, + dabInputSetbitrate, + dabInputUdpClose, + dabInputUdpClean, + NULL +}; + + +int dabInputUdpInit(void** args) +{ + dabInputUdpData* input = new dabInputUdpData; + memset(&input->stats, 0, sizeof(input->stats)); + input->stats.id = dabInputFifoData::nb++; + input->socket = new UdpSocket(); + input->packet = new UdpPacket(2048); + *args = input; + + UdpSocket::init(); + return 0; +} + + +int dabInputUdpOpen(void* args, const char* inputName) +{ + int returnCode = 0; + char* address; + char* ptr; + long port; + address = strdup(inputName); + ptr = strchr(address, ':'); + if (ptr == NULL) { + etiLog.print(TcpLog::ERR, + "\"%s\" is an invalid format for udp address: " + "should be [address]:port - > aborting\n", address); + returnCode = -1; + } + *(ptr++) = 0; + port = strtol(ptr, (char **)NULL, 10); + if ((port == LONG_MIN) || (port == LONG_MAX)) { + etiLog.print(TcpLog::ERR, + "can't convert port number in udp address %s\n", + address); + returnCode = -1; + } + if (port == 0) { + etiLog.print(TcpLog::ERR, "can't use port number 0 in udp address\n"); + returnCode = -1; + } + dabInputUdpData* input = (dabInputUdpData*)args; + if (input->socket->create(port) == -1) { + etiLog.print(TcpLog::ERR, "can't set port %i on Udp input (%s: %s)\n", + port, inetErrDesc, inetErrMsg); + returnCode = -1; + } + + if (*address != 0) { + if (input->socket->joinGroup(address) == -1) { + etiLog.print(TcpLog::ERR, + "can't join multicast group %s (%s: %s)\n", + address, inetErrDesc, inetErrMsg); + returnCode = -1; + } + } + + if (input->socket->setBlocking(false) == -1) { + etiLog.print(TcpLog::ERR, "can't set Udp input socket in blocking mode " + "(%s: %s)\n", inetErrDesc, inetErrMsg); + returnCode = -1; + } + + free(address); + etiLog.print(TcpLog::DBG, "check return code of create\n"); + return returnCode;; +} + + +int dabInputUdpRead(dabInputOperations* ops, void* args, void* buffer, int size) +{ + int nbBytes = 0; + uint8_t* data = reinterpret_cast<uint8_t*>(buffer); + + dabInputUdpData* input = (dabInputUdpData*)args; + dabInputFifoStats* stats = (dabInputFifoStats*)&input->stats; + + input->stats.frameRecords[input->stats.frameCount].curSize = 0; + input->stats.frameRecords[input->stats.frameCount].maxSize = size; + + if (input->packet->getLength() == 0) { + input->socket->receive(*input->packet); + } + + while (nbBytes < size) { + unsigned freeSize = size - nbBytes; + if (input->packet->getLength() > freeSize) { + // Not enought place in output + memcpy(&data[nbBytes], input->packet->getData(), freeSize); + nbBytes = size; + input->packet->setOffset(input->packet->getOffset() + freeSize); + } else { + unsigned length = input->packet->getLength(); + memcpy(&data[nbBytes], input->packet->getData(), length); + nbBytes += length; + input->packet->setOffset(0); + input->socket->receive(*input->packet); + if (input->packet->getLength() == 0) { + break; + } + } + } + input->stats.frameRecords[input->stats.frameCount].curSize = nbBytes; + bzero(&data[nbBytes], size - nbBytes); + + input->stats.frameRecords[input->stats.frameCount].curSize = nbBytes; + if (++stats->frameCount == NB_RECORDS) { + etiLog.print(TcpLog::INFO, "Data subchannel usage: (%i)", + stats->id); + for (int i = 0; i < stats->frameCount; ++i) { + etiLog.print(TcpLog::INFO, " %i/%i", + stats->frameRecords[i].curSize, + stats->frameRecords[i].maxSize); + } + etiLog.print(TcpLog::INFO, "\n"); + stats->frameCount = 0; + } + + return size; +} + + +int dabInputUdpClose(void* args) +{ + return 0; +} + + +int dabInputUdpClean(void** args) +{ + dabInputUdpData* input = (dabInputUdpData*)(*args); + delete input->socket; + delete input->packet; + delete input; + return 0; +} + + +# endif +#endif diff --git a/src/dabInputUdp.h b/src/dabInputUdp.h new file mode 100644 index 0000000..c0de1dd --- /dev/null +++ b/src/dabInputUdp.h @@ -0,0 +1,59 @@ +/* + Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications + Research Center Canada) + */ +/* + This file is part of CRC-DabMux. + + CRC-DabMux is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + CRC-DabMux is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CRC-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef DAB_INPUT_UDP_H +#define DAB_INPUT_UDP_H + + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#include "dabInput.h" +#include "dabInputFifo.h" +#include "UdpSocket.h" + + +#ifdef HAVE_FORMAT_RAW +# ifdef HAVE_INPUT_UDP + + +extern struct dabInputOperations dabInputUdpOperations; + + +struct dabInputUdpData { + UdpSocket* socket; + UdpPacket* packet; + dabInputFifoStats stats; +}; + + +int dabInputUdpInit(void** args); +int dabInputUdpOpen(void* args, const char* inputName); +int dabInputUdpRead(dabInputOperations* ops, void* args, void* buffer, int size); +int dabInputUdpClose(void* args); +int dabInputUdpClean(void** args); + + +# endif +#endif + + +#endif // DAB_INPUT_UDP_H diff --git a/src/dabOutput.cpp b/src/dabOutput.cpp new file mode 100644 index 0000000..5351501 --- /dev/null +++ b/src/dabOutput.cpp @@ -0,0 +1,1112 @@ +/* + Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Her Majesty the Queen in + Right of Canada (Communications Research Center Canada) + */ +/* + This file is part of CRC-DabMux. + + CRC-DabMux is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + CRC-DabMux is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CRC-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "dabOutput.h" +#include "UdpSocket.h" + +#include <string.h> +#include <stdio.h> +#include <fcntl.h> +#include <limits.h> + +#ifdef _WIN32 +# include <io.h> +# ifdef __MINGW32__ +# define FS_DECLARE_CFG_ARRAYS +# include <winioctl.h> +# endif +# include <sdci.h> +#else +# include <farsync.h> +# include <unistd.h> +# include <sys/time.h> +# ifndef O_BINARY +# define O_BINARY 0 +# endif // O_BINARY +#endif + + +int dabOutputDefaultInit(void** args) { + return -1; +} + + +int dabOutputDefaultOpen(void* args, const char* filename) +{ + return -1; +} + + +int dabOutputDefaultWrite(void* args, void* buffer, int size) +{ + return -1; +} + + +int dabOutputDefaultClose(void* args) +{ + return -1; +} + + +int dabOutputDefaultClean(void** args) +{ + return -1; +} + + +struct dabOutputOperations dabOutputDefaultOperations = { + dabOutputDefaultInit, + dabOutputDefaultOpen, + dabOutputDefaultWrite, + dabOutputDefaultClose, + dabOutputDefaultClean +}; + + +enum EtiFileType { + ETI_FILE_TYPE_NONE = 0, + ETI_FILE_TYPE_RAW, + ETI_FILE_TYPE_STREAMED, + ETI_FILE_TYPE_FRAMED +}; + + +struct dabOutputFifoData { + int file; + EtiFileType type; + unsigned long nbFrames; +}; + + +int dabOutputFifoInit(void** args) +{ + dabOutputFifoData* data = new dabOutputFifoData; + + *args = data; + data->file = -1; + data->type = ETI_FILE_TYPE_STREAMED; + data->nbFrames = 0; + return 0; +} + + +int dabOutputFifoOpen(void* args, const char* filename) +{ + dabOutputFifoData* data = (dabOutputFifoData*)args; + + char* token = strchr((char*)filename, '?'); + if (token != NULL) { + *(token++) = 0; + char* nextPair; + char* key; + char* value; + do { + nextPair = strchr(token, '&'); + if (nextPair != NULL) { + *nextPair = 0; + } + key = token; + value = strchr(token, '='); + if (value != NULL) { + *(value++) = 0; + if (strcmp(key, "type") == 0) { + if (strcmp(value, "raw") == 0) { + data->type = ETI_FILE_TYPE_RAW; + break; + } else if (strcmp(value, "framed") == 0) { + data->type = ETI_FILE_TYPE_FRAMED; + break; + } else if (strcmp(value, "streamed") == 0) { + data->type = ETI_FILE_TYPE_STREAMED; + break; + } else { + etiLog.printHeader(TcpLog::ERR, + "File type '%s' is not supported.\n", value); + return -1; + } + } + } + } while (nextPair != NULL); + } + + data->file = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666); + if (data->file == -1) { + perror(filename); + return -1; + } + return 0; +} + + +int dabOutputFifoWrite(void* args, void* buffer, int size) +{ + dabOutputFifoData* data = (dabOutputFifoData*)args; + uint8_t padding[6144]; + + switch (data->type) { + case ETI_FILE_TYPE_FRAMED: + if (data->nbFrames == 0) { + uint32_t nbFrames = (uint32_t)-1; + // Writting nb frame + if (write(data->file, &nbFrames, 4) == -1) goto FIFO_WRITE_ERROR; + } + case ETI_FILE_TYPE_STREAMED: + // Writting frame length + if (write(data->file, &size, 2) == -1) goto FIFO_WRITE_ERROR; + // Appending data + if (write(data->file, buffer, size) == -1) goto FIFO_WRITE_ERROR; + break; + case ETI_FILE_TYPE_RAW: + // Appending data + if (write(data->file, buffer, size) == -1) goto FIFO_WRITE_ERROR; + // Appending padding + memset(padding, 0x55, 6144 - size); + if (write(data->file, padding, 6144 - size) == -1) goto FIFO_WRITE_ERROR; + break; + default: + etiLog.printHeader(TcpLog::ERR, "File type is not supported.\n"); + return -1; + } + + + return size; + +FIFO_WRITE_ERROR: + perror("Error while writting to file"); + return -1; +} + + +int dabOutputFifoClose(void* args) +{ + dabOutputFifoData* data = (dabOutputFifoData*)args; + + if (close(data->file) == 0) { + data->file = -1; + return 0; + } + perror("Can't close file"); + return -1; +} + + +int dabOutputFifoClean(void** args) +{ + delete (dabOutputFifoData*)(*args); + return 0; +} + + +struct dabOutputOperations dabOutputFifoOperations = { + dabOutputFifoInit, + dabOutputFifoOpen, + dabOutputFifoWrite, + dabOutputFifoClose, + dabOutputFifoClean +}; + + +struct dabOutputFileData { + int file; + EtiFileType type; + unsigned long nbFrames; +}; + + +int dabOutputFileInit(void** args) +{ + dabOutputFileData* data = new dabOutputFileData; + + *args = data; + data->file = -1; + data->type = ETI_FILE_TYPE_FRAMED; + data->nbFrames = 0; + return 0; +} + + +int dabOutputFileWrite(void* args, void* buffer, int size) +{ + dabOutputFileData* data = (dabOutputFileData*)args; + + uint8_t padding[6144]; + ++data->nbFrames; + + switch (data->type) { + case ETI_FILE_TYPE_FRAMED: + // Writting nb of frames at beginning of file + if (lseek(data->file, 0, SEEK_SET) == -1) goto FILE_WRITE_ERROR; + if (write(data->file, &data->nbFrames, 4) == -1) goto FILE_WRITE_ERROR; + + // Writting nb frame length at end of file + if (lseek(data->file, 0, SEEK_END) == -1) goto FILE_WRITE_ERROR; + if (write(data->file, &size, 2) == -1) goto FILE_WRITE_ERROR; + + // Appending data + if (write(data->file, buffer, size) == -1) goto FILE_WRITE_ERROR; + break; + case ETI_FILE_TYPE_STREAMED: + // Writting nb frame length at end of file + if (write(data->file, &size, 2) == -1) goto FILE_WRITE_ERROR; + + // Appending data + if (write(data->file, buffer, size) == -1) goto FILE_WRITE_ERROR; + break; + case ETI_FILE_TYPE_RAW: + // Appending data + if (write(data->file, buffer, size) == -1) goto FILE_WRITE_ERROR; + + // Appending padding + memset(padding, 0x55, 6144 - size); + if (write(data->file, padding, 6144 - size) == -1) goto FILE_WRITE_ERROR; + break; + default: + etiLog.printHeader(TcpLog::ERR, "File type is not supported.\n"); + return -1; + } + + return size; + +FILE_WRITE_ERROR: + perror("Error while writting to file"); + return -1; +} + + +int dabOutputFileClean(void** args) +{ + delete (dabOutputFileData*)(*args); + return 0; +} + + +struct dabOutputOperations dabOutputFileOperations = { + dabOutputFileInit, + dabOutputFifoOpen, + dabOutputFileWrite, + dabOutputFifoClose, + dabOutputFileClean +}; + + +struct dabOutputRawData { +#ifdef _WIN32 + HANDLE socket; +#else + int socket; + bool isCyclades; +#endif + unsigned char* buffer; +}; + + +const unsigned char revTable[] = { + 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, + 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, + 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, + 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, + 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, + 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, + 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, + 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, + 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, + 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, + 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, + 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, + 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, + 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, + 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, + 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, + 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, + 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, + 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, + 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, + 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, + 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, + 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, + 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, + 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, + 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, + 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, + 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, + 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, + 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, + 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, + 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff +}; + + +int dabOutputRawInit(void** args) +{ + dabOutputRawData* data = new dabOutputRawData; + + *args = data; +#ifdef _WIN32 + data->socket = INVALID_HANDLE_VALUE; +#else + data->socket = -1; + data->isCyclades = false; +#endif + data->buffer = new unsigned char[6144]; + return 0; +} + + +#ifdef _WIN32 +# include <fscfg.h> +# include <sdci.h> +#else +# include <netinet/in.h> +# include <sys/types.h> +# include <sys/socket.h> +# include <sys/ioctl.h> +# include <linux/if_packet.h> +# include <linux/netdevice.h> +# include <net/if_arp.h> +#endif +int dabOutputRawOpen(void* args, const char* filename) +{ + dabOutputRawData* data = (dabOutputRawData*)args; + + if (filename == NULL) { + etiLog.printHeader(TcpLog::ERR, "Socket name must be provided!\n"); + return -1; + } + +#ifdef _WIN32 + // Opening device + data->socket = CreateFile(filename, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, NULL); + if (data->socket == INVALID_HANDLE_VALUE) { + etiLog.printHeader(TcpLog::ERR, "Can't open raw device '%s': %i\n", + filename, GetLastError()); + return -1; + } + + // Configuring device + DWORD result; + FS_TE1_CONFIG config; + if (!DeviceIoControl(data->socket, IoctlCodeFarSyncGetTE1Config, NULL, 0, + &config, sizeof(config), &result, NULL)) { + etiLog.printHeader(TcpLog::ERR, + "Can't get raw device '%s' config: %i\n", + filename, GetLastError()); + return -1; + } + config.dataRate = 2048000; + config.clocking = CLOCKING_MASTER; + config.framing = FRAMING_E1; + config.structure = STRUCTURE_UNFRAMED; + config.iface = INTERFACE_BNC; + config.coding = CODING_HDB3; + config.lineBuildOut = LBO_0dB; + config.equalizer = EQUALIZER_SHORT; + config.transparentMode = TRUE; + config.loopMode = LOOP_NONE; + config.range = RANGE_0_40_M; + config.txBufferMode = BUFFER_2_FRAME; + config.rxBufferMode = BUFFER_2_FRAME; + config.startingTimeSlot = 0; + config.losThreshold = 2; + config.enableIdleCode = TRUE; + config.idleCode = 0xff; + if (!DeviceIoControl(data->socket, IoctlCodeFarSyncSetTE1Config, + &config, sizeof(config), NULL, 0, &result, NULL)) { + etiLog.printHeader(TcpLog::ERR, + "Can't set raw device '%s' config: %i\n", + filename, GetLastError()); + return -1; + } + + // Starting device + if (!DeviceIoControl(data->socket, IoctlCodeFarSyncQuickStart, NULL, 0, + NULL, 0, &result, NULL)) { + etiLog.printHeader(TcpLog::ERR, "Can't start raw device '%s': %i\n", + filename, GetLastError()); + return -1; + } +#else + data->socket = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP); + if (data->socket == -1) { + etiLog.printHeader(TcpLog::ERR, "Are you logged as root?\n"); + perror(filename); + return -1; + } + + struct ifreq ifr; + struct sockaddr_ll saddr; + memset(&ifr, 0, sizeof(struct ifreq)); + (void)strncpy(ifr.ifr_name, filename, sizeof(ifr.ifr_name)); + + // Get current Farsync configuration + struct fstioc_info info; + memset(&info, 0, sizeof(info)); + ifr.ifr_data = (char*)&info; + if (ioctl(data->socket, FSTGETCONF, &ifr) == -1) { + etiLog.printHeader(TcpLog::DBG, "Cyclades card identified.\n"); + data->isCyclades = true; + + // Set the interface MTU if needed + if (ioctl(data->socket, SIOCGIFMTU, &ifr) == -1) { + etiLog.printHeader(TcpLog::ERR, "Can't get raw device MTU!\n"); + perror(filename); + return -1; + } else { + if (ifr.ifr_mtu != 6143) { + ifr.ifr_mtu = 6143; + if (ioctl(data->socket, SIOCSIFMTU, &ifr) == -1) { + etiLog.printHeader(TcpLog::ERR, + "Can't Cyclades device MTU!\n"); + perror(filename); + return -1; + } + } + } + } else { + etiLog.printHeader(TcpLog::DBG, "Farsync card identified.\n"); + data->isCyclades = false; + + info.lineInterface = E1; + info.proto = FST_RAW; + info.internalClock = EXTCLK; + info.lineSpeed = 2048000; + //info.debug = DBG_INIT | DBG_OPEN | DBG_PCI | DBG_IOCTL | DBG_TX; + info.transparentMode = 1; + info.ignoreCarrier = 1; + info.numTxBuffers = 8; + info.numRxBuffers = 8; + info.txBufferSize = 6144; + info.rxBufferSize = 6144; + // E1 specific config + info.clockSource = CLOCKING_SLAVE; + info.structure = STRUCTURE_UNFRAMED; + info.interface = INTERFACE_BNC; //RJ48C; + info.coding = CODING_HDB3; + info.txBufferMode = BUFFER_2_FRAME; + info.idleCode = 0xff; + info.valid = FSTVAL_ALL; + + // Setting configuration + etiLog.printHeader(TcpLog::DBG, "Set configuration.\n"); + ifr.ifr_data = (char*)&info; + if (ioctl(data->socket, FSTSETCONF, &ifr) == -1) { + etiLog.printHeader(TcpLog::ERR, + "Can't set Farsync configurationi!\n"); + perror(filename); + return -1; + } + + // Disabling notify + etiLog.printHeader(TcpLog::DBG, "Disable notify.\n"); + int notify = 0; + ifr.ifr_data = (char*)¬ify; + if (ioctl(data->socket, FSTSNOTIFY, &ifr) == -1) { + etiLog.printHeader(TcpLog::ERR, "Can't disable Farsync notify!\n"); + perror(filename); + return -1; + } + + // Apply the new configuration + // Set the interface down if needed + etiLog.printHeader(TcpLog::DBG, "Get flags.\n"); + if (ioctl(data->socket, SIOCGIFFLAGS, &ifr) == -1) { + etiLog.printHeader(TcpLog::ERR, "Can't get Farsync flags!\n"); + perror(filename); + return -1; + } else { + if (ifr.ifr_flags & IFF_UP) { + etiLog.printHeader(TcpLog::DBG, "Set flags.\n"); + ifr.ifr_flags &= ~IFF_UP; + if (ioctl(data->socket, SIOCSIFFLAGS, &ifr) == -1) { + etiLog.printHeader(TcpLog::ERR, + "Can't turn down Farsync device!\n"); + perror(filename); + return -1; + } + } + } + + // Set the interface MTU if needed + etiLog.printHeader(TcpLog::DBG, "Get MTU.\n"); + if (ioctl(data->socket, SIOCGIFMTU, &ifr) == -1) { + etiLog.printHeader(TcpLog::ERR, "Can't get Farsync MTU!\n"); + perror(filename); + return -1; + } else { + if (ifr.ifr_mtu != 6144) { + etiLog.printHeader(TcpLog::DBG, "Set MTU.\n"); + ifr.ifr_mtu = 6144; + if (ioctl(data->socket, SIOCSIFMTU, &ifr) == -1) { + etiLog.printHeader(TcpLog::ERR, "Can't set Farsync MTU!\n"); + perror(filename); + return -1; + } + } + } + } + + // Set the interface up if needed + etiLog.printHeader(TcpLog::DBG, "Get flags.\n"); + if (ioctl(data->socket, SIOCGIFFLAGS, &ifr) == -1) { + etiLog.printHeader(TcpLog::ERR, "Can't get raw device flags!\n"); + perror(filename); + return -1; + } else { + if (!(ifr.ifr_flags & IFF_UP)) { + ifr.ifr_flags |= IFF_UP; + etiLog.printHeader(TcpLog::DBG, "Set flags.\n"); + if (ioctl(data->socket, SIOCSIFFLAGS, &ifr) == -1) { + etiLog.printHeader(TcpLog::ERR, "Can't turn up raw device!\n"); + perror(filename); + return -1; + } + } + } + + close(data->socket); + + //////////////////// + // Opening device // + //////////////////// + + if ((data->socket = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_CUST))) == -1) { + etiLog.printHeader(TcpLog::ERR, "Are you logged as root?\n"); + perror(filename); + return -1; + } + + // ioctl to read the interface number + etiLog.printHeader(TcpLog::DBG, "Get index.\n"); + memset(&ifr, 0, sizeof(struct ifreq)); + strncpy(ifr.ifr_name, filename, sizeof(ifr.ifr_name)); + if (ioctl(data->socket, SIOCGIFINDEX, (char *) &ifr) == -1) { + perror(filename); + return -1; + } + + // Bind to the interface name + etiLog.printHeader(TcpLog::DBG, "Bind interface.\n"); + memset(&saddr, 0, sizeof(struct sockaddr_ll)); + saddr.sll_family = AF_PACKET; + saddr.sll_protocol = ARPHRD_RAWHDLC; + saddr.sll_ifindex = ifr.ifr_ifindex; + if (bind(data->socket, (struct sockaddr *) &saddr, sizeof(saddr)) == -1) { + etiLog.printHeader(TcpLog::ERR, "Can't bind raw device!\n"); + perror(filename); + return -1; + } +#endif + + return 0; +} + + +int dabOutputRawWrite(void* args, void* buffer, int size) +{ + dabOutputRawData* data = (dabOutputRawData*)args; + + // Encoding data + memcpy(data->buffer, buffer, size); + memset(data->buffer + size, 0x55, 6144 - size); + for (int i = 0; i < 6144; ++i) { + data->buffer[i] = revTable[data->buffer[i]]; + } + + // Writting data +#ifdef _WIN32 + DWORD result; + if(!DeviceIoControl(data->socket, IoctlCodeTxFrame, data->buffer, 6144, + NULL, 0, &result, NULL)) { + goto RAW_WRITE_ERROR; + } +#else + /* + if (write(data->socket, data->buffer + 1, 6143) != 6143) { + goto RAW_WRITE_ERROR; + } + */ + if (data->isCyclades) { + if (write(data->socket, data->buffer + 1, 6143) != 6143) { + goto RAW_WRITE_ERROR; + } + } else { + int ret = send(data->socket, data->buffer, 6144, 0); + if (ret != 6144) { + fprintf(stderr, "%i/6144 bytes written\n", ret); + goto RAW_WRITE_ERROR; + } + } +#endif + + return size; + +RAW_WRITE_ERROR: +#ifdef _WIN32 + DWORD err = GetLastError(); + LPSTR errMsg; + if(FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + err, + 0, + (LPTSTR)&errMsg, + 0, + NULL) == 0) { + fprintf(stderr, "Error while writting to raw socket: %i\n", err); + } else { + fprintf(stderr, "Error while writting to raw socket: %s\n", errMsg); + LocalFree(errMsg); + } +#else + perror("Error while writting to raw socket"); +#endif + + return -1; +} + + +int dabOutputRawClose(void* args) +{ + dabOutputRawData* data = (dabOutputRawData*)args; + +#ifdef _WIN32 + CancelIo(data->socket); + CloseHandle(data->socket); + return 0; +#else + if (close(data->socket) == 0) { + data->socket = -1; + return 0; + } + perror("Can't close raw socket"); +#endif + + return -1; +} + + +int dabOutputRawClean(void** args) +{ + dabOutputRawData* data = *((dabOutputRawData**)args); + + delete []data->buffer; + delete data; + return 0; +} + + +struct dabOutputOperations dabOutputRawOperations = { + dabOutputRawInit, + dabOutputRawOpen, + dabOutputRawWrite, + dabOutputRawClose, + dabOutputRawClean +}; + + +struct dabOutputUdpData { + UdpSocket* socket; + UdpPacket* packet; +}; + + +int dabOutputUdpInit(void** args) +{ + dabOutputUdpData* data = new dabOutputUdpData; + + *args = data; + UdpSocket::init(); + data->packet = new UdpPacket(6144); + data->socket = new UdpSocket(); + + return 0; +} + + +int dabOutputUdpOpen(void* args, const char* filename) +{ + dabOutputUdpData* data = (dabOutputUdpData*)args; + filename = strdup(filename); + + char* address; + long port; + address = strchr((char*)filename, ':'); + if (address == NULL) { + etiLog.printHeader(TcpLog::ERR, + "\"%s\" is an invalid format for udp address: " + "should be [address]:port - > aborting\n", + filename); + return -1; + } + *(address++) = 0; + port = strtol(address, (char **)NULL, 10); + if ((port == LONG_MIN) || (port == LONG_MAX)) { + etiLog.printHeader(TcpLog::ERR, + "can't convert port number in udp address %s\n", address); + return -1; + } + if (port == 0) { + etiLog.printHeader(TcpLog::ERR, + "can't use port number 0 in udp address\n"); + return -1; + } + address = (char*)filename; + if (strlen(address) > 0) { + if (data->packet->getAddress().setAddress(address) == -1) { + etiLog.printHeader(TcpLog::ERR, "can't set address %s (%s: %s) " + "-> aborting\n", address, inetErrDesc, inetErrMsg); + return -1; + } + } + data->packet->getAddress().setPort(port); + + if (data->socket->create() == -1) { + etiLog.printHeader(TcpLog::ERR, "can't create Udp socket (%s: %s) " + "-> aborting\n)", inetErrDesc, inetErrMsg); + return -1; + } + + //sprintf(filename, "%s:%i", data->packet->getAddress().getHostAddress(), + // data->packet->getAddress().getPort()); + return 0; +} + + +int dabOutputUdpWrite(void* args, void* buffer, int size) +{ + dabOutputUdpData* data = (dabOutputUdpData*)args; + + data->packet->setLength(0); + data->packet->addData(buffer, size); + return data->socket->send(*data->packet); +} + + +int dabOutputUdpClose(void* args) +{ + //dabOutputUdpData* data = (dabOutputUdpData*)args; + + return 0; +} + + +int dabOutputUdpClean(void** args) +{ + dabOutputUdpData* data = *((dabOutputUdpData**)args); + + delete data->socket; + delete data->packet; + delete data; + + return 0; +} + + +struct dabOutputOperations dabOutputUdpOperations = { + dabOutputUdpInit, + dabOutputUdpOpen, + dabOutputUdpWrite, + dabOutputUdpClose, + dabOutputUdpClean +}; + + +#include "TcpServer.h" +struct dabOutputTcpData { + TcpServer* server; + TcpSocket* client; + pthread_t thread; +}; + + +int dabOutputTcpInit(void** args) +{ + dabOutputTcpData* data = new dabOutputTcpData; + + *args = data; + TcpSocket::init(); + data->server = new TcpServer(); + data->client = NULL; + + return 0; +} + + +void* dabOutputTcpThread(void* args) +{ + dabOutputTcpData* data = (dabOutputTcpData*)args; + TcpSocket* client; + + while ((client = data->server->accept()) != NULL) { + etiLog.print(TcpLog::INFO, "TCP server got a new client.\n"); + if (data->client != NULL) { + delete data->client; + } + data->client = client; + } + etiLog.print(TcpLog::ERR, "TCP thread can't accept new client (%s)\n", + inetErrDesc, inetErrMsg); + + return NULL; +} + + +int dabOutputTcpOpen(void* args, const char* filename) +{ + dabOutputTcpData* data = (dabOutputTcpData*)args; + filename = strdup(filename); + + char* address; + long port; + address = strchr((char*)filename, ':'); + if (address == NULL) { + etiLog.printHeader(TcpLog::ERR, + "\"%s\" is an invalid format for tcp address: " + "should be [address]:port - > aborting\n", + filename); + return -1; + } + *(address++) = 0; + port = strtol(address, (char **)NULL, 10); + if ((port == LONG_MIN) || (port == LONG_MAX)) { + etiLog.printHeader(TcpLog::ERR, + "can't convert port number in tcp address %s\n", address); + return -1; + } + if (port == 0) { + etiLog.printHeader(TcpLog::ERR, + "can't use port number 0 in tcp address\n"); + return -1; + } + address = (char*)filename; + if (strlen(address) > 0) { + if (data->server->create(port, address) == -1) { + etiLog.printHeader(TcpLog::ERR, "Can't create Tcp server on %s:%i " + "(%s: %s) -> aborting\n", + address, port, inetErrDesc, inetErrMsg); + return -1; + } + } else { + if (data->server->create(port) == -1) { + etiLog.printHeader(TcpLog::ERR, "Can't create Tcp server on :%i " + "(%s: %s) -> aborting\n", + port, inetErrDesc, inetErrMsg); + return -1; + } + } + + //sprintf(filename, "%s:%i", data->packet->getAddress().getHostAddress(), + // data->packet->getAddress().getPort()); + + if (data->server->listen() == -1) { + etiLog.printHeader(TcpLog::ERR, "Can't listen on Tcp socket (%s: %s)\n", + inetErrDesc, inetErrMsg); + return -1; + } +#ifdef _WIN32 + data->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)dabOutputTcpThread, data, 0, NULL); + if (data->thread == NULL) { + fprintf(stderr, "Can't create TCP child"); + return -1; + } +#else + if (pthread_create(&data->thread, NULL, dabOutputTcpThread, data)) { + perror("Can't create TCP child"); + return -1; + } +#endif + + return 0; +} + + +int dabOutputTcpWrite(void* args, void* buffer, int size) +{ + dabOutputTcpData* data = (dabOutputTcpData*)args; + + if (data->client != NULL) { + if (data->client->write(&size, 2) == 2) { + if (data->client->write(buffer, size) != size) { + return size; + } + } + else { + etiLog.print(TcpLog::INFO, "TCP server client disconnected.\n"); + delete data->client; + data->client = NULL; + } + } + return size; +} + + +#include <signal.h> +int dabOutputTcpClose(void* args) +{ + dabOutputTcpData* data = (dabOutputTcpData*)args; + + data->server->close(); + if( data->client != NULL ) + data->client->close(); +#ifdef WIN32 + DWORD status; + for (int i = 0; i < 5; ++i) { + if (GetExitCodeThread(data->thread, &status)) { + break; + } + Sleep(100); + } + TerminateThread(data->thread, 1); +#else + pthread_kill(data->thread, SIGPIPE); +#endif + + return 0; +} + + +int dabOutputTcpClean(void** args) +{ + dabOutputTcpData* data = *((dabOutputTcpData**)args); + +#ifdef _WIN32 + CloseHandle(data->thread); +#endif + + delete data->server; + delete data->client; + delete data; + + return 0; +} + + +struct dabOutputOperations dabOutputTcpOperations = { + dabOutputTcpInit, + dabOutputTcpOpen, + dabOutputTcpWrite, + dabOutputTcpClose, + dabOutputTcpClean +}; + + +struct dabOutputSimulData { +#ifdef _WIN32 + DWORD startTime; +#else + timeval startTime; +#endif +}; + + +int dabOutputSimulInit(void** args) { + dabOutputSimulData* data = new dabOutputSimulData; + + *args = data; + + return 0; +} + + +int dabOutputSimulOpen(void* args, const char* filename) +{ + dabOutputSimulData* data = (dabOutputSimulData*)args; + +#ifdef _WIN32 + data->startTime = GetTickCount(); +#else + gettimeofday(&data->startTime, NULL); +#endif + + return 0; +} + + +int dabOutputSimulWrite(void* args, void* buffer, int size) +{ + dabOutputSimulData* data = (dabOutputSimulData*)args; + + unsigned long current; + unsigned long start; + unsigned long waiting; + +#ifdef _WIN32 + current = GetTickCount(); + start = data->startTime; + if (current < start) { + waiting = start - current + 24; + Sleep(waiting); + } else { + waiting = 24 - (current - start); + if ((current - start) < 24) { + Sleep(waiting); + } + } + data->startTime += 24; +#else + timeval curTime; + gettimeofday(&curTime, NULL); + current = (1000000ul * curTime.tv_sec) + curTime.tv_usec; + start = (1000000ul * data->startTime.tv_sec) + data->startTime.tv_usec; + waiting = 24000ul - (current - start); + if ((current - start) < 24000ul) { + usleep(waiting); + } + + data->startTime.tv_usec += 24000; + if (data->startTime.tv_usec >= 1000000) { + data->startTime.tv_usec -= 1000000; + ++data->startTime.tv_sec; + } +#endif + + return size; +} + + +int dabOutputSimulClose(void* args) +{ + //dabOutputSimulData* data = (dabOutputSimulData*)args); + + return 0; +} + + +int dabOutputSimulClean(void** args) +{ + dabOutputSimulData* data = *((dabOutputSimulData**)args); + + delete data; + + return 0; +} + + +struct dabOutputOperations dabOutputSimulOperations = { + dabOutputSimulInit, + dabOutputSimulOpen, + dabOutputSimulWrite, + dabOutputSimulClose, + dabOutputSimulClean +}; + + diff --git a/src/dabOutput.h b/src/dabOutput.h new file mode 100644 index 0000000..26c154a --- /dev/null +++ b/src/dabOutput.h @@ -0,0 +1,72 @@ +/* + Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Her Majesty the Queen in + Right of Canada (Communications Research Center Canada) + */ +/* + This file is part of CRC-DabMux. + + CRC-DabMux is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + CRC-DabMux is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CRC-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _DABOUTPUT +#define _DABOUTPUT + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + + +struct dabOutputOperations { + int (*init)(void** args); + int (*open)(void* args, const char* name); + int (*write)(void* args, void* buffer, int size); + int (*close)(void* args); + int (*clean)(void** args); +}; + +extern struct dabOutputOperations dabOutputDefaultOperations; + +#if defined(HAVE_OUTPUT_FILE) +extern struct dabOutputOperations dabOutputFileOperations; +#endif // defined(HAVE_OUTPUT_FILE) + +#if defined(HAVE_OUTPUT_FIFO) +extern struct dabOutputOperations dabOutputFifoOperations; +#endif // defined(HAVE_OUTPUT_FIFO) + +#if defined(HAVE_OUTPUT_UDP) +extern struct dabOutputOperations dabOutputUdpOperations; +#endif // defined(HAVE_OUTPUT_UDP) + +#if defined(HAVE_OUTPUT_TCP) +extern struct dabOutputOperations dabOutputTcpOperations; +#endif // defined(HAVE_OUTPUT_TCP) + +#if defined(HAVE_OUTPUT_RAW) +extern struct dabOutputOperations dabOutputRawOperations; +#endif // defined(HAVE_OUTPUT_RAW) + +#if defined(HAVE_OUTPUT_SIMUL) +extern struct dabOutputOperations dabOutputSimulOperations; +#endif // defined(HAVE_OUTPUT_SIMUL) + + +extern const unsigned char revTable[]; + + +#include "TcpLog.h" +extern TcpLog etiLog; + + +#endif // _DABOUTPUT diff --git a/src/dabUtils.cpp b/src/dabUtils.cpp new file mode 100644 index 0000000..693d300 --- /dev/null +++ b/src/dabUtils.cpp @@ -0,0 +1,52 @@ +/* + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Her Majesty the + Queen in Right of Canada (Communications Research Center Canada) + */ +/* + This file is part of CRC-DabMux. + + CRC-DabMux is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + CRC-DabMux is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CRC-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "dabUtils.h" + +long gregorian2mjd(int year,int month,int day) +{ + long MJD; + + //This is the algorithm for the JD, just substract 2400000.5 for MJD + year += 8000; + if(month < 3) { + year--; + month += 12; + } + MJD = (year * 365) + (year / 4) - (year / 100) + (year / 400) - 1200820 + + ((month * 153 + 3) / 5) - 92 + (day - 1); + + return (long)(MJD - 2400000.5); //truncation, loss of data OK! +} + + +void dumpBytes(void* data, int size, FILE* out) +{ + fprintf(out, "Packet of %i bytes", size); + + for (int index = 0; index < size; ++index) { + if ((index % 8) == 0) { + fprintf(out, "\n 0x%.4x(%.4i):", index, index); + } + fprintf(out, " 0x%.2x", ((unsigned char*)data)[index]); + } + fprintf(out, "\n\n"); +} diff --git a/src/dabUtils.h b/src/dabUtils.h new file mode 100644 index 0000000..04bb468 --- /dev/null +++ b/src/dabUtils.h @@ -0,0 +1,35 @@ +/* + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Her Majesty the + Queen in Right of Canada (Communications Research Center Canada) + */ +/* + This file is part of CRC-DabMux. + + CRC-DabMux is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + CRC-DabMux is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CRC-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef DABUTILS +#define DABUTILS + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <stdio.h> + +long gregorian2mjd(int year,int month,int day); +void dumpBytes(void* data, int size, FILE* out = stdout); + + +#endif // DABUTILS diff --git a/src/mpeg.c b/src/mpeg.c new file mode 100644 index 0000000..57f4231 --- /dev/null +++ b/src/mpeg.c @@ -0,0 +1,221 @@ +/* + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Her Majesty + the Queen in Right of Canada (Communications Research Center Canada) + */ +/* + This file is part of CRC-DabMux. + + CRC-DabMux is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + CRC-DabMux is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CRC-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "mpeg.h" + +#include <stdio.h> +#include <errno.h> + + +const static short bitrateArray[4][4][16] = { + { // MPEG 2.5 + { -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1 }, // layer invalid + { 0, 8, 16, 24, 32, 40, 48, 56, + 64, 80, 96, 112, 128, 144, 160, -1 }, // layer 3 + { 0, 8, 16, 24, 32, 40, 48, 56, + 64, 80, 96, 112, 128, 144, 160, -1 }, // layer 2 + { 0, 32, 48, 56, 64, 80, 96, 112, + 128, 144, 160, 176, 192, 224, 256, -1 } // layer 1 + }, + { + { -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1 }, // MPEG invalid + { -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1 } + }, + { + { -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1 }, // MPEG 2 + { 0, 8, 16, 24, 32, 40, 48, 56, + 64, 80, 96, 112, 128, 144, 160, -1 }, + { 0, 8, 16, 24, 32, 40, 48, 56, + 64, 80, 96, 112, 128, 144, 160, -1 }, + { 0, 32, 48, 56, 64, 80, 96, 112, + 128, 144, 160, 176, 192, 224, 256, -1 } + }, + { + { -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1 }, // MPEG 1 + { 0, 32, 40, 48, 56, 64, 80, 96, + 112, 128, 160, 192, 224, 256, 320, -1 }, + { 0, 32, 48, 56, 64, 80, 96, 112, + 128, 160, 192, 224, 256, 320, 384, -1 }, + { 0, 32, 64, 96, 128, 160, 192, 224, + 256, 288, 320, 352, 384, 416, 448, -1 } + } +}; + + +const static int samplingrateArray[4][4] = { + { 11025, 12000, 8000, 0 }, // MPEG 2.5 + { -1, -1, -1, -1 }, // MPEG invalid + { 22050, 24000, 16000, 0 }, // MPEG 2 + { 44100, 48000, 32000, 0 } // MPEG 1 +}; + + +short getMpegBitrate(void* data) +{ + mpegHeader* header = (mpegHeader*)data; + return bitrateArray[header->id][header->layer][header->bitrate]; +} + + +int getMpegFrequency(void* data) +{ + mpegHeader* header = (mpegHeader*)data; + return samplingrateArray[header->id][header->samplingrate]; +} + + +int getMpegFrameLength(mpegHeader* header) +{ + short bitrate = getMpegBitrate(header); + int samplingrate = getMpegFrequency(header); + int framelength = -1; + + + if (bitrate <= 0) { + return -1; + } + if (samplingrate <= 0) { + return -1; + } + + switch (header->layer) { + case 1: // layer III + case 2: // layer II + framelength = (int)144000 * bitrate / samplingrate + header->padding; + break; + case 3: // layer I + framelength = (12 * bitrate / samplingrate + header->padding) * 4; + break; + default: + framelength = -1; + } + return framelength; +} + + +/** + * This function replace the read function by trying many times a reading. + * It tries to read until all bytes are read. Very useful when reading from a + * pipe because sometimes 2 pass is necessary to read all bytes. + * @param file File descriptor. + * @param data Address of the buffer to write data into. + * @param size Number of bytes to read. + * @param tries Max number of tries to read. + * @return Same as read function: + * Nb of bytes read. + * -1 if error. + */ +ssize_t readData(int file, void* data, size_t size, unsigned int tries) +{ + ssize_t result; + size_t offset = 0; + if (size == 0) return 0; + if (tries == 0) return 0; + result = read(file, data, size); + if (result == -1) { + if (errno == EAGAIN) { + return readData(file, data, size, tries - 1); + } + return -1; + } + offset = result; + size -= offset; + data = (char*)data + offset; + result = readData(file, data, size, tries - 1); + if (result == -1) { + return -1; + } + offset += result; + return offset; +} + + +int readMpegHeader(int file, void* data, int size) +{ + // Max byte reading for searching sync + unsigned int flagmax = 0; + unsigned long* syncword = (unsigned long*)data; + int result; + + if (size < 4) return MPEG_BUFFER_OVERFLOW; + // Mpeg header reading + result = readData(file, data, 4, 2); + if (result == 0) return MPEG_FILE_EMPTY; + if (result == -1) { + fprintf(stderr, "header\n"); + return MPEG_FILE_ERROR; + } + if (result < 4) { + return MPEG_BUFFER_UNDERFLOW; + } + while ((*syncword & 0xe0ff) != 0xe0ff) { + *syncword >>= 8; + result = readData(file, (char*)data + 3, 1, 2); + if (result == 0) { + return MPEG_FILE_EMPTY; + } else if (result == -1) { + return MPEG_FILE_ERROR; + } + if (++flagmax > 1200) { + return MPEG_SYNC_NOT_FOUND; + } + } + return 4; +} + + +int readMpegFrame(int file, void* data, int size) +{ + mpegHeader* header = (mpegHeader*)data; + int framelength; + int result; + + framelength = getMpegFrameLength(header); + if (framelength < 0) return MPEG_INVALID_FRAME; + if (framelength > size) { + //lseek(file, framelength - 4, SEEK_CUR); + //return MPEG_BUFFER_OVERFLOW; + result = readData(file, ((char*)data) + 4, size - 4, 2); + if (size == 4) { + lseek(file, framelength - size, SEEK_CUR); + result = framelength - 4; + } + } else { + result = readData(file, ((char*)data) + 4, framelength - 4, 2); + } + if (result == 0) return MPEG_FILE_EMPTY; + if (result == -1) { + return MPEG_FILE_ERROR; + } + if (result < framelength - 4) { + return MPEG_BUFFER_UNDERFLOW; + } + return framelength; +} diff --git a/src/mpeg.h b/src/mpeg.h new file mode 100644 index 0000000..d892225 --- /dev/null +++ b/src/mpeg.h @@ -0,0 +1,82 @@ +/* + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Her Majesty + the Queen in Right of Canada (Communications Research Center Canada) + */ +/* + This file is part of CRC-DabMux. + + CRC-DabMux is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + CRC-DabMux is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CRC-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _MPEG +#define _MPEG + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef _WIN32 +# include <stddef.h> +# include <basetsd.h> +# include <io.h> + +# define ssize_t SSIZE_T +#else +# include <unistd.h> +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + unsigned long sync1:8; + + unsigned long protection:1; + unsigned long layer:2; + unsigned long id:2; + unsigned long sync2:3; + + unsigned long priv:1; + unsigned long padding:1; + unsigned long samplingrate:2; + unsigned long bitrate:4; + + unsigned long emphasis:2; + unsigned long original:1; + unsigned long copyright:1; + unsigned long mode:2; + unsigned long channel:2; +} mpegHeader; + + +extern short getMpegBitrate(void* data); +extern int getMpegFrequency(void* data); +int getMpegFrameLength(mpegHeader* header); +ssize_t readData(int file, void* data, size_t size, unsigned int tries); + +#define MPEG_BUFFER_OVERFLOW -2 +#define MPEG_FILE_EMPTY -3 +#define MPEG_FILE_ERROR -4 +#define MPEG_SYNC_NOT_FOUND -5 +#define MPEG_INVALID_FRAME -6 +#define MPEG_BUFFER_UNDERFLOW -7 +int readMpegHeader(int file, void* data, int size); +int readMpegFrame(int file, void* data, int size); + +#ifdef __cplusplus +} +#endif + +#endif // _MPEG diff --git a/src/prbs.c b/src/prbs.c new file mode 100644 index 0000000..8a11266 --- /dev/null +++ b/src/prbs.c @@ -0,0 +1,140 @@ +/* + Copyright (C) 2005, 2006, 2007, 2008, 2009 Her Majesty the Queen in Right + of Canada (Communications Research Center Canada) + */ +/* + This file is part of CRC-DabMux. + + CRC-DabMux is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + CRC-DabMux is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CRC-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "prbs.h" + +#include <string.h> +#include <stdlib.h> +#include <limits.h> + + +/* + * Generate a parity check for a 32-bit word. + */ +unsigned long parity_check(unsigned long prbs_accum) +{ + unsigned long mask=1UL, parity=0UL; + int i; + for (i = 0; i < 32; ++i) { + parity ^= ((prbs_accum & mask) != 0UL); + mask <<= 1; + } + return parity; +} + +/* + * Generate a table of matrix products to update a 32-bit PRBS generator. + */ +void gen_prbs_table(void* args) +{ + prbs_data* data = (prbs_data*)args; + int i; + for (i = 0; i < 4; ++i) { + int j; + for (j = 0; j < 256; ++j) { + unsigned long prbs_accum = ((unsigned long)j << (i * 8)); + int k; + for (k = 0; k < 8; ++k) { + prbs_accum = (prbs_accum << 1) + ^ parity_check(prbs_accum & data->polynomial); + } + data->prbs_table[i][j] = (prbs_accum & 0xff); + } + } +} + +/* + * Update a 32-bit PRBS generator eight bits at a time. + */ +unsigned long update_prbs(void* args) +{ + prbs_data* data = (prbs_data*)args; + unsigned char acc_lsb = 0; + int i; + for (i = 0; i < 4; ++i ) { + acc_lsb ^= data->prbs_table [i] [ (data->accum >> (i * 8) ) & 0xff ]; + } + return (data->accum << 8) ^ ((unsigned long)acc_lsb); +} + +/* + * Generate the weight table. + */ +void gen_weight_table(void* args) +{ + prbs_data* data = (prbs_data*)args; + int i; + for (i = 0; i < 256; ++i) { + unsigned char mask=1U, ones_count = 0U; + int j; + for (j = 0; j < 8; ++j) { + ones_count += ((i & mask) != 0U); + mask = mask << 1; + } + data->weight[i] = ones_count; + } +} + +/* + * Count the number of errors in a block of received data. + */ +unsigned long error_count(void* args, unsigned char *rx_data, + int rx_data_length) +{ + prbs_data* data = (prbs_data*)args; + unsigned long error_count = 0U; + unsigned long prbs_accum = 0U; + int i; + + /* seed the PRBS accumulator */ + for (i = 0; i < 4; ++i) { + prbs_accum = (prbs_accum << 8) ^ (rx_data[i] ^ data->polarity_mask); + } + + /* check the received data */ + for (i = 0; i < rx_data_length; ++i) { + unsigned char error_pattern = (unsigned char) + ((prbs_accum >> 24) + ^ (rx_data[i] ^ data->polarity_mask)); + if (error_pattern != 0U) { + error_count += data->weight[error_pattern]; + } + prbs_accum = update_prbs(data); + } + return error_count; +} + +void gen_sequence(void* args, unsigned char *tx_data, int tx_data_length, + unsigned long polynomial) +{ + prbs_data* data = (prbs_data*)args; + unsigned long prbs_accum = 0U; + + while (prbs_accum < polynomial) { + prbs_accum <<= 1; + prbs_accum |= 1; + } + + while (tx_data_length-- > 0) { + prbs_accum = update_prbs(data); + *(tx_data++) = (unsigned char)(prbs_accum & 0xff); + } +} diff --git a/src/prbs.h b/src/prbs.h new file mode 100644 index 0000000..827ded6 --- /dev/null +++ b/src/prbs.h @@ -0,0 +1,61 @@ +/* + Copyright (C) 2005, 2006, 2007, 2008, 2009 Her Majesty the Queen in Right + of Canada (Communications Research Center Canada) + */ +/* + This file is part of CRC-DabMux. + + CRC-DabMux is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + CRC-DabMux is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CRC-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _PRBS +#define _PRBS + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + + +#ifdef __cplusplus +extern "C" { // } +#endif + +typedef struct { + // table of matrix products used to update a 32-bit PRBS generator + unsigned long prbs_table [4] [256]; + // table of weights for 8-bit bytes + unsigned char weight[256]; + // PRBS polynomial generator + unsigned long polynomial; + // PRBS generator polarity mask + unsigned char polarity_mask; + // PRBS accumulator + unsigned long accum; +} prbs_data; + + +unsigned long parity_check(unsigned long prbs_accum); +void gen_prbs_table(void* args); +unsigned long update_prbs(void* args); +void gen_weight_table(void* args); +unsigned long error_count(void* args, unsigned char *rx_data, + int rx_data_length); +void gen_sequence(void* args, unsigned char *tx_data, int tx_data_length, + unsigned long polynomial); + +#ifdef __cplusplus +} +#endif + +#endif // _PRBS |