@Override public Dialog onCreateDialog(Bundle savedInstanceState) { AlertDialog.Builder adb = new AlertDialog.Builder(getActivity()); Settings settings = Settings.getInstance(getActivity()); String actionName; switch (getAction()) { case ADD_ACTION: actionName = getString(R.string.add); break; case EDIT_ACTION: actionName = getString(R.string.edit); break; case CONNECT_ACTION: actionName = getString(R.string.connect); break; default: throw new RuntimeException("Unknown action " + getAction()); } adb.setPositiveButton(actionName, null); adb.setNegativeButton(android.R.string.cancel, null); LayoutInflater inflater = LayoutInflater.from(getActivity()); View view = inflater.inflate(R.layout.dialog_server_edit, null, false); TextView titleLabel = (TextView) view.findViewById(R.id.server_edit_name_title); mNameEdit = (EditText) view.findViewById(R.id.server_edit_name); mHostEdit = (EditText) view.findViewById(R.id.server_edit_host); mPortEdit = (EditText) view.findViewById(R.id.server_edit_port); mUsernameEdit = (EditText) view.findViewById(R.id.server_edit_username); mUsernameEdit.setHint(settings.getDefaultUsername()); mPasswordEdit = (EditText) view.findViewById(R.id.server_edit_password); Server oldServer = getServer(); if (oldServer != null) { mNameEdit.setText(oldServer.getName()); mHostEdit.setText(oldServer.getHost()); mPortEdit.setText(String.valueOf(oldServer.getPort())); mUsernameEdit.setText(oldServer.getUsername()); mPasswordEdit.setText(oldServer.getPassword()); } if (shouldIgnoreTitle()) { titleLabel.setVisibility(View.GONE); mNameEdit.setVisibility(View.GONE); } // Fixes issues with text colour on light themes with pre-honeycomb devices. adb.setInverseBackgroundForced(true); adb.setView(view); return adb.create(); }
@Override public boolean onKeyUp(int keyCode, KeyEvent event) { // Push to talk hardware key if (settings.isPushToTalk() && keyCode == settings.getPushToTalkKey() && event.getAction() == KeyEvent.ACTION_UP) { setPushToTalk(false); return true; } return super.onKeyUp(keyCode, event); }
public UserListAdapter(final Context context, final Runnable visibleUsersChangedCallback) { this.context = context; this.visibleUsersChangedCallback = visibleUsersChangedCallback; this.dbAdapter = new DbAdapter(context); // Fetch theme dependent icon Settings settings = Settings.getInstance(context); chatDrawable = getResources() .getDrawable( settings.getTheme().equals(Settings.ARRAY_THEME_LIGHTDARK) ? R.drawable.ic_action_chat_light : R.drawable.ic_action_chat_dark); }
@Override protected void onResume() { super.onResume(); if (settings.getCallMode().equals(Settings.ARRAY_CALL_MODE_VOICE)) setProximityEnabled(true); if (mService != null && mService.getCurrentUser() != null) updateMuteDeafenMenuItems(mService.isMuted(), mService.isDeafened()); // Clear chat notifications when activity is re-opened if (mService != null && settings.isChatNotifyEnabled()) { mService.setActivityVisible(true); mService.clearChatNotification(); } }
void updateConnectionState() { final int oldState = serviceState; switch (state) { case MumbleConnectionHost.STATE_CONNECTING: serviceState = CONNECTION_STATE_CONNECTING; break; case MumbleConnectionHost.STATE_CONNECTED: settings.addObserver(this); serviceState = synced ? CONNECTION_STATE_CONNECTED : CONNECTION_STATE_SYNCHRONIZING; if (settings.isDeafened()) { setDeafened(true); } else if (settings.isMuted()) { setMuted(true); } updateFavourites(); if (synced) { // Initialize audio input mAudioInput = new AudioInput(this, mProtocol.codec); if (settings.isVoiceActivity()) mAudioInput.startRecording(); // Immediately begin record if using voice activity showNotification(); } break; case MumbleConnectionHost.STATE_DISCONNECTED: settings.deleteObserver(this); serviceState = CONNECTION_STATE_DISCONNECTED; if (mAudioInput != null) { try { mAudioInput.stopRecordingAndBlock(); } catch (InterruptedException e) { e.printStackTrace(); } finally { mAudioInput.terminate(); mAudioInput = null; } } hideNotification(); break; default: Assert.fail(); } if (oldState != serviceState) { broadcastState(); } }
public AudioOutput(final Context ctx, final AudioOutputHost host) { this.settings = new Settings(ctx); this.host = host; minBufferSize = AudioTrack.getMinBufferSize( MumbleProtocol.SAMPLE_RATE, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT); // Double the buffer size to reduce stuttering. final int desiredBufferSize = minBufferSize * 2; // Resolve the minimum frame count that fills the minBuffer requirement. final int frameCount = (int) Math.ceil((double) desiredBufferSize / MumbleProtocol.FRAME_SIZE); bufferSize = frameCount * MumbleProtocol.FRAME_SIZE; at = new AudioTrack( settings.getAudioStream(), MumbleProtocol.SAMPLE_RATE, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT, bufferSize, AudioTrack.MODE_STREAM); // Set this here so this.start(); this.shouldRun = false; doesn't // result in run() setting shouldRun to true afterwards and continuing // running. shouldRun = true; }
/** * Handles activity initialization when the Service has connected. * * <p>Should be called when there is a reason to believe that the connection might have became * valid. The connection MUST be established but other validity criteria may still be unfilled * such as server synchronization being complete. * * <p>The method implements the logic required for making sure that the Connected service is in * such a state that it fills all the connection criteria for ChannelList. * * <p>The method also takes care of making sure that its initialization code is executed only once * so calling it several times doesn't cause problems. */ protected void onConnected() { // Tell the service that we are now visible. mService.setActivityVisible(true); // Update user control updateUserControlMenuItems(); // Restore push to talk state, if toggled. Otherwise make sure it's turned off. if (settings.isPushToTalk() && mService.isRecording()) { if (settings.isPushToTalkToggle() && settings.isPushToTalkButtonShown()) setPushToTalk(true); else mService.setPushToTalk(false); } if (settings.isPushToTalk() && mService.isRecording()) if (chatTarget != null) { listFragment.setChatTarget(chatTarget); chatFragment.setChatTarget(chatTarget); } }
public void addFrameToBuffer(final User u, final PacketDataStream pds, final int flags) { AudioUser user = users.get(u); if (user == null) { user = new AudioUser(u, settings.isJitterBuffer()); users.put(u, user); // Don't add the user to userPackets yet. The collection should // have only users with ready frames. Since this method is // called only from the TCP connection thread it will never // create a new AudioUser while a previous one is still decoding. } user.addFrameToBuffer(pds, packetReadyHandler); }
/** Connects to the passed 'Server' object. */ public void connectToServer(Server server) { this.connectedServer = server; String plumbleVersion; try { plumbleVersion = getPackageManager().getPackageInfo(getPackageName(), 0).versionName; } catch (NameNotFoundException e) { plumbleVersion = "???"; } final String certificatePath = settings.getCertificatePath(); final String certificatePassword = settings.getCertificatePassword(); mProtocolHost = new ServiceProtocolHost(); mConnectionHost = new ServiceConnectionHost(); mAudioHost = new ServiceAudioOutputHost(); mClient = new MumbleConnection( mConnectionHost, plumbleVersion, connectedServer.getHost(), connectedServer.getPort(), connectedServer.getUsername(), connectedServer.getPassword(), certificatePath, certificatePassword, settings.isTcpForced(), settings.isOpusDisabled()); mProtocol = new MumbleProtocol(mProtocolHost, mAudioHost, mClient, getApplicationContext()); mClientThread = mClient.start(mProtocol); // Acquire wake lock wakeLock.acquire(); // Enable TTS tts = new TextToSpeech(this, this); }
@Override public boolean onKeyDown(final int keyCode, final KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) { final AlertDialog.Builder b = new AlertDialog.Builder(this); b.setTitle(R.string.disconnect); b.setMessage(R.string.disconnectSure); b.setPositiveButton(android.R.string.yes, onDisconnectConfirm); b.setNegativeButton(android.R.string.no, null); b.show(); return true; } // Push to talk hardware key if (settings.isPushToTalk() && keyCode == settings.getPushToTalkKey() && event.getAction() == KeyEvent.ACTION_DOWN) { setPushToTalk(true); return true; } return super.onKeyDown(keyCode, event); }
public void setPushToTalk(final boolean state) { if (mProtocol == null || mProtocol.currentUser == null) return; Assert.assertTrue( "Push to talk not on, but setPushToTalk called!", !settings.isVoiceActivity()); if (state) { mAudioHost.setTalkState(getCurrentUser(), AudioOutputHost.STATE_TALKING); mAudioInput.startRecording(); } else { mAudioHost.setTalkState(getCurrentUser(), AudioOutputHost.STATE_PASSIVE); mAudioInput.stopRecording(); } }
// Settings observer @Override public void update(Observable observable, Object data) { Settings settings = (Settings) observable; if (data.equals(Settings.OBSERVER_KEY_ALL)) { // Create PTT overlay dismissPTTOverlay(); if (settings.isPushToTalk() && !settings.getHotCorner().equals(Settings.ARRAY_HOT_CORNER_NONE)) { createPTTOverlay(); } // Handle voice activity try { mAudioInput .stopRecordingAndBlock(); // We block because we want to wait before restarting // recording to avoid a concurrent modificatione exception. } catch (InterruptedException e) { e.printStackTrace(); } finally { if (settings.isVoiceActivity()) mAudioInput.startRecording(); } } }
@Override protected void onPause() { super.onPause(); if (settings.getCallMode().equals(Settings.ARRAY_CALL_MODE_VOICE)) setProximityEnabled(false); if (mService != null) { mService.setActivityVisible(false); // Turn off push to talk when rotating so it doesn't get stuck on, except if it's in toggled // state. // if(settings.isPushToTalk() && !mTalkToggleBox.isChecked()) { // mService.setRecording(false); // } } }
/** * Creates a system overlay that allows the user to touch the corner of the screen to push to * talk. */ public void createPTTOverlay() { WindowManager.LayoutParams pttParams = new WindowManager.LayoutParams( WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.TYPE_SYSTEM_ALERT, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH, PixelFormat.TRANSLUCENT); String hotCorner = settings.getHotCorner(); if (hotCorner.equals(Settings.ARRAY_HOT_CORNER_TOP_LEFT)) { pttParams.gravity = Gravity.LEFT | Gravity.TOP; } else if (hotCorner.equals(Settings.ARRAY_HOT_CORNER_BOTTOM_LEFT)) { pttParams.gravity = Gravity.LEFT | Gravity.BOTTOM; } else if (hotCorner.equals(Settings.ARRAY_HOT_CORNER_TOP_RIGHT)) { pttParams.gravity = Gravity.RIGHT | Gravity.TOP; } else if (hotCorner.equals(Settings.ARRAY_HOT_CORNER_BOTTOM_RIGHT)) { pttParams.gravity = Gravity.RIGHT | Gravity.BOTTOM; } WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE); LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE); overlayView = inflater.inflate(R.layout.overlay, null); final Vibrator vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE); overlayView.setOnTouchListener( new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { setPushToTalk(true); // Vibrate to provide haptic feedback vibrator.vibrate(10); overlayView.setBackgroundColor(0xAA33b5e5); } else if (event.getAction() == MotionEvent.ACTION_UP) { setPushToTalk(false); overlayView.setBackgroundColor(0); } return false; } }); // Add layout to window manager wm.addView(overlayView, pttParams); }
@Override public void onCreate() { super.onCreate(); // Make sure our notification is gone. hideNotification(); settings = Settings.getInstance(this); PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE); wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "plumbleLock"); Log.i(Globals.LOG_TAG, "MumbleService: Created"); serviceState = CONNECTION_STATE_DISCONNECTED; chatFormatter = new PlumbleChatFormatter(this); dbAdapter = new DbAdapter(this); dbAdapter.open(); }
/** * Handles activity initialization when the Service has connected. * * <p>Should be called when there is a reason to believe that the connection might have became * valid. The connection MUST be established but other validity criteria may still be unfilled * such as server synchronization being complete. * * <p>The method implements the logic required for making sure that the Connected service is in * such a state that it fills all the connection criteria for ChannelList. * * <p>The method also takes care of making sure that its initialization code is executed only once * so calling it several times doesn't cause problems. */ protected void onConnected() { // Tell the service that we are now visible. mService.setActivityVisible(true); // Update user control updateUserControlMenuItems(); // Restore push to talk state, if toggled. Otherwise make sure it's turned off. if (settings.isPushToTalk() && mService.isRecording()) { if (settings.isPushToTalkToggle() && settings.isPushToTalkButtonShown()) setPushToTalk(true); else mService.setPushToTalk(false); } if (settings.isPushToTalk() && mService.isRecording()) if (chatTarget != null) { listFragment.setChatTarget(chatTarget); chatFragment.setChatTarget(chatTarget); } // Showcase hints List<ShowcaseView> showcaseViews = new ArrayList<ShowcaseView>(); if (settings.isPushToTalk() && settings.isPushToTalkButtonShown()) { ConfigOptions pttConfig = new ConfigOptions(); pttConfig.shotType = ShowcaseView.TYPE_ONE_SHOT; pttConfig.showcaseId = Globals.SHOWCASE_PUSH_TO_TALK; showcaseViews.add( ShowcaseView.insertShowcaseView( pttView, this, R.string.hint_ptt, R.string.hint_ptt_summary, pttConfig)); } if (mViewPager != null) { ConfigOptions switcherConfig = new ConfigOptions(); switcherConfig.shotType = ShowcaseView.TYPE_ONE_SHOT; switcherConfig.showcaseId = Globals.SHOWCASE_SWITCHER; showcaseViews.add( ShowcaseView.insertShowcaseView( ShowcaseView.ITEM_ACTION_HOME, 0, this, R.string.hint_switching, R.string.hint_switching_summary, switcherConfig)); } ShowcaseViewQueue queue = new ShowcaseViewQueue(showcaseViews); queue.queueNext(); }
private void updatePTTConfiguration() { pttView.setVisibility( settings.isPushToTalk() && settings.isPushToTalkButtonShown() ? View.VISIBLE : View.GONE); }
@Override public void onCreate(Bundle savedInstanceState) { settings = Settings.getInstance(this); settings.addObserver(this); // Use theme from settings int theme = 0; if (settings.getTheme().equals(Settings.ARRAY_THEME_LIGHTDARK)) { theme = R.style.Theme_Sherlock_Light_DarkActionBar; } else if (settings.getTheme().equals(Settings.ARRAY_THEME_DARK)) { theme = R.style.Theme_Sherlock; } setTheme(theme); super.onCreate(savedInstanceState); setContentView(R.layout.activity_channel); // Bind to service Intent serviceIntent = new Intent(this, MumbleService.class); bindService(serviceIntent, conn, 0); // Register bluetooth SCO monitor registerReceiver( bluetoothReceiver, new IntentFilter(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED)); // Handle differences in CallMode String callMode = settings.getCallMode(); setVolumeControlStream( Settings.ARRAY_CALL_MODE_SPEAKER.equals(callMode) ? AudioManager.STREAM_MUSIC : AudioManager.STREAM_VOICE_CALL); // Set up proximity sensor PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE); proximityLock = powerManager.newWakeLock(PROXIMITY_SCREEN_OFF_WAKE_LOCK, Globals.LOG_TAG); // Set up PTT button. mTalkButton = (Button) findViewById(R.id.pushtotalk); pttView = findViewById(R.id.pushtotalk_view); mTalkButton.setOnTouchListener( new OnTouchListener() { private static final int TOGGLE_INTERVAL = 250; // 250ms is the interval needed to toggle push to talk. private long lastTouch = 0; @Override public boolean onTouch(View v, MotionEvent event) { if (mService == null) { return false; } if (event.getAction() == MotionEvent.ACTION_DOWN && !settings.isPushToTalkToggle()) { setPushToTalk(true); } else if (event.getAction() == MotionEvent.ACTION_UP) { if (settings.isPushToTalkToggle()) setPushToTalk(!mService.isRecording()); else { if (System.currentTimeMillis() - lastTouch <= TOGGLE_INTERVAL) { // Do nothing. We leave the push to talk on, as it has toggled. } else { setPushToTalk(false); lastTouch = System.currentTimeMillis(); } } } return true; // We return true so that the selector that changes the background does not // fire. } }); updatePTTConfiguration(); mViewPager = (ViewPager) findViewById(R.id.pager); FragmentManager fragmentManager = getSupportFragmentManager(); listFragment = (ChannelListFragment) fragmentManager.findFragmentByTag(LIST_FRAGMENT_TAG); chatFragment = (ChannelChatFragment) fragmentManager.findFragmentByTag(CHAT_FRAGMENT_TAG); FragmentTransaction remove = fragmentManager.beginTransaction(); if (listFragment == null) listFragment = new ChannelListFragment(); else remove.remove(listFragment); if (chatFragment == null) chatFragment = new ChannelChatFragment(); else remove.remove(chatFragment); if (!remove.isEmpty()) { remove.commit(); fragmentManager.executePendingTransactions(); } if (mViewPager != null) { // Set up the ViewPager with the sections adapter. mViewPager.setOnPageChangeListener( new OnPageChangeListener() { @Override public void onPageSelected(int arg0) { // Hide keyboard if moving to channel list. if (arg0 == 0) { InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(mViewPager.getApplicationWindowToken(), 0); } // Update indicator channelsIndicator.setVisibility(arg0 == 0 ? View.VISIBLE : View.INVISIBLE); chatIndicator.setVisibility(arg0 == 1 ? View.VISIBLE : View.INVISIBLE); } @Override public void onPageScrolled(int arg0, float arg1, int arg2) {} @Override public void onPageScrollStateChanged(int arg0) {} }); // Set up tabs getSupportActionBar().setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM); View channelTabView = getLayoutInflater().inflate(R.layout.channel_tab_view, null); channelsIndicator = channelTabView.findViewById(R.id.tab_channels_indicator); chatIndicator = channelTabView.findViewById(R.id.tab_chat_indicator); ImageButton channelsButton = (ImageButton) channelTabView.findViewById(R.id.tab_channels); ImageButton chatButton = (ImageButton) channelTabView.findViewById(R.id.tab_chat); channelsButton.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { mViewPager.setCurrentItem(0, true); } }); chatButton.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { mViewPager.setCurrentItem(1, true); } }); getSupportActionBar().setCustomView(channelTabView); // Setup a pager that will return a fragment for each of the two primary sections of the app. mSectionsPagerAdapter = new PlumbleSectionsPagerAdapter( this, getSupportFragmentManager(), listFragment, chatFragment); mViewPager.setAdapter(mSectionsPagerAdapter); } else { // Create tablet UI leftSplit = findViewById(R.id.left_split); rightSplit = findViewById(R.id.right_split); fragmentManager .beginTransaction() .add(R.id.chat_fragment, chatFragment, CHAT_FRAGMENT_TAG) .add(R.id.list_fragment, listFragment, LIST_FRAGMENT_TAG) .commit(); } if (savedInstanceState != null) { chatTarget = (User) savedInstanceState.getParcelable(SAVED_STATE_CHAT_TARGET); } }
public void setDeafened(final boolean state) { if (mAudioHost != null && mProtocol != null && mProtocol.currentUser != null) { mAudioHost.setSelfDeafened(mProtocol.currentUser, state); settings.setMutedAndDeafened(state, state); } }