- Reestructuración de ficheros y directorios general

- merge v0.01 --> Añadido fileselector
- Añadidas fuentes de Gem y Pure Data
- pix2jpg incluído en Gem. Archivos de construcción de Gem modificados.
- Añadido fichero ompiling.txt con instrucciones de compilación
This commit is contained in:
Santi Noreña 2013-02-04 18:00:17 +01:00
parent c9adfd020b
commit e85d191b46
3100 changed files with 775434 additions and 3073 deletions

94
src/CITPDefines.h Normal file
View file

@ -0,0 +1,94 @@
// -*- mode: C++ -*-
#ifndef _CITPDEFINES_H_
#define _CITPDEFINES_H_
#include <QObject>
//
// The CITP data structures and constants
//
//
// Datatypes
//
typedef qint8 int8;
typedef qint16 int16;
typedef qint32 int32;
typedef qint64 int64;
typedef quint8 uint8;
typedef quint16 uint16;
typedef quint32 uint32;
typedef quint64 uint64;
typedef QByteArray ucs1;
typedef QString ucs2;
//
// Content Type cookies
//
#define COOKIE_CITP 0x50544943 // 'CITP'
#define COOKIE_PINF 0x464e4950 // 'PINF'
#define COOKIE_PINF_PNAM 0x6d614e50 // 'PNam'
#define COOKIE_PINF_PLOC 0x636f4c50 // 'PLoc'
#pragma pack(1)
//
// CITP, Base Layer
//
struct CITP_Header
{
uint32 Cookie; // Set to "CITP".
uint8 VersionMajor; // Set to 1.
uint8 VersionMinor; // Set to 0.
uint8 Reserved[2]; // 4-byte alignment
uint32 MessageSize; // The size of the entire message, including this header.
uint16 MessagePartCount; // Number of message fragments.
uint16 MessagePart; // Index of this message fragment (0-based).
uint32 ContentType; // Cookie identifying the type of contents (the name of the second layer).
};
//
// CITP/PINF, Peer Information Layer
//
#define CITP_PINF_MULTICAST_IP "224.0.0.180"
#define CITP_PINF_MULTICAST_PORT 4809
#define TRANSMIT_INTERVAL_MS 5000
struct CITP_PINF_Header
{
CITP_Header CITPHeader; // The CITP header. CITP ContentType is "PINF".
uint32 ContentType; // A cookie defining which PINF message it is.
};
// DEPRECATED, USE PLoc instead
// Peer Name message
struct CITP_PINF_PNam
{
CITP_PINF_Header CITPPINFHeader; // The CITP PINF header. PINF ContentType is "PNam".
QByteArray Name; // The display name of the peer (null terminated).
// This could be anything from a
// user defined alias for the peer of the name of the
// product, or a combination.
};
// Peer Location message
struct CITP_PINF_PLoc
{
CITP_PINF_Header CITPPINFHeader; // The CITP PINF header. PINF ContentType is "PLoc".
uint16 ListeningTCPPort; // The port on which the peer is listening for
// incoming TCP connections. 0 if not listening.
ucs1 Type[]; // Can be "LightingConsole", "MediaServer",
// "Visualizer" or "OperationHub".
ucs1 Name[]; // The display name of the peer. Corresponds to the
// PINF/PNam/Name field.
ucs1 State[]; // The display state of the peer. This can be any
// descriptive string presentable to the user such
// as "Idle", "Running" etc.
};
#endif // _CITPDEFINES_H_

474
src/MSEXDefines.h Normal file
View file

