Browse Source

Fixed NPE in AndroidAudioRenderer when soundPool is not initialized

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@9175 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
rem..om 13 years ago
parent
commit
446c03935e
1 changed files with 437 additions and 438 deletions
  1. 437 438
      engine/src/android/com/jme3/audio/android/AndroidAudioRenderer.java

+ 437 - 438
engine/src/android/com/jme3/audio/android/AndroidAudioRenderer.java

@@ -58,442 +58,441 @@ import java.util.logging.Logger;
  * @author plan_rich
  */
 public class AndroidAudioRenderer implements AudioRenderer,
-		SoundPool.OnLoadCompleteListener, MediaPlayer.OnCompletionListener {
-
-	private static final Logger logger = Logger
-			.getLogger(AndroidAudioRenderer.class.getName());
-	private final static int MAX_NUM_CHANNELS = 16;
-	private final HashMap<AudioNode, MediaPlayer> musicPlaying = new HashMap<AudioNode, MediaPlayer>();
-	private SoundPool soundPool = null;
-
-	private final Vector3f listenerPosition = new Vector3f();
-	// For temp use
-	private final Vector3f distanceVector = new Vector3f();
-	private final Context context;
-	private final AssetManager assetManager;
-	private HashMap<Integer, AudioNode> soundpoolStillLoading = new HashMap<Integer, AudioNode>();
-	private Listener listener;
-	private boolean audioDisabled = false;
-
-	private final AudioManager manager;
-
-	public AndroidAudioRenderer(Activity context) {
-		this.context = context;
-		manager = (AudioManager) context
-				.getSystemService(Context.AUDIO_SERVICE);
-		context.setVolumeControlStream(AudioManager.STREAM_MUSIC);
-		assetManager = context.getAssets();
-	}
-
-	@Override
-	public void initialize() {
-		soundPool = new SoundPool(MAX_NUM_CHANNELS, AudioManager.STREAM_MUSIC,
-				0);
-		soundPool.setOnLoadCompleteListener(this);
-	}
-
-	@Override
-	public void updateSourceParam(AudioNode src, AudioParam param) {
-		// logger.log(Level.INFO, "updateSourceParam " + param);
-
-		if (audioDisabled) {
-			return;
-		}
-
-		if (src.getChannel() < 0) {
-			return;
-		}
-
-		switch (param) {
-		case Position:
-			if (!src.isPositional()) {
-				return;
-			}
-
-			Vector3f pos = src.getWorldTranslation();
-			break;
-		case Velocity:
-			if (!src.isPositional()) {
-				return;
-			}
-
-			Vector3f vel = src.getVelocity();
-			break;
-		case MaxDistance:
-			if (!src.isPositional()) {
-				return;
-			}
-			break;
-		case RefDistance:
-			if (!src.isPositional()) {
-				return;
-			}
-			break;
-		case ReverbFilter:
-			if (!src.isPositional() || !src.isReverbEnabled()) {
-				return;
-			}
-			break;
-		case ReverbEnabled:
-			if (!src.isPositional()) {
-				return;
-			}
-
-			if (src.isReverbEnabled()) {
-				updateSourceParam(src, AudioParam.ReverbFilter);
-			}
-			break;
-		case IsPositional:
-			break;
-		case Direction:
-			if (!src.isDirectional()) {
-				return;
-			}
-
-			Vector3f dir = src.getDirection();
-			break;
-		case InnerAngle:
-			if (!src.isDirectional()) {
-				return;
-			}
-			break;
-		case OuterAngle:
-			if (!src.isDirectional()) {
-				return;
-			}
-			break;
-		case IsDirectional:
-			if (src.isDirectional()) {
-				updateSourceParam(src, AudioParam.Direction);
-				updateSourceParam(src, AudioParam.InnerAngle);
-				updateSourceParam(src, AudioParam.OuterAngle);
-			} else {
-			}
-			break;
-		case DryFilter:
-			if (src.getDryFilter() != null) {
-				Filter f = src.getDryFilter();
-				if (f.isUpdateNeeded()) {
-					// updateFilter(f);
-				}
-			}
-			break;
-		case Looping:
-			if (src.isLooping()) {
-			}
-			break;
-		case Volume:
-
-			soundPool.setVolume(src.getChannel(), src.getVolume(),
-					src.getVolume());
-
-			break;
-		case Pitch:
-
-			break;
-		}
-
-	}
-
-	@Override
-	public void updateListenerParam(Listener listener, ListenerParam param) {
-		// logger.log(Level.INFO, "updateListenerParam " + param);
-		if (audioDisabled) {
-			return;
-		}
-
-		switch (param) {
-		case Position:
-			listenerPosition.set(listener.getLocation());
-
-			break;
-		case Rotation:
-			Vector3f dir = listener.getDirection();
-			Vector3f up = listener.getUp();
-
-			break;
-		case Velocity:
-			Vector3f vel = listener.getVelocity();
-
-			break;
-		case Volume:
-			// alListenerf(AL_GAIN, listener.getVolume());
-			break;
-		}
-
-	}
-
-	@Override
-	public void update(float tpf) {
-		float distance;
-		float volume;
-
-		// Loop over all mediaplayers
-		for (AudioNode src : musicPlaying.keySet()) {
-
-			MediaPlayer mp = musicPlaying.get(src);
-			{
-				// Calc the distance to the listener
-				distanceVector.set(listenerPosition);
-				distanceVector.subtractLocal(src.getLocalTranslation());
-				distance = FastMath.abs(distanceVector.length());
-
-				if (distance < src.getRefDistance()) {
-					distance = src.getRefDistance();
-				}
-				if (distance > src.getMaxDistance()) {
-					distance = src.getMaxDistance();
-				}
-				volume = src.getRefDistance() / distance;
-
-				AndroidAudioData audioData = (AndroidAudioData) src
-						.getAudioData();
-
-				if (FastMath.abs(audioData.getCurrentVolume() - volume) > FastMath.FLT_EPSILON) {
-					// Left / Right channel get the same volume by now, only
-					// positional
-					mp.setVolume(volume, volume);
-
-					audioData.setCurrentVolume(volume);
-				}
-			}
-		}
-	}
-
-	public void setListener(Listener listener) {
-		if (audioDisabled) {
-			return;
-		}
-
-		if (this.listener != null) {
-			// previous listener no longer associated with current
-			// renderer
-			this.listener.setRenderer(null);
-		}
-
-		this.listener = listener;
-		this.listener.setRenderer(this);
-
-	}
-
-	@Override
-	public void cleanup() {
-		// Cleanup sound pool
-		if (soundPool != null) {
-			soundPool.release();
-			soundPool = null;
-		}
-
-		// Cleanup media player
-		for (AudioNode src : musicPlaying.keySet()) {
-			MediaPlayer mp = musicPlaying.get(src);
-			{
-				mp.stop();
-				mp.release();
-				src.setStatus(Status.Stopped);
-			}
-		}
-		musicPlaying.clear();
-	}
-
-	@Override
-	public void onCompletion(MediaPlayer mp) {
-		mp.seekTo(0);
-		mp.stop();
-		// XXX: This has bad performance -> maybe change overall structure of
-		// mediaplayer in this audiorenderer?
-		for (AudioNode src : musicPlaying.keySet()) {
-			if (musicPlaying.get(src) == mp) {
-				src.setStatus(Status.Stopped);
-				break;
-			}
-		}
-	}
-
-	/**
-	 * Plays using the {@link SoundPool} of Android. Due to hard limitation of
-	 * the SoundPool: After playing more instances of the sound you only have
-	 * the channel of the last played instance.
-	 * 
-	 * It is not possible to get information about the state of the soundpool of
-	 * a specific streamid, so removing is not possilbe -> noone knows when
-	 * sound finished.
-	 */
-	public void playSourceInstance(AudioNode src) {
-		if (audioDisabled) {
-			return;
-		}
-
-		AndroidAudioData audioData = (AndroidAudioData) src.getAudioData();
-
-		if (!(audioData.getAssetKey() instanceof AudioKey)) {
-			throw new IllegalArgumentException("Asset is not a AudioKey");
-		}
-
-		AudioKey assetKey = (AudioKey) audioData.getAssetKey();
-
-		try {
-			if (audioData.getId() < 0) { // found something to load
-				int soundId = soundPool.load(
-						assetManager.openFd(assetKey.getName()), 1);
-				audioData.setId(soundId);
-			}
-
-			int channel = soundPool.play(audioData.getId(), 1f, 1f, 1, 0, 1f);
-
-			if (channel == 0) {
-				soundpoolStillLoading.put(audioData.getId(), src);
-			} else {
-				src.setChannel(channel); // receive a channel at the last
-											// playing at least
-			}
-		} catch (IOException e) {
-			logger.log(Level.SEVERE,
-					"Failed to load sound " + assetKey.getName(), e);
-			audioData.setId(-1);
-		}
-	}
-
-	@Override
-	public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {
-		AudioNode src = soundpoolStillLoading.remove(sampleId);
-
-		if (src == null) {
-			logger.warning("Something went terribly wrong! onLoadComplete"
-					+ " had sampleId which was not in the HashMap of loading items");
-			return;
-		}
-
-		AudioData audioData = src.getAudioData();
-
-		if (status == 0) // load was successfull
-		{
-			int channelIndex;
-			channelIndex = soundPool.play(audioData.getId(), 1f, 1f, 1, 0, 1f);
-			src.setChannel(channelIndex);
-		}
-	}
-
-	public void playSource(AudioNode src) {
-		if (audioDisabled) {
-			return;
-		}
-
-		AndroidAudioData audioData = (AndroidAudioData) src.getAudioData();
-
-		MediaPlayer mp = musicPlaying.get(src);
-		if (mp == null) {
-			mp = new MediaPlayer();
-			mp.setOnCompletionListener(this);
-			mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
-		}
-
-		try {
-			AssetKey<?> key = audioData.getAssetKey();
-
-			AssetFileDescriptor afd = assetManager.openFd(key.getName()); // assetKey.getName()
-			mp.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(),
-					afd.getLength());
-			mp.prepare();
-			mp.setLooping(src.isLooping());
-			mp.start();
-			src.setChannel(0);
-			src.setStatus(Status.Playing);
-			musicPlaying.put(src, mp);
-
-		} catch (IllegalStateException e) {
-			e.printStackTrace();
-		} catch (Exception e) {
-			e.printStackTrace();
-		}
-	}
-
-	/**
-	 * Pause the current playing sounds. Both from the {@link SoundPool} and the
-	 * active {@link MediaPlayer}s
-	 */
-	public void pauseAll() {
-		soundPool.autoPause();
-		for (MediaPlayer mp : musicPlaying.values()) {
-			mp.pause();
-		}
-	}
-	
-	/**
-	 * Resume all paused sounds.
-	 */
-	public void resumeAll() {
-		soundPool.autoResume();
-		for (MediaPlayer mp : musicPlaying.values()) {
-			mp.start(); //no resume -> api says call start to resume
-		}
-	}
-
-	public void pauseSource(AudioNode src) {
-		if (audioDisabled) {
-			return;
-		}
-
-		MediaPlayer mp = musicPlaying.get(src);
-		if (mp != null) {
-			mp.pause();
-			src.setStatus(Status.Paused);
-		} else {
-			int channel = src.getChannel();
-			if (channel != -1)
-				soundPool.pause(channel); // is not very likley to make
-											// something useful :)
-		}
-	}
-
-	public void stopSource(AudioNode src) {
-		if (audioDisabled) {
-			return;
-		}
-
-		// can be stream or buffer -> so try to get mediaplayer
-		// if there is non try to stop soundpool
-		MediaPlayer mp = musicPlaying.get(src);
-		if (mp != null) {
-			mp.stop();
-			src.setStatus(Status.Paused);
-		} else {
-			int channel = src.getChannel();
-			if (channel != -1) {
-				soundPool.pause(channel); // is not very likley to make
-											// something useful :)
-			}
-		}
-
-	}
-
-	@Override
-	public void deleteAudioData(AudioData ad) {
-
-		for (AudioNode src : musicPlaying.keySet()) {
-			if (src.getAudioData() == ad) {
-				MediaPlayer mp = musicPlaying.remove(src);
-				mp.stop();
-				mp.release();
-				src.setStatus(Status.Stopped);
-				src.setChannel(-1);
-				ad.setId(-1);
-				break;
-			}
-		}
-
-		if (ad.getId() > 0) {
-			soundPool.unload(ad.getId());
-			ad.setId(-1);
-		}
-	}
-
-	@Override
-	public void setEnvironment(Environment env) {
-		// not yet supported
-	}
-
-	@Override
-	public void deleteFilter(Filter filter) {
-	}
+        SoundPool.OnLoadCompleteListener, MediaPlayer.OnCompletionListener {
+
+    private static final Logger logger = Logger.getLogger(AndroidAudioRenderer.class.getName());
+    private final static int MAX_NUM_CHANNELS = 16;
+    private final HashMap<AudioNode, MediaPlayer> musicPlaying = new HashMap<AudioNode, MediaPlayer>();
+    private SoundPool soundPool = null;
+    private final Vector3f listenerPosition = new Vector3f();
+    // For temp use
+    private final Vector3f distanceVector = new Vector3f();
+    private final Context context;
+    private final AssetManager assetManager;
+    private HashMap<Integer, AudioNode> soundpoolStillLoading = new HashMap<Integer, AudioNode>();
+    private Listener listener;
+    private boolean audioDisabled = false;
+    private final AudioManager manager;
+
+    public AndroidAudioRenderer(Activity context) {
+        this.context = context;
+        manager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
+        context.setVolumeControlStream(AudioManager.STREAM_MUSIC);
+        assetManager = context.getAssets();
+    }
+
+    @Override
+    public void initialize() {
+        soundPool = new SoundPool(MAX_NUM_CHANNELS, AudioManager.STREAM_MUSIC,
+                0);
+        soundPool.setOnLoadCompleteListener(this);
+    }
+
+    @Override
+    public void updateSourceParam(AudioNode src, AudioParam param) {
+        // logger.log(Level.INFO, "updateSourceParam " + param);
+
+        if (audioDisabled) {
+            return;
+        }
+
+        if (src.getChannel() < 0) {
+            return;
+        }
+
+        switch (param) {
+            case Position:
+                if (!src.isPositional()) {
+                    return;
+                }
+
+                Vector3f pos = src.getWorldTranslation();
+                break;
+            case Velocity:
+                if (!src.isPositional()) {
+                    return;
+                }
+
+                Vector3f vel = src.getVelocity();
+                break;
+            case MaxDistance:
+                if (!src.isPositional()) {
+                    return;
+                }
+                break;
+            case RefDistance:
+                if (!src.isPositional()) {
+                    return;
+                }
+                break;
+            case ReverbFilter:
+                if (!src.isPositional() || !src.isReverbEnabled()) {
+                    return;
+                }
+                break;
+            case ReverbEnabled:
+                if (!src.isPositional()) {
+                    return;
+                }
+
+                if (src.isReverbEnabled()) {
+                    updateSourceParam(src, AudioParam.ReverbFilter);
+                }
+                break;
+            case IsPositional:
+                break;
+            case Direction:
+                if (!src.isDirectional()) {
+                    return;
+                }
+
+                Vector3f dir = src.getDirection();
+                break;
+            case InnerAngle:
+                if (!src.isDirectional()) {
+                    return;
+                }
+                break;
+            case OuterAngle:
+                if (!src.isDirectional()) {
+                    return;
+                }
+                break;
+            case IsDirectional:
+                if (src.isDirectional()) {
+                    updateSourceParam(src, AudioParam.Direction);
+                    updateSourceParam(src, AudioParam.InnerAngle);
+                    updateSourceParam(src, AudioParam.OuterAngle);
+                } else {
+                }
+                break;
+            case DryFilter:
+                if (src.getDryFilter() != null) {
+                    Filter f = src.getDryFilter();
+                    if (f.isUpdateNeeded()) {
+                        // updateFilter(f);
+                    }
+                }
+                break;
+            case Looping:
+                if (src.isLooping()) {
+                }
+                break;
+            case Volume:
+
+                soundPool.setVolume(src.getChannel(), src.getVolume(),
+                        src.getVolume());
+
+                break;
+            case Pitch:
+
+                break;
+        }
+
+    }
+
+    @Override
+    public void updateListenerParam(Listener listener, ListenerParam param) {
+        // logger.log(Level.INFO, "updateListenerParam " + param);
+        if (audioDisabled) {
+            return;
+        }
+
+        switch (param) {
+            case Position:
+                listenerPosition.set(listener.getLocation());
+
+                break;
+            case Rotation:
+                Vector3f dir = listener.getDirection();
+                Vector3f up = listener.getUp();
+
+                break;
+            case Velocity:
+                Vector3f vel = listener.getVelocity();
+
+                break;
+            case Volume:
+                // alListenerf(AL_GAIN, listener.getVolume());
+                break;
+        }
+
+    }
+
+    @Override
+    public void update(float tpf) {
+        float distance;
+        float volume;
+
+        // Loop over all mediaplayers
+        for (AudioNode src : musicPlaying.keySet()) {
+
+            MediaPlayer mp = musicPlaying.get(src);
+            {
+                // Calc the distance to the listener
+                distanceVector.set(listenerPosition);
+                distanceVector.subtractLocal(src.getLocalTranslation());
+                distance = FastMath.abs(distanceVector.length());
+
+                if (distance < src.getRefDistance()) {
+                    distance = src.getRefDistance();
+                }
+                if (distance > src.getMaxDistance()) {
+                    distance = src.getMaxDistance();
+                }
+                volume = src.getRefDistance() / distance;
+
+                AndroidAudioData audioData = (AndroidAudioData) src.getAudioData();
+
+                if (FastMath.abs(audioData.getCurrentVolume() - volume) > FastMath.FLT_EPSILON) {
+                    // Left / Right channel get the same volume by now, only
+                    // positional
+                    mp.setVolume(volume, volume);
+
+                    audioData.setCurrentVolume(volume);
+                }
+            }
+        }
+    }
+
+    public void setListener(Listener listener) {
+        if (audioDisabled) {
+            return;
+        }
+
+        if (this.listener != null) {
+            // previous listener no longer associated with current
+            // renderer
+            this.listener.setRenderer(null);
+        }
+
+        this.listener = listener;
+        this.listener.setRenderer(this);
+
+    }
+
+    @Override
+    public void cleanup() {
+        // Cleanup sound pool
+        if (soundPool != null) {
+            soundPool.release();
+            soundPool = null;
+        }
+
+        // Cleanup media player
+        for (AudioNode src : musicPlaying.keySet()) {
+            MediaPlayer mp = musicPlaying.get(src);
+            {
+                mp.stop();
+                mp.release();
+                src.setStatus(Status.Stopped);
+            }
+        }
+        musicPlaying.clear();
+    }
+
+    @Override
+    public void onCompletion(MediaPlayer mp) {
+        mp.seekTo(0);
+        mp.stop();
+        // XXX: This has bad performance -> maybe change overall structure of
+        // mediaplayer in this audiorenderer?
+        for (AudioNode src : musicPlaying.keySet()) {
+            if (musicPlaying.get(src) == mp) {
+                src.setStatus(Status.Stopped);
+                break;
+            }
+        }
+    }
+
+    /**
+     * Plays using the {@link SoundPool} of Android. Due to hard limitation of
+     * the SoundPool: After playing more instances of the sound you only have
+     * the channel of the last played instance.
+     * 
+     * It is not possible to get information about the state of the soundpool of
+     * a specific streamid, so removing is not possilbe -> noone knows when
+     * sound finished.
+     */
+    public void playSourceInstance(AudioNode src) {
+        if (audioDisabled) {
+            return;
+        }
+
+        AndroidAudioData audioData = (AndroidAudioData) src.getAudioData();
+
+        if (!(audioData.getAssetKey() instanceof AudioKey)) {
+            throw new IllegalArgumentException("Asset is not a AudioKey");
+        }
+
+        AudioKey assetKey = (AudioKey) audioData.getAssetKey();
+
+        try {
+            if (audioData.getId() < 0) { // found something to load
+                int soundId = soundPool.load(
+                        assetManager.openFd(assetKey.getName()), 1);
+                audioData.setId(soundId);
+            }
+
+            int channel = soundPool.play(audioData.getId(), 1f, 1f, 1, 0, 1f);
+
+            if (channel == 0) {
+                soundpoolStillLoading.put(audioData.getId(), src);
+            } else {
+                src.setChannel(channel); // receive a channel at the last
+                // playing at least
+            }
+        } catch (IOException e) {
+            logger.log(Level.SEVERE,
+                    "Failed to load sound " + assetKey.getName(), e);
+            audioData.setId(-1);
+        }
+    }
+
+    @Override
+    public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {
+        AudioNode src = soundpoolStillLoading.remove(sampleId);
+
+        if (src == null) {
+            logger.warning("Something went terribly wrong! onLoadComplete"
+                    + " had sampleId which was not in the HashMap of loading items");
+            return;
+        }
+
+        AudioData audioData = src.getAudioData();
+
+        if (status == 0) // load was successfull
+        {
+            int channelIndex;
+            channelIndex = soundPool.play(audioData.getId(), 1f, 1f, 1, 0, 1f);
+            src.setChannel(channelIndex);
+        }
+    }
+
+    public void playSource(AudioNode src) {
+        if (audioDisabled) {
+            return;
+        }
+
+        AndroidAudioData audioData = (AndroidAudioData) src.getAudioData();
+
+        MediaPlayer mp = musicPlaying.get(src);
+        if (mp == null) {
+            mp = new MediaPlayer();
+            mp.setOnCompletionListener(this);
+            mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
+        }
+
+        try {
+            AssetKey<?> key = audioData.getAssetKey();
+
+            AssetFileDescriptor afd = assetManager.openFd(key.getName()); // assetKey.getName()
+            mp.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(),
+                    afd.getLength());
+            mp.prepare();
+            mp.setLooping(src.isLooping());
+            mp.start();
+            src.setChannel(0);
+            src.setStatus(Status.Playing);
+            musicPlaying.put(src, mp);
+
+        } catch (IllegalStateException e) {
+            e.printStackTrace();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * Pause the current playing sounds. Both from the {@link SoundPool} and the
+     * active {@link MediaPlayer}s
+     */
+    public void pauseAll() {
+        if (soundPool != null) {
+            soundPool.autoPause();
+            for (MediaPlayer mp : musicPlaying.values()) {
+                mp.pause();
+            }
+        }
+    }
+
+    /**
+     * Resume all paused sounds.
+     */
+    public void resumeAll() {
+        if (soundPool != null) {
+            soundPool.autoResume();
+            for (MediaPlayer mp : musicPlaying.values()) {
+                mp.start(); //no resume -> api says call start to resume
+            }
+        }
+    }
+
+    public void pauseSource(AudioNode src) {
+        if (audioDisabled) {
+            return;
+        }
+
+        MediaPlayer mp = musicPlaying.get(src);
+        if (mp != null) {
+            mp.pause();
+            src.setStatus(Status.Paused);
+        } else {
+            int channel = src.getChannel();
+            if (channel != -1) {
+                soundPool.pause(channel); // is not very likley to make
+            }											// something useful :)
+        }
+    }
+
+    public void stopSource(AudioNode src) {
+        if (audioDisabled) {
+            return;
+        }
+
+        // can be stream or buffer -> so try to get mediaplayer
+        // if there is non try to stop soundpool
+        MediaPlayer mp = musicPlaying.get(src);
+        if (mp != null) {
+            mp.stop();
+            src.setStatus(Status.Paused);
+        } else {
+            int channel = src.getChannel();
+            if (channel != -1) {
+                soundPool.pause(channel); // is not very likley to make
+                // something useful :)
+            }
+        }
+
+    }
+
+    @Override
+    public void deleteAudioData(AudioData ad) {
+
+        for (AudioNode src : musicPlaying.keySet()) {
+            if (src.getAudioData() == ad) {
+                MediaPlayer mp = musicPlaying.remove(src);
+                mp.stop();
+                mp.release();
+                src.setStatus(Status.Stopped);
+                src.setChannel(-1);
+                ad.setId(-1);
+                break;
+            }
+        }
+
+        if (ad.getId() > 0) {
+            soundPool.unload(ad.getId());
+            ad.setId(-1);
+        }
+    }
+
+    @Override
+    public void setEnvironment(Environment env) {
+        // not yet supported
+    }
+
+    @Override
+    public void deleteFilter(Filter filter) {
+    }
 }