Merge pull request #81 from ultrasonic/add-stream-url

Add stream url
This commit is contained in:
Yahor Berdnikau 2017-11-21 21:33:52 +01:00 committed by GitHub
commit b9cfc0ed6d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 86 additions and 3 deletions

View File

@ -0,0 +1,47 @@
package org.moire.ultrasonic.api.subsonic
import okhttp3.mockwebserver.MockResponse
import org.amshove.kluent.`should equal to`
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.moire.ultrasonic.api.subsonic.SubsonicAPIVersions.V1_6_0
import org.moire.ultrasonic.api.subsonic.rules.MockWebServerRule
/**
* Integration test for [SubsonicAPIClient.getStreamUrl] method.
*/
class GetStreamUrlTest {
@JvmField @Rule val mockWebServerRule = MockWebServerRule()
val id = "boom"
private lateinit var client: SubsonicAPIClient
private lateinit var expectedUrl: String
@Before
fun setUp() {
client = SubsonicAPIClient(mockWebServerRule.mockWebServer.url("/").toString(),
USERNAME, PASSWORD, V1_6_0, CLIENT_ID)
val baseExpectedUrl = mockWebServerRule.mockWebServer.url("").toString()
expectedUrl = "$baseExpectedUrl/rest/stream.view?id=$id&u=$USERNAME" +
"&p=${client.passwordHex}&v=${V1_6_0.restApiVersion}&c=$CLIENT_ID&f=json"
}
@Test
fun `Should return valid stream url`() {
mockWebServerRule.enqueueResponse("ping_ok.json")
val streamUrl = client.getStreamUrl(id)
streamUrl `should equal to` expectedUrl
}
@Test
fun `Should still return stream url if connection failed`() {
mockWebServerRule.mockWebServer.enqueue(MockResponse().setResponseCode(500))
val streamUrl = client.getStreamUrl(id)
streamUrl `should equal to` expectedUrl
}
}

View File

@ -131,6 +131,22 @@ class SubsonicAPIClient(baseUrl: String,
}
}
/**
* Get stream url.
*
* Calling this method do actual connection to the backend, though not downloading all content.
*
* Consider do not use this method, but [stream] call.
*/
fun getStreamUrl(id: String): String {
val request = api.stream(id).execute()
val url = request.raw().request().url().toString()
if (request.isSuccessful) {
request.body().close()
}
return url
}
private val salt: String by lazy {
val secureRandom = SecureRandom()
BigInteger(130, secureRandom).toString(32)
@ -145,7 +161,7 @@ class SubsonicAPIClient(baseUrl: String,
}
}
private val passwordHex: String by lazy {
internal val passwordHex: String by lazy {
"enc:${password.toHexBytes()}"
}

View File

@ -104,6 +104,8 @@ import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import kotlin.Pair;
import retrofit2.Response;
@ -739,12 +741,30 @@ public class RESTMusicService implements MusicService {
}
@Override
public String getVideoUrl(Context context, String id, boolean useFlash) throws Exception {
public String getVideoUrl(final Context context,
final String id,
final boolean useFlash) throws Exception {
// This method should not exists as video should be loaded using stream method
// Previous method implementation uses assumption that video will be available
// by videoPlayer.view?id=<id>&maxBitRate=500&autoplay=true, but this url is not
// official Subsonic API call.
throw new UnsupportedOperationException("This method is not longer supported");
if (id == null) {
throw new IllegalArgumentException("Id is null");
}
final String[] expectedResult = new String[1];
expectedResult[0] = null;
final CountDownLatch latch = new CountDownLatch(1);
new Thread(new Runnable() {
@Override
public void run() {
expectedResult[0] = subsonicAPIClient.getStreamUrl(id) + "&format=raw";
latch.countDown();
}
}, "Get-Video-Url").start();
latch.await(3, TimeUnit.SECONDS);
return expectedResult[0];
}
@Override