package kr.co.rito.osicmanager; import androidx.annotation.OptIn; import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.widget.AppCompatTextView; import android.app.Activity; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.res.AssetFileDescriptor; import android.content.res.AssetManager; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.PixelFormat; import android.graphics.Point; import android.graphics.PorterDuff; import android.graphics.Rect; import android.graphics.SurfaceTexture; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.graphics.text.LineBreaker; import android.media.AudioAttributes; import android.media.AudioFormat; import android.media.AudioManager; import android.media.AudioTrack; import android.media.MediaPlayer; import android.media.SoundPool; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.Environment; import android.os.FileUtils; import android.os.SystemClock; import android.provider.MediaStore; import android.text.Layout; import android.text.StaticLayout; import android.text.TextPaint; import android.util.JsonReader; import android.util.Log; import android.view.Display; import android.view.Gravity; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.TextureView; import android.view.View; import android.view.WindowManager; import android.webkit.JavascriptInterface; import android.webkit.WebResourceError; import android.webkit.WebResourceRequest; import android.webkit.WebResourceResponse; import android.webkit.WebView; import android.webkit.WebViewClient; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.ProgressBar; import android.widget.RelativeLayout; import android.widget.TextView; import android.widget.Toast; import com.google.android.exoplayer2.ExoPlayer; import com.google.android.exoplayer2.MediaItem; import com.google.android.exoplayer2.PlaybackException; import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.source.MediaSource; import com.google.android.exoplayer2.source.ProgressiveMediaSource; import com.google.android.exoplayer2.source.hls.HlsManifest; import com.google.android.exoplayer2.upstream.AssetDataSource; import com.google.android.exoplayer2.upstream.DataSource; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.RandomAccessFile; import java.io.UnsupportedEncodingException; import java.lang.ref.WeakReference; import java.lang.reflect.Method; import java.net.URLDecoder; import java.nio.charset.Charset; import java.security.SecureRandom; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.HashMap; import java.util.Queue; import java.util.Random; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; //import com.downloader.Error; //import com.downloader.OnCancelListener; //import com.downloader.OnDownloadListener; //import com.downloader.OnPauseListener; //import com.downloader.OnProgressListener; //import com.downloader.OnStartOrResumeListener; //import com.downloader.PRDownloader; //import com.downloader.PRDownloaderConfig; //import com.downloader.Progress; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSession; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import kr.co.rito.ritoplayer.RitoPlayer; import okhttp3.Call; import okhttp3.Callback; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; import org.eclipse.paho.android.service.MqttAndroidClient; import org.eclipse.paho.client.mqttv3.IMqttActionListener; import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken; import org.eclipse.paho.client.mqttv3.IMqttMessageListener; import org.eclipse.paho.client.mqttv3.IMqttToken; import org.eclipse.paho.client.mqttv3.MqttCallback; import org.eclipse.paho.client.mqttv3.MqttConnectOptions; import org.eclipse.paho.client.mqttv3.MqttException; import org.eclipse.paho.client.mqttv3.MqttMessage; import org.json.JSONArray; import org.json.JSONObject; import org.videolan.libvlc.interfaces.IMedia; import org.videolan.libvlc.interfaces.IVLCVout; import org.videolan.libvlc.LibVLC; import org.videolan.libvlc.Media; //import org.videolan.libvlc.MediaPlayer; public class MainActivity extends AppCompatActivity implements IVLCVout.Callback, TextureView.SurfaceTextureListener { public final static String TAG = "OsicMain"; public static int PLAYER_LIBRARY_TYPE_RITO = 1; public static int PLAYER_LIBRARY_TYPE_VLC = 2; public static int USING_MAIN_PLAYER_LIBRARY_TYPE = PLAYER_LIBRARY_TYPE_VLC; //public static int USING_MAIN_PLAYER_LIBRARY_TYPE = PLAYER_LIBRARY_TYPE_RITO; public static int PLAYER_VIEW_TYPE_SURFACE_VIEW = 1; public static int PLAYER_VIEW_TYPE_TEXTURE_VIEW = 2; public static int USING_PLAYER_VIEW_TYPE = PLAYER_VIEW_TYPE_TEXTURE_VIEW; static int MANAGER_NOTIFY_ORDER_START_PLAYBACK = 1; static int MANAGER_NOTIFY_ORDER_STOP_PLAYBACK = 2; static int MANAGER_NOTIFY_ORDER_START_TICKER = 3; static int MANAGER_NOTIFY_ORDER_START_TTS = 4; static int MANAGER_NOTIFY_ORDER_CEC_CONTROL = 5; static int MANAGER_NOTIFY_ORDER_JSON_ORDER = 6; static int MANAGER_NOTIFY_ORDER_NOTIFY_SCREEN_ORDER = 7; static int MANAGER_NOTIFY_ORDER_EVENT_MESSAGE = 8; static String MANAGER_JSON_ORDER_TYPE_PLAY_CONTENTS = "filecast"; static String MANAGER_JSON_ORDER_TYPE_PLAY_IPCAST = "ipcast"; static String MANAGER_JSON_ORDER_TYPE_PLAY_CARCAST = "carcast"; static String MANAGER_ACTION_MODE_STANDBY = "standby"; static String MANAGER_ACTION_MODE_SERVICE = "inservice"; static int VLC_NETWORK_CACHE_DEFAULT = 1500; static int VLC_LIVE_CACHE_DEFAULT = 1500; static int VLC_UDP_BUFFER_DEFAULT = 32768; private long mKeyPressTime; private long mNotifyMsgStartTime; public boolean mIsOnNotifyMsg; public boolean mIsOnTTSPlaying; public boolean mIsDeviceOSIC10; private int mLastSpeakerVolume; private int mLastDacVolume; private int mLastVideoVolume; private SurfaceView mSurface; private TextureView mTexturePlayView; private SurfaceHolder holder; private LibVLC mVLC; private String mCurrentPlayUrl; private String mLastPlayUrl; private String mShouldPlayUrl; private boolean mShouldStopPlay = false; org.videolan.libvlc.MediaPlayer mVlcPlayer; private Media mVLCMedia; private int mVlcVolume; private int mVlcMaxVolume; ImageView mChannelOsdImageView; ImageView mImageViewBlack; TextView mChannelOsdView; ProgressBar mProgressBar; TextView mCarCastTitleView; private String mManagerActMode; public String mWardId; // for 119 public String mDsrSeq; // for 119 public String mCastReceivedNotifyDsrSeq; // for 119 public long mDsrCastReceivedTime; // for 119 public String mEbcastMqttIp; // for 119 public static final int EBCAST_SAMPLE_RATE = 16000; // 샘플링 레이트 (Hz) public static final int EBCAST_CHANNEL_CONFIG = AudioFormat.CHANNEL_OUT_MONO; // 모노 public static final int EBCAST_AUDIO_FORMAT = AudioFormat.ENCODING_PCM_16BIT; // 16비트 PCM public AudioTrack mAudioTrack; public ExoPlayer mExoPlayer = null; boolean mIsRitoPlayerOver; RitoPlayer mPlayer; RitoPlayer mAudioPlayer; RitoPlayer.playerNotify mPlayerNotify; RitoPlayer.AudioOut mAudioSubOut; AudioFilePlayer mTTSPlayer; TickerManager mTickerManager; VfdManager mVfdManager; SystemManager mSystemManager; CoolerManager mCoolerManager; FileDownloader mFileDownloader; public static MainActivity INSTANCE; public String mSDCardPath; public String mSDSavePath; public String mEmmcSavePath; public JsonResult mJsonResult; public JsonResult mJsonIpSchedule; public JsonResult mJsonFileSchedule; public JsonScheduler mJsonScheduler; public DacScheduler mDacScheduler; private static SoundPool mSoundPool; private static HashMap mSoundPoolMap; public static MqttAndroidClient mqttAndroidClient = null; // Used to load the 'osic-lib' library on application startup. static { System.loadLibrary("osic-lib"); } private static void shellCommand(String order) { try { Process process = Runtime.getRuntime().exec(order); process.waitFor(); process.destroy(); } catch (Exception e) { e.printStackTrace(); } } private static void shellCommand(String[] order) { try { Process process = Runtime.getRuntime().exec(order); process.waitFor(); process.destroy(); } catch (Exception e) { e.printStackTrace(); } } @Override public void onSurfacesCreated(IVLCVout ivlcVout) { } @Override public void onSurfacesDestroyed(IVLCVout ivlcVout) { } @Override public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int i, int i1) { Log.w(TAG, "Surfacee Texture Created!!"); //createPlayer("http://219.255.217.140/ext/contents/Your_wedding.ts"); if(USING_MAIN_PLAYER_LIBRARY_TYPE == PLAYER_LIBRARY_TYPE_VLC) { createPlayer(null); } } @Override public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int i, int i1) { // final IVLCVout vout = mVlcPlayer.getVLCVout(); // vout.detachViews(); // vout.setVideoView(mTexturePlayView); // vout.attachViews(); // mVlcPlayer.updateVideoSurfaces(); } @Override public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) { return false; } @Override public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) { } class CoolerManager extends Thread { public int CPU_FAN_GPIO_NUMBER = 156; public boolean mIsAlive = false; public void terminate() { mIsAlive = false; } public void initialize() { SystemUtil.pinSetup(CPU_FAN_GPIO_NUMBER, SystemUtil.GPIO_OUT); } public void activateCpuFan(boolean activate) { if(activate) { SystemUtil.setPinValue(CPU_FAN_GPIO_NUMBER, SystemUtil.GPIO_HIGH); } else { SystemUtil.setPinValue(CPU_FAN_GPIO_NUMBER, SystemUtil.GPIO_LOW); } } @Override public void run() { mIsAlive = true; while(mIsAlive) { activateCpuFan(true); try { sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } activateCpuFan(false); try { sleep(300); } catch (InterruptedException e) { e.printStackTrace(); } } } } public void setSpeakerVolume(int volume) { try { int volumeInt = volume; if(mLastSpeakerVolume != volumeInt) { mLastSpeakerVolume = volumeInt; String order = String.format("ritoi2c w /dev/i2c-6 0x31 0x13 0x%X", (100 - mLastSpeakerVolume)); shellCommand(order); } } catch(Exception e) { } } public void setVideoVolume(int volume) { try { int volumeInt = volume; if(mLastVideoVolume != volumeInt) { mLastVideoVolume = volumeInt; String order = String.format("ritosysc SHELL-ORDER=media volume --show --stream 3 --set %d", mLastVideoVolume); shellCommand(order); } } catch(Exception e) { } } public void setDacVolume(int volume) { try { int volumeInt = volume; if(mLastDacVolume != volumeInt) { mLastDacVolume = volumeInt; } } catch(Exception e) { } } class SystemManager extends Thread { public int CPU_FAN_GPIO_NUMBER = 156; public boolean mIsAlive = false; public void terminate() { mIsAlive = false; } public void initialize() { SystemUtil.pinSetup(CPU_FAN_GPIO_NUMBER, SystemUtil.GPIO_OUT); } public void activateCpuFan(boolean activate) { if(activate) { SystemUtil.setPinValue(CPU_FAN_GPIO_NUMBER, SystemUtil.GPIO_HIGH); } else { SystemUtil.setPinValue(CPU_FAN_GPIO_NUMBER, SystemUtil.GPIO_LOW); } } public void stopNotifyScreen() { runOnUiThread(new Runnable() { @Override public void run() { findViewById(R.id.surfaceViewCmd).setVisibility(View.INVISIBLE); findViewById(R.id.layoutCommand).setVisibility(View.INVISIBLE); // findViewById(R.id.surfaceViewCmd).setAlpha(0.0f); // findViewById(R.id.layoutCommand).setAlpha(0.0f); if(USING_MAIN_PLAYER_LIBRARY_TYPE == PLAYER_LIBRARY_TYPE_VLC) { if(mVlcPlayer != null) { setMainPlayerVolume(mVlcMaxVolume); } } } }); Log.w(TAG, "**********************"); Log.w(TAG, " 지령화면 표시종료 "); Log.w(TAG, "**********************"); shellCommand("miscctrl function_led red off"); shellCommand("miscctrl function_led green off"); shellCommand("miscctrl function_led blue off"); } @Override public void run() { int aliveCount = 0; int mSpkVolumeCheckCount = 20; mIsAlive = true; while(mIsAlive) { long curTime = SystemClock.uptimeMillis(); if(BuildConfig.SPECIAL_APP_MODE.equals("119NOTI_DEMO")) { curTime = mNotifyMsgStartTime; } if(mNotifyMsgStartTime > 0) { if(curTime - mNotifyMsgStartTime > 60 * 1000) { // 30 * 1000 -> 60 * 1000 by ritoseo - 2021.04.08 mNotifyMsgStartTime = 0; mIsOnNotifyMsg = false; stopNotifyScreen(); } } mSpkVolumeCheckCount++; if(mSpkVolumeCheckCount >= 10) { mSpkVolumeCheckCount = 0; String volume = SystemUtil.getConfigValue("spkvolume"); if(volume.length() == 0) { volume = "100"; } try { int volumeInt = Integer.parseInt(volume); setSpeakerVolume(volumeInt); } catch(Exception e) { } volume = SystemUtil.getConfigValue("videovolume"); if(volume.length() == 0) { volume = "12"; } try { int volumeInt = Integer.parseInt(volume); setVideoVolume(volumeInt); } catch(Exception e) { } volume = SystemUtil.getConfigValue("dacvolume"); if(volume.length() == 0) { volume = "100"; } //Log.d("RITO", "dacvolume : " + volume); try { int volumeInt = Integer.parseInt(volume); setDacVolume(volumeInt); } catch(Exception e) { } } if(!SystemUtil.property_get("sys.rito.freeze").equals("liveness")) { aliveCount++; aliveCount %= 10000000; SystemUtil.property_set("sys.rito.osic.liveness", "" + aliveCount); } try { sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } } class VfdManager extends Thread { public int VFD_TOTAL_WIDTH = 16; public int VFD_TOTAL_HEIGHT = 2; public int VFD_ALIGN_LEFT = 1; public int VFD_ALIGN_CENTER = 2; public int VFD_ALIGN_RIGHT = 3; private long mChangedTime = 0; private Object mLock = new Object(); private int mSetIdx = -1; private int mChangeSection = 0; public String[] mSettingOrder = { "STATION IP", "STATION NM", "STATION GW", "STATION DNS", "SERVER IP", "SERVER PORT" }; public boolean mVfdChangeMode = false; public boolean mVfdConfirmMode = false; // added by ritoseo - 2023-03-21 public boolean mVfdConfirmYesNo = false; // added by ritoseo - 2023-03-21 private int mVfdChangeType = 0; private String mVfdChangingValue = ""; private String mVfdBaseString = ""; private boolean isTitleIpType(String title) { if(title.equals("STATION IP") || title.equals("STATION NM") || title.equals("STATION GW") || title.equals("STATION DNS") || title.equals("SERVER IP")) { return true; } return false; } private String currentTitleString() { int idx; synchronized (mLock) { idx = mSetIdx; } if(idx < 0) return "OSIC-10"; return mSettingOrder[idx]; } public void cancelVfdChangeMode() { if(mSetIdx < 0) return; if(mVfdChangeMode) { moveCursor(0, 0, 0); mChangedTime = SystemClock.uptimeMillis(); mVfdChangeMode = false; } } public void toggleVfdChangeMode() { //Log.w(TAG, "VfdChangeMode : " + mVfdChangeMode); if(mSetIdx < 0) return; if(mVfdChangeMode) { moveCursor(0, 0, 0); /* Added by ritoseo - 2023-03-21 */ // if(!mVfdConfirmMode && confirmSettingCheck()) { // mVfdConfirmMode = true; // mVfdConfirmYesNo = true; // vfdDrawString("SAVE CHANGES?", 0, VFD_ALIGN_CENTER); // toggleConfirmValue(); // return; // } /* ------------------------------ */ confirmSettingValue(); mVfdChangeMode = false; } else { mVfdChangeMode = true; String curTitle = currentTitleString(); if(isTitleIpType(curTitle)) { if(mVfdChangingValue.length() == 0) mVfdChangingValue = "0.0.0.0"; vfdDrawString(mVfdChangingValue, 1, VFD_ALIGN_CENTER); String padString = makePaddingString(mVfdChangingValue); int pos = padString.indexOf('.'); if(pos > 0) { mChangeSection = 0; moveCursor(pos - 1, 1, 1); } } } } private String changeSectionValue(String valueString, int section, int direction) { String result; String[] splitValue = valueString.split("\\."); Log.w(TAG, "splitValue Length : " + splitValue.length + ", valueString : " + valueString); if(splitValue.length < 4) return valueString; int value = Integer.parseInt(splitValue[section]); value += direction; if(value < 0) value = 255; value %= 256; splitValue[section] = "" + value; result = String.format("%s.%s.%s.%s", splitValue[0], splitValue[1], splitValue[2], splitValue[3]); return result; } private int getCursorOfSection(String valueString, int section) { if(section == 3) { for(int i = valueString.length() - 1;i >= 0;i--) { if(valueString.charAt(i) >= '0' && valueString.charAt(i) <= '9') return i; } return valueString.length() - 1; } int cnt = -1; for(int i = 0;i < valueString.length();i++) { if(valueString.charAt(i) == '.') { cnt++; if(cnt == section) { return i - 1; } } } return 0; } public void applyNetworkSettings() { String ipaddr = getConfigValue("ipaddr"); String netmask = getConfigValue("netmask"); String gateway = getConfigValue("gateway"); String dns = getConfigValue("dns"); Log.w(TAG, String.format("[applyNetwork] %s, %s, %s, %s", ipaddr, netmask, gateway, dns)); if(ipaddr.length() > 0 && netmask.length() > 0 && gateway.length() > 0 && dns.length() > 0) { shellCommand("setConfig iptype static"); } } public boolean confirmSettingCheck() { String title = currentTitleString(); boolean needConfirm = false; if(title.equals("STATION IP")) { needConfirm = true; } else if(title.equals("STATION NM")) { needConfirm = true; } else if(title.equals("STATION GW")) { needConfirm = true; } else if(title.equals("STATION DNS")) { needConfirm = true; } else if(title.equals("SERVER IP")) { needConfirm = true; } return needConfirm; } private void drawSaveVfd() { vfdDrawString("SAVE", 0, VFD_ALIGN_CENTER); vfdDrawString("", 1, VFD_ALIGN_CENTER); } public void confirmSettingValue() { String title = currentTitleString(); if(title.equals("STATION IP")) { drawSaveVfd(); shellCommand("setConfig ipaddr " + mVfdChangingValue); applyNetworkSettings(); } else if(title.equals("STATION NM")) { drawSaveVfd(); shellCommand("setConfig netmask " + mVfdChangingValue); applyNetworkSettings(); } else if(title.equals("STATION GW")) { drawSaveVfd(); shellCommand("setConfig gateway " + mVfdChangingValue); applyNetworkSettings(); } else if(title.equals("STATION DNS")) { drawSaveVfd(); shellCommand("setConfig dns " + mVfdChangingValue); applyNetworkSettings(); } else if(title.equals("SERVER IP")) { drawSaveVfd(); shellCommand("setConfig svraddr " + mVfdChangingValue); } } private void toggleConfirmValue() { mVfdConfirmYesNo = !mVfdConfirmYesNo; if(mVfdConfirmMode) { vfdDrawString("YES", 1, VFD_ALIGN_CENTER); } else { vfdDrawString("NO", 1, VFD_ALIGN_CENTER); } } public void changeSettingValue(int direction) { // if(mVfdConfirmMode) { // toggleConfirmValue(); // return; // } if(mVfdChangeMode) { mVfdChangingValue = changeSectionValue(mVfdChangingValue, mChangeSection, direction); vfdDrawString(mVfdChangingValue, 1, VFD_ALIGN_CENTER); String padString = makePaddingString(mVfdChangingValue); int pos = getCursorOfSection(padString, mChangeSection); moveCursor(pos, 1, 1); } } public void moveSettingMode(int direction) { int idx; // if(mVfdConfirmMode) { // return; // } if(mVfdChangeMode) { String curTitle = currentTitleString(); if(isTitleIpType(curTitle)) { //String[] valueDigit = mVfdChangingValue.split("."); mChangeSection += direction; if(mChangeSection < 0) mChangeSection = 3; mChangeSection %= 4; String padString = makePaddingString(mVfdChangingValue); int pos = getCursorOfSection(padString, mChangeSection); moveCursor(pos, 1, 1); } return; } synchronized (mLock) { mSetIdx += direction; if (mSetIdx < 0) mSetIdx = mSettingOrder.length - 1; mSetIdx %= mSettingOrder.length; idx = mSetIdx; } printModeTitle(idx); printModeValue(idx); mChangedTime = SystemClock.uptimeMillis(); } private void setSettingMode(int index) { synchronized (mLock) { mSetIdx = index; } printModeTitle(index); printModeValue(index); mChangedTime = SystemClock.uptimeMillis(); } private void printModeTitle(int mode) { if(mode < 0) { // clear vfdDrawString("OSIC-10", 0, VFD_ALIGN_CENTER); return; } vfdDrawString(mSettingOrder[mode], 0, VFD_ALIGN_CENTER); } private void moveCursor(int x, int y, int mode) { String[] order = {"vfdctrl", "cursorxy", "" + x, "" + y}; shellCommand(order); if(mode == 0) { shellCommand("vfdctrl showcursor off"); } else { shellCommand("vfdctrl showcursor on"); } } private boolean isIptypeStatic() { String iptype = getConfigValue("ipv4type"); if(iptype.equals("static")) return true; return false; } private void printModeValue(int mode) { String value = ""; if(mode < 0) { // clear vfdDrawString("", 1, VFD_ALIGN_CENTER); return; } if(mSettingOrder[mode].equals("STATION IP")) { value = getIPAddress(); if(isIptypeStatic()) { String temp = getConfigValue("ipaddr"); if(temp.length() > 0) value = temp; } } else if(mSettingOrder[mode].equals("STATION NM")) { value = getNetmask(); if(isIptypeStatic()) { String temp = getConfigValue("netmask"); if(temp.length() > 0) value = temp; } } else if(mSettingOrder[mode].equals("STATION GW")) { value = getGateway(); if(isIptypeStatic()) { String temp = getConfigValue("gateway"); if(temp.length() > 0) value = temp; } } else if(mSettingOrder[mode].equals("STATION DNS")) { value = SystemUtil.property_get("net.dns1"); if(isIptypeStatic()) { String temp = getConfigValue("dns"); if(temp.length() > 0) value = temp; } } else if(mSettingOrder[mode].equals("SERVER IP")) { value = getServerAddress(); } else if(mSettingOrder[mode].equals("SERVER PORT")) { value = "" + getServerPort(); } Log.w(TAG, "VALUE : " + value); mVfdChangingValue = value; vfdDrawString(value, 1, VFD_ALIGN_CENTER); } String makePaddingString(String string) { int x; int length; String strMessage = ""; String strLeftPadding = ""; String strRightPadding = ""; length = string.length(); x = (VFD_TOTAL_WIDTH - length) / 2; if(x > 0) { for(int i = 0; i < x;i++) strLeftPadding += " "; } if(VFD_TOTAL_WIDTH - length - x > 0) { for(int i = 0; i < VFD_TOTAL_WIDTH - length - x;i++) strRightPadding += " "; } strMessage = strLeftPadding + string + strRightPadding; return strMessage; } void vfdDrawString(String string, int y, int flag) { int x; int length; String strMessage = ""; String strLeftPadding = ""; String strRightPadding = ""; length = string.length(); if(flag == VFD_ALIGN_LEFT) { x = 0; if(VFD_TOTAL_WIDTH - length > 0) { for(int i = 0; i < VFD_TOTAL_WIDTH - length;i++) strRightPadding += ' '; } } else if(flag == VFD_ALIGN_CENTER) { x = (VFD_TOTAL_WIDTH - length) / 2; if(x > 0) { for(int i = 0; i < x;i++) strLeftPadding += " "; } if(VFD_TOTAL_WIDTH - length - x > 0) { for(int i = 0; i < VFD_TOTAL_WIDTH - length - x;i++) strRightPadding += " "; } } else { x = VFD_TOTAL_WIDTH - length; } strMessage = strLeftPadding + string + strRightPadding; printVfdMessage(0, y, strMessage); } public void printVfdMessage(int x, int y, String msg) { /*Log.w(TAG, String.format("%d, %d, MSG : %s", x, y, msg));*/ /*String order = String.format("vfdctrl printxy %d %d %s", x, y, msg); try { String newOrder = new String(order.getBytes("US-ASCII"), "US-ASCII"); Log.w(TAG, "new order : " + newOrder); shellCommand(newOrder.trim()); } catch (UnsupportedEncodingException e) { e.printStackTrace(); }*/ String[] order = {"vfdctrl", "printxy", "" + x, "" + y, msg}; shellCommand(order); } @Override public void run() { while(true) { long curTime = SystemClock.uptimeMillis(); if(curTime - mChangedTime >= 7 * 1000) { if(!mVfdChangeMode) { setSettingMode(-1); } } try { sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } } class AudioFilePlayer extends Thread { int DOWNLOAD_STATUS_PROCESS = 0; int DOWNLOAD_STATUS_SUCCESS = 1; int DOWNLOAD_STATUS_FAILED = 2; private boolean mChimeUpDone = false; private boolean mChimeDownDone = false; private int mProgress = 0; private int mLastProgress = 0; private int mPlayVolume = 100; private int mDownloadStatus = DOWNLOAD_STATUS_PROCESS; private String mTTSPath; private boolean mIsAlive = false; private String mPlayMode; private String mPlayTarget; //MediaPlayer mMediaPlayer; // deprecated by ritoseo - 2024-12-16 ExoPlayer mExoPlayer; private class CallbackToDownloadFile implements Callback { private File directory; private File fileToBeDownloaded; public CallbackToDownloadFile(String directory, String fileName) { this.directory = new File(directory); this.fileToBeDownloaded = new File(this.directory.getAbsolutePath() + "/" + fileName); } @Override public void onFailure(Call call, IOException e) { mDownloadStatus = DOWNLOAD_STATUS_FAILED; /*runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText( MainActivity.this, "파일을 다운로드할 수 없습니다. 인터넷 연결을 확인하세요.", Toast.LENGTH_SHORT ).show(); } });*/ } @Override public void onResponse(Call call, Response response) throws IOException { if(!response.isSuccessful()) { mDownloadStatus = DOWNLOAD_STATUS_FAILED; return; } if (!this.directory.exists()) { this.directory.mkdirs(); } if (this.fileToBeDownloaded.exists()) { this.fileToBeDownloaded.delete(); } try { this.fileToBeDownloaded.createNewFile(); } catch (IOException e) { e.printStackTrace(); /*runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText( MainActivity.this, "다운로드 파일을 생성할 수 없습니다.", Toast.LENGTH_SHORT ).show(); } });*/ mDownloadStatus = DOWNLOAD_STATUS_FAILED; return; } InputStream is = response.body().byteStream(); OutputStream os = new FileOutputStream(this.fileToBeDownloaded); final int BUFFER_SIZE = 2048; byte[] data = new byte[BUFFER_SIZE]; int count; long total = 0; while ((count = is.read(data)) != -1) { total += count; os.write(data, 0, count); } os.flush(); os.close(); is.close(); mDownloadStatus = DOWNLOAD_STATUS_SUCCESS; /*runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText( MainActivity.this, "다운로드가 완료되었습니다.", Toast.LENGTH_SHORT ).show(); } });*/ } } public AudioFilePlayer() { mPlayMode = "tts"; // mMediaPlayer = new MediaPlayer(); // AudioAttributes aa = new AudioAttributes.Builder() .setUsage(AudioAttributes.USAGE_ALARM) .setContentType(AudioAttributes.CONTENT_TYPE_SPEECH) .build(); // mMediaPlayer.setAudioAttributes(aa); // mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { // @Override // public void onCompletion(MediaPlayer mediaPlayer) { // if(!mChimeUpDone) { // mChimeUpDone = true; // return; // } // if(mProgress < mLastProgress) { // mProgress++; // return; // } // if(!mChimeDownDone) { // mChimeDownDone = true; // return; // } // } // }); // // mMediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() { // @Override // public boolean onError(MediaPlayer mediaPlayer, int i, int i1) { // return false; // } // }); mExoPlayer = new ExoPlayer.Builder(MainActivity.INSTANCE).build(); mExoPlayer.addListener(new Player.Listener() { @Override public void onTimelineChanged( Timeline timeline, @Player.TimelineChangeReason int reason) { Object manifest = mExoPlayer.getCurrentManifest(); if (manifest != null) { HlsManifest hlsManifest = (HlsManifest) manifest; // Do something with the manifest. } } @Override public void onPlayerError(PlaybackException error) { // 오류 처리 switch (error.errorCode) { case PlaybackException.ERROR_CODE_IO_NETWORK_CONNECTION_FAILED: // 네트워크 연결 오류 처리 Log.e("ExoPlayer", "Network connection error: " + error.getMessage()); break; case PlaybackException.ERROR_CODE_DECODING_FAILED: // 디코딩 오류 처리 Log.e("ExoPlayer", "Decoding error: " + error.getMessage()); break; default: // 그 외의 오류 처리 Log.e("ExoPlayer", "Playback error: " + error.getMessage()); break; } } @Override public void onPlaybackStateChanged(int playbackState) { if (playbackState == Player.STATE_ENDED) { // 재생 완료 이벤트 처리 if(!mChimeUpDone) { mChimeUpDone = true; return; } if(mProgress < mLastProgress) { mProgress++; return; } if(!mChimeDownDone) { mChimeDownDone = true; } } } }); } public void setDownloadPath(String ttsPath) { mTTSPath = ttsPath; } public void setPlayCount(int count) { mLastProgress = count; } public void setPlayVolume(int volume) { mPlayVolume = volume; } public void terminate() { mIsAlive = false; } public void resetPlayer() { mChimeUpDone = false; mChimeDownDone = false; mProgress = 0; mLastProgress = 0; mTTSPath = null; } public void setPlayMode(String mode) { mPlayMode = mode; } public void setPlayTarget(String target) { mPlayTarget = target; } public void playAssetAudio(String assetName) { // try { // if(!assetName.endsWith(".wav")) // assetName += ".wav"; // // AssetFileDescriptor afd = getAssets().openFd(assetName); // mMediaPlayer.reset(); // mMediaPlayer.setDataSource(afd); // afd.close(); // mMediaPlayer.prepare(); // mMediaPlayer.start(); // } catch (IOException e) { // e.printStackTrace(); // } if(!assetName.endsWith(".wav")) assetName += ".wav"; playExoWithAsset(assetName); } public void playExoWithAsset(final String urlName) { runOnUiThread(new Runnable() { @Override public void run() { MediaSource mediaSource = buildMediaSource(urlName); mExoPlayer.setMediaSource(mediaSource); mExoPlayer.prepare(); mExoPlayer.play(); } }); } public void playExoWithUrl(final String urlName) { runOnUiThread(new Runnable() { @Override public void run() { MediaSource mediaSource = buildMediaSource(urlName); mExoPlayer.setMediaItem(MediaItem.fromUri(urlName)); mExoPlayer.prepare(); mExoPlayer.play(); } }); } public void playExoWithItem(final MediaItem item) { runOnUiThread(new Runnable() { @Override public void run() { mExoPlayer.setMediaItem(item); mExoPlayer.prepare(); mExoPlayer.play(); } }); } public void stopExoPlayer() { runOnUiThread(new Runnable() { @Override public void run() { mExoPlayer.stop(); //mExoPlayer.release(); } }); } public void playAudioPath(String urlName) { // try { // mMediaPlayer.reset(); // mMediaPlayer.setDataSource(urlName); // mMediaPlayer.prepare(); // mMediaPlayer.start(); // } catch (IOException e) { // e.printStackTrace(); // } playExoWithUrl(urlName); /* File file = new File(urlName); Uri fileUri = Uri.fromFile(file); MediaItem item = MediaItem.fromUri(fileUri); //mExoPlayer.setMediaSource(urlName); mExoPlayer.setMediaItem(item); mExoPlayer.prepare(); mExoPlayer.play(); */ } @Override public void run() { if(mPlayMode.equalsIgnoreCase("asset")) { playAssetAudio(mPlayTarget); return; } if(mPlayMode.equalsIgnoreCase("path")) { playAudioPath(mPlayTarget); return; } if(mTTSPath == null) return; mIsAlive = true; if(!mIsDeviceOSIC10) { setMainPlayerVolume(0); } else { setSpeakerVolume(mPlayVolume); String volume = SystemUtil.getConfigValue("dacvolume"); if(volume.length() == 0) { mLastDacVolume = 100; } } boolean allowUntrusted = true; OkHttpClient client = new OkHttpClient(); OkHttpClient.Builder clientBuilder = client.newBuilder().readTimeout(10, TimeUnit.SECONDS); if(allowUntrusted) { final TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() { @Override public X509Certificate[] getAcceptedIssuers() { X509Certificate[] cArrr = new X509Certificate[0]; return cArrr; } @Override public void checkServerTrusted(final X509Certificate[] chain, final String authType) throws CertificateException { } @Override public void checkClientTrusted(final X509Certificate[] chain, final String authType) throws CertificateException { } }}; try { SSLContext sslContext = SSLContext.getInstance("SSL"); sslContext.init(null, trustAllCerts, new SecureRandom()); clientBuilder.sslSocketFactory(sslContext.getSocketFactory()); HostnameVerifier hostnameVerifier = new HostnameVerifier() { @Override public boolean verify(String hostname, SSLSession session) { Log.d(TAG, "Trust Host :" + hostname); return true; } }; clientBuilder.hostnameVerifier( hostnameVerifier); } catch(Exception e) { e.printStackTrace(); } } OkHttpClient httpClient = clientBuilder.build(); CallbackToDownloadFile cb = new CallbackToDownloadFile("/mnt/obb", "tts.wav"); Request request = new Request.Builder() .url(mTTSPath) .build(); httpClient.newCall(request).enqueue(cb); /*int downloadId = PRDownloader.download(mTTSPath, "/mnt/obb", "tts.wav") .build() .setOnStartOrResumeListener(new OnStartOrResumeListener() { @Override public void onStartOrResume() { } }) .setOnPauseListener(new OnPauseListener() { @Override public void onPause() { } }) .setOnCancelListener(new OnCancelListener() { @Override public void onCancel() { } }) .setOnProgressListener(new OnProgressListener() { @Override public void onProgress(Progress progress) { } }) .start(new OnDownloadListener() { public void onDownloadComplete() { Log.i(TAG, "TTS Download Complete"); mDownloadStatus = DOWNLOAD_STATUS_SUCCESS; } @Override public void onError(Error error) { Log.w(TAG, "Error while TTS Download!"); mDownloadStatus = DOWNLOAD_STATUS_FAILED; } });*/ while(mDownloadStatus == DOWNLOAD_STATUS_PROCESS) { try { sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } if(!mIsAlive) { setTTSViewVisibility(false); setMainPlayerVolume(mVlcMaxVolume); return; } if(mDownloadStatus == DOWNLOAD_STATUS_FAILED) { setTTSViewVisibility(false); setMainPlayerVolume(mVlcMaxVolume); return; } if(mIsDeviceOSIC10) { mIsRitoPlayerOver = false; mPlayer.openUrl(0, "/system/media/upchimes.wav"); while (!mIsRitoPlayerOver) { try { sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } if (!mIsAlive) { mPlayer.stop(); setTTSViewVisibility(false); return; } } mProgress = 0; while (mProgress < mLastProgress) { int curProgress = mProgress; mIsRitoPlayerOver = false; mPlayer.openUrl(0, "/mnt/obb/tts.wav"); while (!mIsRitoPlayerOver) { try { sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } if (!mIsAlive) { mPlayer.stop(); setTTSViewVisibility(false); return; } } mProgress++; } mIsRitoPlayerOver = false; mPlayer.openUrl(0, "/system/media/downchimes.wav"); while (!mIsRitoPlayerOver) { try { sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } if (!mIsAlive) { mPlayer.stop(); setTTSViewVisibility(false); return; } } setTTSViewVisibility(false); } else { playAssetAudio("upchimes.wav"); while (!mChimeUpDone) { try { sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } if (!mIsAlive) { // mMediaPlayer.stop(); // mMediaPlayer.release(); stopExoPlayer(); setTTSViewVisibility(false); setMainPlayerVolume(mVlcMaxVolume); return; } } while (mProgress < mLastProgress) { int curProgress = mProgress; stopExoPlayer(); //mMediaPlayer.reset(); // try { // mMediaPlayer.setDataSource("/mnt/obb/tts.wav"); // mMediaPlayer.prepare(); // mMediaPlayer.start(); // } catch (IOException e) { // e.printStackTrace(); // } playAudioPath("/mnt/obb/tts.wav"); while (curProgress == mProgress) { try { sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } if (!mIsAlive) { //mMediaPlayer.stop(); stopExoPlayer(); //mMediaPlayer.release(); setTTSViewVisibility(false); setMainPlayerVolume(mVlcMaxVolume); return; } } try { sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } // try { // AssetFileDescriptor afd = getAssets().openFd("downchimes.wav"); // mMediaPlayer.reset(); // mMediaPlayer.setDataSource(afd); // afd.close(); // mMediaPlayer.prepare(); // mMediaPlayer.start(); // } catch (IOException e) { // e.printStackTrace(); // } playAssetAudio("downchimes.wav"); while (!mChimeDownDone) { try { sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } if (!mIsAlive) { stopExoPlayer(); // mMediaPlayer.stop(); // mMediaPlayer.release(); setTTSViewVisibility(false); setMainPlayerVolume(mVlcMaxVolume); return; } } stopExoPlayer(); // mMediaPlayer.stop(); // mMediaPlayer.release(); setTTSViewVisibility(false); setMainPlayerVolume(mVlcMaxVolume); } } } @Override public boolean onKeyUp(int keyCode, KeyEvent event) { Log.w(TAG, "keyUpCode : " + keyCode); if(event.getKeyCode() == KeyEvent.KEYCODE_BUTTON_12) { // VFD KEY OKAY long keyTime = SystemClock.uptimeMillis(); if(keyTime - mKeyPressTime > 2000) { //Log.w(TAG, "keyLongUpCode : " + keyCode); //mVfdManager.cancelVfdChangeMode(); //Log.w(TAG, "Vfd Change Mode Cancelled!"); } else { if(!mVfdManager.mVfdChangeMode) mVfdManager.toggleVfdChangeMode(); else mVfdManager.cancelVfdChangeMode(); // short OKAY Key -> Cancel //Log.w(TAG, "keyUpCode : " + keyCode); // if(mVfdManager.mVfdConfirmMode) { // mVfdManager.confirmSettingValue(); // mVfdManager.mVfdChangeMode = false; // mVfdManager.mVfdConfirmMode = false; // } else { // mVfdManager.toggleVfdChangeMode(); // } } mKeyPressTime = 0; return true; } else if(event.getKeyCode() == KeyEvent.KEYCODE_CHANNEL_UP) { // CHANNEL-UP if(mJsonScheduler != null) { mJsonScheduler.advancePlayNext(1); } return true; } else if(event.getKeyCode() == KeyEvent.KEYCODE_CHANNEL_DOWN) { // CHANNEL-DOWN if(mJsonScheduler != null) { mJsonScheduler.advancePlayNext(-1); } return true; } return super.onKeyUp(keyCode, event); } public void sendMqttMsg(String topic, String message) { Log.w("MQTT", "[SEND] <" + topic + "> " + message); MqttMessage mqttMsg = new MqttMessage(message.getBytes()); try { mqttAndroidClient.publish(topic, mqttMsg); } catch (MqttException e) { throw new RuntimeException(e); } } public void handleDsrConfirm() { try { JSONObject topObject = new JSONObject(); topObject.put("status", "confirm"); topObject.put("ward_id", mWardId); topObject.put("dsr_seq", mDsrSeq); sendMqttMsg("ebcast/device/notify", topObject.toString()); mDsrSeq = ""; } catch(Exception e) { } } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if(event.getKeyCode() != 199) { Log.w(TAG, "keyCode : " + keyCode); } if(mWardId != null && mWardId.length() > 0 && mDsrSeq != null && mDsrSeq.length() > 0) { if(event.getKeyCode() == KeyEvent.KEYCODE_DPAD_CENTER) { // 지령 확인 handleDsrConfirm(); } } if(event.getKeyCode() == 200) { // VFD KEY LEFT //mVfdManager.vfdDrawString(getIPAddress(), 1, mVfdManager.VFD_ALIGN_CENTER); mVfdManager.moveSettingMode(-1); return true; } else if(event.getKeyCode() == 201) { // VFD KEY RIGHT mVfdManager.moveSettingMode(1); return true; } else if(event.getKeyCode() == 202) { // VFD KEY UP mVfdManager.changeSettingValue(1); return true; } else if(event.getKeyCode() == 203) { // VFD KEY DOWN mVfdManager.changeSettingValue(-1); return true; } else if(event.getKeyCode() == 199) { // VFD KEY OKAY //mVfdManager.toggleVfdChangeMode(); if(mKeyPressTime == 0) { mKeyPressTime = SystemClock.uptimeMillis(); } else { if(SystemClock.uptimeMillis() - mKeyPressTime > 2000) { //mVfdManager.cancelVfdChangeMode(); if(mVfdManager.mVfdChangeMode) mVfdManager.toggleVfdChangeMode(); } } return true; } else if(event.getKeyCode() == 183) { // SETUP KEY Intent intent = new Intent(this, SettingActivity.class); startActivity(intent); return true; } else if(event.getKeyCode() == KeyEvent.KEYCODE_F12) { // Volume-Up String volume = SystemUtil.getConfigValue("spkvolume"); if(volume.length() == 0) { volume = "100"; } else { int volumeInt = Integer.parseInt(volume); volumeInt++; volume = "" + volumeInt; } SystemUtil.setConfigValue("spkvolume", volume); return true; } else if(event.getKeyCode() == KeyEvent.KEYCODE_F11) { // Volume-Down String volume = SystemUtil.getConfigValue("spkvolume"); if(volume.length() == 0) { volume = "99"; } else { int volumeInt = Integer.parseInt(volume); volumeInt--; if(volumeInt < 0) volumeInt = 0; volume = "" + volumeInt; } SystemUtil.setConfigValue("spkvolume", volume); return true; } else if(event.getKeyCode() == KeyEvent.KEYCODE_PROG_YELLOW) { // Video-Volume-down String volume = SystemUtil.getConfigValue("videovolume"); if(volume.length() == 0) { volume = "11"; } else { int volumeInt = Integer.parseInt(volume); volumeInt--; if(volumeInt < 1) volumeInt = 1; volume = "" + volumeInt; } SystemUtil.setConfigValue("videovolume", volume); return true; } else if(event.getKeyCode() == KeyEvent.KEYCODE_PROG_BLUE) { // Volume-Volume-Up String volume = SystemUtil.getConfigValue("videovolume"); if(volume.length() == 0) { volume = "13"; } else { int volumeInt = Integer.parseInt(volume); volumeInt++; if(volumeInt >= 15) volumeInt = 15; volume = "" + volumeInt; } SystemUtil.setConfigValue("videovolume", volume); return true; } return false; } public void setWaitViewVisibility(final boolean show) { final ImageView view = (ImageView)findViewById(R.id.imageViewWait); if(show) { if(view.getAlpha() == 0.0f) { runOnUiThread(new Runnable() { @Override public void run() { view.setAlpha(1.0f); } }); } } else { if(view.getAlpha() != 0.0f) { runOnUiThread(new Runnable() { @Override public void run() { view.setAlpha(0.0f); } }); } } // runOnUiThread(new Runnable() { // @Override // public void run() { // if(show) { // view.setAlpha(1.0f); // } else { // view.setAlpha(0.0f); // } // } // }); } public void setTTSViewVisibility(final boolean show) { if(mIsDeviceOSIC10) { mIsOnTTSPlaying = show; return; } runOnUiThread(new Runnable() { @Override public void run() { ImageView view = (ImageView)findViewById(R.id.imageViewTts); if(show) { view.setAlpha(1.0f); mIsOnTTSPlaying = true; } else { view.setAlpha(0.0f); mIsOnTTSPlaying = false; } } }); } public void setWebViewUrl(String url) { WebView view = (WebView)findViewById(R.id.webview); view.loadUrl(url); } public void setWebViewVisibility(final boolean show) { runOnUiThread(new Runnable() { @Override public void run() { WebView view = (WebView)findViewById(R.id.webview); if(show) { view.setVisibility(View.VISIBLE); view.setAlpha(1.0f); } else { view.setAlpha(0.0f); } } }); } public void setWebViewLoadingVisibility(final boolean show) { final ImageView view = (ImageView)findViewById(R.id.imageViewLoading); if(show) { if(view.getAlpha() == 0.0f) { runOnUiThread(new Runnable() { @Override public void run() { view.setAlpha(1.0f); } }); } } else { if(view.getAlpha() != 0.0f) { runOnUiThread(new Runnable() { @Override public void run() { view.setAlpha(0.0f); } }); } } } public void setMainPlayerVolume(int volume) { if(USING_MAIN_PLAYER_LIBRARY_TYPE == PLAYER_LIBRARY_TYPE_VLC) { if(mVlcPlayer != null) { mVlcVolume = volume; mVlcPlayer.setVolume(volume); //Log.i(TAG, "VLC Volume Setting : " + volume); if(mIsDeviceOSIC10) { AudioManager audioManager = (AudioManager) this.getSystemService(Context.AUDIO_SERVICE); if (volume == 0) { //audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, 0, 0); audioManager.adjustStreamVolume(AudioManager.STREAM_MUSIC, AudioManager.ADJUST_MUTE, 0); } else { audioManager.adjustStreamVolume(AudioManager.STREAM_MUSIC, AudioManager.ADJUST_UNMUTE, 0); } } } } } /* 표시 버전 1 */ public void handleNotifyScreenOrder(String msgType, final String msgDatetime, final String msgAddress, final String msgDesc, String msgVehicle) { final String msgTypeShow; final Bitmap bitmap; if(msgType.equalsIgnoreCase("fire")) { bitmap = BitmapFactory.decodeFile("/mnt/sdcard/osic/fire.png"); shellCommand("miscctrl function_led red on"); msgTypeShow = "화재"; } else if(msgType.equalsIgnoreCase("emergency")) { bitmap = BitmapFactory.decodeFile("/mnt/sdcard/osic/emer.png"); shellCommand("miscctrl function_led green on"); msgTypeShow = "구급"; } else if(msgType.equalsIgnoreCase("rescue")) { bitmap = BitmapFactory.decodeFile("/mnt/sdcard/osic/rescue.png"); shellCommand("miscctrl function_led red on"); shellCommand("miscctrl function_led green on"); msgTypeShow = "구조"; } else { bitmap = BitmapFactory.decodeFile("/mnt/sdcard/osic/general.png"); msgTypeShow = "일반"; shellCommand("miscctrl function_led blue on"); } final String msgVehicleShow = msgVehicle.replace('|', '\n'); runOnUiThread(new Runnable() { @Override public void run() { ImageView imageView = findViewById(R.id.imageViewCmdBack); imageView.setImageBitmap(bitmap); imageView.setVisibility(View.VISIBLE); SurfaceView surfaceView = findViewById(R.id.surfaceViewCmd); surfaceView.setVisibility(View.VISIBLE); surfaceView.setZOrderOnTop(true); surfaceView.getHolder().setFormat(PixelFormat.TRANSPARENT); Canvas canvas = surfaceView.getHolder().lockCanvas(); if(canvas != null) { float textSize = 50; float textBaseX = 470; float textBaseY = 145; Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); paint.setColor(Color.BLACK); //paint.setTextSize(48); paint.setTextSize(textSize); paint.setFakeBoldText(true); paint.setTextAlign(Paint.Align.LEFT); // Rect bounds = new Rect(); // paint.getTextBounds(text, 0, text.length(), bounds); // // Calculate the desired size as a proportion of our testTextSize. // float desiredTextSize = testTextSize * desiredWidth / bounds.width(); // // Set the paint for that size. // paint.setTextSize(desiredTextSize); float gap = 92; //canvas.drawText("종별종별종별", 470, 160, paint); canvas.drawText(msgTypeShow, textBaseX, textBaseY - ((paint.descent() + paint.ascent()) / 2), paint); canvas.drawText(msgDatetime, textBaseX, textBaseY - ((paint.descent() + paint.ascent()) / 2) + gap, paint); canvas.drawText(msgAddress, textBaseX, textBaseY - ((paint.descent() + paint.ascent()) / 2) + gap * 2, paint); //canvas.drawText(msgDesc, textBaseX, textBaseY - ((paint.descent() + paint.ascent()) / 2) + gap * 3, paint); textSize = 50; do { TextPaint textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); textPaint.setColor(Color.BLACK); textPaint.setTextSize(textSize); textPaint.setFakeBoldText(true); textPaint.setTextAlign(Paint.Align.LEFT); StaticLayout textLayout = new StaticLayout(msgDesc, textPaint, 930, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); if(textLayout.getHeight() > 180) { textSize -= 1; continue; } canvas.save(); canvas.translate(textBaseX, textBaseY + gap * 3 - 25); textLayout.draw(canvas); canvas.restore(); break; } while(true); //canvas.drawText(msgVehicleShow, textBaseX, textBaseY - ((paint.descent() + paint.ascent()) / 2) + gap * 5 + 10, paint); textSize = 50; do { TextPaint textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); textPaint.setColor(Color.BLACK); textPaint.setTextSize(textSize); textPaint.setFakeBoldText(true); textPaint.setTextAlign(Paint.Align.LEFT); StaticLayout textLayout = new StaticLayout(msgVehicleShow, textPaint, 930, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); if(textLayout.getHeight() > 370) { textSize -= 1; continue; } canvas.save(); canvas.translate(textBaseX, textBaseY + gap * 5 - 25); textLayout.draw(canvas); canvas.restore(); break; } while(true); surfaceView.getHolder().unlockCanvasAndPost(canvas); } else { Log.w(TAG, "Canvas is null!"); } findViewById(R.id.layoutCommand).setVisibility(View.VISIBLE); //findViewById(R.id.layoutCommand).setAlpha(1.0f); mNotifyMsgStartTime = SystemClock.uptimeMillis(); mIsOnNotifyMsg = true; if(USING_MAIN_PLAYER_LIBRARY_TYPE == PLAYER_LIBRARY_TYPE_VLC) { if(mVlcPlayer != null) { setMainPlayerVolume(0); } } //bitmap.recycle(); // findViewById(R.id.layoutCommand).bringToFront(); // findViewById(R.id.layoutCommand).setZ(500); } }); } /* 표시 버전 2 */ public void handleNotifyScreenOrder(String msgType, final String msgDsrClass, final String msgDsrSize, final String msgDatetime, final String msgAddressDoro, final String msgAddressJibun, final String msgDesc, String msgVehicle) { final String msgTypeShow; final Bitmap bitmap; if(msgType.equalsIgnoreCase("fire")) { bitmap = BitmapFactory.decodeFile("/mnt/sdcard/osic/fire.png"); shellCommand("miscctrl function_led green off"); shellCommand("miscctrl function_led blue off"); shellCommand("miscctrl function_led red on"); } else if(msgType.equalsIgnoreCase("emergency")) { bitmap = BitmapFactory.decodeFile("/mnt/sdcard/osic/emer.png"); shellCommand("miscctrl function_led red off"); shellCommand("miscctrl function_led blue off"); shellCommand("miscctrl function_led green on"); } else if(msgType.equalsIgnoreCase("rescue")) { bitmap = BitmapFactory.decodeFile("/mnt/sdcard/osic/rescue.png"); shellCommand("miscctrl function_led blue off"); shellCommand("miscctrl function_led red on"); shellCommand("miscctrl function_led green on"); } else { bitmap = BitmapFactory.decodeFile("/mnt/sdcard/osic/general.png"); shellCommand("miscctrl function_led red off"); shellCommand("miscctrl function_led green off"); shellCommand("miscctrl function_led blue on"); } final String msgVehicleShow = msgVehicle.replace("|", ", "); runOnUiThread(new Runnable() { @Override public void run() { ImageView imageView = findViewById(R.id.imageViewCmdBack); imageView.setImageBitmap(bitmap); imageView.setVisibility(View.VISIBLE); SurfaceView surfaceView = findViewById(R.id.surfaceViewCmd); surfaceView.setVisibility(View.VISIBLE); new Thread() { @Override public void run() { try { SurfaceView surfaceView = findViewById(R.id.surfaceViewCmd); surfaceView.setZOrderOnTop(true); surfaceView.getHolder().setFormat(PixelFormat.TRANSPARENT); Canvas canvas = surfaceView.getHolder().lockCanvas(); if (canvas != null) { float textClassSize = 96; float textClassBaseX = 1430; float textClassBaseY = 125; float textSize = 46; float textBaseX = 360; float textBaseY = 215; Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR); paint.setFakeBoldText(true); paint.setTextAlign(Paint.Align.CENTER); paint.setColor(Color.WHITE); do { TextPaint textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); textPaint.setColor(Color.BLACK); textPaint.setTextSize(textClassSize); textPaint.setTextAlign(Paint.Align.LEFT); float textWidth = textPaint.measureText(msgDsrClass); if (textWidth > 910) { textClassSize -= 1; continue; } break; } while (true); paint.setTextSize(textClassSize); canvas.drawText(msgDsrClass, textClassBaseX, textClassBaseY, paint); paint.setTextAlign(Paint.Align.LEFT); paint.setColor(Color.BLACK); paint.setTextSize(textSize); float gap = 75; canvas.drawText(msgDatetime, textBaseX, textBaseY - ((paint.descent() + paint.ascent()) / 2), paint); canvas.drawText(msgDsrSize, textBaseX + 930, textBaseY - ((paint.descent() + paint.ascent()) / 2), paint); canvas.drawText(msgAddressDoro, textBaseX, textBaseY - ((paint.descent() + paint.ascent()) / 2) + gap, paint); canvas.drawText(msgAddressJibun, textBaseX, textBaseY - ((paint.descent() + paint.ascent()) / 2) + gap * 2, paint); textSize = 50; do { TextPaint textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); textPaint.setColor(Color.BLACK); textPaint.setTextSize(textSize); textPaint.setFakeBoldText(true); textPaint.setTextAlign(Paint.Align.LEFT); StaticLayout textLayout = new StaticLayout(msgDesc, textPaint, 1200, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); if (textLayout.getHeight() > 320) { textSize -= 1; continue; } int layoutHeight = textLayout.getHeight(); canvas.save(); canvas.translate(textBaseX, textBaseY + gap * 3 - 30 + (320 - layoutHeight) / 2); textLayout.draw(canvas); canvas.restore(); break; } while (true); //canvas.drawText(msgVehicleShow, textBaseX, textBaseY - ((paint.descent() + paint.ascent()) / 2) + gap * 5 + 10, paint); textSize = 50; do { TextPaint textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); textPaint.setColor(Color.BLACK); textPaint.setTextSize(textSize); textPaint.setFakeBoldText(true); textPaint.setTextAlign(Paint.Align.LEFT); //StaticLayout textLayout = new StaticLayout(msgVehicleShow, textPaint, 530, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); StaticLayout.Builder builder = StaticLayout.Builder.obtain(msgVehicleShow, 0, msgVehicleShow.length(), textPaint, 1200) .setAlignment(Layout.Alignment.ALIGN_NORMAL) .setLineSpacing(0.0f, 1.0f) .setIncludePad(false) .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE) .setBreakStrategy(LineBreaker.BREAK_STRATEGY_SIMPLE) .setMaxLines(5); StaticLayout textLayout = builder.build(); if (textLayout.getHeight() > 200) { textSize -= 1; continue; } int layoutHeight = textLayout.getHeight(); canvas.save(); canvas.translate(textBaseX, textBaseY + gap * 7 + 10 + (210 - layoutHeight) / 2); textLayout.draw(canvas); canvas.restore(); break; } while (true); surfaceView.getHolder().unlockCanvasAndPost(canvas); Log.w(TAG, "======================"); Log.w(TAG, " 지령표출화면 표시시작 "); Log.w(TAG, "======================"); } else { Log.w(TAG, "Canvas is null!"); } } catch(Exception e) { e.printStackTrace(); } } }.start(); findViewById(R.id.layoutCommand).setVisibility(View.VISIBLE); mNotifyMsgStartTime = SystemClock.uptimeMillis(); mIsOnNotifyMsg = true; if(USING_MAIN_PLAYER_LIBRARY_TYPE == PLAYER_LIBRARY_TYPE_VLC) { if(mVlcPlayer != null) { setMainPlayerVolume(0); } } } }); } public void doStoredScheduleUpdate(String target) { if(target.equalsIgnoreCase("ip")) { JsonResult jsonResult = JsonManager.loadJsonData("ip-schedule.json"); if (jsonResult != null) { MainActivity.INSTANCE.mJsonScheduler.updateJsonTargetResult("ip", jsonResult); } } else if(target.equalsIgnoreCase("file")) { JsonResult jsonResult = JsonManager.loadJsonData("file-schedule.json"); if (jsonResult != null) { MainActivity.INSTANCE.mJsonScheduler.updateJsonTargetResult("file", jsonResult); } } } private void setupVlcMediaOption(Media m) { String optValue = SystemUtil.property_get("sys.rito.net.cache"); if(optValue == null || optValue.length() == 0) optValue = "" + VLC_NETWORK_CACHE_DEFAULT; m.addOption(":network-caching=" + optValue); optValue = SystemUtil.property_get("sys.rito.live.cache"); if(optValue == null || optValue.length() == 0) optValue = "" + VLC_LIVE_CACHE_DEFAULT; m.addOption(":live-caching=" + optValue); optValue = SystemUtil.property_get("sys.rito.udp.buffer"); if(optValue == null || optValue.length() == 0) optValue = "" + VLC_UDP_BUFFER_DEFAULT; m.addOption(":udp-buffer=" + optValue); m.addOption(":clock-jitter=0"); m.addOption(":clock-synchro=0"); } public void nativeNotify(int code, String info) { Log.w(TAG, "NOTIFY Code : " + code + ", Info : " + info); if(code == MANAGER_NOTIFY_ORDER_START_PLAYBACK) { if(mIsDeviceOSIC10) { if (SystemUtil.APP_MODE.equals("active")) { // Browser Mode 인 경우 return; // 서버로 부터 재생 명령 무시 } } if(USING_MAIN_PLAYER_LIBRARY_TYPE == PLAYER_LIBRARY_TYPE_RITO) { mPlayer.stop(); String[] cutInfo = info.split(" "); if (cutInfo[0].startsWith("mc://")) { cutInfo[0] = cutInfo[0].replace("mc://", "udp://"); cutInfo[0] = cutInfo[0].replace("_", ":"); } SurfaceView view = findViewById(R.id.playerView); mPlayer.mSurfaceView = view; mPlayer.openUrl(0, cutInfo[0]); } else if(USING_MAIN_PLAYER_LIBRARY_TYPE == PLAYER_LIBRARY_TYPE_VLC) { String[] cutInfo = info.split(" "); if (cutInfo[0].startsWith("mc://")) { cutInfo[0] = cutInfo[0].replace("mc://", "udp://"); // if(!cutInfo[0].contains("@")) { // cutInfo[0] = cutInfo[0].replace("udp://", "udp://@"); // } cutInfo[0] = cutInfo[0].replace("_", ":").trim(); String[] partSplit = cutInfo[0].substring(6).split(":"); if(!partSplit[0].startsWith("2")) { cutInfo[0] = "udp://@:" + partSplit[1]; } else { cutInfo[0] = "udp://@" + partSplit[0] + ":" + partSplit[1]; } } else if (cutInfo[0].startsWith("hsact://")) { cutInfo[0] = cutInfo[0].replace("hsact://", "rtsp://").trim(); } Log.w(TAG, "VLCPlayer URL : " + cutInfo[0]); mLastPlayUrl = cutInfo[0]; if(mCurrentPlayUrl == null || !cutInfo[0].equals(mCurrentPlayUrl)) { mVlcPlayer.stop(); Media m = new Media(mVLC, Uri.parse(cutInfo[0])); if(mIsDeviceOSIC10) { setupVlcMediaOption(m); } mVlcPlayer.setMedia(m); mVLCMedia = m; mVlcPlayer.play(); mCurrentPlayUrl = cutInfo[0]; } } setTTSViewVisibility(false); setWaitViewVisibility(false); } else if(code == MANAGER_NOTIFY_ORDER_STOP_PLAYBACK) { if(USING_MAIN_PLAYER_LIBRARY_TYPE == PLAYER_LIBRARY_TYPE_RITO) { mPlayer.stop(); } else if(USING_MAIN_PLAYER_LIBRARY_TYPE == PLAYER_LIBRARY_TYPE_VLC) { if(mIsDeviceOSIC10) { mLastPlayUrl = null; } mVlcPlayer.stop(); try { AssetFileDescriptor afd = getAssets().openFd("blackground.png"); mVlcPlayer.play(afd); } catch(Exception e) { } } if(!SystemUtil.APP_MODE.equals("active")) { // Browser Mode 아닌경우 setWaitViewVisibility(true); } /*MediaPlayer player = MediaPlayer.create(this, R.raw.upchimes); player.start();*/ /*MediaPlayer player2 = MediaPlayer.create(this, R.raw.downchimes); player2.start();*/ } else if(code == MANAGER_NOTIFY_ORDER_START_TTS) { if(mTTSPlayer != null) { mTTSPlayer.terminate(); } mTTSPlayer = new AudioFilePlayer(); mTTSPlayer.resetPlayer(); String[] tokenList = info.split("\r\n"); for(String token : tokenList) { String[] split = token.split("="); if(split.length == 2) { if(split[0].equalsIgnoreCase("URL")) { mTTSPlayer.setDownloadPath(split[1]); } else if(split[0].equalsIgnoreCase("COUNT")) { mTTSPlayer.setPlayCount(Integer.parseInt(split[1])); } else if(split[0].equalsIgnoreCase("TTS_VOLUME")) { mTTSPlayer.setPlayVolume(Integer.parseInt(split[1])); } } } /* if(USING_MAIN_PLAYER_LIBRARY_TYPE == PLAYER_LIBRARY_TYPE_RITO) { mPlayer.stop(); } else if(USING_MAIN_PLAYER_LIBRARY_TYPE == PLAYER_LIBRARY_TYPE_VLC) { mVlcPlayer.stop(); } */ setTTSViewVisibility(true); mTTSPlayer.start(); } else if(code == MANAGER_NOTIFY_ORDER_CEC_CONTROL) { if(info.equalsIgnoreCase("on")) { Intent intent = new Intent("kr.co.rito.factory.setting"); //intent.setClassName("kr.co.rito.factory", "SettingChanger"); intent.setComponent(new ComponentName("kr.co.rito.factory", "kr.co.rito.factory.SettingChanger")); intent.putExtra("TYPE", "CecControl"); intent.putExtra("ORDER", "active"); sendBroadcast(intent); } else if(info.equalsIgnoreCase("off")) { Intent intent = new Intent("kr.co.rito.factory.setting"); intent.setComponent(new ComponentName("kr.co.rito.factory", "kr.co.rito.factory.SettingChanger")); intent.putExtra("TYPE", "CecControl"); intent.putExtra("ORDER", "standby"); sendBroadcast(intent); } } else if(code == MANAGER_NOTIFY_ORDER_START_TICKER) { String _text = ""; int _x, _y, _width, _height; int _fcolor, _bcolor, _count; int _speed; _x = _y = _width = _height = _fcolor = _bcolor = _count = _speed = 0; String[] tokenList = info.split("\r\n"); for(String token : tokenList) { String[] split = token.split("="); if(split.length == 2) { if(split[0].equalsIgnoreCase("X")) { _x = Integer.parseInt(split[1]); } else if(split[0].equalsIgnoreCase("Y")) { _y = Integer.parseInt(split[1]); } else if(split[0].equalsIgnoreCase("WIDTH")) { _width = Integer.parseInt(split[1]); } else if(split[0].equalsIgnoreCase("HEIGHT")) { _height = Integer.parseInt(split[1]); } else if(split[0].equalsIgnoreCase("SPEED")) { _speed = Integer.parseInt(split[1]); } else if(split[0].equalsIgnoreCase("COUNT")) { _count = Integer.parseInt(split[1]); } else if(split[0].equalsIgnoreCase("FORE_COLOR")) { _fcolor = Integer.parseInt(split[1]); } else if(split[0].equalsIgnoreCase("BACK_COLOR")) { _bcolor = Integer.parseInt(split[1]); } else if(split[0].equalsIgnoreCase("TEXT")) { _text = split[1]; // try { // _text = new String(split[1].getBytes("UTF-8")); // } catch (UnsupportedEncodingException e) { // e.printStackTrace(); // } } } } _x = _x * 1920 / 1280; _y = _y * 1080 / 720; _width = _width * 1920 / 1280; _height = _height * 1080 / 720; mTickerManager.setupTicker(_text, new Rect(_x, _y, _x + _width, _y + _height), _fcolor, _bcolor, _count, (float)_speed); mTickerManager.renderTicker(); } else if(code == MANAGER_NOTIFY_ORDER_JSON_ORDER) { String jsonUrl = null; String jsonType = null; String[] tokenList = info.split("\r\n"); for(String token : tokenList) { String[] split = token.split("="); if(split.length == 2) { if(split[0].equalsIgnoreCase("URL")) { jsonUrl = split[1]; } else if(split[0].equalsIgnoreCase("TYPE")) { jsonType = split[1]; } } } Log.w(TAG, "JSON TYPE : " + jsonType + ", JSON URL : " + jsonUrl); JsonManager jsonManager = new JsonManager(this); jsonManager.setDownloadPath( "http://" + getServerAddress() + "/" + jsonUrl); jsonManager.start(); } else if(code == MANAGER_NOTIFY_ORDER_NOTIFY_SCREEN_ORDER) { Log.w(TAG, "Got Notify Screen Message : " + info); String msgType = ""; String msgDatetime = ""; String msgAddress = ""; String msgDesc = ""; String msgVehicle = ""; String msgAddressDoro = ""; String msgAddressJibun = ""; String msgDsrClass = ""; String msgDsrSize = ""; String[] tokenList = info.split("\r\n"); for(String token : tokenList) { String[] split = token.split("="); if(split.length == 2) { if(split[0].equalsIgnoreCase("MSGTYPE")) { msgType = split[1]; } else if(split[0].equalsIgnoreCase("DATETIME")) { msgDatetime = split[1]; } else if(split[0].equalsIgnoreCase("ADDRESS")) { msgAddress = split[1]; } else if(split[0].equalsIgnoreCase("ADDRESS-DORO")) { msgAddressDoro = split[1]; } else if(split[0].equalsIgnoreCase("ADDRESS-JIBUN")) { msgAddressJibun = split[1]; } else if(split[0].equalsIgnoreCase("CLASS")) { msgDsrClass = split[1]; } else if(split[0].equalsIgnoreCase("SIZE")) { msgDsrSize = split[1]; } else if(split[0].equalsIgnoreCase("DESC")) { msgDesc = split[1]; } else if(split[0].equalsIgnoreCase("VEHICLE")) { msgVehicle = split[1]; } } } /* For Demo Perpose - 2023-09-19 */ /* msgType = "general"; msgDatetime = "2023년 9월 21일"; msgDsrClass = ""; msgDsrSize = "메이저"; msgAddressDoro = "192.168.1.100"; // IP주소 msgAddressJibun = "본청 방송실"; // 대상기관 msgDesc = "비정상적 파일시스템 용량 증가 및 네트워크 트래픽 증가"; msgVehicle = "PC악성 코드 감염 의심|네트워크 분리 및 백신 검사 필요|시스템 로그 분석 필요"; */ if(msgAddress != null && msgAddress.length() > 0) { handleNotifyScreenOrder(msgType, msgDatetime, msgAddress, msgDesc, msgVehicle); } else { handleNotifyScreenOrder(msgType, msgDsrClass, msgDsrSize, msgDatetime, msgAddressDoro, msgAddressJibun, msgDesc, msgVehicle); // Notify Screen Chime AudioFilePlayer chimePlayer = new AudioFilePlayer(); chimePlayer.setPlayMode("asset"); if(msgType.equalsIgnoreCase("fire")) { chimePlayer.setPlayTarget("fire"); } else if(msgType.equalsIgnoreCase("emergency")) { chimePlayer.setPlayTarget("emergency"); } else if(msgType.equalsIgnoreCase("rescue")) { chimePlayer.setPlayTarget("rescue"); } else { chimePlayer.setPlayTarget("general"); } chimePlayer.start(); } } else if(code == MANAGER_NOTIFY_ORDER_EVENT_MESSAGE) { //Log.w(TAG, "Got Event Message : " + info); String evtType = null; String evtClassId = null; String evtBaseUrl = null; String evtJsonRaw = null; String[] tokenList = info.split("\r\n"); for(String token : tokenList) { String[] split = token.split("="); if(split.length == 2) { if(split[0].equalsIgnoreCase("EVENT")) { evtType = split[1]; } else if(split[0].equalsIgnoreCase("CLASS_ID")) { evtClassId = split[1]; } else if(split[0].equalsIgnoreCase("BASE_URL")) { evtBaseUrl = split[1]; } else if(split[0].equalsIgnoreCase("JSON_RAW")) { evtJsonRaw = split[1]; } } } if(evtType.equalsIgnoreCase("image-update")) { if (mFileDownloader != null) { String[] downList = {"fire.png", "rescue.png", "emer.png", "general.png"}; try { String topClass = evtClassId.substring(0, 2) + "0000"; for (String target : downList) { mFileDownloader.addDownloadTarget(evtBaseUrl + "/" + topClass + "-" + target, MainActivity.INSTANCE.mEmmcSavePath, target); } } catch(Exception e) { e.printStackTrace(); } } } else if(evtType.equalsIgnoreCase("channel-update")) { //Log.w(TAG, "JSON RAW : " + evtJsonRaw); try { JSONObject topObject = new JSONObject(evtJsonRaw); JSONArray jsonArray = topObject.getJSONArray("data"); for(int i = 0;i < jsonArray.length();i++) { JSONObject jo = jsonArray.getJSONObject(i); //Log.w(TAG, "Address : " + jo.getString("address")); } File saveFile = new File(MainActivity.INSTANCE.mSDSavePath + "/ip-schedule.json"); if(saveFile.exists()) saveFile.delete(); try { saveFile.createNewFile(); OutputStream os = new FileOutputStream(saveFile); byte[] evtData = evtJsonRaw.getBytes("utf-8"); os.write(evtData, 0, evtData.length); os.flush(); os.close(); } catch (IOException e) { } MainActivity.INSTANCE.doSync(); doStoredScheduleUpdate("ip"); } catch(Exception e) { e.printStackTrace(); } } } } @Override public void onPause() { terminateService(); super.onPause(); } @Override protected void onStart() { super.onStart(); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION); } RitoWebPlayerInterface ritoWebPlayerInterface; RitoWebSystemInterface ritoWebSystemInterface; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION); setContentView(R.layout.activity_main); mChannelOsdView = findViewById(R.id.textViewChannelOsd); mChannelOsdImageView = findViewById(R.id.imageViewChannelOsd); mImageViewBlack = findViewById(R.id.imageViewBlack); mProgressBar = findViewById(R.id.progressBar); mCarCastTitleView = findViewById(R.id.textViewCarcast); mJsonResult = null; mJsonIpSchedule = null; mJsonFileSchedule = null; INSTANCE = this; mManagerActMode = MANAGER_ACTION_MODE_STANDBY; //SystemUtil.logStart(); mIsDeviceOSIC10 = SystemUtil.property_get("rito.device.type").equalsIgnoreCase("osic10"); if(!mIsDeviceOSIC10) { ImageView imgView = findViewById(R.id.imageViewWait); imgView.setImageResource(R.drawable.no_broadcast); } mSDCardPath = SystemUtil.getSDCardPath(); mEmmcSavePath = Environment.getExternalStorageDirectory().getPath() + "/osic"; // PRDownloaderConfig config = PRDownloaderConfig.newBuilder() // .setReadTimeout(30_000) // .setConnectTimeout(30_000) // .build(); // PRDownloader.initialize(getApplicationContext(), config); mTickerManager = new TickerManager(this, (TextView)findViewById(R.id.textViewTicker)); mVfdManager = new VfdManager(); mVfdManager.start(); mSystemManager = new SystemManager(); //mSystemManager.initialize(); //mSystemManager.activateCpuFan(true); mSystemManager.start(); String fancontrol = getConfigValue("fancontrol"); if(!fancontrol.equals("0")) { mCoolerManager = new CoolerManager(); mCoolerManager.initialize(); mCoolerManager.start(); } else { mCoolerManager = new CoolerManager(); mCoolerManager.initialize(); mCoolerManager.activateCpuFan(false); } mFileDownloader = new FileDownloader(this); mFileDownloader.start(); int minBufferSize = AudioTrack.getMinBufferSize(EBCAST_SAMPLE_RATE, EBCAST_CHANNEL_CONFIG, EBCAST_AUDIO_FORMAT); mAudioTrack = new AudioTrack( AudioManager.STREAM_MUSIC, EBCAST_SAMPLE_RATE, EBCAST_CHANNEL_CONFIG, EBCAST_AUDIO_FORMAT, minBufferSize, AudioTrack.MODE_STREAM ); mAudioTrack.play(); // mTTSPlayer = new AudioFilePlayer(); // mTTSPlayer.setDownloadPath("http://192.168.1.60/test.mp3"); // mTTSPlayer.setPlayCount(3); // mTTSPlayer.start(); /*mTTSPlayer.setDownloadPath("http://192.168.1.75/Factory.tgz"); mTTSPlayer.setDownloadPath("https://support.google.com/websearch/answer/1325808"); mTTSPlayer.start();*/ if(USING_MAIN_PLAYER_LIBRARY_TYPE == PLAYER_LIBRARY_TYPE_RITO) { mPlayerNotify = new RitoPlayer.playerNotify() { @Override public void notify(int code, String info) { Log.i("RitoMain", "NOTIFY Code : " + code); if (code == RitoPlayer.PLAYER_NOTIFY_EOS) { //mPlayer.stop(); /*SurfaceView view = findViewById(R.id.surfaceView); mPlayer.mSurfaceView = view; mPlayer.openUrl(0, "http://219.255.217.140/ext/contents/Your_wedding.ts");*/ } } }; if (mPlayer == null) { mPlayer = new RitoPlayer(mPlayerNotify, 0); mPlayer.init(); } if (mAudioPlayer == null) { mAudioPlayer = new RitoPlayer(mPlayerNotify, 1); mAudioPlayer.init(); SystemUtil.setupAudioOut(1); mAudioSubOut = new RitoPlayer.AudioOut() { @Override public void writeSamples(byte[] bytes, int i) { if(mLastDacVolume > 0) { SystemUtil.adjustDataVolume(bytes, i, mLastDacVolume); //Log.i(TAG, "AudioPlayer AudioOut " + i + " bytes..."); SystemUtil.writeAudioOut(bytes, i); } } }; mAudioPlayer.setAudioOut(mAudioSubOut); mAudioPlayer.setAudioDirection(RitoPlayer.AUDIO_OUT_DIRECTION_AOUT); //mAudioPlayer.openUrl(1,"http://211.204.122.90/ext/contents/akdong.mp3"); } // SurfaceView view = findViewById(R.id.playerView); // mPlayer.mSurfaceView = view; mTexturePlayView = findViewById(R.id.texturePlayView); mTexturePlayView.setSurfaceTextureListener(this); mPlayer.mTextureView = mTexturePlayView; mPlayer.openUrl(0,"udp://127.0.0.1:5000"); //mPlayer.openUrl(0,"http://211.204.122.90/ext/contents/IU.mp4"); /*setWaitViewVisibility(false); mPlayer.openUrl(0,"http://219.255.217.140/ext/contents/IU.mp4");*/ //mPlayer.openUrl(0,"rtsp://gookmin.iptime.org:17100/Camera19"); } else if(USING_MAIN_PLAYER_LIBRARY_TYPE == PLAYER_LIBRARY_TYPE_VLC) { mSurface = findViewById(R.id.playerView); holder = mSurface.getHolder(); mTexturePlayView = findViewById(R.id.texturePlayView); mTexturePlayView.setSurfaceTextureListener(this); //mTexturePlayView.setVisibility(View.VISIBLE); String vlcMaxVolume = SystemUtil.property_get("sys.rito.volup.max"); if(vlcMaxVolume.length() > 0) { mVlcMaxVolume = Integer.parseInt(vlcMaxVolume); } else { mVlcMaxVolume = 100; } //createPlayer("rtsp://gookmin.iptime.org:17100/Camera19"); if(USING_PLAYER_VIEW_TYPE == PLAYER_VIEW_TYPE_SURFACE_VIEW) { createPlayer(null); } else { mSurface.setVisibility(View.INVISIBLE); } SystemUtil.setupAudioOut(1); mAudioSubOut = new RitoPlayer.AudioOut() { @Override public void writeSamples(byte[] bytes, int i) { if(mLastDacVolume > 0) { SystemUtil.adjustDataVolume(bytes, i, mLastDacVolume); SystemUtil.writeAudioOut(bytes, i); } } }; mPlayerNotify = new RitoPlayer.playerNotify() { @Override public void notify(int code, String info) { Log.i("RitoNotify", "NOTIFY Code : " + code); if (code == RitoPlayer.PLAYER_NOTIFY_EOS) { mIsRitoPlayerOver = true; } } }; if (mPlayer == null) { mPlayer = new RitoPlayer(mPlayerNotify); mPlayer.init(); mPlayer.setAudioOut(mAudioSubOut); mPlayer.setAudioDirection(RitoPlayer.AUDIO_OUT_DIRECTION_AOUT); //mPlayer.openUrl(0,"http://219.255.217.140/ext/contents/akdong.mp3"); } //createPlayer("http://219.255.217.140/ext/contents/IU.mp4"); //createPlayer("udp://@:1234"); //createPlayer("udp://@:5000"); //createPlayer("http://172.16.40.146/20211118044730.ts"); //createPlayer("http://192.168.1.20/20211118044730.ts"); //createPlayer("udp://@234.6.7.8:5000"); } setTTSViewVisibility(false); setWaitViewVisibility(true); //setWaitViewVisibility(false); mExoPlayer = new ExoPlayer.Builder(MainActivity.INSTANCE).build(); mExoPlayer.addListener(new Player.Listener() { @Override public void onTimelineChanged( Timeline timeline, @Player.TimelineChangeReason int reason) { Object manifest = mExoPlayer.getCurrentManifest(); if (manifest != null) { HlsManifest hlsManifest = (HlsManifest) manifest; // Do something with the manifest. } } @Override public void onPlayerError(PlaybackException error) { // 오류 처리 switch (error.errorCode) { case PlaybackException.ERROR_CODE_IO_NETWORK_CONNECTION_FAILED: // 네트워크 연결 오류 처리 Log.e("ExoPlayer", "Network connection error: " + error.getMessage()); break; case PlaybackException.ERROR_CODE_DECODING_FAILED: // 디코딩 오류 처리 Log.e("ExoPlayer", "Decoding error: " + error.getMessage()); break; default: // 그 외의 오류 처리 Log.e("ExoPlayer", "Playback error: " + error.getMessage()); break; } } @Override public void onPlaybackStateChanged(int playbackState) { if (playbackState == Player.STATE_ENDED) { // 재생 완료 이벤트 처리 } } }); mWardId = getConfigValue("ward_id"); mEbcastMqttIp = getConfigValue("ebcast_ip"); String app_mode = getConfigValue("app_mode"); SystemUtil.APP_MODE = app_mode; if(mIsDeviceOSIC10) { if (SystemUtil.APP_MODE.equals("active")) { // Browser Mode 인 경우 setWaitViewVisibility(false); WebView webview = (WebView) findViewById(R.id.webview); webview.setWebViewClient(new RitoWebViewClient()); webview.getSettings().setJavaScriptEnabled(true); ritoWebPlayerInterface = new RitoWebPlayerInterface(); ritoWebSystemInterface = new RitoWebSystemInterface(); webview.addJavascriptInterface(ritoWebSystemInterface, "system"); webview.addJavascriptInterface(ritoWebPlayerInterface, "player"); String value = SystemUtil.getConfigValue("svraddr"); //setWebViewUrl("http://" + value + "/stbpage/"); setWebViewUrl("http://" + value + "/stbpage/osic10.php"); // modified by ritoseo - 2023-05-21 setWebViewVisibility(true); setWebViewLoadingVisibility(true); } } if(mSDCardPath != null) { mSDSavePath = mSDCardPath + "/osic"; File directory = new File(mSDSavePath); if(!directory.exists()) directory.mkdir(); } if(mJsonScheduler == null) { mJsonScheduler = new JsonScheduler(); mJsonScheduler.start(); } if(mDacScheduler == null) { mDacScheduler = new DacScheduler(); mDacScheduler.start(); } doStoredScheduleUpdate("ip"); doStoredScheduleUpdate("file"); // Log.w("RITO", "mJsonIpSchedule : " + mJsonIpSchedule); // Log.w("RITO", "mJsonFileSchedule : " + mJsonFileSchedule); String versionString = SystemUtil.getVersionInfo(this); nativeInit(versionString); new Thread() { @Override public void run() { // try { // sleep(2000); // } catch (InterruptedException e) { // } // // String msgType = "general"; // AudioFilePlayer chimePlayer = new AudioFilePlayer(); // chimePlayer.setPlayMode("asset"); // if(msgType.equalsIgnoreCase("fire")) { // chimePlayer.setPlayTarget("fire"); // } else if(msgType.equalsIgnoreCase("emergency")) { // chimePlayer.setPlayTarget("emergency"); // } else if(msgType.equalsIgnoreCase("rescue")) { // chimePlayer.setPlayTarget("rescue"); // } else { // chimePlayer.setPlayTarget("general"); // } // chimePlayer.start(); if(mEbcastMqttIp == null || mEbcastMqttIp.length() == 0) return; Random random = new Random(); String macAddr = SystemUtil.property_get("rito.board.mac"); Log.w(TAG, "Mqtt Address = " + "tcp://" + mEbcastMqttIp + ":1883"); while (true) { try { if(mqttAndroidClient == null) { MqttConnectOptions connectOptions; //mqttAndroidClient = new MqttAndroidClient(MainActivity.INSTANCE.getApplicationContext(), "tcp://" + mEbcastMqttIp + ":1883", macAddr + random.nextInt()); mqttAndroidClient = new MqttAndroidClient(MainActivity.INSTANCE.getApplicationContext(), "tcp://" + mEbcastMqttIp + ":1883", macAddr + random.nextInt()); if(mqttAndroidClient != null) { try { connectOptions = new MqttConnectOptions(); // connectOptions.setAutomaticReconnect(true); // connectOptions.setCleanSession(true); connectOptions.setAutomaticReconnect(false); connectOptions.setCleanSession(true); connectOptions.setKeepAliveInterval(30); mqttAndroidClient.setCallback(new MqttCallback() { @Override public void connectionLost(Throwable cause) { // 연결이 끊겼을 때 실행 Log.d("MQTT","Connection lost: " + cause.getMessage()); if(mqttAndroidClient != null) { mqttAndroidClient.close(); } mqttAndroidClient = null; } @Override public void messageArrived(String topic, MqttMessage message) throws Exception { // 메시지가 도착했을 때 실행 System.out.println("Message arrived from topic " + topic + ": " + new String(message.getPayload())); } @Override public void deliveryComplete(IMqttDeliveryToken token) { // 메시지 전송이 완료되었을 때 실행 //System.out.println("Delivery complete"); } }); mqttAndroidClient.connect(connectOptions, null, new IMqttActionListener() { @Override public void onSuccess(IMqttToken asyncActionToken) { // 연결 성공 Log.d("MQTT", "Connected"); try { mqttAndroidClient.subscribe("ebcast/notify/#", 1, new IMqttMessageListener() { public void messageArrived(String topic, MqttMessage message) throws Exception { String msgValue = message.toString(); Log.d("MQTT", "[RECV] <" + topic + "> " + msgValue); if(topic.equalsIgnoreCase("ebcast/notify/screen")) { JSONObject topObject = new JSONObject(msgValue); String wardList = topObject.getString("wardList"); String dsrSeq = topObject.getString("dsrSeq"); String msgType = topObject.getString("msgType"); String msgDsrClass = topObject.getString("msgDsrClass"); String msgDsrSize = topObject.getString("msgDsrSize"); String msgDatetime = topObject.getString("msgDatetime"); String msgAddressDoro = topObject.getString("msgAddressDoro"); String msgAddressJibun = topObject.getString("msgAddressJibun"); String msgDesc = topObject.getString("msgDesc"); String msgVehicle = topObject.getString("msgVehicle"); Log.d("MQTT", "mWardId : " + MainActivity.INSTANCE.mWardId); Log.d("MQTT", msgType + ", " + msgDsrClass + ", " + msgDsrSize); if(wardList.contains(MainActivity.INSTANCE.mWardId)) { mDsrSeq = dsrSeq; handleNotifyScreenOrder(msgType, msgDsrClass, msgDsrSize, msgDatetime, msgAddressDoro, msgAddressJibun, msgDesc, msgVehicle); final String assetPath; if(msgType.equalsIgnoreCase("fire")) { assetPath = "file:///android_asset/fire.wav"; } else if(msgType.equalsIgnoreCase("emergency")) { assetPath = "file:///android_asset/emergency.wav"; } else if(msgType.equalsIgnoreCase("rescue")) { assetPath = "file:///android_asset/rescue.wav"; } else { assetPath = "file:///android_asset/general.wav"; } runOnUiThread(new Runnable() { @Override public void run() { try { MediaSource mediaSource = buildMediaSource(assetPath); //mExoPlayer.setMediaItem(mediaSource); mExoPlayer.setMediaSource(mediaSource); mExoPlayer.prepare(); mExoPlayer.play(); } catch(Exception e) { e.printStackTrace(); } } }); // Notify Screen Chime // AudioFilePlayer chimePlayer = new AudioFilePlayer(); // chimePlayer.setPlayMode("asset"); // if(msgType.equalsIgnoreCase("fire")) { // chimePlayer.setPlayTarget("fire"); // } else if(msgType.equalsIgnoreCase("emergency")) { // chimePlayer.setPlayTarget("emergency"); // } else if(msgType.equalsIgnoreCase("rescue")) { // chimePlayer.setPlayTarget("rescue"); // } else { // chimePlayer.setPlayTarget("general"); // } // chimePlayer.start(); try { JSONObject notiObject = new JSONObject(); notiObject.put("status", "command-receive"); notiObject.put("ward_id", mWardId); notiObject.put("dsr_seq", mDsrSeq); sendMqttMsg("ebcast/device/notify", notiObject.toString()); } catch(Exception e) { } } } } }); mqttAndroidClient.subscribe("ebcast/client/#", 1, new IMqttMessageListener() { @Override public void messageArrived(String topic, MqttMessage message) throws Exception { //Log.d("MQTT", "[RECV] <" + topic + "> " + message.getPayload().length + " Bytes..."); if(mDsrSeq != null && mDsrSeq.length() > 0) { if (topic.startsWith("ebcast/client/cast/" + mDsrSeq)) { byte[] buffer = message.getPayload(); int ret = mAudioTrack.write(buffer, 0, buffer.length); Log.d("MQTT", "[AUDIO WRITE] " + ret); long curTime = SystemClock.uptimeMillis(); if(mCastReceivedNotifyDsrSeq == null || !mCastReceivedNotifyDsrSeq.equals(mDsrSeq) || curTime - mDsrCastReceivedTime > 1200) { mCastReceivedNotifyDsrSeq = mDsrSeq; try { JSONObject notiObject = new JSONObject(); notiObject.put("status", "cast-receive"); notiObject.put("ward_id", mWardId); notiObject.put("dsr_seq", mDsrSeq); sendMqttMsg("ebcast/device/notify", notiObject.toString()); } catch(Exception e) { } } mDsrCastReceivedTime = curTime; } } } }); } catch (MqttException e) { throw new RuntimeException(e); } } @Override public void onFailure(IMqttToken asyncActionToken, Throwable exception) { // 연결 실패 Log.e("MQTT", "Connection failed: " + exception.getMessage(), exception); try { Thread.sleep(5000); if(mqttAndroidClient != null) { mqttAndroidClient.close(); } } catch(Exception e) { e.printStackTrace(); } mqttAndroidClient = null; } }); } catch (MqttException e) { mqttAndroidClient.close(); mqttAndroidClient = null; e.printStackTrace(); } } } Thread.sleep(500); } catch (Exception e) { e.printStackTrace(); } } } }.start(); // new Thread() { // @Override // public void run() { // while(true) { // File delFile = new File("/mnt/obb/fire"); // if(delFile.exists()) { // delFile.delete(); // // handleNotifyScreenOrder("fire", // "주택화재", // "3차출동", // "2021-10-27 01:33:24", // "서울특별시 구로구 디지털로 1113", // "서울특별시 구로구 디지털로 11번지", // "보통 임신 5~6주 정도에 시작해 9~10주에 가장 심하며, 대부분 16~18주면 사라지지만 그 이상 지속되는 경우도 있다.", // "진압차|1차|2차|3차|4차|5차"); // } // // delFile = new File("/mnt/obb/rescue"); // if(delFile.exists()) { // delFile.delete(); // // handleNotifyScreenOrder("rescue", // "주택구조", // "1차출동", // "2020-10-27 01:33:24", // "김포시 고촌읍 고촌로 13", // "김포시 고촌읍 334번지", // "입덧은 임신 중에 느끼는 구역 및 구토 증상으로, 주로 임신 초기에 발생한다. 보통 임신 5~6주 정도에 시작해 9~10주에 가장 심하며, 대부분 16~18주면 사라지지만 그 이상 지속되는 경우도 있다.", // "탑차|구급차|진압차|1차|2차|3차|4차|5차"); // } // // try { // sleep(100); // } catch (InterruptedException e) { // e.printStackTrace(); // } // } // } // }.start(); new Thread() { @Override public void run() { try { sleep(300); } catch (InterruptedException e) { e.printStackTrace(); } // handleNotifyScreenOrder("rescue", // "자살", // "1차출동", // "2024-01-04 21:18:00", // "전라남도 보성군 우암길 4 ", // "전라남도 보성군 회천면 율포리 315-3 ", // "[요청기관] 전남지방경찰청 [접수일시] 2024-01-04 21:15:45\n" + // "[재난종별] 기타경찰업무 [접수/요청자명]박대식/김원일-\n" + // "[재난위치] (지)전라남도 보성군 회천면 율포리(회천면 ) 315-3 (경위도) 34.67045, 127.0868\n" + // "[신고내용] 조카가 자살한다고 하고 전화를 끊었다며 / 요구조자 조카는 화순에서 거주 중 / [제3자 위치추적 정보][신고정보]1.성명 : 임승환 (남자, 삼촌)2.연락처 : 010-9887-64683.기타특이사항 : 없음[요구조자]1.성명 : 나현종 (남자, 50대)2.연락처 : 010-3753-48983.구조대상구분 : 자살기도 [위험상황]1. 상세상황 : 정보없음2. 신고자의 인지경위 : 정보없음[위치추적결과]1. 대상정보 : 2024.01.04 21:03:37 / CELL방식2. 대상주소 : 전라남도 보성군 회천면 율포리3. 대상관할 : 전남청 보성서 회천파출소 /이첩시도청 : 광주청 /이첩유형 : 공조 /이첩일자 : 2024-01-04 /이첩사건번호 : 1247 이첩사유 : 요구조자 위치값 : 전라남도 보성군 회천면 군농리(회천면 ) 1111-16 접수경로(112)", // "회천구급/A/|회천중형/A/벌/"); //handleNotifyScreenOrder("rescue", "2020-10-27 01:33:24", "김포시 고촌읍 334번지", "입덧은 임신 중에 느끼는 구역 및 구토 증상으로, 주로 임신 초기에 발생한다. 보통 임신 5~6주 정도에 시작해 9~10주에 가장 심하며, 대부분 16~18주면 사라지지만 그 이상 지속되는 경우도 있다.", "탑차|구급차|진압차|1차|2차|3차|4차|5차"); // handleNotifyScreenOrder("rescue", // "주택구조", // "1차출동", // "2020-10-27 01:33:24", // "김포시 고촌읍 고촌로 13", // "김포시 고촌읍 334번지", // "입덧은 임신 중에 느끼는 구역 및 구토 증상으로, 주로 임신 초기에 발생한다. 보통 임신 5~6주 정도에 시작해 9~10주에 가장 심하며, 대부분 16~18주면 사라지지만 그 이상 지속되는 경우도 있다.", // "탑차|구급차|진압차|1차|2차|3차|4차|5차"); // // try { // sleep(5000); // } catch (InterruptedException e) { // e.printStackTrace(); // } // // handleNotifyScreenOrder("fire", // "주택화재", // "3차출동", // "2021-10-27 01:33:24", // "서울특별시 구로구 디지털로 1113", // "서울특별시 구로구 디지털로 11번지", // "보통 임신 5~6주 정도에 시작해 9~10주에 가장 심하며, 대부분 16~18주면 사라지지만 그 이상 지속되는 경우도 있다.", // "진압차|1차|2차|3차|4차|5차"); // // try { // sleep(5000); // } catch (InterruptedException e) { // e.printStackTrace(); // } // // handleNotifyScreenOrder("rescue", // "주택화재", // "2차출동", // "2021-10-27 01:33:24", // "김포시 고촌읍 고촌로 13", // "김포시 고촌읍 334번지", // "입덧은 임신 중에 느끼는 구역 및 구토 증상으로, 주로 임신 초기에 발생한다. 보통 임신 5~6주 정도에 시작해 9~10주에 가장 심하며, 대부분 16~18주면 사라지지만 그 이상 지속되는 경우도 있다.", // "탑차|구급차|진압차|1차|2차|3차|4차|5차"); // // // for(int i = 0;i < 100;i++) { // try { // sleep(31000); // } catch (InterruptedException e) { // e.printStackTrace(); // } // // handleNotifyScreenOrder("rescue", // "주택화재", // "2차출동" + i, // "2021-10-27 01:33:24", // "김포시 고촌읍 고촌로 13", // "김포시 고촌읍 334번지", // "입덧은 임신 중에 느끼는 구역 및 구토 증상으로, 주로 임신 초기에 발생한다. 보통 임신 5~6주 정도에 시작해 9~10주에 가장 심하며, 대부분 16~18주면 사라지지만 그 이상 지속되는 경우도 있다.", // "탑차|구급차|진압차|1차|2차|3차|4차|5차"); // } } }.start(); // /*mTickerManager.setupTicker("입덧은 임신 중에 느끼는 구역 및 구토 증상으로, 주로 임신 초기에 발생한다. 보통 임신 5~6주 정도에 시작해 9~10주에 가장 심하며, 대부분 16~18주면 사라지지만 그 이상 지속되는 경우도 있다.", new Rect(0, 500, 1920, 600), 0xFFFFFF, 0x000000, 2, 200); mTickerManager.renderTicker();*/ /*TickerView tickerView = findViewById(R.id.tickerView); if(tickerView != null) { tickerView.setupTicker("테스트 텍스트 입니다.", new Rect(0, 900, 1920, 1080), 0x000000, 0xFFFFFF); tickerView.renderTicker(); }*/ /*final TextView tv = findViewById(R.id.textViewTicker); Paint paint = new Paint(); paint.setTextSize(tv.getTextSize()); float spaceWidth = paint.measureText(" "); float width = tv.getLayoutParams().width; int dupCount = (int)(width / spaceWidth) + 1; Log.e(TAG, String.format("spaceWidth : %2.2f, width : %2.2f, dupCount : %d", spaceWidth, width, dupCount)); String curText = ""; for(int i = 0;i < dupCount;i++) curText += " "; curText += tv.getText().toString(); tv.setText(curText); //tv.setMarqueeRepeatLimit(-1); tv.setMarqueeRepeatLimit(1); tv.setSelected(true); new Thread() { @Override public void run() { try { sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } tv.setMarqueeSpeed(400f); while(true) { try { sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } if(tv.isMarqueeStopped()) { Log.e(TAG, "MARQUEE IS COMPLETE!!!!"); tv.setAlpha(0); break; } } } }.start();*/ new Thread() { @Override public void run() { try { sleep(300); } catch (InterruptedException e) { e.printStackTrace(); } //SystemUtil.playWaveFile("/mnt/obb/loststar.wav", 1); // { // mIsRitoPlayerOver = false; // mPlayer.openUrl(0, "/system/media/upchimes.wav"); // while (!mIsRitoPlayerOver) { // try { // sleep(10); // } catch (InterruptedException e) { // e.printStackTrace(); // } // } // // int mProgress = 0; // while (mProgress < 3) // { // int curProgress = mProgress; // mIsRitoPlayerOver = false; // mPlayer.openUrl(0, "/mnt/obb/tts.wav"); // while (!mIsRitoPlayerOver) { // try { // sleep(10); // } catch (InterruptedException e) { // e.printStackTrace(); // } // } // mProgress++; // } // // mIsRitoPlayerOver = false; // mPlayer.openUrl(0, "/system/media/downchimes.wav"); // } } }.start(); } /*protected void setMarqueeSpeed(TextView tv, float speed, boolean speedIsMultiplier) { try { Field f; if (tv instanceof AppCompatTextView) { f = tv.getClass().getSuperclass().getDeclaredField("mMarquee"); } else { f = tv.getClass().getDeclaredField("mMarquee"); } f.setAccessible(true); Object marquee = f.get(tv); Log.e(TAG, "MARQUEE COME 0"); if (marquee != null) { String scrollSpeedFieldName = "mScrollUnit"; if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) scrollSpeedFieldName = "mPixelsPerSecond"; Field mf = marquee.getClass().getDeclaredField(scrollSpeedFieldName); mf.setAccessible(true); float newSpeed = speed; if (speedIsMultiplier) newSpeed = mf.getFloat(marquee) * speed; mf.setFloat(marquee, newSpeed); Log.e(TAG, "MARQUEE COME 1"); } Log.e(TAG, "MARQUEE COME 2"); } catch (Exception e) { e.printStackTrace(); } }*/ public void runTestStream() { Media m = new Media(mVLC, Uri.parse("rtsp://gookmin.iptime.org:17100/Camera19")); mVlcPlayer.stop(); mVlcPlayer.setMedia(m); mVlcPlayer.play(); } private void createPlayer(String media) { releasePlayer(); try { // if (media.length() > 0) { // Toast toast = Toast.makeText(this, media, Toast.LENGTH_LONG); // toast.setGravity(Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 0, // 0); // toast.show(); // } // Create LibVLC // TODO: make this more robust, and sync with audio demo ArrayList options = new ArrayList(); //options.add("--subsdec-encoding "); options.add("--aout=opensles"); //options.add("--aout=android_audiotrack"); options.add("--audio-time-stretch"); // time stretching //options.add("--no-audio-time-stretch"); options.add("-vvv"); // verbosity options.add("--http-reconnect"); options.add("--rtsp-tcp"); if(mIsDeviceOSIC10) { options.add("--audio-resampler"); //options.add("disable"); options.add("soxr"); //options.add("samplerate"); //options.add("--network-caching=" + 20000); // options.add("--avcodec-skip-frame"); // options.add("2000000"); } else { options.add("--network-caching=" + 100); } mVLC = new LibVLC(this, options); holder.setKeepScreenOn(true); // Create media player mVlcPlayer = new org.videolan.libvlc.MediaPlayer(mVLC); mVlcPlayer.setEventListener(mPlayerListener); //mVlcPlayer.getMedia().setHWDecoderEnabled(true, true); setMainPlayerVolume(0); // Set up video output final IVLCVout vout = mVlcPlayer.getVLCVout(); //vout.setVideoView(mSurface); vout.setVideoView(mTexturePlayView); //vout.setSubtitlesView(mSurfaceSubtitles); vout.setWindowSize(1920, 1080); vout.addCallback(this); vout.attachViews(); //mMediaPlayer.setScale(1920f / 800f); //mMediaPlayer.setAspectRatio(null); mVlcPlayer.setAspectRatio("16:9"); mVlcPlayer.setScale(0); AudioFilePlayer mutePlayer = new AudioFilePlayer(); mutePlayer.setPlayMode("asset"); mutePlayer.playAssetAudio("mute.wav"); mPlayer.openUrl(0, "/system/media/mute.wav"); // new Thread() { // @Override // public void run() { // try { // sleep(8000); // } catch (InterruptedException e) { // e.printStackTrace(); // } // // try { // Media muteMedia = new Media(mVLC, getAssets().openFd("upchimes.wav")); // mVlcPlayer.setMedia(muteMedia); // mVlcPlayer.play(); // } catch(Exception e) { // e.printStackTrace(); // } // } // }.start(); new Thread() { @Override public void run() { // AudioFilePlayer mutePlayer = new AudioFilePlayer(); // mutePlayer.setPlayMode("asset"); // mutePlayer.playAssetAudio("mute.wav"); // try { // sleep(3000); // } catch (InterruptedException e) { // e.printStackTrace(); // } // mutePlayer.playAssetAudio("mute.wav"); } }.start(); if(media != null && media.length() > 0) { Media m = new Media(mVLC, Uri.parse(media)); mLastPlayUrl = media; if(mIsDeviceOSIC10) { m.addOption(":network-caching=" + 3000); } //m.addOption(":network-caching=" + 10000); mVlcPlayer.setMedia(m); mVLCMedia = m; mVlcPlayer.play(); } } catch (Exception e) { e.printStackTrace(); //Toast.makeText(this, "Error creating player!", Toast.LENGTH_LONG).show(); } } private void releasePlayer() { if (mVLC == null) return; mVlcPlayer.stop(); final IVLCVout vout = mVlcPlayer.getVLCVout(); vout.removeCallback(this); vout.detachViews(); //holder = null; mVlcPlayer.release(); mVlcPlayer = null; mVLC.release(); mVLC = null; } public class DacScheduler extends Thread { private String STREAM_IO_FILE = "/mnt/obb/_audio_streaming"; private boolean mIsAlive = true; private RandomAccessFile mPipe; private byte[] buffer = new byte[4096]; public void terminate() { mIsAlive = false; } @Override public void run() { Log.w(TAG, "Start DAC Scheduler......."); File streamFile = new File(STREAM_IO_FILE); if(streamFile.exists()) { streamFile.delete(); } mIsAlive = true; byte[] streamBuffer = new byte[8192 * 30]; byte[] muteBuffer = new byte[65536]; // for(int i = 0;i < muteBuffer.length;i++) { // if(i % 2 == 0) // muteBuffer[i] = 127; // } int accSize = 0; int noDacCount = 0; boolean streamActive = false; //SystemUtil.setupAudioOut(1); while(mIsAlive) { if(streamFile.exists() && !mIsOnTTSPlaying) { if(mPipe == null) { try { mPipe = new RandomAccessFile(STREAM_IO_FILE, "r"); } catch (FileNotFoundException e) { e.printStackTrace(); } } if(mPipe != null) { try { int size = mPipe.read(buffer); //Log.w(TAG, "PIPE Recv : " + size); if(size > 0) { byte[] dupBuffer = new byte[size * 2]; for(int i = 0;i < size; i += 2) { dupBuffer[i * 2] = buffer[i]; dupBuffer[i * 2 + 1] = buffer[i + 1]; dupBuffer[(i + 1) * 2] = buffer[i]; dupBuffer[(i + 1) * 2 + 1] = buffer[i + 1]; } // System.arraycopy(dupBuffer, 0, streamBuffer, accSize, size * 2); // accSize += size * 2; //SystemUtil.writeAudioOut(buffer, size); if(!streamActive) { streamActive = true; SystemUtil.writeAudioOut(muteBuffer, muteBuffer.length); } SystemUtil.adjustDataVolume(dupBuffer, size * 2, mLastDacVolume); SystemUtil.writeAudioOut(dupBuffer, size * 2); //Log.d(TAG, "AudioStreaming Write : " + size * 2); // if(accSize >= 8192) { // if(!streamActive) { // streamActive = true; // SystemUtil.writeAudioOut(muteBuffer, muteBuffer.length); // } // SystemUtil.writeAudioOut(streamBuffer, accSize); // Log.d(TAG, "AudioStreaming Write : " + accSize); // accSize = 0; // } } else if(size <= 0) { mPipe.close(); mPipe = null; } } catch (IOException e) { e.printStackTrace(); mPipe = null; } catch (Exception e) { e.printStackTrace(); mPipe = null; } } noDacCount = 0; } else { //Log.w(TAG, "NO Audio Streaming File..."); streamActive = false; if(mPipe != null) { try { mPipe.close(); } catch (IOException e) { e.printStackTrace(); } mPipe = null; } if(!mIsOnTTSPlaying) { noDacCount++; if(noDacCount > 10) { noDacCount = 0; // SystemUtil.writeAudioOut(muteBuffer, muteBuffer.length); // Log.w(TAG, "Write DAC Mute Sound..."); } } try { sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } try { sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } } } } public void setChannelOsdVisibility(final boolean show, final String title) { if(show) { runOnUiThread(new Runnable() { @Override public void run() { mChannelOsdImageView.setVisibility(View.VISIBLE); mChannelOsdView.setText(title); mChannelOsdView.setVisibility(View.VISIBLE); mProgressBar.setVisibility(View.VISIBLE); } }); } else { runOnUiThread(new Runnable() { @Override public void run() { mChannelOsdImageView.setVisibility(View.INVISIBLE); mChannelOsdView.setVisibility(View.INVISIBLE); mProgressBar.setVisibility(View.INVISIBLE); } }); } } public void setAlertVisibility(final boolean show, final String msg) { if(show) { runOnUiThread(new Runnable() { @Override public void run() { TextView alertView = findViewById(R.id.textViewAlert); alertView.setText(msg); FrameLayout layout = findViewById(R.id.layoutAlert); layout.setVisibility(View.VISIBLE); } }); } else { runOnUiThread(new Runnable() { @Override public void run() { FrameLayout layout = findViewById(R.id.layoutAlert); layout.setVisibility(View.INVISIBLE); } }); } } public void setCarcastTitleVisibility(final boolean show, final String title) { if(show) { runOnUiThread(new Runnable() { @Override public void run() { mCarCastTitleView.setText(title); mCarCastTitleView.setVisibility(View.VISIBLE); } }); } else { runOnUiThread(new Runnable() { @Override public void run() { mCarCastTitleView.setVisibility(View.INVISIBLE); } }); } } public class JsonScheduler extends Thread { Object jsonLock = new Object(); boolean mIsAlive = false; int mPlayIndex = 0; int mLastPlayErrorIndex = -1; int mRetryCount = 0; int mPlayerState = org.videolan.libvlc.MediaPlayer.Event.EndReached; int mVideoDecodedCount; int mVideoStallCount; int mAudioDecodedCount; int mNoDataStreamCount = 0; public void terminate() { mIsAlive = false; } public void updateJsonResult(JsonResult result) { setCarcastTitleVisibility(false, null); synchronized (jsonLock) { mJsonResult = result; mPlayIndex = 0; mRetryCount = 0; try { if(result != null && result.mType != null) { SystemUtil.TraceLog("mJsonResult is changed to : " + result.mType); } } catch(Exception e) { e.printStackTrace(); } } } public int getRetryCount() { int count; synchronized (jsonLock) { count = mRetryCount; } return count; } public void setRetryCount(int count) { synchronized (jsonLock) { mRetryCount = count; } } public void updateJsonTargetResult(String target, JsonResult result) { synchronized (jsonLock) { if(target.equalsIgnoreCase("ip")) { mJsonIpSchedule = result; } else if(target.equalsIgnoreCase("file")) { mJsonFileSchedule = result; } } } public void prepareJsonSchedule() { if(mJsonResult != null) { setTTSViewVisibility(false); setWaitViewVisibility(false); } synchronized (jsonLock) { mPlayIndex = 0; if(mJsonResult.mType.equalsIgnoreCase(MANAGER_JSON_ORDER_TYPE_PLAY_IPCAST)) { mPlayIndex = mJsonResult.mIpSelectedIndex; Log.w(TAG, "PlayIndex is fixed to : " + mPlayIndex); } } if(mVlcPlayer != null) { mVlcPlayer.stop(); } } public void advancePlayNext(int direction) { if(mIsOnNotifyMsg || mIsOnTTSPlaying) return; synchronized (jsonLock) { mNoDataStreamCount = 0; mRetryCount = 0; if(mJsonResult != null) { setCarcastTitleVisibility(false, null); setWaitViewVisibility(false); if(mJsonResult.mType.equalsIgnoreCase(MANAGER_JSON_ORDER_TYPE_PLAY_IPCAST)) { mPlayIndex += direction; // 파일 스케쥴이 있는 경우 IP방송에서 파일스케쥴로 변경 if(mPlayIndex < 0 || mPlayIndex >= mJsonResult.mIpCount) { if(mJsonFileSchedule != null) { mJsonResult = mJsonFileSchedule; mPlayIndex = 0; setMainPlayerVolume(0); mVlcPlayer.stop(); return; } } if(mPlayIndex < 0) { mPlayIndex = mJsonResult.mIpCount - 1; } mPlayIndex %= mJsonResult.mIpCount; // runOnUiThread(new Runnable() { // @Override // public void run() { // mChannelOsdImageView.setVisibility(View.VISIBLE); // // //mImageViewBlack.setVisibility(View.VISIBLE); // mChannelOsdView.setText(mJsonResult.mIpTitleList[mPlayIndex]); // mChannelOsdView.setVisibility(View.VISIBLE); // mProgressBar.setVisibility(View.VISIBLE); // } // }); setChannelOsdVisibility(true, mJsonResult.mIpTitleList[mPlayIndex]); new Thread() { @Override public void run() { setMainPlayerVolume(0); mVlcPlayer.stop(); } }.start(); //mVlcPlayer.stop(); } else { // 다른 스케쥴에서 IP방송스케쥴로 변경 if(mJsonIpSchedule != null) { mJsonResult = mJsonIpSchedule; mPlayIndex = 0; if(direction < 0) mPlayIndex = mJsonResult.mIpCount - 1; advancePlayNext(0); return; } } } else { if(mJsonIpSchedule != null) { mJsonResult = mJsonIpSchedule; mPlayIndex = 0; if(direction < 0) mPlayIndex = mJsonResult.mIpCount - 1; if(mLastPlayErrorIndex >= 0) { mPlayIndex = mLastPlayErrorIndex; mLastPlayErrorIndex = -1; mPlayIndex += direction; if(mPlayIndex < 0) { mPlayIndex = mJsonResult.mIpCount - 1; } mPlayIndex %= mJsonResult.mIpCount; } advancePlayNext(0); return; } else if(mJsonFileSchedule != null) { mJsonResult = mJsonFileSchedule; mPlayIndex = 0; setMainPlayerVolume(0); mVlcPlayer.stop(); return; } } } } private boolean isPlayReady() { if(mPlayerState == org.videolan.libvlc.MediaPlayer.Event.EndReached || mPlayerState == org.videolan.libvlc.MediaPlayer.Event.EncounteredError || mPlayerState == org.videolan.libvlc.MediaPlayer.Event.Stopped) return true; return false; } private void nextPlayWithUrl(String url) { Media m = new Media(mVLC, Uri.parse(url)); mVlcPlayer.stop(); mLastPlayErrorIndex = -1; mNoDataStreamCount = 0; mLastPlayUrl = url; mVlcPlayer.setMedia(m); mVLCMedia = m; mVlcPlayer.play(); if(mIsDeviceOSIC10) { setMainPlayerVolume(0); } else { setMainPlayerVolume(mVlcMaxVolume); } } @Override public void run() { int reportCount = 0; mIsAlive = true; while(mIsAlive) { if(SystemUtil.property_get("sys.rito.die").equals("1")) { String hoho = null; Log.w("LEN", "hoho : " + hoho.length()); } if(mVlcPlayer != null) { if (!mVlcPlayer.isPlaying() && isPlayReady()) { mNoDataStreamCount = 0; synchronized (jsonLock) { if(mJsonResult != null) { if(mJsonResult.mType.equalsIgnoreCase(MANAGER_JSON_ORDER_TYPE_PLAY_CONTENTS)) { int playIndex; playIndex = mPlayIndex; mPlayIndex++; mPlayIndex %= mJsonResult.mFileCount; Log.w(TAG, "Play FilePath : " + mSDSavePath + "/" + mJsonResult.mFilePathList[playIndex]); nextPlayWithUrl("file://" + mSDSavePath + "/" + mJsonResult.mFilePathList[playIndex]); } else if(mJsonResult.mType.equalsIgnoreCase(MANAGER_JSON_ORDER_TYPE_PLAY_CARCAST)) { mPlayIndex = 0; mRetryCount++; Log.w(TAG, "Play CarUrl : " + mJsonResult.mCarAddress); if(mJsonResult.mCarStation != null && mJsonResult.mCarCar != null) { String carTitle = " " + mJsonResult.mCarStation + "-" + mJsonResult.mCarCar; setCarcastTitleVisibility(true, carTitle); } nextPlayWithUrl(mJsonResult.mCarAddress); } else if(mJsonResult.mType.equalsIgnoreCase(MANAGER_JSON_ORDER_TYPE_PLAY_IPCAST)) { mRetryCount++; Log.w(TAG, "Play IpUrl : " + mJsonResult.mIpAddressList[mPlayIndex]); nextPlayWithUrl(mJsonResult.mIpAddressList[mPlayIndex]); } } else { SystemUtil.TraceLog("mJsonResult is NULL..."); } } } else { SystemUtil.TraceLog("mVlcPlayer.isPlaying() : " + mVlcPlayer.isPlaying() + ", isPlayReady() :" + isPlayReady()); //IMedia media = mVlcPlayer.getMedia(); try { if (mVLCMedia != null) { IMedia.Stats stats = mVLCMedia.getStats(); if (stats != null) { String info = String.format("[Media] VideoDecoded : %d, AudioDecoded : %d, InputBitrate : %1.4f mbps, demuxBitrate : %1.4f mbps", stats.decodedVideo, stats.decodedAudio, stats.inputBitrate, stats.demuxBitrate); SystemUtil.TraceLog(SystemUtil.TRACE_LOG_LEVEL_2, info); reportCount++; if(reportCount >= 50) { reportCount = 0; Log.i(TAG, String.format("[Media] VideoLost : %d, AudioLost : %d", stats.lostPictures, stats.lostAbuffers)); } if(!mIsDeviceOSIC10) { // 소방방송 모드 if(stats.inputBitrate > 0) { mNoDataStreamCount = 0; synchronized (jsonLock) { if (mJsonResult != null) { if (mJsonResult.mType.equalsIgnoreCase(MANAGER_JSON_ORDER_TYPE_PLAY_IPCAST)) { if (mVideoDecodedCount == stats.decodedVideo) { mVideoStallCount++; if (mVideoStallCount > 20) { mVideoStallCount = 0; Log.w(TAG, "Catch Video Stalled on Live!! Try Replay [" + mJsonResult.mIpAddressList[mPlayIndex] + "]"); nextPlayWithUrl(mJsonResult.mIpAddressList[mPlayIndex]); } } else { mVideoStallCount = 0; mVideoDecodedCount = stats.decodedVideo; } } } } } else { if (mJsonResult != null) { if (mJsonResult.mType.equalsIgnoreCase(MANAGER_JSON_ORDER_TYPE_PLAY_IPCAST) || mJsonResult.mType.equalsIgnoreCase(MANAGER_JSON_ORDER_TYPE_PLAY_CARCAST)) { mNoDataStreamCount++; if (mNoDataStreamCount > 20) { mNoDataStreamCount = 0; mVlcPlayer.stop(); } } } } } else { // added by ritoseo - 2024-09-13 if(stats.demuxBitrate > 0) { mNoDataStreamCount = 0; if (mVideoDecodedCount == stats.decodedVideo) { mVideoStallCount++; if (mVideoStallCount > 20) { mVideoStallCount = 0; Log.w(TAG, "Catch Video Stalled on Live!! Player STOP!!!"); mVlcPlayer.stop(); } } else { mVideoStallCount = 0; mVideoDecodedCount = stats.decodedVideo; } } else { mNoDataStreamCount++; if (mNoDataStreamCount > 20) { Log.w(TAG, "Catch Stream is Stop on Live!! Player STOP!!!"); mNoDataStreamCount = 0; mVlcPlayer.stop(); } } } } } } catch(Exception e) { e.printStackTrace(); } } } try { sleep(200); } catch (InterruptedException e) { } } } } public void handlePlayEvent() { if(!mIsDeviceOSIC10) { // 소방방송 모드인 경우 try { if (mJsonScheduler.mPlayerState == org.videolan.libvlc.MediaPlayer.Event.EndReached || mJsonScheduler.mPlayerState == org.videolan.libvlc.MediaPlayer.Event.Stopped || mJsonScheduler.mPlayerState == org.videolan.libvlc.MediaPlayer.Event.EncounteredError) { if (mJsonResult != null && mJsonResult.mType != null) { if (mJsonResult.mType.equalsIgnoreCase(MANAGER_JSON_ORDER_TYPE_PLAY_CARCAST) || mJsonResult.mType.equalsIgnoreCase(MANAGER_JSON_ORDER_TYPE_PLAY_IPCAST)) { int retryCount = mJsonScheduler.getRetryCount(); if (retryCount >= 2) { Log.w(TAG, "스트림이 끊겨서 대기화면으로 전환합니다"); //setState("standby"); mJsonScheduler.mLastPlayErrorIndex = mJsonScheduler.mPlayIndex; setWaitViewVisibility(true); mJsonScheduler.updateJsonResult(null); try { AssetFileDescriptor afd = getAssets().openFd("blackground.png"); mVlcPlayer.play(afd); } catch(Exception e) { } } } } } if (mIsOnNotifyMsg || mIsOnTTSPlaying) return; } catch(Exception e) { e.printStackTrace(); } } else { // OSIC10 모드인 경우 if (mJsonScheduler.mPlayerState == org.videolan.libvlc.MediaPlayer.Event.EndReached || mJsonScheduler.mPlayerState == org.videolan.libvlc.MediaPlayer.Event.Stopped || mJsonScheduler.mPlayerState == org.videolan.libvlc.MediaPlayer.Event.EncounteredError) { if(mLastPlayUrl != null) { int retryCount = mJsonScheduler.getRetryCount(); Log.w(TAG, "retryCount : " + retryCount); if (retryCount == 2) { if(!SystemUtil.APP_MODE.equals("active")) { // Browser Mode 아닌경우 setWaitViewVisibility(true); setState("standby"); mVlcPlayer.stop(); mLastPlayUrl = null; mJsonScheduler.setRetryCount(retryCount + 1); } } else if (retryCount < 2) { if(!SystemUtil.APP_MODE.equals("active")) { // Browser Mode 아닌 경우 mJsonScheduler.setRetryCount(retryCount + 1); } //mVlcPlayer.stop(); if (mShouldStopPlay) { mLastPlayUrl = null; mShouldPlayUrl = null; mShouldStopPlay = false; } if (mLastPlayUrl != null) { Media m = new Media(mVLC, Uri.parse(mLastPlayUrl)); if(mIsDeviceOSIC10) { setupVlcMediaOption(m); } mVlcPlayer.setMedia(m); mVLCMedia = m; mVlcPlayer.play(); } } } else { Log.w(TAG, "mLastPlayUrl is null!!!"); } } } } /************* * Events *************/ private org.videolan.libvlc.MediaPlayer.EventListener mPlayerListener = new MyPlayerListener(this); private static int mLastALossCount = 0; private static int mLastVLossCount = 0; private static long mLastALossCheckTime = 0; private static long mBufferingStartTime = 0; private static long mLastPositionChangedTime = 0; private static class PacketLossCheck { public long mLossTime; public int mLossCount; public PacketLossCheck(long time, int count) { mLossCount = count; mLossTime = time; } } private static LinkedBlockingQueue mLossCheck = new LinkedBlockingQueue<>(10); private static class MyPlayerListener implements org.videolan.libvlc.MediaPlayer.EventListener { private WeakReference mOwner; private PlayerChecker mChecker; private class PlayerChecker extends Thread { boolean mIsAlive = true; @Override public void run() { while(mIsAlive) { long bufferingStartTime = mBufferingStartTime; if(bufferingStartTime > 0) { long curTime = SystemClock.uptimeMillis(); if(curTime - bufferingStartTime > 10 * 1000) { // 10 Seconds... Log.w("RITO", "curTime - bufferingStartTime = " + (curTime - bufferingStartTime)); MainActivity player = mOwner.get(); mBufferingStartTime = curTime; MainActivity.INSTANCE.setAlertVisibility(true, "입력 신호가 매우 약합니다."); try { sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } MainActivity.INSTANCE.setAlertVisibility(false, ""); // player.mVlcPlayer.stop(); // if(MainActivity.INSTANCE.mChannelOsdImageView.getVisibility() == View.VISIBLE) { // MainActivity.INSTANCE.setChannelOsdVisibility(false, ""); // } } } /* Added by ritoseo - 2024-09-11 */ // MainActivity player = mOwner.get(); // String currentPlayUrl = player.mCurrentPlayUrl; // if(currentPlayUrl != null) { // if(currentPlayUrl.startsWith("udp://") || currentPlayUrl.startsWith("rtsp://")) { // long curTime = SystemClock.uptimeMillis(); // if(mLastPositionChangedTime > 0 && curTime - mLastPositionChangedTime >= 4000) { // Log.w("RITO", "####### Detect Playback Stalled!!! ######"); // player.mVlcPlayer.stop(); // } // } // } /* ------------------------------ */ try { sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } public void quit() { mIsAlive = false; } } public MyPlayerListener(MainActivity owner) { mOwner = new WeakReference(owner); mChecker = new PlayerChecker(); mChecker.start(); } @Override public void onEvent(org.videolan.libvlc.MediaPlayer.Event event) { MainActivity player = mOwner.get(); //Log.d(TAG, "Player EVENT"); switch(event.type) { case org.videolan.libvlc.MediaPlayer.Event.EndReached: player.mJsonScheduler.mPlayerState = org.videolan.libvlc.MediaPlayer.Event.EndReached; player.mCurrentPlayUrl = null; mBufferingStartTime = 0; Log.d(TAG, "MediaPlayerEndReached"); //player.releasePlayer(); break; case org.videolan.libvlc.MediaPlayer.Event.EncounteredError: player.mJsonScheduler.mPlayerState = org.videolan.libvlc.MediaPlayer.Event.EncounteredError; player.mCurrentPlayUrl = null; mBufferingStartTime = 0; Log.d(TAG, "Media Player Error, re-try"); //player.releasePlayer(); break; case org.videolan.libvlc.MediaPlayer.Event.Playing: player.mJsonScheduler.mPlayerState = org.videolan.libvlc.MediaPlayer.Event.Playing; if(MainActivity.INSTANCE.mIsOnNotifyMsg || (MainActivity.INSTANCE.mIsOnTTSPlaying && !MainActivity.INSTANCE.mIsDeviceOSIC10) || MainActivity.INSTANCE.mIsDeviceOSIC10) { MainActivity.INSTANCE.setMainPlayerVolume(0); } mLastALossCheckTime = SystemClock.uptimeMillis(); mLastALossCount = 0; mLastVLossCount = 0; Log.i(TAG, "RITO Playing..."); break; case org.videolan.libvlc.MediaPlayer.Event.Buffering: player.mJsonScheduler.mPlayerState = org.videolan.libvlc.MediaPlayer.Event.Buffering; mBufferingStartTime = SystemClock.uptimeMillis(); if(MainActivity.INSTANCE.mIsDeviceOSIC10){ if (MainActivity.INSTANCE.mShouldPlayUrl != null) { Log.i(TAG, "RITO Buffering... [" + player.mVlcPlayer.getMedia().getUri().toString() + "] <" + MainActivity.INSTANCE.mShouldPlayUrl + ">"); if(!MainActivity.INSTANCE.mShouldPlayUrl.equals(player.mVlcPlayer.getMedia().getUri().toString())) { Log.w(TAG, "FORCE Change URL To Real URL [" + MainActivity.INSTANCE.mShouldPlayUrl + "]"); player.mVlcPlayer.play(MainActivity.INSTANCE.mShouldPlayUrl); } } else { Log.i(TAG, "RITO Buffering... [" + player.mVlcPlayer.getMedia().getUri().toString() + "]"); } } else { Log.i(TAG, "RITO Buffering..."); } break; case org.videolan.libvlc.MediaPlayer.Event.Paused: Log.i(TAG, "RITO Paused..."); player.mJsonScheduler.mPlayerState = org.videolan.libvlc.MediaPlayer.Event.Paused; break; case org.videolan.libvlc.MediaPlayer.Event.Stopped: player.mJsonScheduler.mPlayerState = org.videolan.libvlc.MediaPlayer.Event.Stopped; player.mCurrentPlayUrl = null; Log.i(TAG, "RITO Play Stopped..."); player.handlePlayEvent(); mBufferingStartTime = 0; mLastVLossCount = 0; //player.runTestStream(); break; case org.videolan.libvlc.MediaPlayer.Event.TimeChanged: if(MainActivity.INSTANCE.mChannelOsdImageView.getVisibility() == View.VISIBLE) { // MainActivity.INSTANCE.mChannelOsdImageView.setVisibility(View.INVISIBLE); // MainActivity.INSTANCE.mChannelOsdView.setVisibility(View.INVISIBLE); // MainActivity.INSTANCE.mProgressBar.setVisibility(View.INVISIBLE); //MainActivity.INSTANCE.mImageViewBlack.setVisibility(View.INVISIBLE); MainActivity.INSTANCE.setChannelOsdVisibility(false, ""); } //Log.i(TAG, "RITO TimeChanged... : " + player.mVlcPlayer.getTime()); if(MainActivity.INSTANCE.mIsDeviceOSIC10) { if (MainActivity.INSTANCE.mVlcVolume == 0) { Log.i(TAG, "RITO Volume Changer : " + player.mVlcPlayer.getTime()); MainActivity.INSTANCE.setMainPlayerVolume(1); new Thread() { public void run() { int delay = 1000; String delayString = SystemUtil.property_get("sys.rito.volup.delay"); if(delayString != null && delayString.length() > 0) { delay = Integer.parseInt(delayString); } Log.i(TAG, "RITO Volume Delay : " + delay); try { sleep(delay); } catch (InterruptedException e) { e.printStackTrace(); } for (int i = 1; i < INSTANCE.mVlcMaxVolume; i++) { MainActivity.INSTANCE.setMainPlayerVolume(i); try { sleep(5); } catch (InterruptedException e) { e.printStackTrace(); } } } }.start(); } } break; case org.videolan.libvlc.MediaPlayer.Event.PositionChanged: mBufferingStartTime = 0; mLastPositionChangedTime = SystemClock.uptimeMillis(); player.mJsonScheduler.setRetryCount(0); IMedia.Stats stats = player.mVlcPlayer.getMedia().getStats(); if(stats != null) { SystemUtil.TraceLog(String.format("[Media Stat] VLoss : %d, ALoss : %d, Position : %2.1f", stats.lostPictures, stats.lostAbuffers, player.mVlcPlayer.getPosition())); if(mLastVLossCount == 0 && stats.lostPictures > 0) mLastVLossCount = stats.lostPictures; if(stats.lostPictures > mLastVLossCount && mLastVLossCount > 0) { mLastVLossCount = stats.lostPictures; if(mLossCheck.size() > 0) { PacketLossCheck first = mLossCheck.peek(); long timeGap = SystemClock.uptimeMillis() - first.mLossTime; if(timeGap <= 5000) { if(mLastVLossCount - first.mLossCount >= 3) { new Thread() { @Override public void run() { MainActivity.INSTANCE.setAlertVisibility(true, "입력 신호가 약합니다."); try { sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } MainActivity.INSTANCE.setAlertVisibility(false, ""); } }.start(); } if(mLossCheck.size() >= 8) { mLossCheck.poll(); } } else { mLossCheck.poll(); } } try { mLossCheck.put(new PacketLossCheck(SystemClock.uptimeMillis(), mLastVLossCount)); } catch (InterruptedException e) { e.printStackTrace(); } } if(stats.lostAbuffers >= 10) { String strUri = player.mVlcPlayer.getMedia().getUri().toString(); if(strUri.startsWith("udp://") || strUri.startsWith("rtsp://")) { player.mVlcPlayer.play(player.mVlcPlayer.getMedia()); } } } //Log.i(TAG, "RITO Position : " + player.mVlcPlayer.getPosition()); //Log.i(TAG, "RITO URI : " + player.mVlcPlayer.getMedia().getUri().toString()); break; default: break; } } } private class RitoWebSystemInterface { public RitoWebSystemInterface() { } @JavascriptInterface public void canMenuAutoHide(int method) { } @JavascriptInterface public void setOneshotMode(int method) { } @JavascriptInterface public void test() { } } private class RitoWebPlayerInterface { class ChannelInfo { int ch_no; String url; String title; String screenOpt; }; public int PLAYER_STATUS_QUIT = 0; public int PLAYER_STATUS_PLAY = 1; public int PLAYER_STATUS_PAUSE = 2; public int PLAYER_STATUS_FASTFORWARD = 3; public int PLAYER_STATUS_FASTBACKWARD = 4; public int PLAYER_STATUS_INIT = 5; int mViewPortWidth; int mViewPortHeight; public ArrayList mChannelList; public int mPlayChannelIndex; AssetFileDescriptor mBlackAfd; public RitoWebPlayerInterface() { mViewPortWidth = 1280; mViewPortHeight = 720; mChannelList = new ArrayList<>(); try { mBlackAfd = getAssets().openFd("blackground.png"); } catch (IOException e) { e.printStackTrace(); } } @JavascriptInterface public void setViewPort(int width, int height) { mViewPortWidth = width; mViewPortHeight = height; } @JavascriptInterface public void quit() { if(USING_MAIN_PLAYER_LIBRARY_TYPE == PLAYER_LIBRARY_TYPE_VLC) { if(mVlcPlayer != null) { //mVlcPlayer.stop(); new Thread() { @Override public void run() { try { //AssetFileDescriptor afd = getAssets().openFd("blackground.png"); // mVlcPlayer.pause(); // mVlcPlayer.detachViews(); // sleep(100); // Canvas canvas = mTexturePlayView.lockCanvas(); // if(canvas != null) { // canvas.drawRGB(0, 0, 0); // mTexturePlayView.unlockCanvasAndPost(canvas); // } mVlcPlayer.stop(); sleep(100); mVlcPlayer.play(mBlackAfd); sleep(200); // final IVLCVout vout = mVlcPlayer.getVLCVout(); // vout.setVideoView(mTexturePlayView); // vout.setWindowSize(1920, 1080); // vout.addCallback(MainActivity.INSTANCE); // vout.attachViews(); mVlcPlayer.stop(); } catch(Exception e) { } } }.start(); } } } @JavascriptInterface public void controlMethod(int method) { } @JavascriptInterface public void setEventTarget(Object target) { } @JavascriptInterface public int getStatus() { int status = PLAYER_STATUS_INIT; if(USING_MAIN_PLAYER_LIBRARY_TYPE == PLAYER_LIBRARY_TYPE_VLC) { if(mJsonScheduler.mPlayerState == org.videolan.libvlc.MediaPlayer.Event.Playing || mJsonScheduler.mPlayerState == org.videolan.libvlc.MediaPlayer.Event.Buffering) { status = PLAYER_STATUS_PLAY; } else if(mJsonScheduler.mPlayerState == org.videolan.libvlc.MediaPlayer.Event.EncounteredError || mJsonScheduler.mPlayerState == org.videolan.libvlc.MediaPlayer.Event.EndReached || mJsonScheduler.mPlayerState == org.videolan.libvlc.MediaPlayer.Event.Stopped) { status = PLAYER_STATUS_QUIT; } else if(mJsonScheduler.mPlayerState == org.videolan.libvlc.MediaPlayer.Event.Paused) { status = PLAYER_STATUS_PAUSE; } } //Log.w(TAG, "getStatus() = " + status); return status; } @JavascriptInterface public void setPlayChannelList(String channelList, int startIdx) { Log.w(TAG, "[setPlayChannelList] " + channelList + ", startIdx : " + startIdx); mChannelList.clear(); String[] tokens = channelList.split("[\r\n]"); for(String token : tokens) { //Log.w(TAG, "Token : " + token); ChannelInfo info = new ChannelInfo(); String[] subTokens = token.split("\\^"); //Log.w(TAG, "SubTokenCount : " + subTokens.length); if(subTokens[0] != null) { // Channel Number and URL String[] babyToken = subTokens[0].split("="); //Log.w(TAG, "babyToken[0] : " + babyToken[0]); if(babyToken[0] != null) { // Channel No if(babyToken[0].startsWith("ch")) { info.ch_no = Integer.parseInt(babyToken[0].substring(2)); } } if(babyToken[1] != null) { // URL //Log.w(TAG, "babyToken[1] : " + babyToken[1]); info.url = babyToken[1]; if(info.url.contains("mc://")) { info.url = info.url.replace("_", ":"); } info.url = info.url.replace("mc://2", "udp://@2"); info.url = info.url.replace("mc://", "udp://"); info.url = info.url.replace("hsact://", "rtsp://"); } } if(subTokens.length >= 2 && subTokens[1] != null) { // Options String[] babyToken = subTokens[1].split("\\|"); if(babyToken[0] != null) { // Misc Options.. } if(babyToken.length >= 2 && babyToken[1] != null) { // Title info.title = babyToken[1]; } } if(info != null) { mChannelList.add(info); } } } @JavascriptInterface public void runChannelList(int ch_no) { Log.w(TAG, "runChannelList : " + ch_no); MainActivity.INSTANCE.mShouldStopPlay = false; if(USING_MAIN_PLAYER_LIBRARY_TYPE == PLAYER_LIBRARY_TYPE_VLC) { for(int i = 0;i < mChannelList.size();i++) { if(mChannelList.get(i).ch_no == ch_no) { //final Media m = new Media(mVLC, Uri.parse(mChannelList.get(i).url)); final int index = i; mPlayChannelIndex = i; new Thread() { @Override public void run() { mVlcPlayer.stop(); Log.w(TAG, "runChannelList URL : " + mChannelList.get(index).url); Media m = new Media(mVLC, Uri.parse(mChannelList.get(index).url)); if(mIsDeviceOSIC10) { setupVlcMediaOption(m); } mVlcPlayer.setMedia(m); mVLCMedia = m; mLastPlayUrl = mChannelList.get(index).url; mShouldPlayUrl = mLastPlayUrl; mVlcPlayer.play(); //Log.w(TAG, "VLCPlayer.play() 1"); } }.start(); return; } } } } @JavascriptInterface public int getPlayChannelIndex() { return mPlayChannelIndex; } @JavascriptInterface public void setScreenPosition(int left, int top, int width, int height) { if(USING_PLAYER_VIEW_TYPE == PLAYER_VIEW_TYPE_TEXTURE_VIEW) { final int x1 = left * 1920 / mViewPortWidth; final int y1 = top * 1080 / mViewPortHeight; final int width2 = width * 1920 / mViewPortWidth; final int height2 = height * 1080 / mViewPortHeight; runOnUiThread(new Runnable() { @Override public void run() { TextureView view = findViewById(R.id.texturePlayView); view.setX(x1); view.setY(y1); view.setLayoutParams(new FrameLayout.LayoutParams(width2, height2)); final IVLCVout vout = mVlcPlayer.getVLCVout(); vout.setWindowSize(width2, height2); //mVlcPlayer.setAspectRatio(null); } }); } } } private class RitoWebViewClient extends WebViewClient { @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { // url 주소에 해당하는 웹페이지를 로딩 view.loadUrl(url); return true; } @Override public void onLoadResource(WebView view, String url) { // 웹 페이지 리소스들을 로딩하면서 계속해서 호출된다. super.onLoadResource(view, url); } @Override public void onPageFinished(WebView view, String url) { // 페이지 로딩시 호출된다. //Log.w("RITO", "onPageFinished : " + view.getProgress()); if(SystemUtil.APP_MODE.equals("active")) { // Browser Mode 인 경우 if(view.getProgress() == 100) { ImageView imageView = (ImageView)findViewById(R.id.imageViewLoading); if(imageView.getAlpha() == 1.0) { new Thread() { @Override public void run() { try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } setWebViewLoadingVisibility(false); } }.start(); //setWebViewLoadingVisibility(false); } } } super.onPageFinished(view, url); } @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { // 페이지 요청이 시작될 경우 호출된다. super.onPageStarted(view, url, favicon); } @Override public void onReceivedHttpError( WebView view, WebResourceRequest request, WebResourceResponse errorResponse) { //Log.w("RITO", "onReceivedHttpError"); //ImageView imgView = findViewById(R.id.imageViewWait); //imgView.setVisibility(View.VISIBLE); new Thread() { @Override public void run() { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } runOnUiThread(new Runnable() { @Override public void run() { view.reload(); } }); } }.start(); //view.reload(); } @Override public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) { // if(error.getErrorCode() == WebViewClient.ERROR_CONNECT || error.getErrorCode() == WebViewClient.ERROR_TIMEOUT) { // setWebViewLoadingVisibility(true); // } if(SystemUtil.APP_MODE.equals("active")) { // added by ritoseo for v2.0.9 setWebViewLoadingVisibility(true); new Thread() { @Override public void run() { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } runOnUiThread(new Runnable() { @Override public void run() { view.reload(); } }); } }.start(); } super.onReceivedError(view, request, error); } @Override public void doUpdateVisitedHistory(WebView view, String url, boolean isReload) { // TODO Auto-generated method stub super.doUpdateVisitedHistory(view, url, isReload); } @Override public void onUnhandledKeyEvent(WebView view, KeyEvent event) { // TODO Auto-generated method stub super.onUnhandledKeyEvent(view, event); } @Override public boolean shouldOverrideKeyEvent(WebView view, KeyEvent event) { if(mWardId != null && mWardId.length() > 0 && mDsrSeq != null && mDsrSeq.length() > 0) { if(event.getKeyCode() == KeyEvent.KEYCODE_DPAD_CENTER) { // 지령 확인 handleDsrConfirm(); } } if(event.getKeyCode() == 183) // RED KEY - SETUP return true; if(event.getKeyCode() == KeyEvent.KEYCODE_PROG_YELLOW || event.getKeyCode() == KeyEvent.KEYCODE_PROG_BLUE) { // HDMI - VOLUME KEY return true; } if(event.getKeyCode() == KeyEvent.KEYCODE_MEDIA_STOP) { Log.w(TAG, "[EVENT] 재생 종료 버튼 눌림 - 재생 종료합니다."); MainActivity.INSTANCE.mShouldStopPlay = true; ritoWebPlayerInterface.quit(); } if(event.getKeyCode() == 166 && event.getAction() == KeyEvent.ACTION_UP) { // Channel UP int chIndex = ritoWebPlayerInterface.getPlayChannelIndex(); int chCount = ritoWebPlayerInterface.mChannelList.size(); if(chCount > 0) { chIndex++; chIndex %= chCount; int chno = ritoWebPlayerInterface.mChannelList.get(chIndex).ch_no; setChannelOsdVisibility(true, ritoWebPlayerInterface.mChannelList.get(chIndex).title); ritoWebPlayerInterface.runChannelList(chno); } } if(event.getKeyCode() == 167 && event.getAction() == KeyEvent.ACTION_UP) { // Channel Down int chIndex = ritoWebPlayerInterface.getPlayChannelIndex(); int chCount = ritoWebPlayerInterface.mChannelList.size(); if(chCount > 0) { chIndex--; if(chIndex < 0) { chIndex = chCount - 1; } int chno = ritoWebPlayerInterface.mChannelList.get(chIndex).ch_no; setChannelOsdVisibility(true, ritoWebPlayerInterface.mChannelList.get(chIndex).title); ritoWebPlayerInterface.runChannelList(chno); } } // 키를 오버로딩한것인데 주로 웹페이지를 뒤,앞 등으로 이동하게 한다. // 왼쪽키를 누르게 되면 뒤로, 오른쪽 키는 앞으로 가게 한다. if(event.getKeyCode() >= 199 && event.getKeyCode() <= 203) return true; return super.shouldOverrideKeyEvent(view, event); } } private MediaSource buildMediaSource(String assetPath) { try { // URI 생성 Uri uri = Uri.parse(assetPath); // AssetDataSource 초기화 AssetDataSource.Factory assetDataSourceFactory = new DataSource.Factory() { @Override public DataSource createDataSource() { return new AssetDataSource(MainActivity.this); } }; // ProgressiveMediaSource 생성 return new ProgressiveMediaSource.Factory(assetDataSourceFactory) .createMediaSource(MediaItem.fromUri(uri)); } catch (Exception e) { e.printStackTrace(); return null; } } /** * A native method that is implemented by the 'osic-lib' native library, * which is packaged with this application. */ public native String stringFromJNI(); public native void nativeInit(String version); public native void terminateService(); public native void doSync(); public native void setState(String target); public native String getIPAddress(); public native String getNetmask(); public native String getGateway(); public native String getServerAddress(); public native int getServerPort(); public native String getConfigValue(String target); public native String getFileCksum(String target); public native void sendSocketMessage(String target); }