<commit_before>$(function() {
  var models = window.models = {};

  var progressInterval = 10;
  var search_throttle_ms = 200;

  // Model representing a song's information.
  models.Song = Backbone.Model.extend({
    defaults: {
      title: 'Unknown'
    }
  });

  // Model of the current song being played back.
  models.Playback = Backbone.Model.extend({
    defaults: {
      selfIsDJ: false,
      progress: 0,
      muted: false
    },

    initialize: function() {
      var audio = new Audio();
      audio.autoplay = true;
      this.set({ audio: audio });

      this.on('change:song', this.songChanged, this);
      this.on('change:muted', this.mutedChanged, this);
    },

    reset: function() {
      this.unset('song');
    },

    songChanged: function() {
      var isDJ = false;
      var song = this.get('song');
      if (song) {
        this.set({
          started: new Date(
            new Date().valueOf() - song.get('elapsed')
          )
        });
        if (window.user && window.user.id &&
            song.get('dj') &&
            song.get('dj').id === window.user.id) {
          isDJ = true;
        }
        this.startPlayback();
      } else {
        this.unset('started');
        this.stopPlayback();
      }

      this.set({ selfIsDJ: isDJ });
    },

    startPlayback: function() {
      this.stopPlayback();
      this._interval = setInterval(
        _.bind(this.updateProgress, this), progressInterval);
      this.startAudio();
    },
    
    stopPlayback: function() {
      if (this._interval) {
        clearInterval(this._interval);
        delete this._interval;
      }
      this.stopAudio();
    },

    startAudio: function() {
      this.stopAudio();
      this.updateProgress();

      if (!this.has('song'))
        return;

      var audio = this.get('audio');
      audio.src = '/stream/' + this.get('room').get('shortname') +
        '/current?' + Math.floor(Math.random() * 100);
      console.log('Setting audio src:', audio.src);
    },

    stopAudio: function() {
      var audio = this.get('audio');
      audio.src = '';
    },

    mutedChanged: function() {
      this.get('audio').muted = this.get('muted');
    },
<commit_msg>Destroy Audio object if muted past end of song to conserve energy.<commit_after>$(function() {
  var models = window.models = {};

  var progressInterval = 10;
  var search_throttle_ms = 200;

  // Model representing a song's information.
  models.Song = Backbone.Model.extend({
    defaults: {
      title: 'Unknown'
    }
  });

  // Model of the current song being played back.
  models.Playback = Backbone.Model.extend({
    defaults: {
      selfIsDJ: false,
      progress: 0,
      muted: false
    },

    initialize: function() {
      this.on('change:song', this.songChanged, this);
      this.on('change:muted', this.mutedChanged, this);
    },

    reset: function() {
      this.unset('song');
    },

    songChanged: function() {
      var isDJ = false;
      var song = this.get('song');
      if (song) {
        this.set({
          started: new Date(
            new Date().valueOf() - song.get('elapsed')
          )
        });
        if (window.user && window.user.id &&
            song.get('dj') &&
            song.get('dj').id === window.user.id) {
          isDJ = true;
        }
        this.startPlayback();
      } else {
        this.unset('started');
        this.stopPlayback();
      }

      this.set({ selfIsDJ: isDJ });
    },

    startPlayback: function() {
      this.stopPlayback();
      this._interval = setInterval(
        _.bind(this.updateProgress, this), progressInterval);
      this.startAudio();
    },
    
    stopPlayback: function() {
      if (this._interval) {
        clearInterval(this._interval);
        delete this._interval;
      }
      this.stopAudio();
    },

    createAudio: function() {
      if (this.has('audio')) return;

      var audio = new Audio();
      audio.autoplay = true;
      audio.muted = this.get('muted');
      this.set({ audio: audio });
    },

    destroyAudio: function() {
      if (!this.has('audio')) return;

      this.get('audio').src = '';
      this.unset('audio');
    },

    startAudio: function() {
      this.stopAudio();
      this.updateProgress();

      if (!this.has('song'))
        return;

      // If there is no audio object and we're not muted, create one.
      if (!this.has('audio') && !this.get('muted')) {
        this.createAudio();
      }

      if (this.has('audio')) {
        var audio = this.get('audio');
        audio.src = '';
        audio.src = '/stream/' + this.get('room').get('shortname') +
          '/current';
      }
    },

    stopAudio: function() {
      if (this.has('audio')) {
        var audio = this.get('audio');
        audio.src = '';

        // Destroy audio if we're stopping audio and it's currently muted.
        if (this.get('muted')) {
          this.destroyAudio();
        }
      }
    },

    mutedChanged: function() {
      if (this.has('audio')) {
        this.get('audio').muted = this.get('muted');
      } else if (!this.get('muted')) {
        // There's no audio object but we're being unmuted, so let's make one.
        this.startAudio();
      }
    },

{'fraction_non_alphanumeric': 0.16042780748663102, 'fraction_numerical': 0.0028647822765469825, 'mean_word_length': 1.9789533560864618, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, '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': '5358723', 'n_tokens_mistral': 1658, 'n_tokens_neox': 1570, 'n_words': 343}