@ -0,0 +1,474 @@
#ifndef MSEXDEFINES_H
#define MSEXDEFINES_H
#include "CITPDefines.h"
#include <QObject>
///////////////////////////////////////////
//
// Defines
//
///////////////////////////////////////////
#define LISTENTCPPORT 4811
#define LAYER_NUMBER 0x08
#define TRANSMIT_INTERVAL_LSTA 1000
#define NAME "LibreMediaServer"
#define STATE "BetaTesting..."
#define UUID "aaaaaaaa-eeee-ffff-dddd-bbbbbbbbbbbb"
// Cookies
#define COOKIE_MSEX 0X5845534d // 'MSEX'
#define COOKIE_MSEX_CINF 0x666e4943 // 'CInf'
#define COOKIE_MSEX_SINF 0x666e4953 // 'SInf'
#define COOKIE_MSEX_NACK 0x6b63614e // 'Nack'
#define COOKIE_MSEX_LSTA 0x6174534c // 'LSta'
#define COOKIE_MSEX_GELI 0x494c4547 // GELI
#define COOKIE_MSEX_ELIN 0x6e494c45 // ELIn
#define COOKIE_MSEX_ELUP 0x71554c45 // ELUp
#define COOKIE_MSEX_GEIN 0x6e494547 // GEIn
#define COOKIE_MSEX_MEIN 0x6e49454d // MEIn
#define COOKIE_MSEX_EEIN 0x6e494545 // EEIn
#define COOKIE_MSEX_GLEI 0x49454c47 // GLEI
#define COOKIE_MSEX_GELT 0x544c4547 // GELT
#define COOKIE_MSEX_ELTH 0x68544c45 // ELTh
#define COOKIE_MSEX_GETH 0x68544547 // GETh
#define COOKIE_MSEX_ETHN 0x6e685445 // EThn
#define COOKIE_MSEX_GVSR 0x72535647 // GVsr
#define COOKIE_MSEX_VSRC 0x63725356 // VSrc
#define COOKIE_MSEX_RQST 0x74537152 // RqSt
#define COOKIE_MSEX_STFR 0x72467453 // StFr
//////////////////////////////////////////////
// //
// Estructuras auxiliares //
// //
//////////////////////////////////////////////
// Estructura Layer Status V1.0
struct LayerStatus {
quint8 LayerNumber;
quint8 PhysicalOutput;
quint8 MediaLibraryNumber;
quint8 MediaNumber;
QString Name;
quint32 MediaPosition;
quint32 MediaLength;
quint8 MediaFPS;
quint32 LayerStatusFlags;
};
// Estructura Media Library ID. MSex 1.1
struct MSEXLibraryId {
quint8 Level; // 0 - 3
quint8 Level1; // Sublevel 1 specifier, when Depth >= 1.
quint8 Level2; // Sublevel 2 specifier, when Depth >= 2.
quint8 Level3; // Sublevel 3 specifier, when Depth == 3.
};
// Media Information for MELIn packages. v1.0
struct MediaInformation {
uint8 Number; // 0-based contiguous index of the media.
// uint32 SerialNumber; //MSEX 1.2
uint8 DMXRangeMin;// DMX range start value.
uint8 DMXRangeMax;// DMX range end value.
QString MediaName;// Media name.
uint64 MediaVersionTimestamp;// Media version in seconds since 1st January 1970.
uint16 MediaWidth; // Media width.
uint16 MediaHeight;// Media height.
uint32 MediaLength;// Media length (in frames).
uint8 MediaFPS;// Media resolution (in frames per second).
};
// Media Library for ELin packages v1.0
struct MediaLibrary {
quint8 m_Id; // Library id.
quint8 m_DMXRangeMin;// DMX range start value.
quint8 m_DMXRangeMax;// DMX range end value.
QString m_Name;// Library name.
// quint8 m_LibraryCount;// Number of sub libraries in the library. MSEX 1.2
quint8 m_ElementCount;// Number of elements in the library.
QList<MediaInformation> m_MediaInformation; // Pointer to the Medias Information List of this Library
};
// for ELUP
struct AffectedItems
{
uint8 ItemSet[32]; // A set of 256 bits used to indicate which item numbers have been changed
};
//////////////////////////////////////////////
// //
// Estructuras de paquetes //
// //
//////////////////////////////////////////////
// MSEX Header
struct CITP_MSEX_Header
{
CITP_Header CITPHeader; // The CITP header. CITP ContentType is "MSEX".
uint8 VersionMajor;
uint8 VersionMinor;
uint32 ContentType; // A cookie defining which MSEX message it is.
};
// Mensaje para solicitar una conexión
struct CITP_MSEX_CInf
{
CITP_MSEX_Header CITPMSEXHeader; // CITP MSEX header. MSEX ContentType is "CInf". Version is 1.2.
uint8 SupportedMSEXVersionsCount; // Number of following MSEX version pairs.
uint16 SupportedMSEXVersions[]; // Each 2 byte value is MSB = major MSEX version, LSB = minor MSEX version.
uint FutureMessageData[]; // A hint that future versions of this message may contain trailing data.
};
// SInf Versiones 1.0 y 1.1. Send after connection established
struct CITP_MSEX_10_SINF
{
CITP_MSEX_Header CITPMSEXHeader; // CITP MSEX header. MSEX ContentType is "SInf". Version is set to 1.0.
// ucs2 ProductName;// Display name of the product.
uint8 ProductVersionMajor;// Major version number of the product.
uint8 ProductVersionMinor;// Minor version number of the product.
uint8 LayerCount;// Number of following layer information blocks.
/* struct LayerInformation
{
ucs1 DMXSource[];// DMX-source connection string. See DMX Connection Strings in Definitions.
};*/
};
// SInf V1.2 Send after CINf received
struct CITP_MSEX_12_SINF
{
CITP_MSEX_Header CITPMSEXHeader;// CITP MSEX header. MSEX ContentType is "SInf". Version is at least 1.2
//and is the highest common version supported by both server and client.
QByteArray uuid; // A standard 36 character UUID that uniquely identifies this media server
QString ProductName; // Display name of the product.
uint8 ProductVersionMajor; // Major version number of the product.
uint8 ProductVersionMinor; // Minor version number of the product.
uint8 ProductVersionBugfix; // Bugfix version number of the product.
uint8 SupportedMSEXVersionsCount; // Number of following MSEX version pairs.
uint16 SupportedMSEXVersions; // Each 2 byte value is MSB = major MSEX version, LSB = minor MSEX version
uint16 SupportedLibraryTypes; // Bit-encoded flagword that identifies which library types are provided by
//the media server.
uint8 ThumbnailFormatsCount; // Number of following thumbnail format cookies
QByteArray ThumbnailFormats; // Must include "RGB8", but can also include "JPEG" and "PNG "
uint8 StreamFormatsCount; // Number of following stream format cookies
QByteArray StreamFormats; // Must include "RGB8", but can also include "JPEG" and "PNG "
uint8 LayerCount; // Number of following layer information blocks.
QString LayerInf;
};
// Nack Negative Acknowledge Message
struct CITP_MSEX_Nack
{
CITP_MSEX_Header CITPMSEXHeader; // CITP MSEX header. MSEX ContentType is "Nack" and version is 1.2.
uint32 ReceivedContentType; // MSEX message type of the message being NACKed (e.g. "GELT" if the Media
//Server does not support library thumbnails)
};
// Layer Status Message 1.0
struct CITP_MSEX_10_LSta
{
CITP_MSEX_Header CITPMSEXHeader; // CITP MSEX header. MSEX ContentType is "LSta" and version is 1.0.
uint8 LayerCount; // Number of following layer information blocks.
struct LayerStatus
{
uint8 LayerNumber; // 0-based layer number, corresponding to the layers reported in the SInf message.
uint8 PhysicalOutput; // Current physical video output index,0-based.
uint8 MediaLibraryNumber; // Current media library number.
uint8 MediaNumber; // Current media number.
ucs2 MediaName[]; // Current media name.
uint32 MediaPosition; // Current media position (in frames).
uint32 MediaLength; // Current media length (in frames).
uint8 MediaFPS; // Current media resolution in frames per second.
uint32 LayerStatusFlags; // Current layer status flags
// 0x0001 MediaPlaying
};
};
// Layer Status Message version 1.2
struct CITP_MSEX_12_LSta
{
CITP_MSEX_Header CITPMSEXHeader; // CITP MSEX header. MSEX ContentType is "LSta" and version is 1.2.
uint8 LayerCount; // Number of following layer information blocks.
};
// Get Element Library v 1.0
struct CITP_MSEX_10_GELI
{
CITP_MSEX_Header CITPMSEXHeader; // CITP MSEX header. MSEX ContentType is "GELI" and version is 1.0.
uint8 LibraryType; // Content type requested.
uint8 LibraryCount; // Number of libraries requested, set to 0 when requesting all available.
uint8 LibraryNumbers[]; // Requested library numbers, none if LibraryCount is 0.
};
// Get Element Library v1.1
struct CITP_MSEX_11_GELI
{
CITP_MSEX_Header CITPMSEXHeader; // CITP MSEX header. MSEX ContentType is "GELI" and version is 1.1.
uint8 LibraryType; // Content type requested.
MSEXLibraryId LibraryParentId; // Parent library id.
uint8 LibraryCount; // Number of libraries requested, set to 0 when requesting all available.
uint8 LibraryNumbers[]; // Requested library numbers, none if LibraryCount is 0.
};
// Get Element Library v1.2
struct CITP_MSEX_12_GELI
{
CITP_MSEX_Header CITPMSEXHeader; // CITP MSEX header. MSEX ContentType is "GELI" and version is 1.2.
uint8 LibraryType; // Content type requested.
MSEXLibraryId LibraryParentId; // Parent library id.
uint16 LibraryCount; // Number of libraries requested, set to 0 when requesting all available.
uint8 LibraryNumbers[]; // Requested library numbers, none if LibraryCount is 0.
};
// Elemnt Library Information v1.0
struct CITP_MSEX_ELIn
{
CITP_MSEX_Header CITPMSEXHeader; // CITP MSEX header. MSEX ContentType is "ELIn" and version is 1.1.
uint8 LibraryType; // Content type requested.
uint8 LibraryCount;// Number of following element library information blocks.
};
// Element Library Updated v1.2
struct CITP_MSEX_12_ELUp
{
CITP_MSEX_Header CITPMSEXHeader; // CITP MSEX header. MSEX ContentType is "ELUp" and version is 1.2.
uint8 LibraryType; // Content type of updated library.
MSEXLibraryId LibraryId; // Library that has been updated.
uint8 UpdateFlags; // Additional information flags.
// 0x01 Existing elements have been updated
// 0x02 Elements have been added or removed
// 0x04 Sub libraries have been updated
// 0x08 Sub libraries have been added or removed
// 0x10 All elements have been affected (ignore AffectedElements)
// 0x20 All sub libraries have been affected (ignore AffectedLibraris)
AffectedItems AffectedElements; // Which elements have been affected
AffectedItems AffectedLibraries; // Which sub-libraries have been affected
};
// Get Element Information v1.1
struct CITP_MSEX_11_GEIn
{
CITP_MSEX_Header CITPMSEXHeader; // CITP MSEX header. MSEX ContentType is "GEIn" and version is 1.1.
uint8 LibraryType; // Content type requested.
MSEXLibraryId LibraryId; // Library for which to retrieve elements
uint8 ElementCount; // Number of elements for which information is requested, set to 0 when requesting all available.
uint8 ElementNumbers[]; // Numbers of the elements for which information is requested.
};
// Get Element Information v1.0
struct CITP_MSEX_10_GEIn
{
CITP_MSEX_Header CITPMSEXHeader; // CITP MSEX header. MSEX ContentType is "GEIn" and version is 1.1.
quint8 LibraryType; // Content type requested.
quint8 LibraryId; // Library for which to retrieve elements
quint8 ElementCount; // Number of elements for which information is requested, set to 0 when requesting all available.
quint8 ElementNumbers; // Numbers of the elements for which information is requested.
};
// Media Element Information v1.0
struct CITP_MSEX_10_MEIn
{
CITP_MSEX_Header CITPMSEXHeader; // CITP MSEX header. MSEX ContentType is "MEIn" and version is 1.0
quint8 LibraryId; // Library containing the media elements.
qint8 ElementCount; // Number of following Media Information structs.
};
// Media Element Information v1.1
struct CITP_MSEX_11_MEIn
{
CITP_MSEX_Header CITPMSEXHeader; // CITP MSEX header. MSEX ContentType is "MEIn" and version is 1.1.
MSEXLibraryId LibraryId; // Library containing the media elements.
qint8 ElementCount; // Number of following Media Information blocks.
};
// Media Element Information v1.2
struct CITP_MSEX_12_MEIn
{
CITP_MSEX_Header CITPMSEXHeader; // CITP MSEX header. MSEX ContentType is "MEIn" and version is 1.1.
MSEXLibraryId LibraryId; // Library containing the media elements.
uint16 ElementCount; // Number of following Media Information blocks.
};
// Effect Element Information v1.2
struct CITP_MSEX_12_EEIn
{
CITP_MSEX_Header CITPMSEXHeader; // CITP MSEX header. MSEX ContentType is "EEIn" and version is 1.1.
MSEXLibraryId LibraryId;// Library containing the effect elements.
uint16 ElementCount;// Number of following (effect) information blocks.
struct EffectInformation
{
uint8 ElementNumber;
uint32 SerialNumber;
uint8 DMXRangeMin;
uint8 DMXRangeMax;
ucs2 EffectName[];
uint8 EffectParameterCount;
ucs2 EffectParameterNames[]; // List of effect parameter names.
};
};
// Generic Element Informatio v1.2
struct CITP_MSEX_12_GLEI
{
CITP_MSEX_Header CITPMSEXHeader; // CITP MSEX header. MSEX ContentType is "GLEI" and version is 1.1.
MSEXLibraryId LibraryId;
uint8 ElementCount;
uint16 LibraryType;
struct GenericInformation
{
uint8 ElementNumber;
uint32 SerialNumber;
uint8 DMXRangeMin;
uint8 DMXRangeMax;
ucs2 Name[];
uint64 VersionTimestamp;
};
};
// Get Element Libary Thumbnail
struct CITP_MSEX_12_GELT
{
CITP_MSEX_Header CITPMSEXHeader;// CITP MSEX header. MSEX ContentType is "GELT" and version is 1.2.
uint32 ThumbnailFormat;// Format of the thumbnail. Can be "RGB8" or "JPEG" (or "PNG " for MSEX 1.2 and up).
uint16 ThumbnailWidth;// Preferred thumbnail image width.
uint16 ThumbnailHeight;// Preferred thumbnail image height.
uint8 ThumbnailFlags;// Additional information flags.
// 0x01 Preserve aspect ratio of image (use width and height as maximum)
uint8 LibraryType;// 1 for Media, 2 for Effects.
uint16 LibraryCount;// Number of libraries requested, set to 0 when requesting all available.
MSEXLibraryId LibraryIds[];// Ids of the libraries requested, not present if LibraryCount is 0.
};
// Element Library Thumbnail
struct CITP_MSEX_11_ELTh
{
CITP_MSEX_Header CITPMSEXHeader;// CITP MSEX header. MSEX ContentType is "ELTh" and version is 1.1.
uint8 LibraryType;// 1 for Media, 2 for Effects.
MSEXLibraryId LibraryId;// Id of the library that the thumbnail belongs to.
uint32 ThumbnailFormat;// Format of the thumbnail. Can be "RGB8" or "JPEG" (or "PNG " for MSEX 1.2 and up).
uint16 ThumbnailWidth;// Thumbnail width.
uint16 ThumbnailHeight;// Thumbnail height.
uint16 ThumbnailBufferSize;// Size of the thumbnail buffer.
uint8 ThumbnailBuffer;// Thumbnail image buffer.
};
// Get Element Thumbnail v1.0
struct CITP_MSEX_10_GETh
{
CITP_MSEX_Header CITPMSEXHeader;
uint32 ThumbnailFormat; // Can be "RGB8" or "JPEG" (or "PNG " for MSEX 1.2 and up).
uint16 ThumbnailWidth;
uint16 ThumbnailHeight;
uint8 ThumbnailFlags; // Additional information flags. 0x01 Preserve aspect ratio of image (use width and height as maximum)
uint8 LibraryType; // 1 for Media, 2 for Effects.
uint8 LibraryNumber; // Number of the media's library.
uint8 ElementCount; // Number of medias for which information is requested, set to 0 when requesting all available.
uint8 ElementNumber; // The numbers of the requested elements.Not present if ElementCount is 0.
};
// Get Element Thumbnail v1.2
struct CITP_MSEX_12_GETh
{
CITP_MSEX_Header CITPMSEXHeader;// CITP MSEX header. MSEX ContentType is "GETh" and version is 1.2.
uint32 ThumbnailFormat;// Format of the thumbnail.Can be "RGB8" or "JPEG" (or "PNG " for MSEX 1.2 and up).
uint16 ThumbnailWidth; //Preferred thumbnail image width.
uint16 ThumbnailHeight; // Preferred thumbnail image height.
uint8 ThumbnailFlags; // Additional information flags.
//0x01 Preserve aspect ratio of image (use width and height as maximum)
uint8 LibraryType; //1 for Media, 2 for Effects.
MSEXLibraryId LibraryId; //Id of the media's library.
uint16 ElementCount; // Number of medias for which information is requested, set to 0 when requesting all available.
uint8 ElementNumbers[]; //The numbers of the requested elements. Not present if ElementCount = 0. For MSEX 1.2 these are 0-based contiguous index values.
};
// Element Thumbnail v1.0
struct CITP_MSEX_10_ETHN
{
CITP_MSEX_Header CITPMSEXHeader;// CITP MSEX header. MSEX ContentType is "EThn" and version is 1.1.
uint8 LibraryType;// 1 for Media, 2 for Effects.
uint8 LibraryId;// Id of the element's library.
uint8 ElementNumber;// Number of the element (For MSEX 1.2 this is a 0-based contiguous index value).
uint32 ThumbnailFormat;// Format of the thumbnail. Can be "RGB8" or "JPEG" (or "PNG " for MSEX 1.2 and up).
uint16 ThumbnailWidth;// Thumbnail width.
uint16 ThumbnailHeight;// Thumbnail height.
uint16 ThumbnailBufferSize;// Size of the thumbnail buffer.
// uint8 ThumbnailBuffer[];// Thumbnail image buffer.
};
// Element Thumbnail v1.1
struct CITP_MSEX_11_EThn
{
CITP_MSEX_Header CITPMSEXHeader;// CITP MSEX header. MSEX ContentType is "EThn" and version is 1.1.
uint8 LibraryType;// 1 for Media, 2 for Effects.
MSEXLibraryId LibraryId;// Id of the element's library.
uint8 ElementNumber;// Number of the element (For MSEX 1.2 this is a 0-based contiguous index value).
uint32 ThumbnailFormat;// Format of the thumbnail. Can be "RGB8" or "JPEG" (or "PNG " for MSEX 1.2 and up).
uint16 ThumbnailWidth;// Thumbnail width.
uint16 ThumbnailHeight;// Thumbnail height.
uint16 ThumbnailBufferSize;// Size of the thumbnail buffer.
uint8 ThumbnailBuffer;// Thumbnail image buffer.
};
// Get Video Sources
struct CITP_MSEX_GVSr
{
CITP_MSEX_Header CITPMSEXHeader; // CITP MSEX header. MSEX ContentType is "GVSr".
};
// Video Sources
struct CITP_MSEX_VSRC
{
CITP_MSEX_Header CITPMSEXHeader;// CITP MSEX header. MSEX ContentType is "VSrc".
uint16 SourceCount;// Number of following source information blocks.
uint16 SourceIdentifier; // Source identifier.
};
struct SourceInformation
{
signed char SourceName[];// Display name of the source (ie "Output 1", "Layer 2", "Camera 1" etc).
uint8 PhysicalOutput;// If applicable, 0-based index designating the physical video output index. Otherwise 0xFF.
uint8 LayerNumber;// If applicable, 0-based layer number, corresponding to the layers reported in the SInf message. Otherwise 0xFF.
uint16 Flags;// Information flags.
// 0x0001 Without effects
uint16 Width;// Full width.
uint16 Height;// Full height.
};
// Request Stream
struct CITP_MSEX_RqSt
{
CITP_MSEX_Header CITPMSEXHeader;// CITP MSEX header. MSEX ContentType is "RqSt".
uint16 SourceIdentifier;// Identifier of the source requested.
uint32 FrameFormat;// Requested frame format. Can be "RGB8" or "JPEG" (or "PNG " for MSEX 1.2 and up).
uint16 FrameWidth;// Preferred minimum frame width.
uint16 FrameHeight;// Preferred minimum frame height.
uint8 fps;// Preferred minimum frames per second.
uint8 Timeout;// Timeout in seconds (for instance 5 seconds, 0 to ask for only one frame).
};
// Stream Frame 1.0
struct CITP_MSEX_10_StFr
{
CITP_MSEX_Header CITPMSEXHeader;// The CITP MSEX header. MSEX ContentType is "StFr".
uint16 SourceIdentifier;// Identifier of the frame's source.
uint32 FrameFormat;// Requested frame format. Can be "RGB8" or "JPEG" (or "PNG " for MSEX 1.2 and up).
uint16 FrameWidth;// Preferred minimum frame width.
uint16 FrameHeight;// Preferred minimum frame height.
uint16 FrameBufferSize;// Size of the frame image buffer.
// uint8 FrameBuffer[];// Frame image buffer.
};
// Stream Frame 1.2
struct CITP_MSEX_12_StFr
{
CITP_MSEX_Header CITPMSEXHeader;// The CITP MSEX header. MSEX ContentType is "StFr".
ucs1 MediaServerUUID[36];// Source media server UUID.
uint16 SourceIdentifier;// Identifier of the frame's source.
uint32 FrameFormat;// Requested frame format. Can be "RGB8" or "JPEG" (or "PNG " for MSEX 1.2 and up).
uint16 FrameWidth;// Preferred minimum frame width.
uint16 FrameHeight;// Preferred minimum frame height.
uint16 FrameBufferSize;// Size of the frame image buffer.
uint8 FrameBuffer[];// Frame image buffer.
};
#endif // MSEXDEFINES_H

