Italian translation: update

This commit is contained in:
Ansa89 2014-11-17 09:50:17 +01:00
commit f262503bc8
16 changed files with 184 additions and 75 deletions

View File

@ -11,8 +11,8 @@ android {
minSdkVersion 16 minSdkVersion 16
targetSdkVersion 21 targetSdkVersion 21
versionName "3.0-beta1.01" versionName "3.0-beta2"
versionCode = 41 versionCode = 43
} }
productFlavors { productFlavors {

Binary file not shown.

View File

@ -64,6 +64,7 @@
<activity <activity
android:name=".Game" android:name=".Game"
android:screenOrientation="sensorLandscape" android:screenOrientation="sensorLandscape"
android:theme="@style/StreamTheme"
android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|screenLayout|fontScale|uiMode|orientation|screenSize|smallestScreenSize|layoutDirection" > android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|screenLayout|fontScale|uiMode|orientation|screenSize|smallestScreenSize|layoutDirection" >
<meta-data <meta-data
android:name="android.support.PARENT_ACTIVITY" android:name="android.support.PARENT_ACTIVITY"

View File

@ -155,6 +155,7 @@ public class Game extends Activity implements SurfaceHolder.Callback,
String host = Game.this.getIntent().getStringExtra(EXTRA_HOST); String host = Game.this.getIntent().getStringExtra(EXTRA_HOST);
String app = Game.this.getIntent().getStringExtra(EXTRA_APP); String app = Game.this.getIntent().getStringExtra(EXTRA_APP);
String uniqueId = Game.this.getIntent().getStringExtra(EXTRA_UNIQUEID); String uniqueId = Game.this.getIntent().getStringExtra(EXTRA_UNIQUEID);
boolean remote = Game.this.getIntent().getBooleanExtra(EXTRA_STREAMING_REMOTE, false);
decoderRenderer = new ConfigurableDecoderRenderer(); decoderRenderer = new ConfigurableDecoderRenderer();
decoderRenderer.initializeWithFlags(drFlags); decoderRenderer.initializeWithFlags(drFlags);
@ -168,6 +169,7 @@ public class Game extends Activity implements SurfaceHolder.Callback,
.enableAdaptiveResolution((decoderRenderer.getCapabilities() & .enableAdaptiveResolution((decoderRenderer.getCapabilities() &
VideoDecoderRenderer.CAPABILITY_ADAPTIVE_RESOLUTION) != 0) VideoDecoderRenderer.CAPABILITY_ADAPTIVE_RESOLUTION) != 0)
.enableLocalAudioPlayback(prefConfig.playHostAudio) .enableLocalAudioPlayback(prefConfig.playHostAudio)
.setMaxPacketSize(remote ? 1024 : 1392)
.build(); .build();
// Initialize the connection // Initialize the connection

View File

@ -324,7 +324,8 @@ public class PcView extends Activity {
message = getResources().getString(R.string.pair_fail); message = getResources().getString(R.string.pair_fail);
} }
else if (pairState == PairingManager.PairState.PAIRED) { 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; success = true;
} }
else { else {

View File

@ -5,7 +5,6 @@ import java.io.File;
import java.io.FileReader; import java.io.FileReader;
import java.io.IOException; import java.io.IOException;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.concurrent.locks.LockSupport;
import android.graphics.PixelFormat; import android.graphics.PixelFormat;
import android.os.Build; import android.os.Build;
@ -21,14 +20,14 @@ import com.limelight.nvstream.av.video.cpu.AvcDecoder;
@SuppressWarnings("EmptyCatchBlock") @SuppressWarnings("EmptyCatchBlock")
public class AndroidCpuDecoderRenderer implements VideoDecoderRenderer { public class AndroidCpuDecoderRenderer implements VideoDecoderRenderer {
private Thread rendererThread; private Thread rendererThread, decoderThread;
private int targetFps; private int targetFps;
private static final int DECODER_BUFFER_SIZE = 92*1024; private static final int DECODER_BUFFER_SIZE = 92*1024;
private ByteBuffer decoderBuffer; private ByteBuffer decoderBuffer;
// Only sleep if the difference is above this value // 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 LOW_PERF = 1;
private static final int MED_PERF = 2; private static final int MED_PERF = 2;
@ -108,9 +107,7 @@ public class AndroidCpuDecoderRenderer implements VideoDecoderRenderer {
case LOW_PERF: case LOW_PERF:
// Disable the loop filter for performance reasons // Disable the loop filter for performance reasons
avcFlags = AvcDecoder.DISABLE_LOOP_FILTER | avcFlags = AvcDecoder.FAST_BILINEAR_FILTERING;
AvcDecoder.FAST_BILINEAR_FILTERING |
AvcDecoder.FAST_DECODE;
// Use plenty of threads to try to utilize the CPU as best we can // Use plenty of threads to try to utilize the CPU as best we can
threadCount = cpuCount - 1; threadCount = cpuCount - 1;
@ -118,8 +115,7 @@ public class AndroidCpuDecoderRenderer implements VideoDecoderRenderer {
default: default:
case MED_PERF: case MED_PERF:
avcFlags = AvcDecoder.BILINEAR_FILTERING | avcFlags = AvcDecoder.BILINEAR_FILTERING;
AvcDecoder.FAST_DECODE;
// Only use 2 threads to minimize frame processing latency // Only use 2 threads to minimize frame processing latency
threadCount = 2; threadCount = 2;
@ -156,6 +152,26 @@ public class AndroidCpuDecoderRenderer implements VideoDecoderRenderer {
@Override @Override
public boolean start(final VideoDepacketizer depacketizer) { 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() { rendererThread = new Thread() {
@Override @Override
public void run() { public void run() {
@ -163,16 +179,14 @@ public class AndroidCpuDecoderRenderer implements VideoDecoderRenderer {
DecodeUnit du; DecodeUnit du;
while (!isInterrupted()) while (!isInterrupted())
{ {
du = depacketizer.pollNextDecodeUnit();
if (du != null) {
submitDecodeUnit(du);
depacketizer.freeDecodeUnit(du);
}
long diff = nextFrameTime - System.currentTimeMillis(); long diff = nextFrameTime - System.currentTimeMillis();
if (diff > WAIT_CEILING_MS) { if (diff > WAIT_CEILING_MS) {
LockSupport.parkNanos(1); try {
Thread.sleep(diff - WAIT_CEILING_MS);
} catch (InterruptedException e) {
return;
}
continue; continue;
} }
@ -194,10 +208,14 @@ public class AndroidCpuDecoderRenderer implements VideoDecoderRenderer {
@Override @Override
public void stop() { public void stop() {
rendererThread.interrupt(); rendererThread.interrupt();
decoderThread.interrupt();
try { try {
rendererThread.join(); rendererThread.join();
} catch (InterruptedException e) { } } catch (InterruptedException e) { }
try {
decoderThread.join();
} catch (InterruptedException e) { }
} }
@Override @Override

View File

@ -1,8 +1,7 @@
package com.limelight.computers; package com.limelight.computers;
import java.net.InetAddress; import java.net.InetAddress;
import java.util.HashMap; import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import com.limelight.LimeLog; import com.limelight.LimeLog;
@ -21,7 +20,7 @@ import android.os.Binder;
import android.os.IBinder; import android.os.IBinder;
public class ComputerManagerService extends Service { 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 static final int MDNS_QUERY_PERIOD_MS = 1000;
private ComputerManagerBinder binder = new ComputerManagerBinder(); private ComputerManagerBinder binder = new ComputerManagerBinder();
@ -30,9 +29,10 @@ public class ComputerManagerService extends Service {
private AtomicInteger dbRefCount = new AtomicInteger(0); private AtomicInteger dbRefCount = new AtomicInteger(0);
private IdentityManager idManager; 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 ComputerManagerListener listener = null;
private AtomicInteger activePolls = new AtomicInteger(0); private AtomicInteger activePolls = new AtomicInteger(0);
private boolean pollingActive = false;
private DiscoveryService.DiscoveryBinder discoveryBinder; private DiscoveryService.DiscoveryBinder discoveryBinder;
private final ServiceConnection discoveryServiceConnection = new ServiceConnection() { private final ServiceConnection discoveryServiceConnection = new ServiceConnection() {
@ -101,18 +101,9 @@ public class ComputerManagerService extends Service {
Thread t = new Thread() { Thread t = new Thread() {
@Override @Override
public void run() { public void run() {
while (!isInterrupted()) { while (!isInterrupted() && pollingActive) {
ComputerDetails originalDetails = new ComputerDetails();
originalDetails.update(details);
// Check if this poll has modified the details // Check if this poll has modified the details
if (runPoll(details) && !originalDetails.equals(details)) { runPoll(details);
// Replace our thread entry with the new one
synchronized (pollingThreads) {
pollingThreads.remove(originalDetails);
pollingThreads.put(details, this);
}
}
// Wait until the next polling interval // Wait until the next polling interval
try { try {
@ -129,29 +120,24 @@ public class ComputerManagerService extends Service {
public class ComputerManagerBinder extends Binder { public class ComputerManagerBinder extends Binder {
public void startPolling(ComputerManagerListener listener) { public void startPolling(ComputerManagerListener listener) {
// Polling is active
pollingActive = true;
// Set the listener // Set the listener
ComputerManagerService.this.listener = listener; ComputerManagerService.this.listener = listener;
// Start mDNS autodiscovery too // Start mDNS autodiscovery too
discoveryBinder.startDiscovery(MDNS_QUERY_PERIOD_MS); discoveryBinder.startDiscovery(MDNS_QUERY_PERIOD_MS);
// Start polling known machines synchronized (pollingTuples) {
if (!getLocalDatabaseReference()) { for (PollingTuple tuple : pollingTuples) {
return;
}
List<ComputerDetails> computerList = dbManager.getAllComputers();
releaseLocalDatabaseReference();
synchronized (pollingThreads) {
for (ComputerDetails computer : computerList) {
// This polling thread might already be there // This polling thread might already be there
if (!pollingThreads.containsKey(computer)) { if (tuple.thread == null) {
// Report this computer initially // Report this computer initially
listener.notifyComputerUpdated(computer); listener.notifyComputerUpdated(tuple.computer);
Thread t = createPollingThread(computer); tuple.thread = createPollingThread(tuple.computer);
pollingThreads.put(computer, t); tuple.thread.start();
t.start();
} }
} }
} }
@ -205,11 +191,15 @@ public class ComputerManagerService extends Service {
discoveryBinder.stopDiscovery(); discoveryBinder.stopDiscovery();
// Stop polling // Stop polling
synchronized (pollingThreads) { pollingActive = false;
for (Thread t : pollingThreads.values()) { synchronized (pollingTuples) {
t.interrupt(); for (PollingTuple tuple : pollingTuples) {
if (tuple.thread != null) {
// Interrupt and remove the thread
tuple.thread.interrupt();
tuple.thread = null;
}
} }
pollingThreads.clear();
} }
// Remove the listener // Remove the listener
@ -245,13 +235,34 @@ public class ComputerManagerService extends Service {
fakeDetails.localIp = addr; fakeDetails.localIp = addr;
fakeDetails.remoteIp = addr; fakeDetails.remoteIp = addr;
// Spawn a thread for this computer addTuple(fakeDetails);
synchronized (pollingThreads) { }
// This polling thread might already be there
if (!pollingThreads.containsKey(fakeDetails)) { private void addTuple(ComputerDetails details) {
Thread t = createPollingThread(fakeDetails); synchronized (pollingTuples) {
pollingThreads.put(fakeDetails, t); for (PollingTuple tuple : pollingTuples) {
t.start(); // 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();
} }
} }
} }
@ -266,7 +277,14 @@ public class ComputerManagerService extends Service {
runPoll(fakeDetails); runPoll(fakeDetails);
// If the machine is reachable, it was successful // 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) { public void removeComputer(String name) {
@ -277,6 +295,20 @@ public class ComputerManagerService extends Service {
// Remove it from the database // Remove it from the database
dbManager.deleteComputer(name); 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(); releaseLocalDatabaseReference();
} }
@ -347,8 +379,19 @@ public class ComputerManagerService extends Service {
} }
private boolean doPollMachine(ComputerDetails details) { private boolean doPollMachine(ComputerDetails details) {
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); 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 @Override
public void onCreate() { public void onCreate() {
@ -362,6 +405,18 @@ public class ComputerManagerService extends Service {
// Initialize the DB // Initialize the DB
dbManager = new ComputerDatabaseManager(this); dbManager = new ComputerDatabaseManager(this);
dbRefCount.set(1); 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 @Override
@ -382,3 +437,13 @@ public class ComputerManagerService extends Service {
return binder; return binder;
} }
} }
class PollingTuple {
public Thread thread;
public ComputerDetails computer;
public PollingTuple(ComputerDetails computer, Thread thread) {
this.computer = computer;
this.thread = thread;
}
}

View File

@ -148,6 +148,9 @@ public class AppGridAdapter extends GenericGridAdapter<AppView.AppObject> {
@Override @Override
public boolean populateTextView(TextView txtView, AppView.AppObject obj) { 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 to use the app's toString method
return false; return false;
} }

View File

@ -14,6 +14,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:numColumns="auto_fit" android:numColumns="auto_fit"
android:columnWidth="160dp" android:columnWidth="160dp"
android:stretchMode="spacingWidth"
android:gravity="center" android:gravity="center"
android:layout_alignParentLeft="true" android:layout_alignParentLeft="true"
android:layout_alignParentRight="true" android:layout_alignParentRight="true"
@ -26,9 +27,9 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_centerHorizontal="true" android:layout_centerHorizontal="true"
android:textAppearance="?android:attr/textAppearanceLarge"
android:layout_alignParentTop="true" android:layout_alignParentTop="true"
android:paddingTop="0dp" android:paddingTop="0dp"
android:paddingBottom="10dp" /> android:paddingBottom="10dp"
android:textSize="28sp"/>
</RelativeLayout> </RelativeLayout>

View File

@ -2,16 +2,19 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:padding="30dp"> android:padding="20dp">
<RelativeLayout <RelativeLayout
android:id="@+id/grid_image_layout" android:id="@+id/grid_image_layout"
android:layout_centerHorizontal="true"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
<ImageView <ImageView
android:id="@+id/grid_image" android:id="@+id/grid_image"
android:cropToPadding="false"
android:scaleType="fitXY"
android:layout_centerHorizontal="true" android:layout_centerHorizontal="true"
android:layout_width="100dp" android:layout_width="150dp"
android:layout_height="150dp"> android:layout_height="175dp">
</ImageView> </ImageView>
<ImageView <ImageView
android:id="@+id/grid_overlay" android:id="@+id/grid_overlay"
@ -23,12 +26,16 @@
</RelativeLayout> </RelativeLayout>
<TextView <TextView
android:id="@+id/grid_text" android:id="@+id/grid_text"
android:layout_width="125dp" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_below="@id/grid_image_layout" android:layout_below="@id/grid_image_layout"
android:layout_marginTop="10dp" android:layout_marginTop="10dp"
android:layout_centerHorizontal="true" android:layout_centerHorizontal="true"
android:gravity="center" android:gravity="center"
android:textSize="20sp" > android:singleLine="true"
android:ellipsize="marquee"
android:marqueeRepeatLimit="marquee_forever"
android:scrollHorizontally="true"
android:textSize="18sp" >
</TextView> </TextView>
</RelativeLayout> </RelativeLayout>

View File

@ -30,6 +30,6 @@
android:layout_marginTop="10dp" android:layout_marginTop="10dp"
android:layout_centerHorizontal="true" android:layout_centerHorizontal="true"
android:gravity="center" android:gravity="center"
android:textSize="20sp" > android:textSize="18sp" >
</TextView> </TextView>
</RelativeLayout> </RelativeLayout>

View File

@ -16,7 +16,6 @@
<string name="pair_pairing_msg">Inserisci il seguente PIN sul PC:</string> <string name="pair_pairing_msg">Inserisci il seguente PIN sul PC:</string>
<string name="pair_incorrect_pin">PIN non corretto</string> <string name="pair_incorrect_pin">PIN non corretto</string>
<string name="pair_fail">Accoppiamento fallito</string> <string name="pair_fail">Accoppiamento fallito</string>
<string name="pair_success">Accoppiato con successo</string>
<!-- WOL messages --> <!-- WOL messages -->
<string name="wol_pc_online">PC già avviato</string> <string name="wol_pc_online">PC già avviato</string>
@ -104,4 +103,5 @@
<string name="category_advanced_settings">Impostazioni Avanzate</string> <string name="category_advanced_settings">Impostazioni Avanzate</string>
<string name="title_decoder_list">Cambia decoder</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> </resources>

View File

@ -3,7 +3,7 @@
<!-- <!--
Base application theme for API 21+. This theme completely replaces Base application theme for API 21+. This theme completely replaces
AppBaseTheme from BOTH res/values/styles.xml and 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"> <style name="AppBaseTheme" parent="android:Theme.Material">
<!-- API 21 theme customizations can go here. --> <!-- API 21 theme customizations can go here. -->

View File

@ -16,7 +16,6 @@
<string name="pair_pairing_msg">Please enter the following PIN on the target PC:</string> <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_incorrect_pin">Incorrect PIN</string>
<string name="pair_fail">Pairing failed</string> <string name="pair_fail">Pairing failed</string>
<string name="pair_success">Paired successfully</string>
<!-- WOL messages --> <!-- WOL messages -->
<string name="wol_pc_online">Computer is online</string> <string name="wol_pc_online">Computer is online</string>
@ -104,4 +103,5 @@
<string name="category_advanced_settings">Advanced Settings</string> <string name="category_advanced_settings">Advanced Settings</string>
<string name="title_decoder_list">Change decoder</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> </resources>

View File

@ -22,4 +22,14 @@
<item name="android:windowNoTitle">true</item> <item name="android:windowNoTitle">true</item>
</style> </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> </resources>

View File

@ -52,6 +52,7 @@
android:title="@string/title_decoder_list" android:title="@string/title_decoder_list"
android:entries="@array/decoder_names" android:entries="@array/decoder_names"
android:entryValues="@array/decoder_values" android:entryValues="@array/decoder_values"
android:summary="@string/summary_decoder_list"
android:defaultValue="auto" /> android:defaultValue="auto" />
</PreferenceCategory> </PreferenceCategory>