mirror of
https://github.com/moonlight-stream/moonlight-android.git
synced 2025-07-20 11:33:06 +00:00
Italian translation: update
This commit is contained in:
commit
f262503bc8
@ -11,8 +11,8 @@ android {
|
||||
minSdkVersion 16
|
||||
targetSdkVersion 21
|
||||
|
||||
versionName "3.0-beta1.01"
|
||||
versionCode = 41
|
||||
versionName "3.0-beta2"
|
||||
versionCode = 43
|
||||
}
|
||||
|
||||
productFlavors {
|
||||
|
Binary file not shown.
@ -64,6 +64,7 @@
|
||||
<activity
|
||||
android:name=".Game"
|
||||
android:screenOrientation="sensorLandscape"
|
||||
android:theme="@style/StreamTheme"
|
||||
android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|screenLayout|fontScale|uiMode|orientation|screenSize|smallestScreenSize|layoutDirection" >
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
|
@ -155,6 +155,7 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
String host = Game.this.getIntent().getStringExtra(EXTRA_HOST);
|
||||
String app = Game.this.getIntent().getStringExtra(EXTRA_APP);
|
||||
String uniqueId = Game.this.getIntent().getStringExtra(EXTRA_UNIQUEID);
|
||||
boolean remote = Game.this.getIntent().getBooleanExtra(EXTRA_STREAMING_REMOTE, false);
|
||||
|
||||
decoderRenderer = new ConfigurableDecoderRenderer();
|
||||
decoderRenderer.initializeWithFlags(drFlags);
|
||||
@ -168,6 +169,7 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
.enableAdaptiveResolution((decoderRenderer.getCapabilities() &
|
||||
VideoDecoderRenderer.CAPABILITY_ADAPTIVE_RESOLUTION) != 0)
|
||||
.enableLocalAudioPlayback(prefConfig.playHostAudio)
|
||||
.setMaxPacketSize(remote ? 1024 : 1392)
|
||||
.build();
|
||||
|
||||
// Initialize the connection
|
||||
|
@ -324,7 +324,8 @@ public class PcView extends Activity {
|
||||
message = getResources().getString(R.string.pair_fail);
|
||||
}
|
||||
else if (pairState == PairingManager.PairState.PAIRED) {
|
||||
message = getResources().getString(R.string.pair_success);
|
||||
// Just navigate to the app view without displaying a toast
|
||||
message = null;
|
||||
success = true;
|
||||
}
|
||||
else {
|
||||
|
@ -5,7 +5,6 @@ import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.concurrent.locks.LockSupport;
|
||||
|
||||
import android.graphics.PixelFormat;
|
||||
import android.os.Build;
|
||||
@ -21,14 +20,14 @@ import com.limelight.nvstream.av.video.cpu.AvcDecoder;
|
||||
@SuppressWarnings("EmptyCatchBlock")
|
||||
public class AndroidCpuDecoderRenderer implements VideoDecoderRenderer {
|
||||
|
||||
private Thread rendererThread;
|
||||
private Thread rendererThread, decoderThread;
|
||||
private int targetFps;
|
||||
|
||||
private static final int DECODER_BUFFER_SIZE = 92*1024;
|
||||
private ByteBuffer decoderBuffer;
|
||||
|
||||
// Only sleep if the difference is above this value
|
||||
private static final int WAIT_CEILING_MS = 8;
|
||||
private static final int WAIT_CEILING_MS = 5;
|
||||
|
||||
private static final int LOW_PERF = 1;
|
||||
private static final int MED_PERF = 2;
|
||||
@ -108,9 +107,7 @@ public class AndroidCpuDecoderRenderer implements VideoDecoderRenderer {
|
||||
|
||||
case LOW_PERF:
|
||||
// Disable the loop filter for performance reasons
|
||||
avcFlags = AvcDecoder.DISABLE_LOOP_FILTER |
|
||||
AvcDecoder.FAST_BILINEAR_FILTERING |
|
||||
AvcDecoder.FAST_DECODE;
|
||||
avcFlags = AvcDecoder.FAST_BILINEAR_FILTERING;
|
||||
|
||||
// Use plenty of threads to try to utilize the CPU as best we can
|
||||
threadCount = cpuCount - 1;
|
||||
@ -118,8 +115,7 @@ public class AndroidCpuDecoderRenderer implements VideoDecoderRenderer {
|
||||
|
||||
default:
|
||||
case MED_PERF:
|
||||
avcFlags = AvcDecoder.BILINEAR_FILTERING |
|
||||
AvcDecoder.FAST_DECODE;
|
||||
avcFlags = AvcDecoder.BILINEAR_FILTERING;
|
||||
|
||||
// Only use 2 threads to minimize frame processing latency
|
||||
threadCount = 2;
|
||||
@ -156,6 +152,26 @@ public class AndroidCpuDecoderRenderer implements VideoDecoderRenderer {
|
||||
|
||||
@Override
|
||||
public boolean start(final VideoDepacketizer depacketizer) {
|
||||
decoderThread = new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
DecodeUnit du;
|
||||
while (!isInterrupted()) {
|
||||
try {
|
||||
du = depacketizer.takeNextDecodeUnit();
|
||||
} catch (InterruptedException e) {
|
||||
break;
|
||||
}
|
||||
|
||||
submitDecodeUnit(du);
|
||||
depacketizer.freeDecodeUnit(du);
|
||||
}
|
||||
}
|
||||
};
|
||||
decoderThread.setName("Video - Decoder (CPU)");
|
||||
decoderThread.setPriority(Thread.MAX_PRIORITY - 1);
|
||||
decoderThread.start();
|
||||
|
||||
rendererThread = new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
@ -163,17 +179,15 @@ public class AndroidCpuDecoderRenderer implements VideoDecoderRenderer {
|
||||
DecodeUnit du;
|
||||
while (!isInterrupted())
|
||||
{
|
||||
du = depacketizer.pollNextDecodeUnit();
|
||||
if (du != null) {
|
||||
submitDecodeUnit(du);
|
||||
depacketizer.freeDecodeUnit(du);
|
||||
}
|
||||
|
||||
long diff = nextFrameTime - System.currentTimeMillis();
|
||||
|
||||
if (diff > WAIT_CEILING_MS) {
|
||||
LockSupport.parkNanos(1);
|
||||
continue;
|
||||
try {
|
||||
Thread.sleep(diff - WAIT_CEILING_MS);
|
||||
} catch (InterruptedException e) {
|
||||
return;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
nextFrameTime = computePresentationTimeMs(targetFps);
|
||||
@ -194,10 +208,14 @@ public class AndroidCpuDecoderRenderer implements VideoDecoderRenderer {
|
||||
@Override
|
||||
public void stop() {
|
||||
rendererThread.interrupt();
|
||||
decoderThread.interrupt();
|
||||
|
||||
try {
|
||||
rendererThread.join();
|
||||
} catch (InterruptedException e) { }
|
||||
rendererThread.join();
|
||||
} catch (InterruptedException e) { }
|
||||
try {
|
||||
decoderThread.join();
|
||||
} catch (InterruptedException e) { }
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,8 +1,7 @@
|
||||
package com.limelight.computers;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.LinkedList;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import com.limelight.LimeLog;
|
||||
@ -21,7 +20,7 @@ import android.os.Binder;
|
||||
import android.os.IBinder;
|
||||
|
||||
public class ComputerManagerService extends Service {
|
||||
private static final int POLLING_PERIOD_MS = 5000;
|
||||
private static final int POLLING_PERIOD_MS = 3000;
|
||||
private static final int MDNS_QUERY_PERIOD_MS = 1000;
|
||||
|
||||
private ComputerManagerBinder binder = new ComputerManagerBinder();
|
||||
@ -30,9 +29,10 @@ public class ComputerManagerService extends Service {
|
||||
private AtomicInteger dbRefCount = new AtomicInteger(0);
|
||||
|
||||
private IdentityManager idManager;
|
||||
private final HashMap<ComputerDetails, Thread> pollingThreads = new HashMap<ComputerDetails, Thread>();
|
||||
private final LinkedList<PollingTuple> pollingTuples = new LinkedList<PollingTuple>();
|
||||
private ComputerManagerListener listener = null;
|
||||
private AtomicInteger activePolls = new AtomicInteger(0);
|
||||
private boolean pollingActive = false;
|
||||
|
||||
private DiscoveryService.DiscoveryBinder discoveryBinder;
|
||||
private final ServiceConnection discoveryServiceConnection = new ServiceConnection() {
|
||||
@ -101,18 +101,9 @@ public class ComputerManagerService extends Service {
|
||||
Thread t = new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
while (!isInterrupted()) {
|
||||
ComputerDetails originalDetails = new ComputerDetails();
|
||||
originalDetails.update(details);
|
||||
|
||||
while (!isInterrupted() && pollingActive) {
|
||||
// Check if this poll has modified the details
|
||||
if (runPoll(details) && !originalDetails.equals(details)) {
|
||||
// Replace our thread entry with the new one
|
||||
synchronized (pollingThreads) {
|
||||
pollingThreads.remove(originalDetails);
|
||||
pollingThreads.put(details, this);
|
||||
}
|
||||
}
|
||||
runPoll(details);
|
||||
|
||||
// Wait until the next polling interval
|
||||
try {
|
||||
@ -129,29 +120,24 @@ public class ComputerManagerService extends Service {
|
||||
|
||||
public class ComputerManagerBinder extends Binder {
|
||||
public void startPolling(ComputerManagerListener listener) {
|
||||
// Polling is active
|
||||
pollingActive = true;
|
||||
|
||||
// Set the listener
|
||||
ComputerManagerService.this.listener = listener;
|
||||
|
||||
// Start mDNS autodiscovery too
|
||||
discoveryBinder.startDiscovery(MDNS_QUERY_PERIOD_MS);
|
||||
|
||||
// Start polling known machines
|
||||
if (!getLocalDatabaseReference()) {
|
||||
return;
|
||||
}
|
||||
List<ComputerDetails> computerList = dbManager.getAllComputers();
|
||||
releaseLocalDatabaseReference();
|
||||
|
||||
synchronized (pollingThreads) {
|
||||
for (ComputerDetails computer : computerList) {
|
||||
synchronized (pollingTuples) {
|
||||
for (PollingTuple tuple : pollingTuples) {
|
||||
// This polling thread might already be there
|
||||
if (!pollingThreads.containsKey(computer)) {
|
||||
if (tuple.thread == null) {
|
||||
// Report this computer initially
|
||||
listener.notifyComputerUpdated(computer);
|
||||
listener.notifyComputerUpdated(tuple.computer);
|
||||
|
||||
Thread t = createPollingThread(computer);
|
||||
pollingThreads.put(computer, t);
|
||||
t.start();
|
||||
tuple.thread = createPollingThread(tuple.computer);
|
||||
tuple.thread.start();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -205,11 +191,15 @@ public class ComputerManagerService extends Service {
|
||||
discoveryBinder.stopDiscovery();
|
||||
|
||||
// Stop polling
|
||||
synchronized (pollingThreads) {
|
||||
for (Thread t : pollingThreads.values()) {
|
||||
t.interrupt();
|
||||
pollingActive = false;
|
||||
synchronized (pollingTuples) {
|
||||
for (PollingTuple tuple : pollingTuples) {
|
||||
if (tuple.thread != null) {
|
||||
// Interrupt and remove the thread
|
||||
tuple.thread.interrupt();
|
||||
tuple.thread = null;
|
||||
}
|
||||
}
|
||||
pollingThreads.clear();
|
||||
}
|
||||
|
||||
// Remove the listener
|
||||
@ -245,16 +235,37 @@ public class ComputerManagerService extends Service {
|
||||
fakeDetails.localIp = addr;
|
||||
fakeDetails.remoteIp = addr;
|
||||
|
||||
// Spawn a thread for this computer
|
||||
synchronized (pollingThreads) {
|
||||
// This polling thread might already be there
|
||||
if (!pollingThreads.containsKey(fakeDetails)) {
|
||||
Thread t = createPollingThread(fakeDetails);
|
||||
pollingThreads.put(fakeDetails, t);
|
||||
t.start();
|
||||
addTuple(fakeDetails);
|
||||
}
|
||||
|
||||
private void addTuple(ComputerDetails details) {
|
||||
synchronized (pollingTuples) {
|
||||
for (PollingTuple tuple : pollingTuples) {
|
||||
// Check if this is the same computer
|
||||
if (tuple.computer == details ||
|
||||
tuple.computer.localIp.equals(details.localIp) ||
|
||||
tuple.computer.remoteIp.equals(details.remoteIp) ||
|
||||
tuple.computer.name.equals(details.name)) {
|
||||
|
||||
// Start a polling thread if polling is active
|
||||
if (pollingActive && tuple.thread == null) {
|
||||
tuple.thread = createPollingThread(details);
|
||||
tuple.thread.start();
|
||||
}
|
||||
|
||||
// Found an entry so we're done
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// If we got here, we didn't find an entry
|
||||
PollingTuple tuple = new PollingTuple(details, pollingActive ? createPollingThread(details) : null);
|
||||
pollingTuples.add(tuple);
|
||||
if (tuple.thread != null) {
|
||||
tuple.thread.start();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean addComputerBlocking(InetAddress addr) {
|
||||
// Setup a placeholder
|
||||
@ -266,7 +277,14 @@ public class ComputerManagerService extends Service {
|
||||
runPoll(fakeDetails);
|
||||
|
||||
// If the machine is reachable, it was successful
|
||||
return fakeDetails.state == ComputerDetails.State.ONLINE;
|
||||
if (fakeDetails.state == ComputerDetails.State.ONLINE) {
|
||||
// Start a polling thread for this machine
|
||||
addTuple(fakeDetails);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void removeComputer(String name) {
|
||||
@ -276,6 +294,20 @@ public class ComputerManagerService extends Service {
|
||||
|
||||
// Remove it from the database
|
||||
dbManager.deleteComputer(name);
|
||||
|
||||
synchronized (pollingTuples) {
|
||||
// Remove the computer from the computer list
|
||||
for (PollingTuple tuple : pollingTuples) {
|
||||
if (tuple.computer.name.equals(name)) {
|
||||
if (tuple.thread != null) {
|
||||
// Interrupt the thread on this entry
|
||||
tuple.thread.interrupt();
|
||||
}
|
||||
pollingTuples.remove(tuple);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
releaseLocalDatabaseReference();
|
||||
}
|
||||
@ -347,7 +379,18 @@ public class ComputerManagerService extends Service {
|
||||
}
|
||||
|
||||
private boolean doPollMachine(ComputerDetails details) {
|
||||
return pollComputer(details, true);
|
||||
if (details.reachability == ComputerDetails.Reachability.UNKNOWN ||
|
||||
details.reachability == ComputerDetails.Reachability.OFFLINE) {
|
||||
// Always try local first to avoid potential UDP issues when
|
||||
// attempting to stream via the router's external IP address
|
||||
// behind its NAT
|
||||
return pollComputer(details, true);
|
||||
}
|
||||
else {
|
||||
// If we're already reached a machine via a particular IP address,
|
||||
// always try that one first
|
||||
return pollComputer(details, details.reachability == ComputerDetails.Reachability.LOCAL);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -362,6 +405,18 @@ public class ComputerManagerService extends Service {
|
||||
// Initialize the DB
|
||||
dbManager = new ComputerDatabaseManager(this);
|
||||
dbRefCount.set(1);
|
||||
|
||||
// Grab known machines into our computer list
|
||||
if (!getLocalDatabaseReference()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (ComputerDetails computer : dbManager.getAllComputers()) {
|
||||
// Add this computer without a thread
|
||||
pollingTuples.add(new PollingTuple(computer, null));
|
||||
}
|
||||
|
||||
releaseLocalDatabaseReference();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -382,3 +437,13 @@ public class ComputerManagerService extends Service {
|
||||
return binder;
|
||||
}
|
||||
}
|
||||
|
||||
class PollingTuple {
|
||||
public Thread thread;
|
||||
public ComputerDetails computer;
|
||||
|
||||
public PollingTuple(ComputerDetails computer, Thread thread) {
|
||||
this.computer = computer;
|
||||
this.thread = thread;
|
||||
}
|
||||
}
|
@ -148,6 +148,9 @@ public class AppGridAdapter extends GenericGridAdapter<AppView.AppObject> {
|
||||
|
||||
@Override
|
||||
public boolean populateTextView(TextView txtView, AppView.AppObject obj) {
|
||||
// Select the text view so it starts marquee mode
|
||||
txtView.setSelected(true);
|
||||
|
||||
// Return false to use the app's toString method
|
||||
return false;
|
||||
}
|
||||
|
@ -14,6 +14,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:numColumns="auto_fit"
|
||||
android:columnWidth="160dp"
|
||||
android:stretchMode="spacingWidth"
|
||||
android:gravity="center"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentRight="true"
|
||||
@ -26,9 +27,9 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||
android:layout_alignParentTop="true"
|
||||
android:paddingTop="0dp"
|
||||
android:paddingBottom="10dp" />
|
||||
android:paddingBottom="10dp"
|
||||
android:textSize="28sp"/>
|
||||
|
||||
</RelativeLayout>
|
@ -2,16 +2,19 @@
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="30dp">
|
||||
android:padding="20dp">
|
||||
<RelativeLayout
|
||||
android:id="@+id/grid_image_layout"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
<ImageView
|
||||
android:id="@+id/grid_image"
|
||||
android:cropToPadding="false"
|
||||
android:scaleType="fitXY"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_width="100dp"
|
||||
android:layout_height="150dp">
|
||||
android:layout_width="150dp"
|
||||
android:layout_height="175dp">
|
||||
</ImageView>
|
||||
<ImageView
|
||||
android:id="@+id/grid_overlay"
|
||||
@ -23,12 +26,16 @@
|
||||
</RelativeLayout>
|
||||
<TextView
|
||||
android:id="@+id/grid_text"
|
||||
android:layout_width="125dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/grid_image_layout"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:gravity="center"
|
||||
android:textSize="20sp" >
|
||||
android:singleLine="true"
|
||||
android:ellipsize="marquee"
|
||||
android:marqueeRepeatLimit="marquee_forever"
|
||||
android:scrollHorizontally="true"
|
||||
android:textSize="18sp" >
|
||||
</TextView>
|
||||
</RelativeLayout>
|
@ -30,6 +30,6 @@
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:gravity="center"
|
||||
android:textSize="20sp" >
|
||||
android:textSize="18sp" >
|
||||
</TextView>
|
||||
</RelativeLayout>
|
@ -16,7 +16,6 @@
|
||||
<string name="pair_pairing_msg">Inserisci il seguente PIN sul PC:</string>
|
||||
<string name="pair_incorrect_pin">PIN non corretto</string>
|
||||
<string name="pair_fail">Accoppiamento fallito</string>
|
||||
<string name="pair_success">Accoppiato con successo</string>
|
||||
|
||||
<!-- WOL messages -->
|
||||
<string name="wol_pc_online">PC già avviato</string>
|
||||
@ -104,4 +103,5 @@
|
||||
|
||||
<string name="category_advanced_settings">Impostazioni Avanzate</string>
|
||||
<string name="title_decoder_list">Cambia decoder</string>
|
||||
<string name="summary_decoder_list">Il decoder software può aumentare la latenza video quando si usano impostazioni streaming basse</string>
|
||||
</resources>
|
||||
|
@ -3,7 +3,7 @@
|
||||
<!--
|
||||
Base application theme for API 21+. This theme completely replaces
|
||||
AppBaseTheme from BOTH res/values/styles.xml and
|
||||
res/values-v11/styles.xml on API 21+ devices.
|
||||
res/values-v21/styles.xml on API 21+ devices.
|
||||
-->
|
||||
<style name="AppBaseTheme" parent="android:Theme.Material">
|
||||
<!-- API 21 theme customizations can go here. -->
|
||||
|
@ -16,7 +16,6 @@
|
||||
<string name="pair_pairing_msg">Please enter the following PIN on the target PC:</string>
|
||||
<string name="pair_incorrect_pin">Incorrect PIN</string>
|
||||
<string name="pair_fail">Pairing failed</string>
|
||||
<string name="pair_success">Paired successfully</string>
|
||||
|
||||
<!-- WOL messages -->
|
||||
<string name="wol_pc_online">Computer is online</string>
|
||||
@ -104,4 +103,5 @@
|
||||
|
||||
<string name="category_advanced_settings">Advanced Settings</string>
|
||||
<string name="title_decoder_list">Change decoder</string>
|
||||
<string name="summary_decoder_list">Software decoding may improve video latency at lower streaming settings</string>
|
||||
</resources>
|
||||
|
@ -22,4 +22,14 @@
|
||||
<item name="android:windowNoTitle">true</item>
|
||||
</style>
|
||||
|
||||
<!-- Stream activity theme -->
|
||||
<style name="StreamTheme" parent="AppBaseTheme">
|
||||
<!-- All customizations that are NOT specific to a particular API-level can go here. -->
|
||||
<item name="android:windowActionBar">false</item>
|
||||
<item name="android:windowNoTitle">true</item>
|
||||
|
||||
<!-- Transparent streaming background to avoid extra overdraw -->
|
||||
<item name="android:windowBackground">@android:color/transparent</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
|
@ -52,6 +52,7 @@
|
||||
android:title="@string/title_decoder_list"
|
||||
android:entries="@array/decoder_names"
|
||||
android:entryValues="@array/decoder_values"
|
||||
android:summary="@string/summary_decoder_list"
|
||||
android:defaultValue="auto" />
|
||||
</PreferenceCategory>
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user