486
src/PacketCreator.cpp Normal file
View file

@ -0,0 +1,486 @@
/*
Libre Media Server - A Media Server Sotfware for stage and performing
Copyright (C) 2012-2013 Santiago Noreña puremediaserver@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "PacketCreator.h"
//#include "PureMediaServer.h"
//#include "MediaServer.h"
#include "CITPDefines.h"
#include "MSEXDefines.h"
#include <QtDebug>
#include <QFileInfo>
#include <QFile>
#include <QDir>
PacketCreator::PacketCreator(QObject *parent)
: QObject(parent)
{
}
PacketCreator::~PacketCreator()
{
}
unsigned char * PacketCreator::createPLocPacket(
const QString &name,
const QString &state,
int &bufferLen)
{
qDebug() << "createPLOC" << name << state;
QString plocType = "MediaServer";
// figure out the packet size, all strings need to be NULL terminated
bufferLen = sizeof(struct CITP_PINF_PLoc) + plocType.size() + 1 + name.size() + 1 + state.size() + 1;
unsigned char *buffer = new unsigned char[bufferLen];
memset(buffer, 0, bufferLen);
CITP_PINF_PLoc *packet = (CITP_PINF_PLoc*)buffer;
// CITP header
packet->CITPPINFHeader.CITPHeader.Cookie = COOKIE_CITP;
packet->CITPPINFHeader.CITPHeader.VersionMajor = 0x01;
packet->CITPPINFHeader.CITPHeader.VersionMinor = 0x00;
packet->CITPPINFHeader.CITPHeader.Reserved[0] = 0x00;
packet->CITPPINFHeader.CITPHeader.Reserved[1] = 0x00;
packet->CITPPINFHeader.CITPHeader.MessageSize = bufferLen;
packet->CITPPINFHeader.CITPHeader.MessagePartCount = 0x01;
packet->CITPPINFHeader.CITPHeader.MessagePart = 0x00; // XXX - doc says 0-based?
packet->CITPPINFHeader.CITPHeader.ContentType = COOKIE_PINF;
// PINF header
packet->CITPPINFHeader.ContentType = COOKIE_PINF_PLOC;
// PLoc data
packet->ListeningTCPPort = LISTENTCPPORT;
// type
int offset = sizeof(struct CITP_PINF_PLoc);
memcpy(buffer + offset, plocType.toAscii().constData(), plocType.size());
// name
offset += plocType.size() + 1;
memcpy(buffer + offset, name.toAscii().constData(), name.size());
// state
offset += name.size() + 1;
memcpy(buffer + offset, state.toAscii().constData(), state.size());
return buffer;
}
// Paquetes MSEX
unsigned char * PacketCreator::createSINFPacket(int &bufferLen)
{
// figure out the packet size
QString name = NAME;
bufferLen = 2*name.size() + 3 + sizeof(struct CITP_MSEX_10_SINF);
// create the buffer
unsigned char *buffer = new unsigned char[bufferLen];
memset(buffer, 0, bufferLen);
CITP_MSEX_10_SINF *packet = (CITP_MSEX_10_SINF *)buffer;
// CITP header
packet->CITPMSEXHeader.CITPHeader.Cookie = COOKIE_CITP;
packet->CITPMSEXHeader.CITPHeader.VersionMajor = 0x01;
packet->CITPMSEXHeader.CITPHeader.VersionMinor = 0x00;
packet->CITPMSEXHeader.CITPHeader.Reserved[0] = 0x00;
packet->CITPMSEXHeader.CITPHeader.Reserved[1] = 0x00;
packet->CITPMSEXHeader.CITPHeader.MessageSize = bufferLen;
packet->CITPMSEXHeader.CITPHeader.MessagePartCount = 0x01;
packet->CITPMSEXHeader.CITPHeader.MessagePart = 0x00; // XXX - doc says 0-based?
packet->CITPMSEXHeader.CITPHeader.ContentType = COOKIE_MSEX;
// MSEX header
packet->CITPMSEXHeader.VersionMajor = 0x01;
packet->CITPMSEXHeader.VersionMinor = 0x00;
packet->CITPMSEXHeader.ContentType = COOKIE_MSEX_SINF;
// SInf content
int offset = sizeof(struct CITP_MSEX_Header);
const ushort * namei = name.utf16();
memcpy((buffer+offset), namei, 2*(name.size()));
offset = offset + 2*name.size() +2;
memset ((buffer+offset), 0x01,1);
offset++;
memset((buffer+offset), 0x00, 3);
return buffer;
}
unsigned char * PacketCreator::createLSTAPacket(layerList layerp,int &bufferLen)
{
// figure out the packet size
const quint8 layerCount = layerp.size();
int layerslen = 0;
LayerStatus layeri;
for (int i=0; i<layerCount; i++) {
layeri = layerp.at(i);
layerslen = layerslen + 2*layeri.Name.size() -4 + sizeof(struct LayerStatus);
}
int offset = sizeof(struct CITP_MSEX_10_LSta);
bufferLen = offset + layerslen;
unsigned char *buffer = new unsigned char[bufferLen];
memset(buffer, 0, bufferLen);
CITP_MSEX_10_LSta *packet;
packet = (CITP_MSEX_10_LSta *)buffer;
// CITP header
packet->CITPMSEXHeader.CITPHeader.Cookie = COOKIE_CITP;
packet->CITPMSEXHeader.CITPHeader.VersionMajor = 0x01;
packet->CITPMSEXHeader.CITPHeader.VersionMinor = 0x00;
packet->CITPMSEXHeader.CITPHeader.Reserved[0] = 0x00;
packet->CITPMSEXHeader.CITPHeader.Reserved[1] = 0x00;
packet->CITPMSEXHeader.CITPHeader.MessageSize = bufferLen;
packet->CITPMSEXHeader.CITPHeader.MessagePartCount = 0x01;
packet->CITPMSEXHeader.CITPHeader.MessagePart = 0x00;
packet->CITPMSEXHeader.CITPHeader.ContentType = COOKIE_MSEX;
// MSEX header
packet->CITPMSEXHeader.ContentType = COOKIE_MSEX_LSTA;
packet->CITPMSEXHeader.VersionMajor = 0x01;
packet->CITPMSEXHeader.VersionMinor = 0x00;
//LSTA
packet->LayerCount = layerCount;
// Convertimos las estructuras a unsigned char
unsigned char * buffer2 = new unsigned char[layerslen];
LayerStatus packet2;
for (int i=0; i<layerCount;i++)
{
int offset2 =0;
memset(buffer2, 0x00, layerslen);
packet2 = layerp.at(i);
memcpy(buffer2, &packet2.LayerNumber,1);
offset2++;
memcpy((buffer2+offset2), &packet2.PhysicalOutput,1);
offset2++;
memcpy((buffer2+offset2), &packet2.MediaLibraryNumber,1);
offset2++;
memcpy((buffer2+offset2), &packet2.MediaNumber,1);
offset2++;
const ushort * name = packet2.Name.utf16();
memcpy((buffer2+offset2), name, 2*packet2.Name.size());
offset2 = offset2 + 2*packet2.Name.size() +2;
memcpy((buffer2+offset2), &packet2.MediaPosition,4);
offset2 = offset2 + 4;
memcpy((buffer2+offset2), &packet2.MediaLength,4);
offset2 = offset2 + 4;
memcpy((buffer2+offset2), &packet2.MediaFPS,1);
offset2 = offset2 + 1;
memcpy((buffer2+offset2), &packet2.LayerStatusFlags,4);
offset2 = offset2 + 4;
memcpy((buffer+offset), buffer2, offset2);
offset = offset + offset2;
}
return buffer;
}
unsigned char * PacketCreator::createELINPacket(QList <MediaLibrary> medialib, int&bufferLen)
{
// Vemos el tamaño total de la estructurta
MediaLibrary mediai;
int medialen = 0;
int size = 0;
int i;
for (i=0; i<medialib.size(); i++)
{
mediai = medialib.at(i);
size = sizeof(mediai) + 2*mediai.m_Name.size() +2 -sizeof(mediai.m_Name) -sizeof(mediai.m_MediaInformation);
medialen = medialen + size;
}
int offset = sizeof(struct CITP_MSEX_ELIn);
bufferLen = offset + medialen;
unsigned char *buffer = new unsigned char[bufferLen];
memset(buffer, 0, bufferLen);
CITP_MSEX_ELIn *packet = (CITP_MSEX_ELIn *)buffer;
// CITP header
packet->CITPMSEXHeader.CITPHeader.Cookie = COOKIE_CITP;
packet->CITPMSEXHeader.CITPHeader.VersionMajor = 0x01;
packet->CITPMSEXHeader.CITPHeader.VersionMinor = 0x00;
packet->CITPMSEXHeader.CITPHeader.Reserved[0] = 0x00;
packet->CITPMSEXHeader.CITPHeader.Reserved[1] = 0x00;
packet->CITPMSEXHeader.CITPHeader.MessageSize = bufferLen;
packet->CITPMSEXHeader.CITPHeader.MessagePartCount = 0x01;
packet->CITPMSEXHeader.CITPHeader.MessagePart = 0x00; // XXX - doc says 0-based?
packet->CITPMSEXHeader.CITPHeader.ContentType = COOKIE_MSEX;
// MSEX header
packet->CITPMSEXHeader.ContentType = COOKIE_MSEX_ELIN;
packet->CITPMSEXHeader.VersionMajor = 0x01;
packet->CITPMSEXHeader.VersionMinor = 0x00;
// ELin Content
packet->LibraryType = 0x01;
packet->LibraryCount = medialib.size();
// Element Library Information
unsigned char *buffer2 = new unsigned char[medialen];
for (i=0; i<medialib.size(); i++)
{
memset(buffer2, 0, medialen);
int offset2 = 0;
mediai = medialib.at(i);
memcpy (buffer2, &mediai.m_Id, 1);
offset2++;
memcpy ((buffer2+offset2), &mediai.m_DMXRangeMin,1);
offset2++;
memcpy((buffer2 +offset2), &mediai.m_DMXRangeMax,1);
offset2++;
const ushort * name = mediai.m_Name.utf16();
memcpy((buffer2+offset2), name, (2*mediai.m_Name.size()));
offset2 = 2+ offset2 + 2*mediai.m_Name.size();
memcpy((buffer2+offset2), &mediai.m_ElementCount, 1);
offset2++;
memcpy((buffer+offset), buffer2, offset2);
offset = offset + offset2;
}
return buffer;
}
unsigned char * PacketCreator::createMEINPacket(MediaLibrary medialib, int &bufferLen)
{
// Vemos el tamaño total de la estructurta
MediaLibrary mediai = medialib;
QList<MediaInformation> mediainflist = mediai.m_MediaInformation;
MediaInformation mediainf;
int medialen = 0;
int size = 0;
int i;
for (i=0; i<mediainflist.size(); i++)
{
mediainf = mediainflist.at(i);
size = 2 + sizeof(mediainf) +2*mediainf.MediaName.size() - sizeof(mediainf.MediaName);
medialen = medialen + size;
}
int offset = sizeof(struct CITP_MSEX_10_MEIn);
bufferLen = offset + medialen;
unsigned char *buffer = new unsigned char[bufferLen];
memset(buffer, 0, bufferLen);
CITP_MSEX_10_MEIn *packet = (CITP_MSEX_10_MEIn *)buffer;
// CITP header
packet->CITPMSEXHeader.CITPHeader.Cookie = COOKIE_CITP;
packet->CITPMSEXHeader.CITPHeader.VersionMajor = 0x01;
packet->CITPMSEXHeader.CITPHeader.VersionMinor = 0x00;
packet->CITPMSEXHeader.CITPHeader.Reserved[0] = 0x00;
packet->CITPMSEXHeader.CITPHeader.Reserved[1] = 0x00;
packet->CITPMSEXHeader.CITPHeader.MessageSize = bufferLen;
packet->CITPMSEXHeader.CITPHeader.MessagePartCount = 0x01;
packet->CITPMSEXHeader.CITPHeader.MessagePart = 0x00; // XXX - doc says 0-based?
packet->CITPMSEXHeader.CITPHeader.ContentType = COOKIE_MSEX;
// MSEX header
packet->CITPMSEXHeader.ContentType = COOKIE_MSEX_MEIN;
packet->CITPMSEXHeader.VersionMajor = 0x01;
packet->CITPMSEXHeader.VersionMinor = 0x00;
// MEIn Header
packet->LibraryId = mediai.m_Id;
packet->ElementCount = mediainflist.size();
// MEIn Data
unsigned char * buffer2 = new unsigned char[medialen];
for (i=0; i<mediainflist.size();i++){
memset(buffer2, 0,medialen);
int offset2 = 0;
mediainf = mediainflist.at(i);
memcpy(buffer2, &mediainf.Number, 1);
offset2= offset2 + 1;
memcpy((buffer2 + offset2),&mediainf.DMXRangeMin,1);
offset2= offset2 + 1;
memcpy((buffer2+offset2), &mediainf.DMXRangeMax ,1 );
offset2= offset2 + 1;
const ushort * name = mediainf.MediaName.utf16();
memcpy((buffer2+offset2), name, 2*mediainf.MediaName.size());
offset2 = 2 + offset2 + 2*mediainf.MediaName.size();
memcpy ((buffer2 + offset2), &mediainf.MediaVersionTimestamp, 8);
offset2= offset2 + 8;
memcpy((buffer2+offset2), &mediainf.MediaWidth,2);
offset2= offset2 + 2;
memcpy((buffer2+offset2), &mediainf.MediaHeight,2);
offset2= offset2 + 2;
memcpy((buffer2+offset2), &mediainf.MediaLength,4);
offset2= offset2 + 4;
memcpy((buffer2+offset2), &mediainf.MediaFPS,1);
offset2= offset2 + 1;
memcpy((buffer+offset), buffer2, offset2);
offset = offset + offset2;
}
return buffer;
}
unsigned char * PacketCreator::createETHNPacket(QString path,MediaLibrary medialib, int elementnumber, int &bufferLen)
{
QDir dir(path);
QFileInfo fileInfo;
QFileInfoList filelist;
if (medialib.m_Name == "image"){
dir.setFilter(QDir::Files);
dir.cd("image");
}
else {
dir.cd("video");
dir.setFilter(QDir::Dirs | QDir::NoSymLinks | QDir::NoDotAndDotDot);
filelist = dir.entryInfoList();
fileInfo = filelist.at(medialib.m_Id);
dir.cd(fileInfo.baseName());
dir.setFilter(QDir::Files);
}
dir.cd("thumbs");
filelist = dir.entryInfoList();
if (filelist.size() > elementnumber){
fileInfo = filelist.at(elementnumber);
}
else {
return NULL;
}
QFile file(fileInfo.filePath());
if (!file.open(QIODevice::ReadOnly)){
qDebug() << "Cannot open the file"<<fileInfo.filePath();
return NULL;
}
unsigned char * bufferthumb = new unsigned char[file.size()];
memset(bufferthumb, 0, file.size());
bufferthumb = file.map(0x00, file.size());
if (bufferthumb == 0){
qDebug() << "Cannot map the file";
}
bufferLen = sizeof(struct CITP_MSEX_10_ETHN) + file.size();
unsigned char * buffer = new unsigned char[bufferLen];
memset(buffer, 0, bufferLen);
CITP_MSEX_10_ETHN *packet = (CITP_MSEX_10_ETHN *)buffer;
// CITP header
packet->CITPMSEXHeader.CITPHeader.Cookie = COOKIE_CITP;
packet->CITPMSEXHeader.CITPHeader.VersionMajor = 0x01;
packet->CITPMSEXHeader.CITPHeader.VersionMinor = 0x00;
packet->CITPMSEXHeader.CITPHeader.Reserved[0] = 0x00;
packet->CITPMSEXHeader.CITPHeader.Reserved[1] = 0x00;
packet->CITPMSEXHeader.CITPHeader.MessageSize = bufferLen;
packet->CITPMSEXHeader.CITPHeader.MessagePartCount = 0x01;
packet->CITPMSEXHeader.CITPHeader.MessagePart = 0x00; // XXX - doc says 0-based?
packet->CITPMSEXHeader.CITPHeader.ContentType = COOKIE_MSEX;
// Mandamos el paquete
// MSEX header
packet->CITPMSEXHeader.ContentType = COOKIE_MSEX_ETHN;
packet->CITPMSEXHeader.VersionMajor = 0x01;
packet->CITPMSEXHeader.VersionMinor = 0x00;
//ETHN Content
packet->LibraryType = 0x01;
packet->LibraryId = medialib.m_Id;
packet->ElementNumber = elementnumber;
packet->ThumbnailFormat = 0x4745504A; // JPEG
packet->ThumbnailWidth = 60;
packet->ThumbnailHeight = 46;
packet->ThumbnailBufferSize = file.size();
// Thumbnail
int offset = sizeof(struct CITP_MSEX_10_ETHN);
memcpy((buffer+offset), bufferthumb, file.size());
file.close();
return buffer;
}
unsigned char * PacketCreator::createNACKPacket(quint32 cookie, int &bufferLen)
{
bufferLen = sizeof(struct CITP_MSEX_Nack);
unsigned char *buffer = new unsigned char[bufferLen];
memset(buffer, 0, bufferLen);
CITP_MSEX_Nack *packet;
packet = (CITP_MSEX_Nack *)buffer;
packet->ReceivedContentType = cookie;
return buffer;
}
// Video Stream
const char * PacketCreator::createVSRCPacket(int &bufferLen)
{
QString name("Output 1");
bufferLen = sizeof(struct CITP_MSEX_VSRC) + 2*name.size() + 10;
// create the buffer
char *buffer = new char[bufferLen];
memset(buffer, 0, bufferLen);
CITP_MSEX_VSRC *packet = (CITP_MSEX_VSRC *)buffer;
// CITP header
packet->CITPMSEXHeader.CITPHeader.Cookie = COOKIE_CITP;
packet->CITPMSEXHeader.CITPHeader.VersionMajor = 0x01;
packet->CITPMSEXHeader.CITPHeader.VersionMinor = 0x00;
packet->CITPMSEXHeader.CITPHeader.Reserved[0] = 0x00;
packet->CITPMSEXHeader.CITPHeader.Reserved[1] = 0x00;
packet->CITPMSEXHeader.CITPHeader.MessageSize = bufferLen;
packet->CITPMSEXHeader.CITPHeader.MessagePartCount = 0x01;
packet->CITPMSEXHeader.CITPHeader.MessagePart = 0x00; // XXX - doc says 0-based?
packet->CITPMSEXHeader.CITPHeader.ContentType = COOKIE_MSEX;
// MSEX header
packet->CITPMSEXHeader.ContentType = COOKIE_MSEX_VSRC;
packet->CITPMSEXHeader.VersionMajor = 0x01;
packet->CITPMSEXHeader.VersionMinor = 0x00;
packet->SourceCount = 0x01;
// VSRC Information
packet->SourceIdentifier = 0x01;
int offset = sizeof(struct CITP_MSEX_VSRC);
const ushort * namei = name.utf16();
memcpy((buffer+offset), namei, 2*(name.size()));
offset = offset + 2*name.size() +2;
QByteArray post;
post[0] = 0xFF; // Physical Ouput uint8
post[1] = 0xFF; // Layer Number uint8
post[2] = 0x00; // Flags uint16
post[3] = 0x00;
post[4] = 0x00; // Width uint16
post[5] = 0x40;
post[6] = 0x00; // Height uint16
post[7] = 0x2E;
memcpy((buffer+offset), post, post.size());
return buffer;
}
/* This will be the send frme for CITP/MSEx 1.1 in the CITP Socket. 1.0 uses the TCP Socket in msex class
const char * PacketCreator::createFrame(uchar *frame, int &bufferLen)
{
int bufferLenTot = sizeof(struct CITP_MSEX_10_StFr ) + bufferLen;
char * buffer = new char[bufferLen];
memset(buffer, 0, bufferLen);
CITP_MSEX_10_StFr *packet = (CITP_MSEX_10_StFr *)buffer;
// CITP header
packet->CITPMSEXHeader.CITPHeader.Cookie = COOKIE_CITP;
packet->CITPMSEXHeader.CITPHeader.VersionMajor = 0x01;
packet->CITPMSEXHeader.CITPHeader.VersionMinor = 0x00;
packet->CITPMSEXHeader.CITPHeader.Reserved[0] = 0x00;
packet->CITPMSEXHeader.CITPHeader.Reserved[1] = 0x00;
packet->CITPMSEXHeader.CITPHeader.MessageSize = bufferLenTot;
packet->CITPMSEXHeader.CITPHeader.MessagePartCount = 0x01;
packet->CITPMSEXHeader.CITPHeader.MessagePart = 0x00; // XXX - doc says 0-based?
packet->CITPMSEXHeader.CITPHeader.ContentType = COOKIE_MSEX;
// MSEX header
packet->CITPMSEXHeader.ContentType = COOKIE_MSEX_STFR;
packet->CITPMSEXHeader.VersionMajor = 0x01;
packet->CITPMSEXHeader.VersionMinor = 0x00;
//STFR Content
packet->FrameBufferSize = bufferLen;
packet->FrameFormat = 943867730;
packet->FrameHeight = 64;
packet->FrameWidth = 88;
packet->SourceIdentifier = 0x0001;
// Copiamos los datos del thumbnail
int offset = sizeof(struct CITP_MSEX_10_StFr);
memcpy((buffer+offset), frame, bufferLen);
bufferLen = bufferLenTot;
return buffer;
}
*/

