<commit_before>/*
 * ServeStream: A HTTP stream browser/player for Android
 * Copyright 2010 <NAME>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package net.sourceforge.servestream.service;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.ArrayList;

import net.sourceforge.servestream.StreamMediaActivity;
import net.sourceforge.servestream.utils.PlaylistHandler;
import net.sourceforge.servestream.utils.PreferenceConstants;

import android.app.Service;
import android.content.Intent;
import android.content.SharedPreferences;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnErrorListener;
import android.media.MediaPlayer.OnPreparedListener;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.SurfaceHolder;

public class MediaService extends Service {
	public final static String TAG = "ServeStream.MediaService";

	public static final int ERROR = -2147483648;
	public static final int NOW_PLAYING_MESSAGE = 100;
	public static final int START_SEEK_BAR = 300;
	public static final int START_DIALOG = 400;
	public static final int STOP_DIALOG = 500;
	
	private boolean streamActivityState;
	
	private final int SEEK_INCREMENT = 15000;
	
    private ArrayList<String> mediaFiles = null;
	private int mediaFilesIndex = 0;
	
	private String nowPlayingPlaylist = "";
	private String currentlyPlayingTrack = "";
	
    private MediaPlayer mediaPlayer = null;
    
	private SharedPreferences preferences = null;
	
	private boolean isOpeningMedia = false;
	
    public Handler mediaPlayerHandler;
	public Handler disconnectHandler = null;
    
    /**
     * Class for clients to access.  Because we know this service always
     * runs in the same process as its clients, we don't need to deal with
     * IPC.
     */
    public class MediaBinder extends Binder {
        public MediaService getService() {
            return MediaService.this;
        }
    }

    @Override
    public void onCreate() {

		preferences = PreferenceManager.getDefaultSharedPreferences(this);

		//streamActivityState = StreamMediaActivity.VISIBLE;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
    	
        Log.i(TAG, "Received start id " + startId + ": " + intent);
        // We want this service to continue running until it is explicitly
        // stopped, so return sticky.
        return START_STICKY;
    }

    @Override
    public void onDestroy() {  	
    	
		Log.v(TAG, "onDestroy called");
    	
        // Cancel the persistent notification.
		ConnectionNotifier.getInstance().hideRunningNotification(this);
		
		releaseMediaPlayer();
    }

    // This is the object that receives interactions from clients.  See
    // RemoteService for a more complete example.
    private final IBinder binder = new MediaBinder();
    
    @Override
    public IBinder onBind(Intent intent) {
    	
		Log.v(TAG, "onBind called");
    	
		// Make sure we stay running to maintain the bridges
		startService(new Intent(this, MediaService.class));
    	
        return binder;
    }
    
    @Override
    public boolean onUnbind(Intent intent) {
		
		Log.v(TAG, "onUnbind called");
    	
		if (!mediaPlayer.isPlaying() || playingVideo()) {
			stopSelf();
			
			if (disconnectHandler != null)
				Message.obtain(disconnectHandler, -1, "").sendToTarget();
		}
    	
		return true;
    }
    
    private void disconnect() {
		
    	ConnectionNotifier.getInstance().hideRunningNotification(this);
		
    	stopSelf();
    	
		if (disconnectHandler != null)
			Message.obtain(disconnectHandler, -1, "").sendToTarget();
    }
    
    public boolean isOpeningMedia() {
    	return isOpeningMedia;
    }
    
    public boolean isPlaying() {
        return mediaPlayer.isPlaying();	
    }
    
    private void releaseMediaPlayer() {
        if (mediaPlayer != null) {
            mediaPlayer.release();
            mediaPlayer = null;
        }
    }
    
    public void setDisplay(SurfaceHolder holder) {
        mediaPlayer.setDisplay(holder);
    }
    
    public void setNowPlayingPlaylist(String nowPlayingPlaylist) {
        this.nowPlayingPlaylist = nowPlayingPlaylist;
    }
    
    public int getNumOfQueuedFiles() {
    	return mediaFiles.size();
    }
    
    public String getNowPlayingPlaylist() {
    	return this.nowPlayingPlaylist;
    }
    
    public String getDecodedNowPlayingTrack(){
		String decodedURL = null;
    	
    	try {
			decodedURL = URLDecoder.decode(this.currentlyPlayingTrack, "UTF-8");
		} catch (UnsupportedEncodingException ex) {
			ex.printStackTrace();
			decodedURL = "";
		}
		
		return decodedURL;
    }
    
    public MediaPlayer getMediaPlayer() {
    	return this.mediaPlayer;
    }
    
    public void setMediaPlayer(MediaPlayer mediaPlayer) {
    	this.mediaPlayer = mediaPlayer;
    	this.mediaPlayer.setOnPreparedListener(m_onPreparedListener);
    	this.mediaPlayer.setOnCompletionListener(m_onCompletionListener);
        this.mediaPlayer.setOnErrorListener(new OnErrorListener() {
			public boolean onError(MediaPlayer arg0, int arg1, int arg2) {
			    mediaPlayerHandler.sendMessage(Message.obtain(mediaPlayerHandler, ERROR));
				return true;
			}

        });
    }
    
    public void startMediaPlayer() {
        startMedia(0);
    }
    
    public void nextMediaFile() {
    	
    	if (mediaFilesIndex == (mediaFiles.size() - 1)) {
    		startMedia(0);
    	} else {
            startMedia(mediaFilesIndex + 1);
    	}
    }
    
    public void pauseMedia() {
    	
    	ConnectionNotifier.getInstance().hideRunningNotification(this);
    	
    	mediaPlayer.pause();
    }
    
    public void resumeMedia() {
    	
		ConnectionNotifier.getInstance().showRunningNotification(this);
    	
    	mediaPlayer.start();
    }
    
    public void previousMediaFile() {
    	if (mediaFilesIndex == 0) {
    		startMedia((mediaFiles.size() - 1));
    	} else {
            startMedia((mediaFilesIndex - 1));
    	}
    }
    
    public void seekTo(int position) {
    	mediaPlayer.seekTo(position);
    }
    
    public void seekBackward() {
    	
    	int seekPosition = mediaPlayer.getCurrentPosition() - SEEK_INCREMENT;
    	
    	if (seekPosition >= 0) {
    		mediaPlayer.seekTo(seekPosition);
    	} else {
    		mediaPlayer.seekTo(0);    		
    	}
    }

    public void seekForward() {
    	
    	int seekPosition = mediaPlayer.getCurrentPosition() + SEEK_INCREMENT;
    	
    	if (seekPosition < mediaPlayer.getDuration()) {
    		mediaPlayer.seekTo(seekPosition);
    	} else {
    		mediaPlayer.seekTo(mediaPlayer.getDuration());    		
    	}
    }
    
    public void setStreamActivityState(boolean state) {
    	streamActivityState = state;
    }
    
    private void startMedia(int index) {
    	
        // Display a notification about us starting.  We put an icon in the status bar.
		//ConnectionNotifier.getInstance().showRunningNotification(this);
		
		// send a message to start the "Opening file..." dialog
    	if (streamActivityState == StreamMediaActivity.VISIBLE)<commit_msg>Modified to allow stream media activity to be paused<commit_after>/*
 * ServeStream: A HTTP stream browser/player for Android
 * Copyright 2010 <NAME>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package net.sourceforge.servestream.service;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.ArrayList;

import net.sourceforge.servestream.StreamMediaActivity;
import net.sourceforge.servestream.utils.PlaylistHandler;
import net.sourceforge.servestream.utils.PreferenceConstants;

import android.app.Service;
import android.content.Intent;
import android.content.SharedPreferences;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnErrorListener;
import android.media.MediaPlayer.OnPreparedListener;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.SurfaceHolder;

public class MediaService extends Service {
	public final static String TAG = "ServeStream.MediaService";

	public static final int ERROR = -2147483648;
	public static final int NOW_PLAYING_MESSAGE = 100;
	public static final int START_SEEK_BAR = 300;
	public static final int START_DIALOG = 400;
	public static final int STOP_DIALOG = 500;
	
	private boolean streamActivityState;
	
	private final int SEEK_INCREMENT = 15000;
	
    private ArrayList<String> mediaFiles = null;
	private int mediaFilesIndex = 0;
	
	private String nowPlayingPlaylist = "";
	private String currentlyPlayingTrack = "";
	
    private MediaPlayer mediaPlayer = null;
    
	private SharedPreferences preferences = null;
	
	private boolean isOpeningMedia = false;
	
    public Handler mediaPlayerHandler;
	public Handler disconnectHandler = null;
    
    /**
     * Class for clients to access.  Because we know this service always
     * runs in the same process as its clients, we don't need to deal with
     * IPC.
     */
    public class MediaBinder extends Binder {
        public MediaService getService() {
            return MediaService.this;
        }
    }

    @Override
    public void onCreate() {

		preferences = PreferenceManager.getDefaultSharedPreferences(this);

		//streamActivityState = StreamMediaActivity.VISIBLE;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
    	
        Log.i(TAG, "Received start id " + startId + ": " + intent);
        // We want this service to continue running until it is explicitly
        // stopped, so return sticky.
        return START_STICKY;
    }

    @Override
    public void onDestroy() {  	
    	
		Log.v(TAG, "onDestroy called");
    	
        // Cancel the persistent notification.
		ConnectionNotifier.getInstance().hideRunningNotification(this);
		
		releaseMediaPlayer();
    }

    // This is the object that receives interactions from clients.  See
    // RemoteService for a more complete example.
    private final IBinder binder = new MediaBinder();
    
    @Override
    public IBinder onBind(Intent intent) {
    	
		Log.v(TAG, "onBind called");
    	
		// Make sure we stay running to maintain the bridges
		startService(new Intent(this, MediaService.class));
    	
        return binder;
    }
    
    @Override
    public boolean onUnbind(Intent intent) {
		
		Log.v(TAG, "onUnbind called");
    	
		if (!mediaPlayer.isPlaying() || playingVideo()) {
			stopSelf();
			
			//if (disconnectHandler != null)
			//	Message.obtain(disconnectHandler, -1, "").sendToTarget();
		}
    	
		return true;
    }
    
    private void disconnect() {
		
    	ConnectionNotifier.getInstance().hideRunningNotification(this);
		
    	stopSelf();
    	
		if (disconnectHandler != null)
			Message.obtain(disconnectHandler, -1, "").sendToTarget();
    }
    
    public boolean isOpeningMedia() {
    	return isOpeningMedia;
    }
    
    public boolean isPlaying() {
        return mediaPlayer.isPlaying();	
    }
    
    private void releaseMediaPlayer() {
        if (mediaPlayer != null) {
            mediaPlayer.release();
            mediaPlayer = null;
        }
    }
    
    public void setDisplay(SurfaceHolder holder) {
        mediaPlayer.setDisplay(holder);
    }
    
    public void setNowPlayingPlaylist(String nowPlayingPlaylist) {
        this.nowPlayingPlaylist = nowPlayingPlaylist;
    }
    
    public int getNumOfQueuedFiles() {
    	return mediaFiles.size();
    }
    
    public String getNowPlayingPlaylist() {
    	return this.nowPlayingPlaylist;
    }
    
    public String getDecodedNowPlayingTrack(){
		String decodedURL = null;
    	
    	try {
			decodedURL = URLDecoder.decode(this.currentlyPlayingTrack, "UTF-8");
		} catch (UnsupportedEncodingException ex) {
			ex.printStackTrace();
			decodedURL = "";
		}
		
		return decodedURL;
    }
    
    public MediaPlayer getMediaPlayer() {
    	return this.mediaPlayer;
    }
    
    public void setMediaPlayer(MediaPlayer mediaPlayer) {
    	this.mediaPlayer = mediaPlayer;
    	this.mediaPlayer.setOnPreparedListener(m_onPreparedListener);
    	this.mediaPlayer.setOnCompletionListener(m_onCompletionListener);
        this.mediaPlayer.setOnErrorListener(new OnErrorListener() {
			public boolean onError(MediaPlayer arg0, int arg1, int arg2) {
			    mediaPlayerHandler.sendMessage(Message.obtain(mediaPlayerHandler, ERROR));
				return true;
			}

        });
    }
    
    public void startMediaPlayer() {
        startMedia(0);
    }
    
    public void nextMediaFile() {
    	
    	if (mediaFilesIndex == (mediaFiles.size() - 1)) {
    		startMedia(0);
    	} else {
            startMedia(mediaFilesIndex + 1);
    	}
    }
    
    public void pauseMedia() {
    	
    	ConnectionNotifier.getInstance().hideRunningNotification(this);
    	
    	mediaPlayer.pause();
    }
    
    public void resumeMedia() {
    	
		ConnectionNotifier.getInstance().showRunningNotification(this);
    	
    	mediaPlayer.start();
    }
    
    public void previousMediaFile() {
    	if (mediaFilesIndex == 0) {
    		startMedia((mediaFiles.size() - 1));
    	} else {
            startMedia((mediaFilesIndex - 1));
    	}
    }
    
    public void seekTo(int position) {
    	mediaPlayer.seekTo(position);
    }
    
    public void seekBackward() {
    	
    	int seekPosition = mediaPlayer.getCurrentPosition() - SEEK_INCREMENT;
    	
    	if (seekPosition >= 0) {
    		mediaPlayer.seekTo(seekPosition);
    	} else {
    		mediaPlayer.seekTo(0);    		
    	}
    }

    public void seekForward() {
    	
    	int seekPosition = mediaPlayer.getCurrentPosition() + SEEK_INCREMENT;
    	
    	if (seekPosition < mediaPlayer.getDuration()) {
    		mediaPlayer.seekTo(seekPosition);
    	} else {
    		mediaPlayer.seekTo(mediaPlayer.getDuration());    		
    	}
    }

    public boolean getStreamActivityState() {
    	return streamActivityState;
    }
    
    public void setStreamActivityState(boolean state) {
    	streamActivityState = state;
    }
    
    private void startMedia(int index) {
    	
        // Display a notification about us starting.  We put an icon in the status bar.
		//ConnectionNotifier.getInstance().showRunningNotification(this);
		
		// send a message to start the "Opening file..." dialog
    	if (streamActivityState == StreamMediaActivity.VISIBLE)
{'fraction_non_alphanumeric': 0.0874976067394218, 'fraction_numerical': 0.006509668772735976, 'mean_word_length': 2.9352084379708687, 'pattern_counts': {'":': 2, '<': 9, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, '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': '6813405', 'n_tokens_mistral': 4703, 'n_tokens_neox': 4375, 'n_words': 1142}