<commit_before>import { IAudioContext } from "standardized-audio-context";
import { AssetPool } from "./assetPool";
import { Playlist } from "./playlist";
import { Roundware } from "./roundware";
import { SpeakerTrack } from "./speaker_track";
import {
  Coordinates,
  GeoListenModeType,
  IMixParams,
  ITimedAssetData,
} from "./types";
import { IAssetData } from "./types/asset";

import { buildAudioContext, coordsToPoints, getUrlParam } from "./utils";

export const GeoListenMode: {
  DISABLED: GeoListenModeType;
  MANUAL: GeoListenModeType;
  AUTOMATIC: GeoListenModeType;
} = Object.freeze({
  DISABLED: 0,
  MANUAL: 1,
  AUTOMATIC: 2,
});

export class Mixer {
  playing: boolean;
  private _windowScope: Window;
  private _client: Roundware;
  private _prefetchSpeakerAudio: any | boolean;

  mixParams: IMixParams;
  playlist: Playlist | undefined;
  assetPool: AssetPool;
  speakerTracks: SpeakerTrack[] | undefined;
  audioContext: IAudioContext;

  constructor({
    client,
    windowScope,
    listenerLocation,
    prefetchSpeakerAudio,
    filters = [],
    sortMethods = [],
    mixParams = {},
  }: {
    client: Roundware;
    windowScope: Window;
    listenerLocation: Coordinates;
    prefetchSpeakerAudio: boolean | unknown;
    filters?: unknown[];
    sortMethods?: unknown[];
    mixParams: IMixParams;
  }) {
    this.playing = false;

    this._windowScope = windowScope;
    this._client = client;
    this._prefetchSpeakerAudio = prefetchSpeakerAudio;
    const assets: IAssetData[] = client.assets();
    const timedAssets = client.timedAssets();

    this.mixParams = {
      listenerPoint: coordsToPoints({
        latitude: listenerLocation.latitude!,
        longitude: listenerLocation.longitude!,
      }),
      ...mixParams,
    };

    this.assetPool = new AssetPool({
      assets,
      timedAssets,
      // @ts-ignore here it asks for a function
      filters,
      sortMethods,
      mixParams: this.mixParams,
    });
    this.audioContext = buildAudioContext(this._windowScope);
  }

  updateParams({ listenerLocation, ...params }: IMixParams) {
    if (listenerLocation) {
      params.listenerPoint = coordsToPoints({
        latitude: listenerLocation.latitude!,
        longitude: listenerLocation.longitude!,
      });
    }
    this.mixParams = { ...this.mixParams, ...params };
    if (this.playlist) {
      this.playlist.updateParams(params);
    }
    if (Array.isArray(this.speakerTracks)) {
      this.speakerTracks.forEach((t) =>
        t.updateParams(this.playing, { listenerPoint: params.listenerPoint })
      );
    }
  }
  /**
   * @param  {number} trackId
   */
  skipTrack(trackId: number) {
    if (this.playlist) this.playlist.skip(trackId);
  }

  skip() {}
  /**
   * @param  {number} trackId
   */
  replayTrack(trackId: number) {
    if (this.playlist) this.playlist.replay(trackId);
  }
  /**
   * @returns string
   */
  toString(): string {
    return "Roundware Mixer";
  }

  /**
   * Builds speaker tracks & playlist instance if it doesn't exist yet
   */
  initContext() {
    if (!this.playlist) {
      if (!this.mixParams.listenerPoint)
        return console.error(
          `[mixer] listenerPoint was missing while initiating mixer!`
        );
      const listenerPoint = this.mixParams.listenerPoint;
      const speakers = this._client.speakers();

      let selectTrackId: string | number | null = getUrlParam(
        this._windowScope.location.toString(),
        "rwfSelectTrackId"
      );
      let audioTracks = this._client.audiotracks();

      if (selectTrackId) {
        selectTrackId = Number(selectTrackId);
        audioTracks = audioTracks.filter((t) => t.id === selectTrackId);
        console.info(`isolating track #${selectTrackId}`);
      }

      this.playlist = new Playlist({
        client: this._client,
        audioTracks,
        listenerPoint,
        assetPool: this.assetPool,
        audioContext: this.audioContext,
        windowScope: this._windowScope,
      });

      this.speakerTracks = speakers.map(
        (speakerData) =>
          new SpeakerTrack({
            audioContext: this.audioContext,
            listenerPoint,
            prefetchAudio: this._prefetchSpeakerAudio,
            data: speakerData,
          })
      );
      this.updateParams(this.mixParams);
      console.info(`Mixer Activated`);
    }
  }

  /**
   * @param  {boolean} true to play false to stop
   * @returns boolean
   */
  toggle(play?: boolean): boolean {
    if (typeof play == "boolean") {
      // do based on what asked..
      play ? this.play() : this.stop();
    } else {
      // automatically decide based on playing status
      this.playing ? this.stop() : this.play();
    }

    return this.playing;
  }

  play() {
    this.initContext();
    // console.log(`playing`);
    // consssole.log(this.audioContext.currentTime);

    this.playing = true;
    if (this.playlist) this.playlist.play();
    if (Array.isArray(this.speakerTracks)) {
      this.speakerTracks.forEach((s) => {
        s.player.timerStart();
        s.play();
      });
    }
  }

  stop() {
    this.initContext();
    this.playing = false;
    if (this.playlist) this.playlist.pause();
    if (Array.isArray(this.speakerTracks))
      this.speakerTracks.forEach((s) => {
        s.player.timerStop();
        s.pause();
      });
  }
}
<commit_msg>use speaker.config for all speaker options<commit_after>import { IAudioContext } from "standardized-audio-context";
import { AssetPool } from "./assetPool";
import { Playlist } from "./playlist";
import { Roundware } from "./roundware";
import { SpeakerTrack } from "./speaker_track";
import {
  Coordinates,
  GeoListenModeType,
  IMixParams,
  ITimedAssetData,
} from "./types";
import { IAssetData } from "./types/asset";