62
src/PacketCreator.h Normal file
View file

@ -0,0 +1,62 @@
// -*- mode: C++ -*-
/*
Libre Media Server - A Media Server Sotfware for stage and performing
Copyright (C) 2012 -2013 Santiago Noreña
belfegor <AT> gmail <DOT> com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* Makes all CITP/MSEx packets */
#ifndef _PACKETCREATOR_H_
#define _PACKETCREATOR_H_
#include "MSEXDefines.h"
#include <QObject>
typedef QList<LayerStatus> layerList;
class PacketCreator : public QObject
{
Q_OBJECT
public:
PacketCreator(QObject *parent=0);
virtual ~PacketCreator();
// CITP
// returns NULL on error. bufferLen is the length of the returned buffer.
static unsigned char * createPLocPacket(const QString &name, const QString &state,
int &bufferLen);
// returns NULL on error. bufferLen is the length of the returned buffer.
static unsigned char * createUNamPacket(quint8 universeIndex, const QString &name,
int &bufferLen);
// MSEX
static unsigned char * createSINFPacket(int &bufferLen);
static unsigned char * createLSTAPacket(layerList layerp, int &bufferLen);
static unsigned char * createNACKPacket(quint32 cookie, int &bufferLen);
static unsigned char * createELINPacket(QList<MediaLibrary> medialib, int &bufferLen);
static unsigned char * createMEINPacket(MediaLibrary medialib, int &bufferLen);
static unsigned char * createETHNPacket(QString path, MediaLibrary medialib, int elementnumber, int &bufferLen);
static const char * createVSRCPacket(int &bufferLen);
// static const char * createFrame(uchar *frame, int &bufferLen);
private:
};
#endif // _PACKETCREATOR_H_

