import * as Path from 'path' ; import { Options as OptionsNS } from './AMCPConnectionOptions' ; import CasparCGVersion = OptionsNS . CasparCGVersion ; import { Config as ConfigNS } from './Config' ; import CasparCGConfig = ConfigNS . Intermediate . CasparCGConfig ; export namespace Response { /***/ export class CasparCGPaths { media : string ; data : string ; log : string ; template : string ; thumbnail : string ; font ? : string | undefined ; root : string ; /***/ static ensureTrailingSlash ( path ) { return ( ( path . slice ( - 1 ) === '/' || path . slice ( - 1 ) === '\\' ) ? path : path + '/' ) ; } /***/ get thumbnails ( ) : string { return this . thumbnail ; } /***/ get absoluteMedia ( ) : string { return this . absolutePath ( this . media ) ; } /***/ get absoluteData ( ) : string { return this . absolutePath ( this . data ) ; } /***/ get absoluteLog ( ) : string { return this . absolutePath ( this . log ) ; } /***/ get absoluteTemplate ( ) : string { return this . absolutePath ( this . template ) ; } /***/ get absoluteThumbnail ( ) : string { return this . absolutePath ( this . thumbnail ) ; } /***/ get absoluteThumbnails ( ) : string { return this . absolutePath ( this . thumbnails ) ; } /***/ get absoluteFont ( ) : string | undefined { return this . font ? this . absolutePath ( this . font ) : undefined ; } /***/ private absolutePath ( relativeOrAbsolutePath ) { if ( relativeOrAbsolutePath . match ( /\:\\|\:\// ) ) { return CasparCGPaths . ensureTrailingSlash ( relativeOrAbsolutePath ) ; } return CasparCGPaths . ensureTrailingSlash ( Path . join ( this . root , relativeOrAbsolutePath ) ) ; } } /***/ export class ChannelRate { public channelRate : number ; public frameRate : number ; public isInterlaced : boolean ; /***/ constructor ( rateExpression ) { this . isInterlaced = rateExpression . indexOf ( 'i' ) > - 1 ; let rateMatch = rateExpression . match ( /[0-9]+$/ ) ; let rate = 0 ; if ( rateMatch ) { rate = + rateMatch [ 0 ] ; } if ( rate === 5994 ) { this . channelRate = 60 * 1000 / 1001 ; this . frameRate = this . isInterlaced ? 30 * 1000 / 1001 : this . channelRate ; } else if ( rateExpression . toLowerCase ( ) === 'pal' ) { this . isInterlaced = true ; this . channelRate = 50 ; this . frameRate = 25 ; } else if ( rateExpression . toLowerCase ( ) === 'ntsc' ) { this . isInterlaced = true ; this . channelRate = 60 * 1000 / 1001 ; this . frameRate = 30 * 1000 / 1001 ; } else { this . channelRate = rate / 100 ; this . frameRate = this . isInterlaced ? rate / 200 : this . channelRate ; } } } /**
     *
     */ export interface IResponseParser { context ? : Object ; parse ( data ) : Object ; } /**
     *
     */ export abstract class AbstractParser { context ? : any ; } /**
     *
     */ export class ChannelParser extends AbstractParser implements IResponseParser { /**
         *
         */ public parse ( data ) { data = [ ] . concat ( data ) ; let result = [ ] ; ( data as Array < Object > ) . forEach ( ( channel ) => { let components = channel . toString ( ) . split ( /\s|,/ ) ; let i = + components . shift ( ) ! ; let format = components . shift ( ) || '' ; let rates = new ChannelRate ( format ) ; result . push ( { channel : i , format : format . toLowerCase ( ) , channelRate : rates . channelRate , frameRate : rates . frameRate , interlaced : rates . isInterlaced } ) ; } ) ; if ( result . length > 0 ) { return result ; } return { } ; } } /***/ export class ConfigParser extends AbstractParser implements IResponseParser { /***/ public parse ( data ) { let serverVersion ; if ( this . context && this . context . hasOwnProperty ( 'serverVersion' ) && this . context . serverVersion > CasparCGVersion . V21x ) { serverVersion = CasparCGVersion . V210 ; } else { serverVersion = CasparCGVersion . V207 ; } let configResult = new CasparCGConfig ( serverVersion ) ; configResult . import ( data ) ; return configResult ; } } /**
     *
     */ export class DataParser extends AbstractParser implements IResponseParser { /**
         *
         */ public parse ( data ) { return data ; } } /**
     *
     */ export class DataListParser extends AbstractParser implements IResponseParser { /**
         *
         */ public parse ( data ) { return data ; } } /**
     *
     */ export class InfoTemplateParser extends AbstractParser implements IResponseParser { /**
         *
         */ public parse ( data ) { return data ; } } /**
     *
     */ export class HelpParser extends AbstractParser implements IResponseParser { /**
         *
         */ public parse ( data ) { return data ; } } /**
     *
     */ export class GLParser extends AbstractParser implements IResponseParser { /**
         *
         */ public parse ( data ) { return data ; } } /**
     *
     */ export class InfoDelayParser extends AbstractParser implements IResponseParser { /**
         *
         */ public parse ( data ) { return data ; } } /**
     *
     */ export class InfoParser extends AbstractParser implements IResponseParser { /**
         *
         */ public parse ( data ) { return data ; } } /**
     *
     */ export class InfoThreadsParser extends AbstractParser implements IResponseParser { /**
         *
         */ public parse ( data ) { return data ; } } /**
     *
     */ export class ThumbnailParser extends AbstractParser implements IResponseParser { /**
         *
         */ public parse ( data ) { return `data:image/png;base64,${ data }` ; } } /**
     *
     */ export class VersionParser extends AbstractParser implements IResponseParser { /**
         *
         */ public parse ( data ) { return data ; } } /**
     *
     */ export class ContentParser extends AbstractParser implements IResponseParser { static parseTimeString ( timeDateString ) { timeDateString = timeDateString . replace ( /[tT]/g , '' ) ; let year = parseInt ( timeDateString . slice ( 0 , 4 ) , 10 ) ; let month = parseInt ( timeDateString . slice ( 4 , 6 ) , 10 ) ; let date = parseInt ( timeDateString . slice ( 6 , 8 ) , 10 ) ; let hours = parseInt ( timeDateString . slice ( 8 , 10 ) , 10 ) ; let minutes = parseInt ( timeDateString . slice ( 10 , 12 ) , 10 ) ; let seconds = parseInt ( timeDateString . slice ( 12 , 14 ) , 10 ) ; return new Date ( year , month , date , hours , minutes , seconds ) . getTime ( ) ; } /**
         *
         */ public parse ( data ) { return data . map ( ( i ) => { let components = i . match ( /\"([\s\S]*)\" +([\s\S]*)/ ) ; if ( components === null ) { return { name : i , type : 'template' } ; } let name = components [ 1 ] . replace ( /\\/g , '/' ) ; let typeData = components [ 2 ] . split ( /\s+/ ) ; if ( typeData . length === 1 ) { return { name : name , type : 'font' , fileName : typeData [ 0 ] . replace ( /\"/g , '' ) } ; } if ( typeData . length === 3 ) { return { name : name , type : 'template' , size : parseInt ( typeData [ 0 ] , 10 ) , changed : ContentParser . parseTimeString ( typeData [ 1 ] ) , format : typeData [ 2 ] } ; } if ( typeData . length === 2 ) { return { name : name , type : 'template' , size : parseInt ( typeData [ 0 ] , 10 ) , changed : ContentParser . parseTimeString ( typeData [ 1 ] ) } ; } let frames = parseInt ( typeData [ 3 ] , 10 ) ; let frameRate = 0 ; let duration = 0 ; let frameTimeSegments = typeData [ 4 ] . split ( '/' ) ; if ( frameTimeSegments [ 0 ] !== '0' ) { frameRate = + ( parseInt ( frameTimeSegments [ 1 ] , 10 ) / parseInt ( frameTimeSegments [ 0 ] , 10 ) ) . toFixed ( 2 ) ; duration = Math . round ( ( frames / frameRate ) * 100 ) / 100 ; } return { name : name , type : typeData [ 0 ] . toLowerCase ( ) === 'movie' ? 'video' : typeData [ 0 ] . toLowerCase ( ) === 'still' ? 'image' : typeData [ 0 ] . toLowerCase ( ) , size : parseInt ( typeData [ 1 ] , 10 ) , changed : ContentParser . parseTimeString ( typeData [ 2 ] ) , frames : frames , frameTime : typeData [ 4 ] , frameRate : frameRate , duration : duration } ; } ) ; } } /**
     *
     */ export class ThumbnailListParser extends AbstractParser implements IResponseParser { /**
         *
         */ public parse ( data ) { return data . map ( ( i ) => { let components = i . match ( /\"([\s\S]*)\" +([\s\S]*)/ ) ; if ( components === null ) { return null ; } let name = components [ 1 ] . replace ( /\\/g , '/' ) ; let typeData = components [ 2 ] . split ( /\s+/ ) ; return { name : name , type : 'thumbnail' , changed : ContentParser . parseTimeString ( typeData [ 0 ] ) , size : parseInt ( typeData [ 1 ] , 10 ) } ; } ) ; } } /**
     *
     */ export class CinfParser extends AbstractParser implements IResponseParser { /**
         *
         */ public parse ( data ) { if ( data && Array . isArray ( data ) ) { let components = data [ 0 ] . match ( /\"([\s\S]*)\" +([\s\S]*)/ ) ; if ( components === null ) { return { } ; } let typeData = components [ 2 ] . split ( /\s+/ ) ; return { size : parseInt ( typeData [ 1 ] , 10 ) , changed : typeData [ 2 ] , duration : parseInt ( typeData [ 3 ] , 10 ) , fps : typeData [ 4 ] } ; } return { } ; } } /**
     *
     */ export class InfoQueuesParser extends AbstractParser implements IResponseParser { /**
         *
         */ public parse ( data ) { return data ; } } /**
     *
     */ export class InfoServerParser extends AbstractParser implements IResponseParser { /**
         *
         */ public parse ( data ) { return data ; } } /**
     *
     */ export class InfoPathsParser extends AbstractParser implements IResponseParser { /**
         *
         */ public parse ( data ) { let paths = new CasparCGPaths ( ) ; if ( data . hasOwnProperty ( 'initial-path' ) ) { paths . root = data [ 'initial-path' ] ; } if ( data . hasOwnProperty ( 'media-path' ) ) { paths . media = data [ 'media-path' ] ; } if ( data . hasOwnProperty ( 'data-path' ) ) { paths . data = data [ 'data-path' ] ; } if ( data . hasOwnProperty ( 'log-path' ) ) { paths . log = data [ 'log-path' ] ; } if ( data . hasOwnProperty ( 'template-path' ) ) { paths . template = data [ 'template-path' ] ; } if ( data . hasOwnProperty ( 'thumbnails-path' ) ) { paths . thumbnail = data [ 'thumbnails-path' ] ; } if ( data . hasOwnProperty ( 'thumbnail-path' ) ) { paths . thumbnail = data [ 'thumbnail-path' ] ; } if ( data . hasOwnProperty ( 'font-path' ) ) { paths . font = data [ 'font-path' ] ; } return paths ; } } /**
     *
     */ export class InfoSystemParser extends AbstractParser implements IResponseParser { /**
         *
         */ public parse ( data ) { if ( data . hasOwnProperty ( 'decklink' ) && data . decklink . hasOwnProperty ( 'device' ) ) { if ( ! Array . isArray ( data . decklink . device ) ) { data . decklink . device = [ data . decklink . device ] ; } } if ( data . hasOwnProperty ( 'bluefish' ) && data . bluefish . hasOwnProperty ( 'device' ) ) { if ( ! Array . isArray ( data . bluefish . device ) ) { data . bluefish . device = [ data . bluefish . device ] ; } } return data ; } } /**
     *
     */ export class MixerStatusKeyerParser extends AbstractParser implements IResponseParser { /**
         *
         */ public parse ( data ) { return { keyer : ! ! data [ 0 ] } ; } } /**
     *
     */ export class MixerStatusChromaParser extends AbstractParser implements IResponseParser { /**
         *
         */ public parse ( data ) { return { chroma : { enable : ! ! data [ 0 ] , targetHue : data [ 1 ] , hueWidth : data [ 2 ] , minSaturation : data [ 3 ] , minBrightness : data [ 4 ] , softness : data [ 5 ] , spillSuppress : data [ 6 ] , spillSuppressSaturation : data [ 7 ] , showMask : ! ! data [ 8 ] } } ; } } /**
     *
     */ export class MixerStatusBlendParser extends AbstractParser implements IResponseParser { /**
         *
         */ public parse ( data ) { return { blend : data } ; } } /**
     *
     */ export class MixerStatusOpacityParser extends AbstractParser implements IResponseParser { /**
         *
         */ public parse ( data ) { return { opacity : data [ 0 ] } ; } } /**
     *
     */ export class MixerStatusBrightnessParser extends AbstractParser implements IResponseParser { /**
         *
         */ public parse ( data ) { return { brightness : data [ 0 ] } ; } } /**
     *
     */ export class MixerStatusSaturationParser extends AbstractParser implements IResponseParser { /**
         *
         */ public parse ( data ) { return { saturation : data [ 0 ] } ; } } /**
     *
     */ export class MixerStatusContrastParser extends AbstractParser implements IResponseParser { /**
         *
         */ public parse ( data ) { return { contrast : data [ 0 ] } ; } } /**
     *
     */ export class MixerStatusLevelsParser extends AbstractParser implements IResponseParser { /**
         *
         */ public parse ( data ) { return { levels : { minInput : data [ 0 ] , maxInput : data [ 1 ] , gamma : data [ 2 ] , minOutput : data [ 3 ] , maxOutput : data [ 4 ] } } ; } } /**
     *
     */ export class MixerStatusFillParser extends AbstractParser implements IResponseParser { /**
         *
         */ public parse ( data ) { return { fill : { x : data [ 0 ] , y : data [ 1 ] , xScale : data [ 2 ] , yScale : data [ 3 ] } } ; } } /**
     *
     */ export class MixerStatusClipParser extends AbstractParser implements IResponseParser { /**
         *
         */ public parse ( data ) { return { clip : { x : data [ 0 ] , y : data [ 1 ] , width : data [ 2 ] , height : data [ 3 ] } } ; } } /**
     *
     */ export class MixerStatusAnchorParser extends AbstractParser implements IResponseParser { /**
         *
         */ public parse ( data ) { return { anchor : { x : data [ 0 ] , y : data [ 1 ] } } ; } } /**
     *
     */ export class MixerStatusCropParser extends AbstractParser implements IResponseParser { /**
         *
         */ public parse ( data ) { return { crop : { left : data [ 0 ] , top : data [ 1 ] , right : data [ 2 ] , bottom : data [ 3 ] } } ; } } /**
     *
     */ export class MixerStatusRotationParser extends AbstractParser implements IResponseParser { /**
         *
         */ public parse ( data ) { return { rotation : data [ 0 ] } ; } } /**
     *
     */ export class MixerStatusPerspectiveParser extends AbstractParser implements IResponseParser { /**
         *
         */ public parse ( data ) { return { perspective : { topLeftX : data [ 0 ] , topLeftY : data [ 1 ] , topRightX : data [ 2 ] , topRightY : data [ 3 ] , bottomRightX : data [ 6 ] , bottomRightY : data [ 7 ] , bottomLeftX : data [ 4 ] , bottomLeftY : data [ 5 ] } } ; } } /**
     *
     */ export class MixerStatusMipmapParser extends AbstractParser implements IResponseParser { /**
         *
         */ public parse ( data ) { return { mipmap : ! ! data [ 0 ] } ; } } /**
     *
     */ export class MixerStatusVolumeParser extends AbstractParser implements IResponseParser { /**
         *
         */ public parse ( data ) { return { volume : data [ 0 ] } ; } } /**
     *
     */ export class MixerStatusMastervolumeParser extends AbstractParser implements IResponseParser { /**
         *
         */ public parse ( data ) { return { mastervolume : data [ 0 ] } ; } } /**
     *
     */ export class MixerStatusStraightAlphaOutputParser extends AbstractParser implements IResponseParser { /**
         *
         */ public parse ( data ) { return { straightAlphaOutput : ! ! data [ 0 ] } ; } } }