<commit_before>package net.littlebigisland.droidibus.activity;
/**
 * Control Fragment for IBus UI 
 * @author <NAME> <<EMAIL>>
 * @package net.littlebigisland.droidibus.activity
 */
import java.util.Calendar;
import net.littlebigisland.droidibus.R;
import net.littlebigisland.droidibus.ibus.IBusCommand;
import net.littlebigisland.droidibus.ibus.IBusCommandsEnum;
import net.littlebigisland.droidibus.ibus.IBusCallbackReceiver;
import net.littlebigisland.droidibus.ibus.IBusMessageService;
import net.littlebigisland.droidibus.ibus.IBusMessageService.IOIOBinder;
import net.littlebigisland.droidibus.music.MusicControllerService;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.media.MediaMetadataRetriever;
import android.media.RemoteControlClient;
import android.media.RemoteController;
import android.media.RemoteController.MetadataEditor;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.preference.PreferenceManager;
import android.annotation.SuppressLint;
import android.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.Switch;
import android.widget.TextView;
import android.widget.Toast;

public class DashboardFragment extends Fragment {
	public String TAG = "DroidIBus";
	
	protected Handler mHandler = new Handler();
	
	protected SharedPreferences mSettings = null;
	
	protected IBusMessageService mIBusService;
	protected boolean mIBusBound = false;
	
	// Fields in the activity
	protected TextView stationText, radioRDSIndicatorField, radioProgramField,
					   radioBroadcastField, radioStereoIndicatorField, 
					   speedField, rpmField, rangeField, outTempField,
					   coolantTempField, fuel1Field, fuel2Field, avgSpeedField,
					   geoCoordinatesField ,geoStreetField, geoLocaleField,
					   geoAltitudeField, dateField, timeField;
	
	private TextView speedUnit, avgSpeedUnit, rangeFieldUnit, consumption1Unit,
		consumption2Unit, outdoorTempUnit, coolantTempUnit;
	
	// Views in the Activity
	protected RelativeLayout dashboardLayout;
	protected LinearLayout radioLayout, tabletLayout;
	protected ImageButton mPlayerPrevBtn, mPlayerControlBtn, mPlayerNextBtn;
	protected TextView mPlayerArtistText, mPlayerTitleText, mPlayerAlbumText;
	protected SeekBar mPlayerScrubBar;
	protected ImageView mPlayerArtwork;
	protected Switch mBtnMusicMode;
	
	protected MusicControllerService mPlayerService;
	protected boolean mPlayerBound = false;

	protected boolean mIsPlaying = false;
	protected boolean mWasPlaying = false; // Was the song playing before we shut
	protected long mSongDuration = 1;
	
	protected PowerManager mPowerManager = null;
	protected WakeLock screenWakeLock;
	protected boolean mScreenOn = false; // Screen on = true  Screen off = false
	
	protected RadioModes mCurrentRadioMode = null; // Current Radio Text
	protected long mLastRadioStatus = 0; // Epoch of last time we got a status message from the Radio
	protected long mLastModeChange = 0; // Time that the radio mode last changed
	protected long mLastRadioStatusRequest = 0; // Time we last requested the Radio's status
	protected boolean mCDPlayerPlaying = false;
	
	private enum RadioModes{
		AUX,
		CD,
		Radio
	}
	
	private enum RadioTypes{
		BM53,
		CD53
	}
	
	private RadioTypes mRadioType = null;
	
