- 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:
parent
c9adfd020b
commit
e85d191b46
3100 changed files with 775434 additions and 3073 deletions
94
src/CITPDefines.h
Normal file
94
src/CITPDefines.h
Normal 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
474
src/MSEXDefines.h
Normal 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
486
src/PacketCreator.cpp
Normal 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
62
src/PacketCreator.h
Normal 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_
|
182
src/PeerInformationSocket.cpp
Normal file
182
src/PeerInformationSocket.cpp
Normal 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;
|
||||
}
|
68
src/PeerInformationSocket.h
Normal file
68
src/PeerInformationSocket.h
Normal 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
52
src/citp-lib.cpp
Normal 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
68
src/citp-lib.h
Normal 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
1638
src/libremediaserver.cpp
Normal file
File diff suppressed because it is too large
Load diff
153
src/libremediaserver.h
Normal file
153
src/libremediaserver.h
Normal 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
34
src/libremediaserver.pro
Normal 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
1175
src/libremediaserver.ui
Normal file
File diff suppressed because it is too large
Load diff
28
src/main.cpp
Normal file
28
src/main.cpp
Normal 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
614
src/msex.cpp
Normal 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
109
src/msex.h
Normal 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
|
Loading…
Add table
Add a link
Reference in a new issue