import * as child from 'child_process' ; import { Sink } from './sink' ; import { SinkInput } from './sinkInput' ; import { promisify } from 'util' ; const exec = promisify ( child . exec ) ; export class Pactl { public static readonly CMD = 'LANG=C pactl' ; public ready : Promise < any > ; private sinks : { [ key ] : Sink ; } ; private inputs : { [ key ] : SinkInput ; } ; constructor ( ) { this . inputs = { } ; this . sinks = { } ; this . ready = this . update ( ) ; } public async setVolume ( id , volume ) { if ( id . charAt ( 0 ) === 's' ) { this . sinks [ id . slice ( 1 ) ] . setVolume ( volume ) ; } else { this . inputs [ id . slice ( 1 ) ] . setVolume ( volume ) ; } await this . update ( ) ; } public async setMute ( id , mute ) { if ( id . charAt ( 0 ) === 's' ) { await this . sinks [ id . slice ( 1 ) ] . setMute ( mute ) ; } else { await this . inputs [ id . slice ( 1 ) ] . setMute ( mute ) ; } await this . update ( ) ; } public async move ( id , sink ) { this . inputs [ id . slice ( 1 ) ] . move ( sink . slice ( 1 ) ) ; await this . update ( ) ; } public getData ( ) { return { inputs : JSON . parse ( JSON . stringify ( this . inputs ) ) , sinks : JSON . parse ( JSON . stringify ( this . sinks ) ) } ; } private clear ( ) { this . inputs = { } ; this . sinks = { } ; } private async update ( ) { this . clear ( ) ; await this . createInputSinks ( ) ; await this . createOutputSinks ( ) ; } private arrayChunk ( filteredOutput , size ) { let i ; let j ; const temparray = [ ] ; for ( i = 0 , j = filteredOutput . length ; i < j ; i += size ) { temparray . push ( filteredOutput . slice ( i , i + size ) ) ; } return temparray ; } private async createInputSinks ( ) { const { stdout , stderr } = await exec ( [ Pactl . CMD , 'list' , SinkInput . CMD ] . join ( ' ' ) ) ; const output = stdout . split ( '\n' ) ; let filteredOutput = output . filter ( SinkInput . sink_inputs_filter ) ; filteredOutput . forEach ( ( current , index , array ) => { array [ index ] = ( current as any ) . trimStart ( ) ; } ) ; filteredOutput = this . arrayChunk ( filteredOutput , 5 ) ; filteredOutput . forEach ( ( sinkInput ) => { const id = sinkInput [ 0 ] . substring ( sinkInput [ 0 ] . indexOf ( '#' ) + 1 ) ; this . inputs [ id ] = new SinkInput ( sinkInput ) ; } ) ; } private async createOutputSinks ( ) { const { stdout , stderr } = await exec ( [ Pactl . CMD , 'list' , Sink . CMD ] . join ( ' ' ) ) ; const output = stdout . split ( '\n' ) ; let filteredOutput = output . filter ( Sink . sinks_filter ) ; filteredOutput . forEach ( ( current , index , array ) => { array [ index ] = current . trimLeft ( ) ; } ) ; filteredOutput = this . arrayChunk ( filteredOutput , 4 ) ; filteredOutput . forEach ( ( sink ) => { const id = sink [ 0 ] . substring ( sink [ 0 ] . indexOf ( '#' ) + 1 ) ; this . sinks [ id ] = new Sink ( sink ) ; } ) ; } }