View file

@ -0,0 +1,182 @@
/*
The MIT License
Copyright (c) 2012-2013 Santi Noreña
Copyright (c) 2009 John Warwick
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include "PeerInformationSocket.h"
#include "citp-lib.h"
#include "CITPDefines.h"
#include "PacketCreator.h"
//#include "MediaServer.h"
#include <QTimer>
#include <QtDebug>
#include <QNetworkInterface>
#ifdef Q_OS_WIN
#include <winsock2.h>
#include <ws2tcpip.h>
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#endif
PeerInformationSocket::PeerInformationSocket(QObject *parent)
: QUdpSocket(parent),
m_name(tr("Unknown name")),
m_state(tr("Unknown state")),
m_packetBuffer(NULL),
m_packetBufferLen(0)
{
m_timer = new QTimer(this);
Q_CHECK_PTR(m_timer);
connect(m_timer, SIGNAL(timeout()),
this, SLOT(transmitPLoc()));
m_timer->setInterval(TRANSMIT_INTERVAL_MS);
setSocketState(QUdpSocket::BoundState);
}
PeerInformationSocket::~PeerInformationSocket()
{
if (m_timer)
{
m_timer->stop();
}
}
bool PeerInformationSocket::init(const QString &name, const QString &state, quint32 ipadd)
{
if (m_timer)
{
m_timer->stop();
}
m_name = name;
m_state = state;
// create multicast socket, bind to port
QHostAddress address;
address.setAddress(ipadd);
if (!bind(address, CITP_PINF_MULTICAST_PORT, ShareAddress | ReuseAddressHint))
{
qDebug() << "Multicast bind failed";
return false;
}
struct ip_mreq mreq;
mreq.imr_multiaddr.s_addr = inet_addr(CITP_PINF_MULTICAST_IP);
mreq.imr_interface.s_addr = ipadd;
int r = ::setsockopt(socketDescriptor(), IPPROTO_IP, IP_ADD_MEMBERSHIP,
(const char *)&mreq, sizeof(struct ip_mreq));
if (0 != r)
{
qDebug() << "setsockopt failed, r:" << r;
return false;
}
delete m_packetBuffer;
m_packetBuffer = PacketCreator::createPLocPacket(name, state, m_packetBufferLen);
if (!m_packetBuffer)
{
m_packetBufferLen = 0;
return false;
}
// transmitPLoc();
// XXX - don't connect this more than once..
connect(this, SIGNAL(readyRead()),
this, SLOT(handleReadReady()));
if (m_timer)
{
m_timer->start();
}
return true;
}
void PeerInformationSocket::transmitPLoc()
{
if (m_packetBuffer && m_packetBufferLen > 0)
{
QHostAddress addr(CITP_PINF_MULTICAST_IP);
writeDatagram((const char*)m_packetBuffer, m_packetBufferLen, addr, CITP_PINF_MULTICAST_PORT);
}
}
void PeerInformationSocket::handleReadReady()
{
while (hasPendingDatagrams())
{
QByteArray datagram;
datagram.resize(pendingDatagramSize());
QHostAddress sender;
quint16 senderPort;
if (-1 != readDatagram(datagram.data(), datagram.size(),
&sender, &senderPort))
{
processPacket(sender, datagram);
}
}
}
void PeerInformationSocket::processPacket(const QHostAddress &address, const QByteArray &packetArray)
{
const char *data = packetArray.constData();
CITP_PINF_PLoc *packet = (CITP_PINF_PLoc*)data;
// CITP header
if (packet->CITPPINFHeader.CITPHeader.Cookie != COOKIE_CITP)
{
qDebug() << "No CITP";
return;
}
/*
if (packet->CITPPINFHeader.CITPHeader.VersionMajor != 0x01)
{
qDebug() << "Invalid VersionMajor value:" << packet->CITPPINFHeader.CITPHeader.VersionMajor;
return;
}
if (packet->CITPPINFHeader.CITPHeader.VersionMinor != 0x00)
{
qDebug() << "Invalid VersionMinor value:" << packet->CITPPINFHeader.CITPHeader.VersionMinor;
return;
}
*/
if (packet->CITPPINFHeader.CITPHeader.ContentType != COOKIE_PINF)
{
qDebug() << "NO PINF";
return;
}
// PINF header
// if (packet->CITPPINFHeader.ContentType = COOKIE_PINF_PLOC)
// {
// qDebug() << "PLOC found" << packet->Name;
// return;
// }
// PLoc data
// quint16 listeningPort = packet->ListeningTCPPort;
}

