<commit_before>//
// $Id$

package com.threerings.openal;

import static com.threerings.media.Log.log;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.Map;

import org.lwjgl.util.WaveData;

import com.google.common.collect.Maps;

import com.samskivert.util.BasicRunQueue;
import com.samskivert.util.RunQueue;

import com.threerings.media.FrameManager;
import com.threerings.media.sound.SoundLoader;
import com.threerings.media.sound.SoundPlayer;
import com.threerings.media.timer.MediaTimer;

/**
 * Implements the abstract pieces of {@link SoundPlayer} via OpenAL.
 */
public class OpenALSoundPlayer extends SoundPlayer
    implements ClipProvider
{

    public OpenALSoundPlayer (SoundLoader loader)
    {
        _loader = loader;
        _alSoundManager = new MediaALSoundManager();
        _group = _alSoundManager.createGroup(this, SOURCE_COUNT);
        _ticker.start();
    }

    public Clip loadClip (String path)
        throws IOException
    {
        int pkgEnd = path.lastIndexOf("/") + 1;
        byte[] data = _loader.load(path.substring(0, pkgEnd), path.substring(pkgEnd))[0];
        return new Clip(WaveData.create(new ByteArrayInputStream(data)));
    }

    @Override
    public RunQueue getSoundQueue ()
    {
        return _ticker;
    }

    @Override
    public void lock (String pkgPath, String... keys)
    {
        for (String key : keys) {
            final String path = pkgPath + key;
            getSoundQueue().postRunnable(new Runnable() {
                public void run () {
                    if (_locked.containsKey(path)) {
                        return;
                    }
                    _alSoundManager.loadClip(OpenALSoundPlayer.this, path,
                        new ClipBuffer.Observer() {
                            public void clipFailed (ClipBuffer buffer) {
                                log.warning("Unable to load sound", "path", path);
                            }

                            public void clipLoaded (ClipBuffer buffer) {
                                _locked.put(path, buffer);
                            }
                        });
                }
            });
        }
    }

    @Override
    public void unlock (final String pkgPath, String... keys)
    {
        for (final String key : keys) {
            getSoundQueue().postRunnable(new Runnable() {
                public void run () {
                    _locked.remove(pkgPath + key);
                }
            });
        }
    }

    @Override
    protected Frob loop (String pkgPath, String key, float pan)
    {
        final SoundGrabber loader = new SoundGrabber(pkgPath, key) {
            @Override
            protected void soundLoaded () {
                sound.loop(true);
            }};
        getSoundQueue().postRunnable(loader);
        return new Frob() {
            public float getPan () {
                return 0;
            }

            public float getVolume () {
                return 0;
            }

            public void setPan (float pan) {}

            public void setVolume (float vol) {}

            public void stop () {
                getSoundQueue().postRunnable(new Runnable(){
                    public void run () {
                        if (loader.sound != null) {
                            loader.sound.stop();
                        }
                    }});
            }};
    }

    @Override
    public void play (String pkgPath, String key, float pan)
    {
        getSoundQueue().postRunnable(new SoundGrabber(pkgPath, key) {
            @Override
            protected void soundLoaded () {
                sound.play(true);
            }});
    }

    @Override
    public void shutdown ()
    {
        _group.dispose();
        _locked.clear();
        for (Stream stream : _alSoundManager.getStreams()) {
            stream.dispose();
        }
    }

    /**
     * Extends sound manager to allow sounds to be pulled out of the locked map.
     */
    protected class MediaALSoundManager extends SoundManager {
        protected MediaALSoundManager () {
            super(getSoundQueue());
        }

        @Override
        protected ClipBuffer getClip (ClipProvider provider, String path) {
            if (_locked.containsKey(path)) {
                return _locked.get(path);
            }
            return super.getClip(provider, path, null);
        }
    }

    /**
     * Updates the sound manager's streams every STREAM_UPDATE_INTERVAL and processes sound
     * runnables added to its queue.
     */
    protected class TickingQueue extends BasicRunQueue
    {
        @Override
        protected void iterate ()
        {
            long elapsed = _timer.getElapsedMillis() - _lastTick;
            Runnable r;
            if (elapsed >= STREAM_UPDATE_INTERVAL) {<commit_msg>Uhh, probably makes sense to actually hook the volume setting up to the sound manager<commit_after>//
// $Id$

package com.threerings.openal;

import static com.threerings.media.Log.log;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.Map;

import org.lwjgl.util.WaveData;

import com.google.common.collect.Maps;

import com.samskivert.util.BasicRunQueue;
import com.samskivert.util.RunQueue;

import com.threerings.media.FrameManager;
import com.threerings.media.sound.SoundLoader;
import com.threerings.media.sound.SoundPlayer;
import com.threerings.media.timer.MediaTimer;

/**
 * Implements the abstract pieces of {@link SoundPlayer} via OpenAL.
 */
public class OpenALSoundPlayer extends SoundPlayer
    implements ClipProvider
{

    public OpenALSoundPlayer (SoundLoader loader)
    {
        _loader = loader;
        _alSoundManager = new MediaALSoundManager();
        _group = _alSoundManager.createGroup(this, SOURCE_COUNT);
        _ticker.start();
    }

    public Clip loadClip (String path)
        throws IOException
    {
        int pkgEnd = path.lastIndexOf("/") + 1;
        byte[] data = _loader.load(path.substring(0, pkgEnd), path.substring(pkgEnd))[0];
        return new Clip(WaveData.create(new ByteArrayInputStream(data)));
    }

    @Override
    public RunQueue getSoundQueue ()
    {
        return _ticker;
    }

    @Override
    public void setClipVolume (final float vol)
    {
        super.setClipVolume(vol);
        _ticker.postRunnable(new Runnable(){
            public void run () {
                _alSoundManager.setBaseGain(vol);
            }});
    }

    @Override
    public void lock (String pkgPath, String... keys)
    {
        for (String key : keys) {
            final String path = pkgPath + key;
            getSoundQueue().postRunnable(new Runnable() {
                public void run () {
                    if (_locked.containsKey(path)) {
                        return;
                    }
                    _alSoundManager.loadClip(OpenALSoundPlayer.this, path,
                        new ClipBuffer.Observer() {
                            public void clipFailed (ClipBuffer buffer) {
                                log.warning("Unable to load sound", "path", path);
                            }

                            public void clipLoaded (ClipBuffer buffer) {
                                _locked.put(path, buffer);
                            }
                        });
                }
            });
        }
    }

    @Override
    public void unlock (final String pkgPath, String... keys)
    {
        for (final String key : keys) {
            getSoundQueue().postRunnable(new Runnable() {
                public void run () {
                    _locked.remove(pkgPath + key);
                }
            });
        }
    }

    @Override
    protected Frob loop (String pkgPath, String key, float pan)
    {
        final SoundGrabber loader = new SoundGrabber(pkgPath, key) {
            @Override
            protected void soundLoaded () {
                sound.loop(true);
            }};
        getSoundQueue().postRunnable(loader);
        return new Frob() {
            public float getPan () {
                return 0;
            }

            public float getVolume () {
                return 0;
            }

            public void setPan (float pan) {}

            public void setVolume (float vol) {}

            public void stop () {
                getSoundQueue().postRunnable(new Runnable(){
                    public void run () {
                        if (loader.sound != null) {
                            loader.sound.stop();
                        }
                    }});
            }};
    }

    @Override
    public void play (String pkgPath, String key, float pan)
    {
        getSoundQueue().postRunnable(new SoundGrabber(pkgPath, key) {
            @Override
            protected void soundLoaded () {
                sound.play(true);
            }});
    }

    @Override
    public void shutdown ()
    {
        _group.dispose();
        _locked.clear();
        for (Stream stream : _alSoundManager.getStreams()) {
            stream.dispose();
        }
    }

    /**
     * Extends sound manager to allow sounds to be pulled out of the locked map.
     */
    protected class MediaALSoundManager extends SoundManager {
        protected MediaALSoundManager () {
            super(getSoundQueue());
        }

        @Override
        protected ClipBuffer getClip (ClipProvider provider, String path) {
            if (_locked.containsKey(path)) {
                return _locked.get(path);
            }
            return super.getClip(provider, path, null);
        }
    }

    /**
     * Updates the sound manager's streams every STREAM_UPDATE_INTERVAL and processes sound
     * runnables added to its queue.
     */
    protected class TickingQueue extends BasicRunQueue
    {
        public TickingQueue ()
        {
            super("SoundPlayerQueue");
        }

        @Override
        protected void iterate ()
        {
            long elapsed = _timer.getElapsedMillis() - _lastTick;
            Runnable r;
            if (elapsed >= STREAM_UPDATE_INTERVAL) {
{'fraction_non_alphanumeric': 0.09121388423232422, 'fraction_numerical': 0.0009860960457548566, 'mean_word_length': 1.6065278848625033, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, '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': '5103137', 'n_tokens_mistral': 2728, 'n_tokens_neox': 2598, 'n_words': 649}