	private RemoteController.OnClientUpdateListener mPlayerUpdateListener = new RemoteController.OnClientUpdateListener() {

		private boolean mScrubbingSupported = false;
		
		private boolean isScrubbingSupported(int flags) {
			return (flags & RemoteControlClient.FLAG_KEY_MEDIA_POSITION_UPDATE) != 0; 
		}

		@Override
		public void onClientTransportControlUpdate(int transportControlFlags) {
			mScrubbingSupported = isScrubbingSupported(transportControlFlags);
			// If we can update the seek bar, set that up, else disable it
			if(mScrubbingSupported) {
				mPlayerScrubBar.setEnabled(true);
				mHandler.post(mUpdateSeekBar);
			}else{
				mPlayerScrubBar.setEnabled(false);
				mHandler.removeCallbacks(mUpdateSeekBar);
			}
		}

		@Override
		public void onClientPlaybackStateUpdate(int state, long stateChangeTimeMs, long currentPosMs, float speed) {
			stateUpdate(state);
			mPlayerScrubBar.setProgress((int) (currentPosMs * mPlayerScrubBar.getMax() / mSongDuration));
		}
		
		/**
		 * Evaluate the player state and update play/pause button as needed
		 */
		@Override
		public void onClientPlaybackStateUpdate(int state) {
			stateUpdate(state);
		}
		
		private void stateUpdate(int state){
			switch(state){
				case RemoteControlClient.PLAYSTATE_PLAYING:
					if(mScrubbingSupported) mHandler.post(mUpdateSeekBar);
					mIsPlaying = true;
					mPlayerControlBtn.setImageResource(android.R.drawable.ic_media_pause);
					break;
				default:
					mHandler.removeCallbacks(mUpdateSeekBar);
					mIsPlaying = false;
					mPlayerControlBtn.setImageResource(android.R.drawable.ic_media_play);
					break;
			}
		}
		
		@Override
		public void onClientMetadataUpdate(MetadataEditor editor) {
			// Some players write artist name to METADATA_KEY_ALBUMARTIST instead of METADATA_KEY_ARTIST, so we should double-check it
			mPlayerArtistText.setText(editor.getString(MediaMetadataRetriever.METADATA_KEY_ARTIST, 
				editor.getString(MediaMetadataRetriever.METADATA_KEY_ALBUMARTIST, getString(R.string.defaultText))
			));
			
			mPlayerTitleText.setText(editor.getString(MediaMetadataRetriever.METADATA_KEY_TITLE, getString(R.string.defaultText)));
			mPlayerAlbumText.setText(editor.getString(MediaMetadataRetriever.METADATA_KEY_ALBUM, getString(R.string.defaultText)));
			
			mSongDuration = editor.getLong(MediaMetadataRetriever.METADATA_KEY_DURATION, 1);
			mPlayerArtwork.setImageBitmap(editor.getBitmap(MetadataEditor.BITMAP_KEY_ARTWORK, null));
		}

		@Override
		public void onClientChange(boolean clearing) {
		}
	};
	
