Compare commits

...

9 Commits

Author SHA1 Message Date
Cameron Gutman 5efcd606e3 Increment version to 2.2 2014-05-07 02:12:21 -04:00
Cameron Gutman 3524cdd764 Add TinyRTSP Jar 2014-05-07 02:12:07 -04:00
Cameron Gutman 368cd8808d Add support for selecting stream bitrate. 2014-05-07 02:11:10 -04:00
Cameron Gutman b52a6ce93c Merge branch 'master' of github.com:cgutman/limelight 2014-05-06 10:25:10 -04:00
Cameron Gutman 7ab4e5d0a5 Bump version to 2.1.6 2014-05-06 10:24:34 -04:00
Cameron Gutman 095dfd8035 Update common 2014-05-06 10:24:21 -04:00
Cameron Gutman f7c33ef975 Display the same warning when trying to pair without an IP address supplied as we do when trying to stream 2014-05-06 10:23:39 -04:00
Aaron Neyer 57b0bce5a4 update some wording for internet streaming 2014-05-02 12:14:52 -04:00
Cameron Gutman 7a017d7b97 Make the d-pad center button emulate the A button so remotes with only d-pad buttons are usable in the Steam UI 2014-04-21 17:40:50 -04:00
9 changed files with 129 additions and 25 deletions
+2 -2
View File
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.limelight"
android:versionCode="11"
android:versionName="2.1.5" >
android:versionCode="13"
android:versionName="2.2" >
<uses-sdk
android:minSdkVersion="16"
+5 -6
View File
@@ -3,10 +3,8 @@
Limelight is an open source implementation of NVIDIA's GameStream, as used by the NVIDIA Shield.
We reverse engineered the Shield streaming software, and created a version that can be run on any Android device.
Limelight will allow you to stream your full collection of Steam games from your Windows PC to your Android device on the same network.
Streaming can be done remotely using the [Shield Proxy](http://forum.xda-developers.com/showthread.php?t=2435481)
application.
Limelight will allow you to stream your full collection of Steam games from your Windows PC to your Android device,
in your own home, or over the internet.
[Limelight-pc](https://github.com/limelight-stream/limelight-pc) is also currently in development for Windows, OS X and Linux. Versions for [iOS](https://github.com/limelight-stream/limelight-ios) and [Windows Phone](https://github.com/limelight-stream/limelight-wp) are also in development.
@@ -36,9 +34,10 @@ application.
##Usage
* Ensure your Android device and your PC are on the same network or you're running [Shield Proxy](http://forum.xda-developers.com/showthread.php?t=2435481).
* Turn on Shield Streaming in the GFE settings
* In Limelight, enter your PC's IP or Hostname and click "Pair".
* If you are connecting from outside the same network, turn on internet
streaming
* In Limelight, enter your PC's IP or Hostname and click "Pair"
* Accept the pairing confirmation on your PC
* In Limelight, click "Start Streaming"
* Play games!
+12 -9
View File
@@ -35,18 +35,21 @@ or to a theme attribute in the form "<code>?[<i>package</i>:][<i>type</i>:]<i>na
public static final int ic_launcher=0x7f020000;
}
public static final class id {
public static final int autoDec=0x7f080005;
public static final int config1080p30Selected=0x7f080009;
public static final int config1080p60Selected=0x7f08000a;
public static final int config720p30Selected=0x7f080007;
public static final int config720p60Selected=0x7f080008;
public static final int hardwareDec=0x7f080006;
public static final int autoDec=0x7f080006;
public static final int bitrateLabel=0x7f08000c;
public static final int bitrateSeekBar=0x7f08000d;
public static final int config1080p30Selected=0x7f08000a;
public static final int config1080p60Selected=0x7f08000b;
public static final int config720p30Selected=0x7f080008;
public static final int config720p60Selected=0x7f080009;
public static final int decoderConfigGroup=0x7f080003;
public static final int hardwareDec=0x7f080007;
public static final int hostTextView=0x7f080000;
public static final int pairButton=0x7f080002;
public static final int softwareDec=0x7f080004;
public static final int softwareDec=0x7f080005;
public static final int statusButton=0x7f080001;
public static final int streamConfigGroup=0x7f080003;
public static final int surfaceView=0x7f08000b;
public static final int streamConfigGroup=0x7f080004;
public static final int surfaceView=0x7f08000e;
}
public static final class layout {
public static final int activity_connection=0x7f030000;
Binary file not shown.
BIN
View File
Binary file not shown.
+21 -2
View File
@@ -45,12 +45,13 @@
android:text="Pair with PC" />
<RadioGroup
android:id="@+id/decoderConfigGroup"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_below="@+id/streamConfigGroup"
android:layout_marginTop="25dp"
android:layout_marginTop="15dp"
android:orientation="vertical" >
<RadioButton
@@ -79,7 +80,7 @@
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_below="@+id/pairButton"
android:layout_marginTop="25dp"
android:layout_marginTop="10dp"
android:orientation="vertical" >
<RadioButton
@@ -110,6 +111,24 @@
android:text="1080p 60 FPS (Requires extremely fast device and network)" />
</RadioGroup>
<TextView
android:id="@+id/bitrateLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginTop="10dp"
android:layout_alignParentRight="true"
android:layout_below="@+id/decoderConfigGroup" />
<SeekBar
android:id="@+id/bitrateSeekBar"
android:layout_marginTop="10dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="@+id/decoderConfigGroup"
android:layout_toLeftOf="@+id/bitrateLabel" />
</RelativeLayout>
</ScrollView>
+70 -4
View File
@@ -20,6 +20,8 @@ import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.RadioButton;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;
import android.widget.Toast;
import android.app.Activity;
@@ -33,6 +35,8 @@ public class Connection extends Activity {
private SharedPreferences prefs;
private RadioButton rbutton720p30, rbutton720p60, rbutton1080p30, rbutton1080p60;
private RadioButton forceSoftDec, autoDec, forceHardDec;
private SeekBar bitrateSlider;
private TextView bitrateLabel;
private static final String DEFAULT_HOST = "";
public static final String HOST_KEY = "hostText";
@@ -42,6 +46,7 @@ public class Connection extends Activity {
SharedPreferences.Editor editor = prefs.edit();
editor.putString(Connection.HOST_KEY, this.hostText.getText().toString());
editor.putInt(Game.BITRATE_PREF_STRING, bitrateSlider.getProgress());
editor.apply();
super.onPause();
@@ -66,12 +71,18 @@ public class Connection extends Activity {
this.forceSoftDec = (RadioButton) findViewById(R.id.softwareDec);
this.autoDec = (RadioButton) findViewById(R.id.autoDec);
this.forceHardDec = (RadioButton) findViewById(R.id.hardwareDec);
this.bitrateLabel = (TextView) findViewById(R.id.bitrateLabel);
this.bitrateSlider = (SeekBar) findViewById(R.id.bitrateSeekBar);
prefs = getSharedPreferences(Game.PREFS_FILE_NAME, Context.MODE_MULTI_PROCESS);
this.hostText.setText(prefs.getString(Connection.HOST_KEY, Connection.DEFAULT_HOST));
boolean res720p = prefs.getInt(Game.HEIGHT_PREF_STRING, Game.DEFAULT_HEIGHT) == 720;
boolean fps30 = prefs.getInt(Game.REFRESH_RATE_PREF_STRING, Game.DEFAULT_REFRESH_RATE) == 30;
bitrateSlider.setMax(Game.BITRATE_CEILING);
bitrateSlider.setProgress(prefs.getInt(Game.BITRATE_PREF_STRING, Game.DEFAULT_BITRATE));
updateBitrateLabel();
rbutton720p30.setChecked(false);
rbutton720p60.setChecked(false);
@@ -124,22 +135,30 @@ public class Connection extends Activity {
if (buttonView == rbutton720p30) {
prefs.edit().putInt(Game.WIDTH_PREF_STRING, 1280).
putInt(Game.HEIGHT_PREF_STRING, 720).
putInt(Game.REFRESH_RATE_PREF_STRING, 30).commit();
putInt(Game.REFRESH_RATE_PREF_STRING, 30).
putInt(Game.BITRATE_PREF_STRING, Game.BITRATE_DEFAULT_720_30).commit();
bitrateSlider.setProgress(Game.BITRATE_DEFAULT_720_30);
}
else if (buttonView == rbutton720p60) {
prefs.edit().putInt(Game.WIDTH_PREF_STRING, 1280).
putInt(Game.HEIGHT_PREF_STRING, 720).
putInt(Game.REFRESH_RATE_PREF_STRING, 60).commit();
putInt(Game.REFRESH_RATE_PREF_STRING, 60).
putInt(Game.BITRATE_PREF_STRING, Game.BITRATE_DEFAULT_720_60).commit();
bitrateSlider.setProgress(Game.BITRATE_DEFAULT_720_60);
}
else if (buttonView == rbutton1080p30) {
prefs.edit().putInt(Game.WIDTH_PREF_STRING, 1920).
putInt(Game.HEIGHT_PREF_STRING, 1080).
putInt(Game.REFRESH_RATE_PREF_STRING, 30).commit();
putInt(Game.REFRESH_RATE_PREF_STRING, 30).
putInt(Game.BITRATE_PREF_STRING, Game.BITRATE_DEFAULT_1080_30).commit();
bitrateSlider.setProgress(Game.BITRATE_DEFAULT_1080_30);
}
else if (buttonView == rbutton1080p60) {
prefs.edit().putInt(Game.WIDTH_PREF_STRING, 1920).
putInt(Game.HEIGHT_PREF_STRING, 1080).
putInt(Game.REFRESH_RATE_PREF_STRING, 60).commit();
putInt(Game.REFRESH_RATE_PREF_STRING, 60).
putInt(Game.BITRATE_PREF_STRING, Game.BITRATE_DEFAULT_1080_60).commit();
bitrateSlider.setProgress(Game.BITRATE_DEFAULT_1080_60);
}
else if (buttonView == forceSoftDec) {
prefs.edit().putInt(Game.DECODER_PREF_STRING, Game.FORCE_SOFTWARE_DECODER).commit();
@@ -160,6 +179,45 @@ public class Connection extends Activity {
forceHardDec.setOnCheckedChangeListener(occl);
autoDec.setOnCheckedChangeListener(occl);
this.bitrateSlider.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
// Verify the user's selection
if (fromUser) {
int floor;
if (rbutton720p30.isChecked()) {
floor = Game.BITRATE_FLOOR_720_30;
}
else if (rbutton720p60.isChecked()){
floor = Game.BITRATE_FLOOR_720_60;
}
else if (rbutton1080p30.isChecked()){
floor = Game.BITRATE_FLOOR_1080_30;
}
else /*if (rbutton1080p60.isChecked())*/ {
floor = Game.BITRATE_FLOOR_1080_60;
}
if (progress < floor) {
seekBar.setProgress(floor);
return;
}
}
updateBitrateLabel();
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
this.statusButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
@@ -177,6 +235,11 @@ public class Connection extends Activity {
this.pairButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
if (Connection.this.hostText.getText().length() == 0) {
Toast.makeText(Connection.this, "Please enter the target PC's IP address in the text box at the top of the screen.", Toast.LENGTH_LONG).show();
return;
}
Toast.makeText(Connection.this, "Pairing...", Toast.LENGTH_LONG).show();
new Thread(new Runnable() {
@Override
@@ -235,4 +298,7 @@ public class Connection extends Activity {
}
private void updateBitrateLabel() {
bitrateLabel.setText(bitrateSlider.getProgress()+" Mbps");
}
}
+17 -2
View File
@@ -63,11 +63,25 @@ public class Game extends Activity implements SurfaceHolder.Callback, OnGenericM
public static final String HEIGHT_PREF_STRING = "ResV";
public static final String REFRESH_RATE_PREF_STRING = "FPS";
public static final String DECODER_PREF_STRING = "Decoder";
public static final String BITRATE_PREF_STRING = "Bitrate";
public static final int BITRATE_FLOOR_720_30 = 4;
public static final int BITRATE_FLOOR_720_60 = 8;
public static final int BITRATE_FLOOR_1080_30 = 10;
public static final int BITRATE_FLOOR_1080_60 = 20;
public static final int BITRATE_DEFAULT_720_30 = 7;
public static final int BITRATE_DEFAULT_720_60 = 10;
public static final int BITRATE_DEFAULT_1080_30 = 16;
public static final int BITRATE_DEFAULT_1080_60 = 30;
public static final int BITRATE_CEILING = 50;
public static final int DEFAULT_WIDTH = 1280;
public static final int DEFAULT_HEIGHT = 720;
public static final int DEFAULT_REFRESH_RATE = 60;
public static final int DEFAULT_DECODER = 0;
public static final int DEFAULT_BITRATE = BITRATE_DEFAULT_720_60;
public static final int FORCE_HARDWARE_DECODER = -1;
public static final int AUTOSELECT_DECODER = 0;
@@ -116,10 +130,11 @@ public class Game extends Activity implements SurfaceHolder.Callback, OnGenericM
break;
}
int refreshRate;
int refreshRate, bitrate;
width = prefs.getInt(WIDTH_PREF_STRING, DEFAULT_WIDTH);
height = prefs.getInt(HEIGHT_PREF_STRING, DEFAULT_HEIGHT);
refreshRate = prefs.getInt(REFRESH_RATE_PREF_STRING, DEFAULT_REFRESH_RATE);
bitrate = prefs.getInt(BITRATE_PREF_STRING, DEFAULT_BITRATE);
sh.setFixedSize(width, height);
Display display = getWindowManager().getDefaultDisplay();
@@ -130,7 +145,7 @@ public class Game extends Activity implements SurfaceHolder.Callback, OnGenericM
// Start the connection
conn = new NvConnection(Game.this.getIntent().getStringExtra("host"), Game.this,
new StreamConfiguration(width, height, refreshRate));
new StreamConfiguration(width, height, refreshRate, bitrate * 1000));
keybTranslator = new KeyboardTranslator(conn);
controllerHandler = new ControllerHandler(conn);
@@ -325,6 +325,7 @@ public class ControllerHandler {
case KeyEvent.KEYCODE_BUTTON_B:
inputMap &= ~ControllerPacket.B_FLAG;
break;
case KeyEvent.KEYCODE_DPAD_CENTER:
case KeyEvent.KEYCODE_BUTTON_A:
inputMap &= ~ControllerPacket.A_FLAG;
break;
@@ -405,6 +406,7 @@ public class ControllerHandler {
case KeyEvent.KEYCODE_BUTTON_B:
inputMap |= ControllerPacket.B_FLAG;
break;
case KeyEvent.KEYCODE_DPAD_CENTER:
case KeyEvent.KEYCODE_BUTTON_A:
inputMap |= ControllerPacket.A_FLAG;
break;