View file

@ -0,0 +1,68 @@
// -*- mode: C++ -*-
/*
The MIT License
Copyright (c) 2012-2013 Santi Noreña libremediaserver@gmail.com
Copyright (c) 2009 John Warwick
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
/* This class makes the socket for the PLoc packets and process answers on that socket */
#ifndef _PEERINFORMATIONSOCKET_H_
#define _PEERINFORMATIONSOCKET_H_
#include <QUdpSocket>
class QTimer;
//class MediaServer;
struct PeerDescripton;
class PeerInformationSocket : public QUdpSocket
{
Q_OBJECT
public:
PeerInformationSocket(QObject *parent=0);
virtual ~PeerInformationSocket();
bool init(const QString &name, const QString &state, quint32 ipadd);
private slots:
void transmitPLoc();
void handleReadReady();
private:
QString m_name;
QString m_state;
QTimer *m_timer;
unsigned char *m_packetBuffer;
int m_packetBufferLen;
void processPacket(const QHostAddress &sender, const QByteArray &packet);
signals:
// void peersUpdated();
};
#endif // _PEERINFORMATIONSOCKET_H_

52
src/citp-lib.cpp Normal file
View file

@ -0,0 +1,52 @@
/*
The MIT License
Copyright c() 2012-2013 Santi Noreña
Copyright (c) 2009 John Warwick
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include "citp-lib.h"
#include <QtDebug>
#include "CITPDefines.h"
#include "PeerInformationSocket.h"
CITPLib::CITPLib(QObject *parent)
: QObject(parent),
m_peerSocket(NULL)
{
m_peerSocket = new PeerInformationSocket(this);
Q_CHECK_PTR(m_peerSocket);
}
CITPLib::~CITPLib()
{
}
bool CITPLib::createPeerInformationSocket(const QString &name, const QString &state, quint32 ipadd)
{
if (!m_peerSocket)
{
return false;
}
return m_peerSocket->init(name, state, ipadd);
}

68
src/citp-lib.h Normal file
View file

@ -0,0 +1,68 @@
// -*- mode: C++ -*-
/*
The MIT License
Copyright (c) 2012-2013 Santi Noreña libremediaserver@gmail.com
Copyright (c) 2009 John Warwick
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef _CITPLIB_H_
#define _CITPLIB_H_
#include <qglobal.h>
#ifdef CITPLIB_LIB
# define CITPLIB_EXPORT Q_DECL_EXPORT
#else
# define CITPLIB_EXPORT Q_DECL_IMPORT
#endif
#include <QObject>
#include <QScriptable>
#include <QHostAddress>
#include <QNetworkInterface>
class PeerInformationSocket;
class MediaServer;
class CITPLIB_EXPORT CITPLib : public QObject, public QScriptable
{
Q_OBJECT
public:
CITPLib(QObject *parent = 0);
virtual ~CITPLib();
bool createPeerInformationSocket(const QString &name, const QString &state, quint32 ipadd);
PeerInformationSocket *m_peerSocket;
private:
signals:
};
#endif // _CITPLIB_H_

1638
src/libremediaserver.cpp Normal file

File diff suppressed because it is too large Load diff

153
src/libremediaserver.h Normal file
View file

@ -0,0 +1,153 @@
/*
Libre Media Server - A Media Server Sotfware for stage and performing
Copyright (C) 2012-2013 Santiago Noreña libremediaserver@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef LIBREMEDIASERVER_H
#define LIBREMEDIASERVER_H
#include <QMainWindow>
#include "msex.h"
#include "ui_libremediaserver.h"
#include <QLocalServer>
#include <QLocalSocket>
class msex;
class QMenu;
class QProcess;
class libreMediaServer : public QMainWindow
{
Q_OBJECT
public:
libreMediaServer (QWidget *parent = 0);
virtual ~libreMediaServer();
Ui::LibreMediaServer ui;
protected:
QString m_pathmedia; // Path to Medias
msex *m_msex; // MSEx
QProcess *m_ola; // OLA daemon process
QProcess *m_pd_video; // Pure Data process for video
QProcess *m_pd_audio; // Pure Data process for audio
// Video Sockets
QTcpSocket *m_pd_write_video;
// Unix Local Sockets
// QLocalSocket *m_write_vid;
QLocalServer *m_server_vid;
QLocalSocket *m_read_vid;
// Audio TCP Sockets
QTcpSocket *m_pd_write_audio;
QTcpServer *m_pd_read_audio;
QTcpSocket *m_tcpsocket_audio;
QTimer *m_preview;
// void contextMenuEvent(QContextMenuEvent *event);
private:
bool sendPacket(const char *buffer, int bufferLen);
void pdstart();
void errorsending();
bool sendPacket_audio(const char *buffer, int bufferLen);
void pdstart_audio();
void errorsending_audio();
public slots:
void sendFrame();
private slots:
void olastart(); // Init the OLA daemon
void on_ChangePath_clicked();// Change the path to medias
// Video
void on_updateButton_clicked(); // Init the CITP/MSEx protocol
void newPeer();
void newmessage();
void newconexion();
void on_window_stateChanged(int state);
void on_winpositionx_valueChanged();
void on_winpositiony_valueChanged();
void on_winsizex_valueChanged();
void on_winsizey_valueChanged();
void on_readDMX_stateChanged(int state);
void on_layer1Add_valueChanged();
void on_layer1Check_stateChanged (int state);
void on_layer2Add_valueChanged();
void on_layer2Check_stateChanged (int state);
void on_layer3Add_valueChanged();
void on_layer3Check_stateChanged (int state);
void on_layer4Add_valueChanged();
void on_layer4Check_stateChanged (int state);
void on_layer5Add_valueChanged();
void on_layer5Check_stateChanged (int state);
void on_layer6Add_valueChanged();
void on_layer6Check_stateChanged (int state);
void on_layer7Add_valueChanged();
void on_layer7Check_stateChanged (int state);
void on_layer8Add_valueChanged();
void on_layer8Check_stateChanged (int state);
void pdrestart();
void stdout();
void on_video_stateChanged(int state);
//Audio
void newPeer_audio();
void newmessage_audio();
void newconexion_audio();
void on_readDMX_audio_stateChanged(int state);
void on_layer1Add_audio_valueChanged();
void on_layer1Check_audio_stateChanged (int state);
void on_layer2Add_audio_valueChanged();
void on_layer2Check_audio_stateChanged (int state);
void on_layer3Add_audio_valueChanged();
void on_layer3Check_audio_stateChanged (int state);
void on_layer4Add_audio_valueChanged();
void on_layer4Check_audio_stateChanged (int state);
void on_layer5Add_audio_valueChanged();
void on_layer5Check_audio_stateChanged (int state);
void on_layer6Add_audio_valueChanged();
void on_layer6Check_audio_stateChanged (int state);
void on_layer7Add_audio_valueChanged();
void on_layer7Check_audio_stateChanged (int state);
void on_layer8Add_audio_valueChanged();
void on_layer8Check_audio_stateChanged (int state);
void pdrestart_audio();
void stdout_audio();
void on_audio_stateChanged(int state);
// File configuration
void open();
void save();
// Previews
void previewMaster();
};
#endif // LIBREMEDIASERVER_H

34
src/libremediaserver.pro Normal file
View file

@ -0,0 +1,34 @@
TEMPLATE = app
TARGET = libremediaserver
QT += network script
CONFIG += debug
DESTDIR = ./debug
HEADERS += libremediaserver.h \
citp-lib.h \
PacketCreator.h \
PeerInformationSocket.h \
msex.h \
CITPDefines.h \
MSEXDefines.h
SOURCES += main.cpp \
libremediaserver.cpp \
citp-lib.cpp \
PacketCreator.cpp \
PeerInformationSocket.cpp \
msex.cpp
FORMS += \
libremediaserver.ui
#INCLUDEPATH += ./
LIBS += -L./debug
#win32:CONFIG(release, debug|release): LIBS += -L$$PWD/../debug/release/ -lcitp
#else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/../debug/debug/ -lcitp
#else:symbian: LIBS += -lcitp
#else:unix: LIBS += -L$$PWD/../debug/ -lcitp
#INCLUDEPATH += $$PWD/../debug
#DEPENDPATH += $$PWD/../debug

1175
src/libremediaserver.ui Normal file

File diff suppressed because it is too large Load diff

28
src/main.cpp Normal file
View file

@ -0,0 +1,28 @@
/*
Libre Media Server - A Media Server Sotfware for stage and performing
Copyright (C) 2012-2013 Santiago Noreña libremediaserver@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <QApplication>
#include "libremediaserver.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
libreMediaServer libreMediaServer;
libreMediaServer.show();
return app.exec();
}

614
src/msex.cpp Normal file
View file

@ -0,0 +1,614 @@
/*
Pure Media Server - A Media Server Sotfware for stage and performing
Copyright (C) 2012-2013 Santiago Noreña puremediaserver@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "msex.h"
//#include "libremediaserver.h"
#include "MSEXDefines.h"
#include "PacketCreator.h"
#include "citp-lib.h"
#include <QtDebug>
#include <QTimer>
#include <QTcpServer>
#include <QTcpSocket>
#include <QDir>
#include <QDateTime>
msex::msex(QObject *parent)
: QObject(parent),
m_peerState(STATE),
m_peerName(NAME),
m_listeningPort(LISTENTCPPORT)
{
// Iniciamos la lista de estatus de layer
LayerStatus layermodel;
m_layers.clear();
int i;
for (i=0; i < LAYER_NUMBER; i++)
{
layermodel.LayerNumber = i;
layermodel.PhysicalOutput = 0x01;
layermodel.MediaLibraryNumber = 0x00;
layermodel.MediaNumber = i;
layermodel.Name = "medianame";
layermodel.MediaPosition = 0x1111;
layermodel.MediaLength = 0x2222;
layermodel.MediaFPS = 25;
m_layers.append(layermodel);
}
// Variables para el buffer de LSTA
m_bufferLen = 0x00;
m_buffer = NULL;
m_pathmedia.clear();
// Inicio del TCP Server
m_tcpServer = new QTcpServer(this);
Q_CHECK_PTR(m_tcpServer);
if (!m_tcpServer)
qWarning("error TCP Server no creado");
if (!m_tcpServer->listen(QHostAddress::Any, LISTENTCPPORT))
{
qWarning("error creando tcpServer");
}
connect(m_tcpServer, SIGNAL(newConnection()),
this, SLOT(newPeer()));
// Timer for frame preview
n_timer = new QTimer(this);
Q_CHECK_PTR(n_timer);
}
// Propiedades de clase
msex::~msex()
{
if (m_tcpServer)
m_tcpServer->close();
}
/*
QString msex::peerName() const
{
return m_peerName;
}
QString msex::peerState() const
{
return m_peerState;
}
QString msex::peerHost() const
{
return m_host.toString();
}
quint16 msex::peerListeningPort() const
{
return m_listeningPort;
}
*/
bool msex::newPeer()
{
m_tcpSocket = m_tcpServer->nextPendingConnection();
connect(m_tcpSocket, SIGNAL(readyRead()),
this, SLOT(handleReadyRead()));
// Ahora tenemos que mandar un Sinf para MSEX 1.1 y 1.0
//Creamos un paquete SINf
int bufferLen = sizeof(struct CITP_MSEX_10_SINF);
unsigned char * buffer = PacketCreator::createSINFPacket(bufferLen);
if (!buffer)
{
qDebug() << "msex::new peer:createSINFPacket() failed";
return false;
}
// Mandamos el paquete
if (!msex::sendPacket(buffer, bufferLen))
{
qDebug() << "msex::new peer: Send SInf Message failed";
return false;
}
qDebug() << "msex::new peer: SInf Sent...";
return true;
/* Iniciamos el layer Status
// Creamos un paquete LSTA
m_bufferLen = sizeof(struct CITP_MSEX_12_LSta);
unsigned char *buffer2 = PacketCreator::createLSTAPacket(m_layers, m_bufferLen);
if (!buffer2)
{
qDebug() << "createLSTAPacket() failed";
return false;
}
m_buffer = buffer2;
// Iniciamos el temporizador para mandar LSTA
// n_timer->start();
// qDebug("Start sending LSta");
transmitlsta();
return true;*/
}
/*
bool msex::transmitlsta()
{
if (!msex::sendPacket(m_buffer, m_bufferLen))
{
qDebug() << "msex::LSta Message failed";
qDebug() << "Peer disconnected?";
n_timer->stop();
m_tcpSocket->close();
return false;
}
return true;
}*/
// Lectura de paquetes
void msex::handleReadyRead()
{
while(m_tcpSocket->bytesAvailable())
{
QByteArray peekArray = m_tcpSocket->peek(12);
if (12 != peekArray.size())
{
return;
}
if (peekArray[0] != 'C' &&
peekArray[1] != 'I' &&
peekArray[2] != 'T' &&
peekArray[3] != 'P')
{
// remove the first byte and try again
QByteArray b = m_tcpSocket->read(1);
qDebug() << "Discarding byte:" << b[0];
continue;
}
quint32 messageSize = 0;
messageSize = peekArray[11];
messageSize <<= 8;
messageSize |= peekArray[10];
messageSize <<= 8;
messageSize |= peekArray[9];
messageSize <<= 8;
messageSize |= peekArray[8];
if (messageSize > m_tcpSocket->bytesAvailable())
{
qDebug() << "Not enough bytes available, only have:" << m_tcpSocket->bytesAvailable();
return;
}
QByteArray byteArray = m_tcpSocket->read(messageSize);
parsePacket(byteArray);
}
}
// Mandar paquetes
bool msex::sendPacket(const unsigned char *buffer, int bufferLen)
{
if (!m_tcpSocket)
{
return false;
}
if (QAbstractSocket::ConnectedState != m_tcpSocket->state())
{
qDebug() << "msex::sendPacket() - Socket not connected";
return false;
}
if (bufferLen != m_tcpSocket->write((const char*)buffer, bufferLen))
{
qDebug() << "msex::sendPacket() write failed:" << m_tcpSocket->error();
return false;
}
delete buffer;
return true;
}
// Overload Send Packet
bool msex::sendPacket(const char *buffer, int bufferLen)
{
if (!m_tcpSocket)
{
return false;
}
if (QAbstractSocket::ConnectedState != m_tcpSocket->state())
{
qDebug() << "msex::sendPacket() - Socket not connected";
return false;
}
if (bufferLen != m_tcpSocket->write(buffer, bufferLen))
{
qDebug() << "msex::sendPacket() write failed:" << m_tcpSocket->error();
return false;
}
return true;
}
// Determina qué tipo de paquete es
void msex::parsePacket(const QByteArray &byteArray)
{
const char *data = byteArray.constData();
struct CITP_Header *citpHeader = (struct CITP_Header*)data;
// CITP header
if (citpHeader->Cookie != COOKIE_CITP)
{
qDebug() << "parsePacket: invalid Cookie" << citpHeader->Cookie;
return;
}
/*
if (citpHeader->VersionMajor != 0x01)
{
qDebug() << "parsePacket: invalid VersionMajor:" << citpHeader->VersionMajor;
return;
}
if (citpHeader->VersionMinor != 0x00)
{
qDebug() << "parsePacket: invalid VersionMinor:" << citpHeader->VersionMinor;
return;
}
*/
switch (citpHeader->ContentType)
{
case COOKIE_PINF:
qDebug() << "parsePacket: got COOKIE_PINF packet on TCP Socket...";
parsePINFPacket(byteArray);
break;
case COOKIE_MSEX:
parseMSEXPacket(byteArray);
break;
default:
qDebug() << "parsePacket: unknown ContentType:" << citpHeader->ContentType;
return;
}
}
//Process PINF Packets
void msex::parsePINFPacket(const QByteArray &byteArray)
{
const char *data = byteArray.constData();
struct CITP_PINF_Header *pinfHeader = (struct CITP_PINF_Header*)data;
switch (pinfHeader->ContentType)
{
case COOKIE_PINF_PNAM:
{
int offset = sizeof(struct CITP_PINF_Header);
int size = byteArray.size();
char * name = new char[size];
memcpy(name,(data+offset),size);
QString namei = name;
qDebug() << "Ploc arrives. NAME:" << namei;
}
}
}
// Procesa paquete MSEX
void msex::parseMSEXPacket(const QByteArray &byteArray)
{
const char *data = byteArray.constData();
struct CITP_MSEX_Header *msexHeader = (struct CITP_MSEX_Header*)data;
switch (msexHeader->ContentType)
{
case COOKIE_MSEX_CINF:
parseCINFPacket(byteArray);
break;
/* case COOKIE_MSEX_NACK:
parseNACKPacket(byteArray);
break;*/
case COOKIE_MSEX_GELI:
parseGELIPacket(byteArray);
break;
case COOKIE_MSEX_GEIN:
parseGEINPacket(byteArray);
break;
case COOKIE_MSEX_GELT:
parseGELTPacket();
break;
case COOKIE_MSEX_GETH:
parseGETHPacket(byteArray);
break;
case COOKIE_MSEX_GVSR:
parseGVSRPacket();
break;
case COOKIE_MSEX_RQST:
parseRQSTPacket(byteArray);
break;
default:
qDebug() << "parseMSEXPacket: unknown ContentType:" << msexHeader->ContentType ;
msex::sendNACK(msexHeader->ContentType);
}
}
void msex::parseCINFPacket(const QByteArray &byteArray)
{
const char *data = byteArray.constData();
struct CITP_MSEX_CInf *cinf = (struct CITP_MSEX_CInf*)data;
int size = 2 * cinf->SupportedMSEXVersionsCount;
unsigned short * versions = new unsigned short[size];
memcpy(versions, &cinf->SupportedMSEXVersions, size);
for (int i=0; i < cinf->SupportedMSEXVersionsCount;i++){
qDebug() << "CInf arrives. Suported Versions: " <<versions[i];
}
}
void msex::parseGELIPacket(const QByteArray &byteArray)
{
const char *data = byteArray.constData();
struct CITP_MSEX_11_GELI *geliPacket = (struct CITP_MSEX_11_GELI*)data;
if (geliPacket->LibraryType != 0x01)
{
qDebug() << "parseGELIPacket:Not library type supported, only MEDIA now 0x01";
return;
}
// Creamos un paquete ELin
int bufferLen = sizeof(struct CITP_MSEX_ELIn);
unsigned char * buffer = PacketCreator::createELINPacket(m_media, bufferLen);
if (!buffer)
{
qDebug() << "parseGELIPacket:createELINPacket() failed";
return;
}
// Mandamos el paquete
if (!msex::sendPacket(buffer, bufferLen))
{
qDebug() << "parseGELIPacket: Send ELin Message failed";
return;
}
qDebug() << "parseGELIPacket finish ok. ELin Sent...";
}
void msex::parseGEINPacket(const QByteArray &byteArray)
{
const char *data = byteArray.constData();
struct CITP_MSEX_10_GEIn *geinPacket = (struct CITP_MSEX_10_GEIn*)data;
qDebug() << "GEIn arrives: Elemet count:" << geinPacket->ElementCount << "Libray Id:" << geinPacket->LibraryId << "Library Type:" << geinPacket->LibraryType;
int bufferLen = sizeof (struct CITP_MSEX_10_MEIn);
if (!(geinPacket->LibraryId < m_media.size())) {
qDebug() << "Library ID exceeds size list";
/*unsigned char * buffer = PacketCreator::createMEINPacket(m_media.at(geinPacket->LibraryId),bufferLen);
if (!buffer)
{
qDebug() << "parseGEINPacket:createMEINPacket() failed";
return;
}
// Mandamos el paquete
if (!msex::sendPacket(buffer, bufferLen))
{
qDebug() << "parseGEINPacket: Send MEIn Message failed";
return;
}
qDebug() << "parseGEINPacket finish ok. MEIn Sent...";*/
}
else {
unsigned char * buffer = PacketCreator::createMEINPacket(m_media.at(geinPacket->LibraryId),bufferLen);
if (!buffer)
{
qDebug() << "parseGEINPacket:createMEINPacket() failed";
return;
}
// Mandamos el paquete
if (!msex::sendPacket(buffer, bufferLen))
{
qDebug() << "parseGEINPacket: Send MEIn Message failed";
return;
}
}
}
void msex::parseGELTPacket()
{
// const char *data = byteArray.constData();
// struct CITP_MSEX_12_GELT *geltPacket = (struct CITP_MSEX_12_GELT*)data;
qDebug() << "parseGELTPacket: GELT arrives...";
}
void msex::parseGETHPacket(const QByteArray &byteArray)
{
const char *data = byteArray.constData();
struct CITP_MSEX_10_GETh *gethPacket = (struct CITP_MSEX_10_GETh*)data;
qDebug() << "GETh arrives. Format:"<< gethPacket->ThumbnailFormat<<"Width:"<<gethPacket->ThumbnailWidth<<"Height:"<<gethPacket->ThumbnailHeight;
qDebug() << "Library Number:"<<gethPacket->LibraryNumber<<"Element COunt:"<<gethPacket->ElementCount<<"ElementNumber:"<<gethPacket->ElementNumber;
int bufferLen = sizeof (struct CITP_MSEX_10_ETHN);
if (!(gethPacket->LibraryNumber < m_media.size())) {
qDebug() << "Library ID exceeds size list";
return;
}
MediaLibrary mediai = m_media.at(gethPacket->LibraryNumber);
if (mediai.m_ElementCount <= gethPacket->ElementNumber){
qDebug() << "Element Number is greater than the elements in library";
return;
}
unsigned char * buffer = PacketCreator::createETHNPacket(m_pathmedia, mediai, gethPacket->ElementNumber, bufferLen);
if (!buffer)
{
qDebug() << "parseGETHPacket:createETHNPacket() failed";
return;
}
// Mandamos el paquete
if (!msex::sendPacket(buffer, bufferLen))
{
qDebug() << "parseGETHPacket: Send ETHN Message failed";
return;
}
}
void msex::parseGVSRPacket()
{
int bufferLen;
// Create a VSrc message
const char * buffer = PacketCreator::createVSRCPacket(bufferLen);
if (!buffer)
{
qDebug() << "parseGVSRacket:createVSRCPacket() failed";
return;
}
// Mandamos el paquete
if (!msex::sendPacket(buffer, bufferLen))
{
qDebug() << "parseGVSRPacket: Send VRSC Message failed";
return;
}
delete buffer;
}
void msex::parseRQSTPacket(const QByteArray &byteArray)
{
const char *data = byteArray.constData();
struct CITP_MSEX_RqSt *Packet = (struct CITP_MSEX_RqSt*)data;
// Here we need start the streaming MagicQ 88x64 RGB8 1 FPS
// Iniciamos el timer
if (!n_timer->isActive()) {
n_timer->setInterval(1000 * Packet->fps);
n_timer->start();
connect(n_timer, SIGNAL(timeout()), this, SLOT(sendFrame()));
}
}
bool msex::sendNACK(quint32 header)
{
int bufferLen;
unsigned char *buffer = PacketCreator::createNACKPacket(header, bufferLen);
if (!buffer)
{
qDebug() << "createNACKPacket() failed";
return false;
}
if (!sendPacket(buffer, bufferLen))
{
qDebug() << "sendNACK failed";
return false;
}
return true;
}
// Fin de mensajes MSEX
bool msex::updatemedia()
{
qDebug()<<"Actualizando biblioteca de medias en " << m_pathmedia;
QDir dir;
dir.cd(m_pathmedia);
m_media.clear();
// Miramos cuantas librerías tenemos en /video
if (!dir.cd("video"))
{ qWarning("Cannot cd to the video directory");
return false;
}
dir.setFilter(QDir::Dirs | QDir::NoSymLinks | QDir::NoDotAndDotDot);
QFileInfoList filelist = dir.entryInfoList();
dir.setFilter(QDir::Files);
QFileInfo fileInfo;
struct MediaLibrary mediai;
int i;
for (i = 0; i < filelist.size(); ++i) {
fileInfo = filelist.at(i);
QString name = fileInfo.baseName();
dir.cd(fileInfo.baseName());
mediai.m_Id = i;
mediai.m_DMXRangeMax = i;
mediai.m_DMXRangeMin = i;
mediai.m_Name = name;
// mediai.m_LibraryCount = 0; msex 1.2
mediai.m_ElementCount = dir.count();
mediai.m_MediaInformation = getMediaInformation(dir);
dir.cdUp();
m_media.append(mediai);
}
/*
// Miramos las librerías en /imagenes
i++;
dir.cd(m_pathmedia);
if (!dir.cd("image"))
{
qWarning("Can not find images dir");
return false;
}
mediai.m_Id = i;
mediai.m_DMXRangeMax = i;
mediai.m_DMXRangeMin = i;
mediai.m_Name = "Images";
// mediai.m_LibraryCount = 0; msex 1.2
mediai.m_ElementCount = dir.count();
mediai.m_MediaInformation = getMediaInformation(dir);
dir.cdUp();
m_media.append(mediai);
// Creamos una vacía
i++;
mediai.m_Id = i;
mediai.m_DMXRangeMax = i;
mediai.m_DMXRangeMin = i;
mediai.m_Name = "empty";
// mediai.m_LibraryCount = 0; msex 1.2
mediai.m_ElementCount = 0x00;
// mediai.m_MediaInformation = NULL;
m_media.append(mediai);
*/
// Lanzar aquí la creación de thumbs?
// Mandamos las señal ELup (Msex 1.2)
return true;
}
QList<MediaInformation> msex::getMediaInformation(QDir dir)
{
QList<MediaInformation> mediaList;
MediaInformation mediainf;
dir.setFilter(QDir::Files);
QFileInfoList filelist = dir.entryInfoList();
QFileInfo fileInfo;
for (int i = 0; i < filelist.size(); ++i) {
fileInfo = filelist.at(i);
QDateTime date = fileInfo.created();
mediainf.Number = i;
mediainf.DMXRangeMin = i;
mediainf.DMXRangeMax = i;
mediainf.MediaName = fileInfo.baseName();
// mediainf.MediaVersionTimestamp = date.toMSecsSinceEpoch();
mediainf.MediaWidth = 320;
mediainf.MediaHeight = 200;
mediainf.MediaLength = 1000;
mediainf.MediaFPS = 25;
mediaList.append(mediainf);
}
return mediaList;
}
void msex::setpath(QString path)
{
//m_pathmedia = NULL;
m_pathmedia.clear();
m_pathmedia.append(path);
}
void msex::startCitp(quint32 ipadd)
{
m_citp = new CITPLib(this);
Q_CHECK_PTR(m_citp);
if (!m_citp->createPeerInformationSocket(NAME, STATE, ipadd))
{
qDebug()<<("CreatePeerInformationSocket failed");
}
}
void msex::sendFrame()
{
emit frameRequest();
}