	/**
	 * IBus Callback Functions
	 */ 	
	private IBusCallbackReceiver mIBusUpdateListener = new IBusCallbackReceiver() {
		private int mCurrentTextColor = R.color.dayColor;
		
		/**
		 * Callback to handle any updates to the station text when in Radio Mode
		 * @param text Text to set
		 */
		@Override
		public void onUpdateRadioStation(final String text){
			RadioModes lastState = mCurrentRadioMode; 
	    	switch(text){
	    		case "TR 01 ":
	    		case "NO CD":
	    			mCurrentRadioMode = RadioModes.CD;
	    			break;
	    		case "AUX":
	    			mCurrentRadioMode = RadioModes.AUX;
	    			break;
	    		default:
	    			mCurrentRadioMode = RadioModes.Radio;
	    			break;
	    	}
	    	
	    	if(lastState != mCurrentRadioMode){
	    		mLastModeChange = Calendar.getInstance().getTimeInMillis();
	    	}
	    	
	    	/* 
	    	 We're not in the right mode, sync with the car
	    	 Make sure this isn't CD mode and that we're not in the middle of a mode change
	    	 by making sure we've been in the current mode for at least 1.5 seconds
	    	 If lastState is null then we should also check as this is the first bit of data
	    	 see about radio mode 
	    	 */
	    	if((!(mCurrentRadioMode == RadioModes.CD) && (Calendar.getInstance().getTimeInMillis() - mLastModeChange) > 1500) || lastState == null){
	    		if(mCurrentRadioMode == RadioModes.AUX && tabletLayout.getVisibility() == View.GONE){
	    			mBtnMusicMode.toggle();
	    		}
	    		if(!(mCurrentRadioMode == RadioModes.AUX) && tabletLayout.getVisibility() == View.VISIBLE){
	    			mBtnMusicMode.toggle();
	    		}
	    	}
	    	
	    	mLastRadioStatus = Calendar.getInstance().getTimeInMillis();
	    	stationText.setText(text);
		}
		
		@Override
		public void onUpdateRadioBrodcasts(final String broadcastType){
			mLastRadioStatus = Calendar.getInstance().getTimeInMillis();
			radioBroadcastField.setText(broadcastType);
		}

		@Override
		public void onUpdateRadioStereoIndicator(final String stereoIndicator){
			if(radioLayout.getVisibility() == View.VISIBLE){
				mLastRadioStatus = Calendar.getInstance().getTimeInMillis();
				int visibility = (stereoIndicator.equals("")) ? View.GONE : View.VISIBLE;
				radioStereoIndicatorField.setVisibility(visibility);
			}
		}

		@Override
		public void onUpdateRadioRDSIndicator(final String rdsIndicator){
			mLastRadioStatus = Calendar.getInstance().getTimeInMillis();
			if(radioLayout.getVisibility() == View.VISIBLE){
				int visibility = (rdsIndicator.equals("")) ? View.GONE : View.VISIBLE;
				radioRDSIndicatorField.setVisibility(visibility);
			}
		}

		@Override
		public void onUpdateRadioProgramIndicator(final String currentProgram){
			mLastRadioStatus = Calendar.getInstance().getTimeInMillis();
			radioProgramField.setText(currentProgram);
		}
		
		/**
		 * Callback to handle any vehicle speed Changes
		 * @param text Text to set
		 */
		@Override
		public void onUpdateSpeed(final int speed){
			if(mSettings.getString("speedUnit", "1").equals("0")){
				speedField.setText(String.valueOf(speed));
			}else{
				speedField.setText(String.valueOf((int) ((speed * 2) * 0.621371)));
			}
		}
		
		@Override
		public void onUpdateRPM(final int rpm){
			rpmField.setText(Integer.toString(rpm));
		}
		
		@Override
		public void onUpdateRange(final String range){
			rangeField.setText(range);
		}
		
		@Override
		public void onUpdateOutdoorTemp(final String temp){
			outTempField.setText(temp);
		}
		
		@Override
		public void onUpdateCoolantTemp(final int temp){
			if(mSettings.getString("temperatureUnit", "1").equals("0")){
				coolantTempField.setText(Integer.toString(temp));
			}else{
				coolantTempField.setText(
					"+" + Integer.toString(((temp * 9) / 5) + 32)
				);
			}
		}
		
		@Override
		public void onUpdateFuel1(final String mpg){
			fuel1Field.setText(mpg);
		}
		
		@Override
		public void onUpdateFuel2(final String mpg){
			fuel2Field.setText(mpg);
		}
		
		@Override
		public void onUpdateAvgSpeed(final String speed){
			avgSpeedField.setText(speed);
		}
		
		@Override
		public void onUpdateTime(final String time){
			timeField.setText(time);
		}
		
		@Override
		public void onUpdateDate(final String date){
			dateField.setText(date);
		}

		@Override
		public void onUpdateIgnitionSate(final int state) {
	    	boolean carState = (state > 0) ? true : false;
	    	if(carState){
	    		// The screen isn't on but the car is, turn it on
	    		if(!mScreenOn){
	    			changeScreenState(true);
	    			if(mPlayerBound && mCurrentRadioMode == RadioModes.AUX && !mIsPlaying && mWasPlaying){
	    				// Post a runnable to play the last song in 3.5 seconds
	    				new Handler(getActivity().getMainLooper()).postDelayed(new Runnable(){
							@Override
							public void run() {
								mIsPlaying = true;
								mPlayerService.sendPlayKey();
							}
						}, 3500);
	    				mWasPlaying = false;
	    			}
    			}
	    	}else{
	    		// The car is not on and the screen is, turn it off
	    		if(mScreenOn){
	    			// Pause the music as we exit the vehicle
	    			if(mPlayerBound && mCurrentRadioMode == RadioModes.AUX && mIsPlaying){
	    				mPlayerService.sendPauseKey();
	    				mIsPlaying = false;
	    				mWasPlaying = true;
	    			}
	    			changeScreenState(false);
	    			// Blank out values that aren't set while the car isn't on
	    			speedField.setText(R.string.defaultText);
	    			rpmField.setText(R.string.defaultText);
	    			coolantTempField.setText(R.string.defaultText);
	    		}
	    	}
		}

		@Override
		public void onUpdateStreetLocation(final String streetName) {
			geoStreetField.setText(streetName);
		}
		
		@Override
		public void onUpdateLocale(final String cityName) {
			geoLocaleField.setText(cityName);
		}

		@Override
		public void onUpdateGPSCoordinates(final String gpsCoordinates){
			geoCoordinatesField.setText(gpsCoordinates);
		}
		
		@Override
		public void onUpdateGPSAltitude(final int altitude){
			geoAltitudeField.setText(String.format("%s'", (int) Math.round(altitude * 3.28084)));
		}

		@Override
		public void onTrackFwd(){
			if(mPlayerBound && mIsPlaying){
				mPlayerService.sendNextKey();
			}
		}

		@Override
		public void onTrackPrev(){
			if(mPlayerBound && mIsPlaying){
				mPlayerService.sendPreviousKey();
			}
		}
		
		@Override
		public void onVoiceBtnPress(){
			// Re-purpose this button to pause/play music
	    	if(mPlayerBound && mCurrentRadioMode == RadioModes.AUX){
	    		if(mIsPlaying){
					mPlayerService.sendPauseKey();
					mIsPlaying = true;
	    		}else{
					mPlayerService.sendPlayKey();
					mIsPlaying = false;
	    		}
	    	}
		}

		@Override
		public void onUpdateRadioStatus(int status){
			// Radio is off, turn it on
			if(status == 0){
				sendIBusCommand(IBusCommandsEnum.BMToRadioPwrPress);
				sendIBusCommandDelayed(IBusCommandsEnum.BMToRadioPwrRelease, 500);<commit_msg>Fixing logic issue with next/prev btns<commit_after>package net.littlebigisland.droidibus.activity;
/**
 * Control Fragment for IBus UI 
 * @author <NAME> <<EMAIL>>
 * @package net.littlebigisland.droidibus.activity
 */
import java.util.Calendar;
import net.littlebigisland.droidibus.R;
import net.littlebigisland.droidibus.ibus.IBusCommand;
import net.littlebigisland.droidibus.ibus.IBusCommandsEnum;
import net.littlebigisland.droidibus.ibus.IBusCallbackReceiver;
import net.littlebigisland.droidibus.ibus.IBusMessageService;
import net.littlebigisland.droidibus.ibus.IBusMessageService.IOIOBinder;
import net.littlebigisland.droidibus.music.MusicControllerService;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.media.MediaMetadataRetriever;
import android.media.RemoteControlClient;
import android.media.RemoteController;
import android.media.RemoteController.MetadataEditor;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.preference.PreferenceManager;
import android.annotation.SuppressLint;
import android.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.Switch;
import android.widget.TextView;
import android.widget.Toast;

public class DashboardFragment extends Fragment {
	public String TAG = "DroidIBus";
	
	protected Handler mHandler = new Handler();
	
	protected SharedPreferences mSettings = null;
	
	protected IBusMessageService mIBusService;
	protected boolean mIBusBound = false;
	
	// Fields in the activity
	protected TextView stationText, radioRDSIndicatorField, radioProgramField,
					   radioBroadcastField, radioStereoIndicatorField, 
					   speedField, rpmField, rangeField, outTempField,
					   coolantTempField, fuel1Field, fuel2Field, avgSpeedField,
					   geoCoordinatesField ,geoStreetField, geoLocaleField,
					   geoAltitudeField, dateField, timeField;
	
	private TextView speedUnit, avgSpeedUnit, rangeFieldUnit, consumption1Unit,
		consumption2Unit, outdoorTempUnit, coolantTempUnit;
	
	// Views in the Activity
	protected RelativeLayout dashboardLayout;
	protected LinearLayout radioLayout, tabletLayout;
	protected ImageButton mPlayerPrevBtn, mPlayerControlBtn, mPlayerNextBtn;
	protected TextView mPlayerArtistText, mPlayerTitleText, mPlayerAlbumText;
	protected SeekBar mPlayerScrubBar;
	protected ImageView mPlayerArtwork;
	protected Switch mBtnMusicMode;
	
	protected MusicControllerService mPlayerService;
	protected boolean mPlayerBound = false;

	protected boolean mIsPlaying = false;
	protected boolean mWasPlaying = false; // Was the song playing before we shut
	protected long mSongDuration = 1;
	
	protected PowerManager mPowerManager = null;
	protected WakeLock screenWakeLock;
	protected boolean mScreenOn = false; // Screen on = true  Screen off = false
	
	protected RadioModes mCurrentRadioMode = null; // Current Radio Text
	protected long mLastRadioStatus = 0; // Epoch of last time we got a status message from the Radio
	protected long mLastModeChange = 0; // Time that the radio mode last changed
	protected long mLastRadioStatusRequest = 0; // Time we last requested the Radio's status
	protected boolean mCDPlayerPlaying = false;
	
	private enum RadioModes{
		AUX,
		CD,
		Radio
	}
	
	private enum RadioTypes{
		BM53,
		CD53
	}
	
	private RadioTypes mRadioType = null;
	
	private RemoteController.OnClientUpdateListener mPlayerUpdateListener = new RemoteController.OnClientUpdateListener() {

		private boolean mScrubbingSupported = false;
		
		private boolean isScrubbingSupported(int flags) {
			return (flags & RemoteControlClient.FLAG_KEY_MEDIA_POSITION_UPDATE) != 0; 
		}

		@Override
		public void onClientTransportControlUpdate(int transportControlFlags) {
			mScrubbingSupported = isScrubbingSupported(transportControlFlags);
			// If we can update the seek bar, set that up, else disable it
			if(mScrubbingSupported) {
				mPlayerScrubBar.setEnabled(true);
				mHandler.post(mUpdateSeekBar);
			}else{
				mPlayerScrubBar.setEnabled(false);
				mHandler.removeCallbacks(mUpdateSeekBar);
			}
		}

		@Override
		public void onClientPlaybackStateUpdate(int state, long stateChangeTimeMs, long currentPosMs, float speed) {
			stateUpdate(state);
			mPlayerScrubBar.setProgress((int) (currentPosMs * mPlayerScrubBar.getMax() / mSongDuration));
		}
		
		/**
		 * Evaluate the player state and update play/pause button as needed
		 */
		@Override
		public void onClientPlaybackStateUpdate(int state) {
			stateUpdate(state);
		}
		
		private void stateUpdate(int state){
			switch(state){
				case RemoteControlClient.PLAYSTATE_PLAYING:
					if(mScrubbingSupported) mHandler.post(mUpdateSeekBar);
					mIsPlaying = true;
					mPlayerControlBtn.setImageResource(android.R.drawable.ic_media_pause);
					break;
				default:
					mHandler.removeCallbacks(mUpdateSeekBar);
					mIsPlaying = false;
					mPlayerControlBtn.setImageResource(android.R.drawable.ic_media_play);
					break;
			}
		}
		
		@Override
		public void onClientMetadataUpdate(MetadataEditor editor) {
			// Some players write artist name to METADATA_KEY_ALBUMARTIST instead of METADATA_KEY_ARTIST, so we should double-check it
			mPlayerArtistText.setText(editor.getString(MediaMetadataRetriever.METADATA_KEY_ARTIST, 
				editor.getString(MediaMetadataRetriever.METADATA_KEY_ALBUMARTIST, getString(R.string.defaultText))
			));
			
			mPlayerTitleText.setText(editor.getString(MediaMetadataRetriever.METADATA_KEY_TITLE, getString(R.string.defaultText)));
			mPlayerAlbumText.setText(editor.getString(MediaMetadataRetriever.METADATA_KEY_ALBUM, getString(R.string.defaultText)));
			
			mSongDuration = editor.getLong(MediaMetadataRetriever.METADATA_KEY_DURATION, 1);
			mPlayerArtwork.setImageBitmap(editor.getBitmap(MetadataEditor.BITMAP_KEY_ARTWORK, null));
		}

		@Override
		public void onClientChange(boolean clearing) {
		}
	};
	
	/**
	 * IBus Callback Functions
	 */ 	
	private IBusCallbackReceiver mIBusUpdateListener = new IBusCallbackReceiver() {
		private int mCurrentTextColor = R.color.dayColor;
		
		/**
		 * Callback to handle any updates to the station text when in Radio Mode
		 * @param text Text to set
		 */
		@Override
		public void onUpdateRadioStation(final String text){
			RadioModes lastState = mCurrentRadioMode; 
	    	switch(text){
	    		case "TR 01 ":
	    		case "NO CD":
	    			mCurrentRadioMode = RadioModes.CD;
	    			break;
	    		case "AUX":
	    			mCurrentRadioMode = RadioModes.AUX;
	    			break;
	    		default:
	    			mCurrentRadioMode = RadioModes.Radio;
	    			break;
	    	}
	    	
	    	if(lastState != mCurrentRadioMode){
	    		mLastModeChange = Calendar.getInstance().getTimeInMillis();
	    	}
	    	
	    	/* 
	    	 We're not in the right mode, sync with the car
	    	 Make sure this isn't CD mode and that we're not in the middle of a mode change
	    	 by making sure we've been in the current mode for at least 1.5 seconds
	    	 If lastState is null then we should also check as this is the first bit of data
	    	 see about radio mode 
	    	 */
	    	if((!(mCurrentRadioMode == RadioModes.CD) && (Calendar.getInstance().getTimeInMillis() - mLastModeChange) > 1500) || lastState == null){
	    		if(mCurrentRadioMode == RadioModes.AUX && tabletLayout.getVisibility() == View.GONE){
	    			mBtnMusicMode.toggle();
	    		}
	    		if(!(mCurrentRadioMode == RadioModes.AUX) && tabletLayout.getVisibility() == View.VISIBLE){
	    			mBtnMusicMode.toggle();
	    		}
	    	}
	    	
	    	mLastRadioStatus = Calendar.getInstance().getTimeInMillis();
	    	stationText.setText(text);
		}
		
		@Override
		public void onUpdateRadioBrodcasts(final String broadcastType){
			mLastRadioStatus = Calendar.getInstance().getTimeInMillis();
			radioBroadcastField.setText(broadcastType);
		}

		@Override
		public void onUpdateRadioStereoIndicator(final String stereoIndicator){
			if(radioLayout.getVisibility() == View.VISIBLE){
				mLastRadioStatus = Calendar.getInstance().getTimeInMillis();
				int visibility = (stereoIndicator.equals("")) ? View.GONE : View.VISIBLE;
				radioStereoIndicatorField.setVisibility(visibility);
			}
		}

		@Override
		public void onUpdateRadioRDSIndicator(final String rdsIndicator){
			mLastRadioStatus = Calendar.getInstance().getTimeInMillis();
			if(radioLayout.getVisibility() == View.VISIBLE){
				int visibility = (rdsIndicator.equals("")) ? View.GONE : View.VISIBLE;
				radioRDSIndicatorField.setVisibility(visibility);
			}
		}

		@Override
		public void onUpdateRadioProgramIndicator(final String currentProgram){
			mLastRadioStatus = Calendar.getInstance().getTimeInMillis();
			radioProgramField.setText(currentProgram);
		}
		
		/**
		 * Callback to handle any vehicle speed Changes
		 * @param text Text to set
		 */
		@Override
		public void onUpdateSpeed(final int speed){
			if(mSettings.getString("speedUnit", "1").equals("0")){
				speedField.setText(String.valueOf(speed));
			}else{
				speedField.setText(String.valueOf((int) ((speed * 2) * 0.621371)));
			}
		}
		
		@Override
		public void onUpdateRPM(final int rpm){
			rpmField.setText(Integer.toString(rpm));
		}
		
		@Override
		public void onUpdateRange(final String range){
			rangeField.setText(range);
		}
		
		@Override
		public void onUpdateOutdoorTemp(final String temp){
			outTempField.setText(temp);
		}
		
		@Override
		public void onUpdateCoolantTemp(final int temp){
			if(mSettings.getString("temperatureUnit", "1").equals("0")){
				coolantTempField.setText(Integer.toString(temp));
			}else{
				coolantTempField.setText(
					"+" + Integer.toString(((temp * 9) / 5) + 32)
				);
			}
		}
		
		@Override
		public void onUpdateFuel1(final String mpg){
			fuel1Field.setText(mpg);
		}
		
		@Override
		public void onUpdateFuel2(final String mpg){
			fuel2Field.setText(mpg);
		}
		
		@Override
		public void onUpdateAvgSpeed(final String speed){
			avgSpeedField.setText(speed);
		}
		
		@Override
		public void onUpdateTime(final String time){
			timeField.setText(time);
		}
		
		@Override
		public void onUpdateDate(final String date){
			dateField.setText(date);
		}

		@Override
		public void onUpdateIgnitionSate(final int state) {
	    	boolean carState = (state > 0) ? true : false;
	    	if(carState){
	    		// The screen isn't on but the car is, turn it on
	    		if(!mScreenOn){
	    			changeScreenState(true);
	    			if(mPlayerBound && mCurrentRadioMode == RadioModes.AUX && !mIsPlaying && mWasPlaying){
	    				// Post a runnable to play the last song in 3.5 seconds
	    				new Handler(getActivity().getMainLooper()).postDelayed(new Runnable(){
							@Override
							public void run() {
								mIsPlaying = true;
								mPlayerService.sendPlayKey();
							}
						}, 3500);
	    				mWasPlaying = false;
	    			}
    			}
	    	}else{
	    		// The car is not on and the screen is, turn it off
	    		if(mScreenOn){
	    			// Pause the music as we exit the vehicle
	    			if(mPlayerBound && mCurrentRadioMode == RadioModes.AUX && mIsPlaying){
	    				mPlayerService.sendPauseKey();
	    				mIsPlaying = false;
	    				mWasPlaying = true;
	    			}
	    			changeScreenState(false);
	    			// Blank out values that aren't set while the car isn't on
	    			speedField.setText(R.string.defaultText);
	    			rpmField.setText(R.string.defaultText);
	    			coolantTempField.setText(R.string.defaultText);
	    		}
	    	}
		}

		@Override
		public void onUpdateStreetLocation(final String streetName) {
			geoStreetField.setText(streetName);
		}
		
		@Override
		public void onUpdateLocale(final String cityName) {
			geoLocaleField.setText(cityName);
		}

		@Override
		public void onUpdateGPSCoordinates(final String gpsCoordinates){
			geoCoordinatesField.setText(gpsCoordinates);
		}
		
		@Override
		public void onUpdateGPSAltitude(final int altitude){
			geoAltitudeField.setText(String.format("%s'", (int) Math.round(altitude * 3.28084)));
		}

		@Override
		public void onTrackFwd(){
			if(mPlayerBound){
				mPlayerService.sendNextKey();
			}
		}

		@Override
		public void onTrackPrev(){
			if(mPlayerBound){
				mPlayerService.sendPreviousKey();
			}
		}
		
		@Override
		public void onVoiceBtnPress(){
			// Re-purpose this button to pause/play music
	    	if(mPlayerBound && mCurrentRadioMode == RadioModes.AUX){
	    		if(mIsPlaying){
					mPlayerService.sendPauseKey();
					mIsPlaying = true;
	    		}else{
					mPlayerService.sendPlayKey();
					mIsPlaying = false;
	    		}
	    	}
		}

		@Override
		public void onUpdateRadioStatus(int status){
			// Radio is off, turn it on
			if(status == 0){
				sendIBusCommand(IBusCommandsEnum.BMToRadioPwrPress);
				sendIBusCommandDelayed(IBusCommandsEnum.BMToRadioPwrRelease, 500);
{'fraction_non_alphanumeric': 0.09010372448414602, 'fraction_numerical': 0.004355690081576907, 'mean_word_length': 4.042248278429183, 'pattern_counts': {'":': 6, '<': 9, '<?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': '937710', 'n_tokens_mistral': 9566, 'n_tokens_neox': 8031, 'n_words': 1816}