import { buildAudioContext, coordsToPoints, getUrlParam } from "./utils";

export const GeoListenMode: {
  DISABLED: GeoListenModeType;
  MANUAL: GeoListenModeType;
  AUTOMATIC: GeoListenModeType;
} = Object.freeze({
  DISABLED: 0,
  MANUAL: 1,
  AUTOMATIC: 2,
});

export class Mixer {
  playing: boolean;
  private _windowScope: Window;
  private _client: Roundware;
  private _prefetchSpeakerAudio: any | boolean;

  mixParams: IMixParams;
  playlist: Playlist | undefined;
  assetPool: AssetPool;
  speakerTracks: SpeakerTrack[] | undefined;
  audioContext: IAudioContext;

  constructor({
    client,
    windowScope,
    listenerLocation,
    filters = [],
    sortMethods = [],
    mixParams = {},
  }: {
    client: Roundware;
    windowScope: Window;
    listenerLocation: Coordinates;
    filters?: unknown[];
    sortMethods?: unknown[];
    mixParams: IMixParams;
  }) {
    this.playing = false;

    this._windowScope = windowScope;
    this._client = client;

    const assets: IAssetData[] = client.assets();
    const timedAssets = client.timedAssets();

    this.mixParams = {
      listenerPoint: coordsToPoints({
        latitude: listenerLocation.latitude!,
        longitude: listenerLocation.longitude!,
      }),
      ...mixParams,
    };

    this.assetPool = new AssetPool({
      assets,
      timedAssets,
      // @ts-ignore here it asks for a function
      filters,
      sortMethods,
      mixParams: this.mixParams,
    });
    this.audioContext = buildAudioContext(this._windowScope);
  }

  updateParams({ listenerLocation, ...params }: IMixParams) {
    if (listenerLocation) {
      params.listenerPoint = coordsToPoints({
        latitude: listenerLocation.latitude!,
        longitude: listenerLocation.longitude!,
      });
    }
    this.mixParams = { ...this.mixParams, ...params };
    if (this.playlist) {
      this.playlist.updateParams(params);
    }
    if (Array.isArray(this.speakerTracks)) {
      this.speakerTracks.forEach((t) =>
        t.updateParams(this.playing, { listenerPoint: params.listenerPoint })
      );
    }
  }
  /**
   * @param  {number} trackId
   */
  skipTrack(trackId: number) {
    if (this.playlist) this.playlist.skip(trackId);
  }

  skip() {}
  /**
   * @param  {number} trackId
   */
  replayTrack(trackId: number) {
    if (this.playlist) this.playlist.replay(trackId);
  }
  /**
   * @returns string
   */
  toString(): string {
    return "Roundware Mixer";
  }

  /**
   * Builds speaker tracks & playlist instance if it doesn't exist yet
   */
  initContext() {
    if (!this.playlist) {
      if (!this.mixParams.listenerPoint)
        return console.error(
          `[mixer] listenerPoint was missing while initiating mixer!`
        );
      const listenerPoint = this.mixParams.listenerPoint;
      const speakers = this._client.speakers();

      let selectTrackId: string | number | null = getUrlParam(
        this._windowScope.location.toString(),
        "rwfSelectTrackId"
      );
      let audioTracks = this._client.audiotracks();

      if (selectTrackId) {
        selectTrackId = Number(selectTrackId);
        audioTracks = audioTracks.filter((t) => t.id === selectTrackId);
        console.info(`isolating track #${selectTrackId}`);
      }

      this.playlist = new Playlist({
        client: this._client,
        audioTracks,
        listenerPoint,
        assetPool: this.assetPool,
        audioContext: this.audioContext,
        windowScope: this._windowScope,
      });

      this.speakerTracks = speakers.map(
        (speakerData) =>
          new SpeakerTrack({
            audioContext: this.audioContext,
            listenerPoint,

            data: speakerData,
            config: this.mixParams.speakerConfig || {
              sync: false,
              length: 600,
              loop: false,
              prefetch: false,
            },
          })
      );
      this.updateParams(this.mixParams);
      console.info(`Mixer Activated`);
    }
  }

  /**
   * @param  {boolean} true to play false to stop
   * @returns boolean
   */
  toggle(play?: boolean): boolean {
    if (typeof play == "boolean") {
      // do based on what asked..
      play ? this.play() : this.stop();
    } else {
      // automatically decide based on playing status
      this.playing ? this.stop() : this.play();
    }

    return this.playing;
  }

  play() {
    this.initContext();
    // console.log(`playing`);
    // consssole.log(this.audioContext.currentTime);

    this.playing = true;
    if (this.playlist) this.playlist.play();
    if (Array.isArray(this.speakerTracks)) {
      this.speakerTracks.forEach((s) => {
        s.player.timerStart();
        s.play();
      });
    }
  }

  stop() {
    this.initContext();
    this.playing = false;
    if (this.playlist) this.playlist.pause();
    if (Array.isArray(this.speakerTracks))
      this.speakerTracks.forEach((s) => {
        s.player.timerStop();
        s.pause();
      });
  }
}

{'fraction_non_alphanumeric': 0.12810493999441808, 'fraction_numerical': 0.0008372871895060006, 'mean_word_length': 2.5929144385026737, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1943246', 'n_tokens_mistral': 3337, 'n_tokens_neox': 3253, 'n_words': 677}