109
src/msex.h Normal file
View file

@ -0,0 +1,109 @@
/*
Libre Media Server - A Media Server Sotfware for stage and performing
Copyright (C) 2012-2013 Santiago Noreña
belfegor <AT> gmail <DOT> com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* This class do all the MSEX work */
#ifndef MSEX_H
#define MSEX_H
#include <QObject>
#include <QHostAddress>
#include "MSEXDefines.h"
class QTimer;
class QTcpSocket;
class QTcpServer;
class QDir;
class CITPLib;
class msex : public QObject
{
Q_OBJECT
public:
msex(QObject *parent);
virtual ~msex();
// virtual QString peerName() const;
// virtual QString peerState() const;
// virtual QString peerHost() const;
// virtual quint16 peerListeningPort() const;
// void previewLayer1();
bool CreateMSEXSocket();
bool updatemedia();
virtual void setpath(QString path); // path to media dir
void startCitp(quint32 ipadd); // Start the Peer Informatio Socket
bool sendPacket(const unsigned char *buffer, int bufferLen);
QTimer *n_timer; // Frame Request
QList<LayerStatus> m_layers;
QList<MediaLibrary> m_media;
protected:
CITPLib *m_citp; // CITP Peer. PLOc and frame transmit
QString m_pathmedia;
unsigned char * m_buffer;
int m_bufferLen;
QString m_peerState;
QString m_peerName;
QHostAddress m_host;
quint16 m_listeningPort;
QTcpServer *m_tcpServer;
QTcpSocket *m_tcpSocket;
bool sendPacket(const char *buffer, int bufferLen);
bool sendNACK(quint32 header);
// Procesado de paquetes MSEX
void parsePacket(const QByteArray &byteArray);
void parsePINFPacket(const QByteArray &byteArray);
void parseMSEXPacket(const QByteArray &bytearray);
void parseCINFPacket(const QByteArray &byteArray);
void parseNACKPacket(const QByteArray &byteArray);
void parseGELIPacket(const QByteArray &byteArray);
void parseGEINPacket(const QByteArray &byteArray);
void parseGLEIPacket(const QByteArray &byteArray);
void parseGELTPacket();
void parseGETHPacket(const QByteArray &byteArray);
void parseGVSRPacket();
void parseGELNPacket(const QByteArray &byteArray);
void parseRQSTPacket(const QByteArray &byteArray);
private:
QList<MediaInformation> getMediaInformation(QDir dir);
public slots:
protected slots:
void handleReadyRead();
private slots:
bool newPeer();
void sendFrame(); // Slot temporizado para mandar una señal a libremediaserver::sendframe() para mandar un frame
signals:
void frameRequest();
};
#endif // MEDIASERVER_H