86 changes: 86 additions & 0 deletions assets/about.html
@@ -0,0 +1,86 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<style type="text/css">

body {
margin: 20px;
}

body, td, div, p, li {
font-family:helvetica, arial, sans-serif;
font-size:13px;
line-height:1.3;
color:#555;
}

h1, h2 {
font-family: helvetica, arial, sans-serif;
font-weight:normal;
color: #222;
margin: 0;
margin-top: .7em;
padding: 0;
line-height: 1.0;
}

h1 {
font-size:22px;
padding: 0px;
margin: 0px;
color:#222;
}

h2 {
font-size:20px;
padding: 0px;
margin: 30px 0px 0px;
color:#222;
}

versiontag {
color: gray;
}

a {
font-size: 14px;
color: #00A8DF;
text-decoration: none;
}

</style>
<title>About ServeStream</title>
</head>
<body>
<div id="header" align="center">
<p>ServeStream, Version 0.6.8</p>
<p>Copyright © 2014 William Seemann</p>
<p>Released under the Apache License, Version 2.0 <a href="LICENSE.html">(View)</a></p>
</div>
<h1><b>Libraries</b></h1>
<h2>drag-sort-listview <a href="https://github.com/bauerca/drag-sort-listview">(Link)</a></h2>
by Carl A. Bauer, licensed under the Apache 2.0 license

<h2>FFmpeg <a href="http://www.ffmpeg.org" title="Link">(Link)</a></h2>
by the FFmpeg team, licensed under the General Public License (GPL)

<h2>jsoup <a href="http://jsoup.org">(Link)</a></h2>
by Jonathan Hedley, licensed under the MIT license

<h2>Java Playlist Parser <a href="http://sourceforge.net/projects/jplaylistparser">(Link)</a></h2>
by William Seemann, licensed under the Apache 2.0 license

<h2>FFmpegMediaMetadataRetriever <a href="https://github.com/wseemann/FFmpegMediaMetadataRetriever">(Link)</a></h2>
by William Seemann, licensed under the Apache 2.0 license

<h2>FFmpegMediaPlayer <a href="https://github.com/wseemann/FFmpegMediaPlayer">(Link)</a></h2>
by William Seemann, licensed under the Apache 2.0 license

<br>
<br>
<h1><b>Helpful code</b></h1>
<h2>AntennaPod <a href="https://github.com/danieloeh/AntennaPod">(Link)</a></h2>
by Daniel Oeh, licensed under the MIT license
</body>
</html>
92 changes: 92 additions & 0 deletions build.xml
@@ -0,0 +1,92 @@
<?xml version="1.0" encoding="UTF-8"?>
<project name="ServeStream" default="help">

<!-- The local.properties file is created and updated by the 'android' tool.
It contains the path to the SDK. It should *NOT* be checked into
Version Control Systems. -->
<property file="local.properties" />

<!-- The ant.properties file can be created by you. It is only edited by the
'android' tool to add properties to it.
This is the place to change some Ant specific build properties.
Here are some properties you may want to change/update:
source.dir
The name of the source directory. Default is 'src'.
out.dir
The name of the output directory. Default is 'bin'.
For other overridable properties, look at the beginning of the rules
files in the SDK, at tools/ant/build.xml
Properties related to the SDK location or the project target should
be updated using the 'android' tool with the 'update' action.
This file is an integral part of the build system for your
application and should be checked into Version Control Systems.
-->
<property file="ant.properties" />

<!-- if sdk.dir was not set from one of the property file, then
get it from the ANDROID_HOME env var.
This must be done before we load project.properties since
the proguard config can use sdk.dir -->
<property environment="env" />
<condition property="sdk.dir" value="${env.ANDROID_HOME}">
<isset property="env.ANDROID_HOME" />
</condition>

<!-- The project.properties file is created and updated by the 'android'
tool, as well as ADT.
This contains project specific properties such as project target, and library
dependencies. Lower level build properties are stored in ant.properties
(or in .classpath for Eclipse projects).
This file is an integral part of the build system for your
application and should be checked into Version Control Systems. -->
<loadproperties srcFile="project.properties" />

<!-- quick check on sdk.dir -->
<fail
message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable."
unless="sdk.dir"
/>

<!--
Import per project custom build rules if present at the root of the project.
This is the place to put custom intermediary targets such as:
-pre-build
-pre-compile
-post-compile (This is typically used for code obfuscation.
Compiled code location: ${out.classes.absolute.dir}
If this is not done in place, override ${out.dex.input.absolute.dir})
-post-package
-post-build
-pre-clean
-->
<import file="custom_rules.xml" optional="true" />

<!-- Import the actual build file.
To customize existing targets, there are two options:
- Customize only one target:
- copy/paste the target into this file, *before* the
<import> task.
- customize it to your needs.
- Customize the whole content of build.xml
- copy/paste the content of the rules files (minus the top node)
into this file, replacing the <import> task.
- customize to your needs.
***********************
****** IMPORTANT ******
***********************
In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
in order to avoid having your file be overridden by tools such as "android update project"
-->
<!-- version-tag: 1 -->
<import file="${sdk.dir}/tools/ant/build.xml" />

</project>
45 changes: 45 additions & 0 deletions custom_rules.xml
@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<project name="custom_rules">

<!-- quick check on ndk.dir -->
<target name="-check-ndk">
<fail
message="ndk.dir is missing. Make sure to put it in local.properties"
unless="ndk.dir"
/>
</target>

<target name="-check-dependencies">
<fail
message="yasm is missing. Make ensure yasm is installed and present in /usr/bin"
unless="yasm.exists"
/>
</target>

<target name="native-build" depends="native-clean">
<exec executable="${ndk.dir}/ndk-build" failonerror="true" />
</target>

<target name="native-clean">
<exec executable="${ndk.dir}/ndk-build" failonerror="true">
<arg value="clean" />
</exec>
</target>

<target name="build-ffmpeg">
<exec executable="/bin/sh" dir="." failonerror="true" osfamily="unix">
<arg value="scripts/build-ffmpeg.sh" />
</exec>
</target>

<target name="-pre-build">
<available file="/usr/bin/yasm" type="file" property="yasm.exists"/>
<antcall target="-check-dependencies" />
<echo>Building native code...</echo>
<antcall target="-check-ndk" />
<antcall target="build-ffmpeg" />
<antcall target="native-build" />
<echo>Successfully built native code</echo>
</target>

</project>
1 change: 1 addition & 0 deletions jni/Android.mk
@@ -0,0 +1 @@
include $(call all-subdir-makefiles)
1 change: 1 addition & 0 deletions jni/Application.mk
@@ -0,0 +1 @@
APP_ABI := armeabi armeabi-v7a x86 mips
33 changes: 33 additions & 0 deletions jni/ffmpeg/Android.mk
@@ -0,0 +1,33 @@
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE := libavcodec
LOCAL_SRC_FILES := ffmpeg/$(TARGET_ARCH_ABI)/lib/$(LOCAL_MODULE).so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/ffmpeg/$(TARGET_ARCH_ABI)/include
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := libavformat
LOCAL_SRC_FILES := ffmpeg/$(TARGET_ARCH_ABI)/lib/$(LOCAL_MODULE).so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/ffmpeg/$(TARGET_ARCH_ABI)/include
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := libavutil
LOCAL_SRC_FILES := ffmpeg/$(TARGET_ARCH_ABI)/lib/$(LOCAL_MODULE).so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/ffmpeg/$(TARGET_ARCH_ABI)/include
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := libswresample
LOCAL_SRC_FILES := ffmpeg/$(TARGET_ARCH_ABI)/lib/$(LOCAL_MODULE).so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/ffmpeg/$(TARGET_ARCH_ABI)/include
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := libswscale
LOCAL_SRC_FILES := ffmpeg/$(TARGET_ARCH_ABI)/lib/$(LOCAL_MODULE).so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/ffmpeg/$(TARGET_ARCH_ABI)/include
include $(PREBUILT_SHARED_LIBRARY)

LOCAL_PATH:= $(call my-dir)
14 changes: 14 additions & 0 deletions jni/metadata/Android.mk
@@ -0,0 +1,14 @@
LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := ffmpeg_mediametadataretriever_jni
LOCAL_CFLAGS :=
LOCAL_SRC_FILES := net_sourceforge_servestream_media_MediaMetadataRetriever.cpp \
mediametadataretriever.cpp \
ffmpeg_mediametadataretriever.c
LOCAL_SHARED_LIBRARIES := libswscale libavcodec libavformat libavutil
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../ffmpeg/ffmpeg/$(TARGET_ARCH_ABI)/include
LOCAL_LDLIBS := -llog

include $(BUILD_SHARED_LIBRARY)
582 changes: 582 additions & 0 deletions jni/metadata/ffmpeg_mediametadataretriever.c

Large diffs are not rendered by default.

49 changes: 49 additions & 0 deletions jni/metadata/ffmpeg_mediametadataretriever.h
@@ -0,0 +1,49 @@
/*
* ServeStream: A HTTP stream browser/player for Android
* Copyright 2014 William Seemann
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#ifndef FFMPEG_MEDIAMETADATARETRIEVER_H_
#define FFMPEG_MEDIAMETADATARETRIEVER_H_

#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>

// Keep these in synch with the constants defined in FFmpegMediaMetadataRetriever.java
// class.
typedef enum {
OPTION_PREVIOUS_SYNC = 0,
OPTION_NEXT_SYNC = 1,
OPTION_CLOSEST_SYNC = 2,
OPTION_CLOSEST = 3,

// Add more here...
} Options;

typedef struct State {
AVFormatContext *pFormatCtx;
int audio_stream;
int video_stream;
AVStream *audio_st;
AVStream *video_st;
} State;

int set_data_source(State **ps, const char* path);
const char* extract_metadata(State **ps, const char* key);
int get_embedded_picture(State **ps, AVPacket *pkt);
int get_frame_at_time(State **ps, int64_t timeUs, int option, AVPacket *pkt);
void release(State **ps);

#endif /*FFMPEG_MEDIAMETADATARETRIEVER_H_*/
59 changes: 59 additions & 0 deletions jni/metadata/mediametadataretriever.cpp
@@ -0,0 +1,59 @@
/*
* ServeStream: A HTTP stream browser/player for Android
* Copyright 2014 William Seemann
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

//#define LOG_NDEBUG 0
#define LOG_TAG "MediaMetadataRetriever"

#include <mediametadataretriever.h>

extern "C" {
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "ffmpeg_mediametadataretriever.h"
}

using namespace std;

MediaMetadataRetriever::MediaMetadataRetriever()
{
state = NULL;
}

MediaMetadataRetriever::~MediaMetadataRetriever()
{
::release(&state);
}

int MediaMetadataRetriever::setDataSource(const char *srcUrl)
{
return ::set_data_source(&state, srcUrl);
}

int MediaMetadataRetriever::getFrameAtTime(int64_t timeUs, int option, AVPacket *pkt)
{
return ::get_frame_at_time(&state, timeUs, option, pkt);
}

const char* MediaMetadataRetriever::extractMetadata(const char *key)
{
return ::extract_metadata(&state, key);
}

int MediaMetadataRetriever::extractAlbumArt(AVPacket *pkt)
{
return ::get_embedded_picture(&state, pkt);
}
42 changes: 42 additions & 0 deletions jni/metadata/mediametadataretriever.h
@@ -0,0 +1,42 @@
/*
* ServeStream: A HTTP stream browser/player for Android
* Copyright 2014 William Seemann
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#ifndef MEDIAMETADATARETRIEVER_H
#define MEDIAMETADATARETRIEVER_H

extern "C" {
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "ffmpeg_mediametadataretriever.h"
}

using namespace std;

class MediaMetadataRetriever
{
State* state;
public:
MediaMetadataRetriever();
~MediaMetadataRetriever();
void disconnect();
int setDataSource(const char* dataSourceUrl);
int getFrameAtTime(int64_t timeUs, int option, AVPacket *pkt);
int extractAlbumArt(AVPacket *pkt);
const char* extractMetadata(const char* key);
};

#endif // MEDIAMETADATARETRIEVER_H
@@ -0,0 +1,267 @@
/*
* ServeStream: A HTTP stream browser/player for Android
* Copyright 2014 William Seemann
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

//#define LOG_NDEBUG 0
#define LOG_TAG "MediaMetadataRetrieverJNI"

#include <assert.h>
#include <android/log.h>
#include <mediametadataretriever.h>
#include "jni.h"

extern "C" {
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
}

using namespace std;

struct fields_t {
jfieldID context;
};

static fields_t fields;
static const char* const kClassPathName = "net/sourceforge/servestream/media/FFmpegMediaMetadataRetriever";

void jniThrowException(JNIEnv* env, const char* className,
const char* msg) {
jclass exception = env->FindClass(className);
env->ThrowNew(exception, msg);
}

static void process_media_retriever_call(JNIEnv *env, int opStatus, const char* exception, const char *message)
{
if (opStatus == -2) {
jniThrowException(env, "java/lang/IllegalStateException", NULL);
} else if (opStatus == -1) {
if (strlen(message) > 230) {
// If the message is too long, don't bother displaying the status code.
jniThrowException( env, exception, message);
} else {
char msg[256];
// Append the status code to the message.
sprintf(msg, "%s: status = 0x%X", message, opStatus);
jniThrowException( env, exception, msg);
}
}
}

static MediaMetadataRetriever* getRetriever(JNIEnv* env, jobject thiz)
{
// No lock is needed, since it is called internally by other methods that are protected
MediaMetadataRetriever* retriever = (MediaMetadataRetriever*) env->GetIntField(thiz, fields.context);
return retriever;
}

static void setRetriever(JNIEnv* env, jobject thiz, int retriever)
{
// No lock is needed, since it is called internally by other methods that are protected
MediaMetadataRetriever *old = (MediaMetadataRetriever*) env->GetIntField(thiz, fields.context);
env->SetIntField(thiz, fields.context, retriever);
}

extern "C" JNIEXPORT void JNICALL
Java_net_sourceforge_servestream_media_FFmpegMediaMetadataRetriever_setDataSource(JNIEnv *env, jobject thiz, jstring path) {
//__android_log_write(ANDROID_LOG_INFO, LOG_TAG, "setDataSource");
MediaMetadataRetriever* retriever = getRetriever(env, thiz);
if (retriever == 0) {
jniThrowException(env, "java/lang/IllegalStateException", "No retriever available");
return;
}

if (!path) {
jniThrowException(env, "java/lang/IllegalArgumentException", "Null pointer");
return;
}

const char *tmp = env->GetStringUTFChars(path, NULL);
if (!tmp) { // OutOfMemoryError exception already thrown
return;
}

// Don't let somebody trick us in to reading some random block of memory
if (strncmp("mem://", tmp, 6) == 0) {
jniThrowException(env, "java/lang/IllegalArgumentException", "Invalid pathname");
return;
}

// Workaround for FFmpeg ticket #998
// "must convert mms://... streams to mmsh://... for FFmpeg to work"
char *restrict_to = strstr(tmp, "mms://");
if (restrict_to) {
strncpy(restrict_to, "mmsh://", 6);
puts(tmp);
}

process_media_retriever_call(
env,
retriever->setDataSource(tmp),
"java/lang/IllegalArgumentException",
"setDataSource failed");

env->ReleaseStringUTFChars(path, tmp);
tmp = NULL;
}

extern "C" JNIEXPORT jbyteArray JNICALL
Java_net_sourceforge_servestream_media_FFmpegMediaMetadataRetriever__1getFrameAtTime(JNIEnv *env, jobject thiz, jlong timeUs, jint option)
{
//__android_log_write(ANDROID_LOG_INFO, LOG_TAG, "getFrameAtTime");
MediaMetadataRetriever* retriever = getRetriever(env, thiz);
if (retriever == 0) {
jniThrowException(env, "java/lang/IllegalStateException", "No retriever available");
return NULL;
}

AVPacket packet;
av_init_packet(&packet);
jbyteArray array = NULL;

if (retriever->getFrameAtTime(timeUs, option, &packet) == 0) {
int size = packet.size;
uint8_t* data = packet.data;
array = env->NewByteArray(size);
if (!array) { // OutOfMemoryError exception has already been thrown.
__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "getFrameAtTime: OutOfMemoryError is thrown.");
} else {
//__android_log_print(ANDROID_LOG_INFO, LOG_TAG, "getFrameAtTime: Got frame.");
jbyte* bytes = env->GetByteArrayElements(array, NULL);
if (bytes != NULL) {
memcpy(bytes, data, size);
env->ReleaseByteArrayElements(array, bytes, 0);
}
}
}

av_free_packet(&packet);

return array;
}

extern "C" JNIEXPORT jbyteArray JNICALL
Java_net_sourceforge_servestream_media_FFmpegMediaMetadataRetriever_getEmbeddedPicture(JNIEnv *env, jobject thiz)
{
//__android_log_write(ANDROID_LOG_INFO, LOG_TAG, "getEmbeddedPicture");
MediaMetadataRetriever* retriever = getRetriever(env, thiz);
if (retriever == 0) {
jniThrowException(env, "java/lang/IllegalStateException", "No retriever available");
return NULL;
}

AVPacket packet;
av_init_packet(&packet);
jbyteArray array = NULL;

if (retriever->extractAlbumArt(&packet) == 0) {
int size = packet.size;
uint8_t* data = packet.data;
array = env->NewByteArray(size);
if (!array) { // OutOfMemoryError exception has already been thrown.
//__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "getEmbeddedPicture: OutOfMemoryError is thrown.");
} else {
//__android_log_print(ANDROID_LOG_INFO, LOG_TAG, "getEmbeddedPicture: Found album art.");
jbyte* bytes = env->GetByteArrayElements(array, NULL);
if (bytes != NULL) {
memcpy(bytes, data, size);
env->ReleaseByteArrayElements(array, bytes, 0);
}
}
}

av_free_packet(&packet);

return array;
}

extern "C" JNIEXPORT jobject JNICALL
Java_net_sourceforge_servestream_media_FFmpegMediaMetadataRetriever_extractMetadata(JNIEnv *env, jobject thiz, jstring jkey)
{
//__android_log_write(ANDROID_LOG_INFO, LOG_TAG, "extractMetadata");
MediaMetadataRetriever* retriever = getRetriever(env, thiz);
if (retriever == 0) {
jniThrowException(env, "java/lang/IllegalStateException", "No retriever available");
return NULL;
}

if (!jkey) {
jniThrowException(env, "java/lang/IllegalArgumentException", "Null pointer");
return NULL;
}

const char *key = env->GetStringUTFChars(jkey, NULL);
if (!key) { // OutOfMemoryError exception already thrown
return NULL;
}

const char* value = retriever->extractMetadata(key);
if (!value) {
//__android_log_write(ANDROID_LOG_INFO, LOG_TAG, "extractMetadata: Metadata is not found");
return NULL;
}
//__android_log_print(ANDROID_LOG_INFO, LOG_TAG, "extractMetadata: value (%s) for keyCode(%s)", value, key);
env->ReleaseStringUTFChars(jkey, key);
return env->NewStringUTF(value);
}

extern "C" JNIEXPORT void JNICALL
Java_net_sourceforge_servestream_media_FFmpegMediaMetadataRetriever_release(JNIEnv *env, jobject thiz)
{
__android_log_write(ANDROID_LOG_INFO, LOG_TAG, "release");
//Mutex::Autolock lock(sLock);
MediaMetadataRetriever* retriever = getRetriever(env, thiz);
delete retriever;
setRetriever(env, thiz, 0);
}

extern "C" JNIEXPORT void JNICALL
Java_net_sourceforge_servestream_media_FFmpegMediaMetadataRetriever_native_1finalize(JNIEnv *env, jobject thiz)
{
//__android_log_write(ANDROID_LOG_INFO, LOG_TAG, "native_finalize");
// No lock is needed, since Java_net_sourceforge_servestream_media_MediaMetadataRetriever_release() is protected
Java_net_sourceforge_servestream_media_FFmpegMediaMetadataRetriever_release(env, thiz);
}

extern "C" JNIEXPORT void JNICALL
Java_net_sourceforge_servestream_media_FFmpegMediaMetadataRetriever_native_1init(JNIEnv *env, jobject thiz)
{
__android_log_write(ANDROID_LOG_INFO, LOG_TAG, "native_init");
jclass clazz = env->FindClass(kClassPathName);
if (clazz == NULL) {
return;
}

fields.context = env->GetFieldID(clazz, "mNativeContext", "I");
if (fields.context == NULL) {
return;
}

// Initialize libavformat and register all the muxers, demuxers and protocols.
av_register_all();
avformat_network_init();
}

extern "C" JNIEXPORT void JNICALL
Java_net_sourceforge_servestream_media_FFmpegMediaMetadataRetriever_native_1setup(JNIEnv *env, jobject thiz)
{
__android_log_write(ANDROID_LOG_INFO, LOG_TAG, "native_setup");
MediaMetadataRetriever* retriever = new MediaMetadataRetriever();
if (retriever == 0) {
jniThrowException(env, "java/lang/RuntimeException", "Out of memory");
return;
}
setRetriever(env, thiz, (int)retriever);
}
14 changes: 14 additions & 0 deletions jni/player/Android.mk
@@ -0,0 +1,14 @@
LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := ffmpeg_mediaplayer_jni
LOCAL_CFLAGS :=
LOCAL_SRC_FILES := net_sourceforge_servestream_media_FFmpegMediaPlayer.cpp \
mediaplayer.cpp \
ffmpeg_mediaplayer.c
LOCAL_SHARED_LIBRARIES := libswresample libavcodec libavformat libavutil
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/../ffmpeg/ffmpeg/$(TARGET_ARCH_ABI)/include
LOCAL_LDLIBS := -llog

include $(BUILD_SHARED_LIBRARY)
87 changes: 87 additions & 0 deletions jni/player/Errors.h
@@ -0,0 +1,87 @@
/*
* ServeStream: A HTTP stream browser/player for Android
* Copyright 2014 William Seemann
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#ifndef ERRORS_H
#define ERRORS_H

#include <sys/types.h>
#include <errno.h>

using namespace std;

// use this type to return error codes
#ifdef HAVE_MS_C_RUNTIME
typedef int status_t;
#else
typedef int32_t status_t;
#endif

/* the MS C runtime lacks a few error codes */

/*
* Error codes.
* All error codes are negative values.
*/

// Win32 #defines NO_ERROR as well. It has the same value, so there's no
// real conflict, though it's a bit awkward.
#ifdef _WIN32
# undef NO_ERROR
#endif

enum {
OK = 0, // Everything's swell.
NO_ERROR = 0, // No errors.

UNKNOWN_ERROR = 0x80000000,

NO_MEMORY = -ENOMEM,
INVALID_OPERATION = -ENOSYS,
BAD_VALUE = -EINVAL,
BAD_TYPE = 0x80000001,
NAME_NOT_FOUND = -ENOENT,
PERMISSION_DENIED = -EPERM,
NO_INIT = -ENODEV,
ALREADY_EXISTS = -EEXIST,
DEAD_OBJECT = -EPIPE,
FAILED_TRANSACTION = 0x80000002,
JPARKS_BROKE_IT = -EPIPE,
#if !defined(HAVE_MS_C_RUNTIME)
BAD_INDEX = -EOVERFLOW,
NOT_ENOUGH_DATA = -ENODATA,
WOULD_BLOCK = -EWOULDBLOCK,
TIMED_OUT = -ETIME,
UNKNOWN_TRANSACTION = -EBADMSG,
#else
BAD_INDEX = -E2BIG,
NOT_ENOUGH_DATA = 0x80000003,
WOULD_BLOCK = 0x80000004,
TIMED_OUT = 0x80000005,
UNKNOWN_TRANSACTION = 0x80000006,
#endif
};

// Restore define; enumeration is in "android" namespace, so the value defined
// there won't work for Win32 code in a different namespace.
#ifdef _WIN32
# define NO_ERROR 0L
#endif

// ---------------------------------------------------------------------------

#endif // ERRORS_H

785 changes: 785 additions & 0 deletions jni/player/ffmpeg_mediaplayer.c

Large diffs are not rendered by default.

115 changes: 115 additions & 0 deletions jni/player/ffmpeg_mediaplayer.h
@@ -0,0 +1,115 @@
/*
* ServeStream: A HTTP stream browser/player for Android
* Copyright 2014 William Seemann
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#ifndef FFMPEG_MEDIAPLAYER_H_
#define FFMPEG_MEDIAPLAYER_H_

#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <pthread.h>

#define AUDIO_DATA_ID 1
#define MAX_AUDIO_FRAME_SIZE 200000;

const int NOT_FROM_THREAD = 0;
const int FROM_THREAD = 1;

typedef enum media_event_type {
MEDIA_NOP = 0, // interface test message
MEDIA_PREPARED = 1,
MEDIA_PLAYBACK_COMPLETE = 2,
MEDIA_BUFFERING_UPDATE = 3,
MEDIA_SEEK_COMPLETE = 4,
MEDIA_ERROR = 100,
} media_event_type;

typedef int media_error_type;
const media_error_type MEDIA_ERROR_UNKNOWN = 1;
const media_error_type MEDIA_ERROR_SERVER_DIED = 100;

typedef enum {
MEDIA_PLAYER_STATE_ERROR = 0,
MEDIA_PLAYER_IDLE = 1 << 0,
MEDIA_PLAYER_INITIALIZED = 1 << 1,
MEDIA_PLAYER_PREPARING = 1 << 2,
MEDIA_PLAYER_PREPARED = 1 << 3,
MEDIA_PLAYER_STARTED = 1 << 4,
MEDIA_PLAYER_PAUSED = 1 << 5,
MEDIA_PLAYER_STOPPED = 1 << 6,
MEDIA_PLAYER_PLAYBACK_COMPLETE = 1 << 7
} media_player_states;

typedef struct State {
AVFormatContext *pFormatCtx;
int audio_stream;
int video_stream;
AVStream *audio_st;
AVStream *video_st;
int buffer_size;
int loop;

pthread_t decoder_thread;
int abort_request;
int paused;
int last_paused;
int seek_req;
int seek_flags;
int64_t seek_pos;
int64_t seek_rel;
int read_pause_return;
double audio_clock;
char filename[1024];
char headers[2048];

void (*notify_callback) (void*, int, int, int, int);
int (*init_audio_track_callback) (void*, int, int, int);
void (*write_audio_callback) (void*, int16_t *, int, int);
void* clazz;

char *allow[0];
char *block[0];
} State;

void init(State **ps);
void disconnect(State **ps);
int setNotifyListener(State **ps, void* clazz, void (*listener) (void*, int, int, int, int));
int setInitAudioTrackListener(State **ps, void* clazz, int (*listener) (void*, int, int, int));
int setWriteAudioListener(State **ps, void* clazz, void (*listener) (void*, int16_t *, int, int));
int setDataSource(State **ps, const char *url, const char *headers);
int suspend();
int resume();
int setMetadataFilter(State **ps, char *allow[], char *block[]);
//int getMetadata(bool update_only, bool apply_filter, Parcel *metadata);
int get_metadata(State **ps, const char* key, char** value);
//int setVideoSurface(const sp<Surface>& surface);
int prepareAsync_l(State **ps);
int prepare(State **ps);
int prepareAsync(State **ps);
int start(State **ps);
int stop(State **ps);
int pause(State **ps);
int isPlaying(State **ps);
int getVideoWidth(int *w);
int getVideoHeight(int *h);
int getCurrentPosition(State **ps, int *msec);
int getDuration(State **ps, int *msec);
int seekTo(State **ps, int msec);
int reset(State **ps);
int setLooping(State **ps, int loop);
//void notify(int msg, int ext1, int ext2);

#endif /*FFMPEG_MEDIAPLAYER_H_*/
719 changes: 719 additions & 0 deletions jni/player/mediaplayer.cpp

Large diffs are not rendered by default.

139 changes: 139 additions & 0 deletions jni/player/mediaplayer.h
@@ -0,0 +1,139 @@
/*
* ServeStream: A HTTP stream browser/player for Android
* Copyright 2014 William Seemann
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#ifndef MEDIAPLAYER_H
#define MEDIAPLAYER_H

#include <Errors.h>

extern "C" {
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "ffmpeg_mediaplayer.h"
}

using namespace std;

/*enum media_event_type {
MEDIA_NOP = 0, // interface test message
MEDIA_PREPARED = 1,
MEDIA_PLAYBACK_COMPLETE = 2,
MEDIA_BUFFERING_UPDATE = 3,
MEDIA_SEEK_COMPLETE = 4,
MEDIA_ERROR = 100,
};
typedef int media_error_type;
const media_error_type MEDIA_ERROR_UNKNOWN = 1;
const media_error_type MEDIA_ERROR_SERVER_DIED = 100;
enum media_player_states {
MEDIA_PLAYER_STATE_ERROR = 0,
MEDIA_PLAYER_IDLE = 1 << 0,
MEDIA_PLAYER_INITIALIZED = 1 << 1,
MEDIA_PLAYER_PREPARING = 1 << 2,
MEDIA_PLAYER_PREPARED = 1 << 3,
MEDIA_PLAYER_STARTED = 1 << 4,
MEDIA_PLAYER_PAUSED = 1 << 5,
MEDIA_PLAYER_STOPPED = 1 << 6,
MEDIA_PLAYER_PLAYBACK_COMPLETE = 1 << 7
};*/

// ----------------------------------------------------------------------------
// ref-counted object for callbacks
class MediaPlayerListener
{
public:
virtual void notify(int msg, int ext1, int ext2, int fromThread) = 0;
virtual int initAudioTrack(int streamType, int sampleRateInHz, int channelConfig, int sessionId, int fromThread) = 0;
virtual void writeAudio(int16_t *samples, int frame_size_ptr, int fromThread) = 0;
virtual int setVolume(float leftVolume, float rightVolume) = 0;
virtual int attachAuxEffect(int effectId) = 0;
virtual int setAuxEffectSendLevel(float level) = 0;
};

class MediaPlayer
{
public:
MediaPlayer();
~MediaPlayer();

void disconnect();
status_t setDataSource(const char *url, const char *headers);
status_t setDataSource(int fd, int64_t offset, int64_t length);
status_t setMetadataFilter(char *allow[], char *block[]);
status_t getMetadata(const char *key, char **value);
//status_t setVideoSurface(const sp<Surface>& surface);
status_t setListener(MediaPlayerListener *listener);
MediaPlayerListener * getListener();
status_t prepare();
status_t prepareAsync();
status_t start();
status_t stop();
status_t pause();
bool isPlaying();
status_t getVideoWidth(int *w);
status_t getVideoHeight(int *h);
status_t seekTo(int msec);
status_t getCurrentPosition(int *msec);
status_t getDuration(int *msec);
status_t reset();
status_t setAudioStreamType(int type);
status_t setLooping(int loop);
bool isLooping();
status_t setVolume(float leftVolume, float rightVolume);
void notify(int msg, int ext1, int ext, int fromThread);
status_t setAudioSessionId(int sessionId);
int getAudioSessionId();
status_t setAuxEffectSendLevel(float level);
int attachAuxEffect(int effectId);
status_t setNextMediaPlayer(const MediaPlayer* player);
int initAudioTrack(int sampleRateInHz, int channelConfig, int fromThread);
void writeAudio(int16_t *samples, int frame_size_ptr, int fromThread);


private:
void clear_l();
status_t seekTo_l(int msec);
status_t prepareAsync_l();
status_t getDuration_l(int *msec);
status_t setDataSource(State *state);

//sp<IMediaPlayer> mPlayer;
//Mutex mLock;
//Mutex mNotifyLock;
//Condition mSignal;
MediaPlayerListener* mListener;
void* mCookie;
media_player_states mCurrentState;
int mDuration;
int mCurrentPosition;
int mSeekPosition;
bool mPrepareSync;
status_t mPrepareStatus;
int mStreamType;
bool mLoop;
float mLeftVolume;
float mRightVolume;
int mVideoWidth;
int mVideoHeight;
int mAudioSessionId;
float mSendLevel;
State* state;
};

#endif // MEDIAPLAYER_H
1,024 changes: 1,024 additions & 0 deletions jni/player/net_sourceforge_servestream_media_FFmpegMediaPlayer.cpp

Large diffs are not rendered by default.

Binary file added libs/android-support-v4.jar
Binary file not shown.
Binary file added libs/android-support-v7-appcompat.jar
Binary file not shown.
Binary file added libs/jplaylistparser-0.2.4.jar
Binary file not shown.
Binary file added libs/jsoup-1.7.3.jar
Binary file not shown.
20 changes: 20 additions & 0 deletions proguard-project.txt
@@ -0,0 +1,20 @@
# To enable ProGuard in your project, edit project.properties
# to define the proguard.config property as described in that file.
#
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in ${sdk.dir}/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the ProGuard
# include property in project.properties.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html

# Add any project specific keep options here:

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
15 changes: 15 additions & 0 deletions project.properties
@@ -0,0 +1,15 @@
# This file is automatically generated by Android Tools.
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
#
# This file must be checked in Version Control Systems.
#
# To customize properties used by the Ant build system edit
# "ant.properties", and override values to adapt the script to your
# project structure.
#
# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt

# Project target.
target=android-17
android.library.reference.1=../../Android/android-sdk-linux/extras/android/support/v7/appcompat
8 changes: 8 additions & 0 deletions res/anim/player_in.xml
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<alpha
android:interpolator="@android:anim/linear_interpolator"
android:duration="200"
android:fromAlpha="0.0"
android:toAlpha="1.0" />
</set>
8 changes: 8 additions & 0 deletions res/anim/player_out.xml
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<alpha
android:interpolator="@android:anim/linear_interpolator"
android:duration="200"
android:fromAlpha="1.0"
android:toAlpha="0.0" />
</set>
Binary file added res/drawable-hdpi/action_search.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added res/drawable-hdpi/action_search_dark.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added res/drawable-hdpi/albumart_mp_unknown.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added res/drawable-hdpi/albumart_mp_unknown_list.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added res/drawable-hdpi/albumart_mp_unknown_widget.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added res/drawable-hdpi/btn_player_next_disabled.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added res/drawable-hdpi/btn_player_next_normal.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added res/drawable-hdpi/btn_player_pause.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added res/drawable-hdpi/btn_player_play.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added res/drawable-hdpi/btn_player_prev_disabled.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added res/drawable-hdpi/btn_player_prev_normal.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added res/drawable-hdpi/btn_player_repeat_checked.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added res/drawable-hdpi/btn_player_repeat_normal.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added res/drawable-hdpi/btn_player_shuffle_checked.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added res/drawable-hdpi/btn_player_shuffle_normal.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added res/drawable-hdpi/btn_playerpreview_pause.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added res/drawable-hdpi/btn_playerpreview_play.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added res/drawable-hdpi/content_new.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added res/drawable-hdpi/content_new_dark.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added res/drawable-hdpi/drawer_shadow.9.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added res/drawable-hdpi/ic_drag_queue.9.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added res/drawable-hdpi/ic_drawer.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added res/drawable-hdpi/ic_launcher.png
Binary file added res/drawable-hdpi/ic_media_next.png
Binary file added res/drawable-hdpi/ic_media_pause.png
Binary file added res/drawable-hdpi/ic_media_play.png
Binary file added res/drawable-hdpi/ic_media_previous.png
Binary file added res/drawable-hdpi/ic_menu_eq.png
Binary file added res/drawable-hdpi/icn_notification_dismiss.png
Binary file added res/drawable-hdpi/icn_play_queue.png
Binary file added res/drawable-hdpi/icn_volume.png
Binary file added res/drawable-hdpi/navigation_accept.png
Binary file added res/drawable-hdpi/navigation_accept_dark.png
Binary file added res/drawable-hdpi/navigation_refresh.png
Binary file added res/drawable-hdpi/navigation_refresh_dark.png
Binary file added res/drawable-hdpi/notification_icon.png
Binary file added res/drawable-ldpi/albumart_mp_unknown.png
Binary file added res/drawable-ldpi/albumart_mp_unknown_list.png
Binary file added res/drawable-ldpi/albumart_mp_unknown_widget.png
Binary file added res/drawable-ldpi/ic_launcher.png
Binary file added res/drawable-mdpi-finger/appwidget_divider.9.png
Binary file added res/drawable-mdpi/action_search.png
Binary file added res/drawable-mdpi/action_search_dark.png
Binary file added res/drawable-mdpi/albumart_mp_unknown.png
Binary file added res/drawable-mdpi/albumart_mp_unknown_list.png
Binary file added res/drawable-mdpi/albumart_mp_unknown_widget.png
Binary file added res/drawable-mdpi/btn_strip_trans_right_normal.9.png
Binary file added res/drawable-mdpi/content_new.png
Binary file added res/drawable-mdpi/content_new_dark.png
Binary file added res/drawable-mdpi/dialog.9.png
Binary file added res/drawable-mdpi/divider_vertical_dark.9.png
Binary file added res/drawable-mdpi/drawer_shadow.9.png
Binary file added res/drawable-mdpi/ic_clock_add_alarm.png
Binary file added res/drawable-mdpi/ic_clock_add_alarm_selected.png
Binary file added res/drawable-mdpi/ic_clock_alarm_off.png
Binary file added res/drawable-mdpi/ic_clock_alarm_on.png
Binary file added res/drawable-mdpi/ic_clock_alarm_selected.png
Binary file added res/drawable-mdpi/ic_clock_strip_desk_clock.png
Binary file added res/drawable-mdpi/ic_dialog_time.png
Binary file added res/drawable-mdpi/ic_drag_queue.9.png
Binary file added res/drawable-mdpi/ic_drawer.png
Binary file added res/drawable-mdpi/ic_indicator_off.png
Binary file added res/drawable-mdpi/ic_indicator_on.png
Binary file added res/drawable-mdpi/ic_launcher.png
Binary file added res/drawable-mdpi/ic_media_next.png
Binary file added res/drawable-mdpi/ic_media_pause.png
Binary file added res/drawable-mdpi/ic_media_play.png
Binary file added res/drawable-mdpi/ic_media_previous.png
Binary file added res/drawable-mdpi/ic_menu_alarms.png
Binary file added res/drawable-mdpi/ic_menu_desk_clock.png
Binary file added res/drawable-mdpi/ic_menu_eq.png
Binary file added res/drawable-mdpi/ic_menu_scan.png
Binary file added res/drawable-mdpi/ic_menu_sleep_timer.png
Binary file added res/drawable-mdpi/navigation_accept.png
Binary file added res/drawable-mdpi/navigation_accept_dark.png
Binary file added res/drawable-mdpi/navigation_refresh.png
Binary file added res/drawable-mdpi/navigation_refresh_dark.png
Binary file added res/drawable-mdpi/notification_icon.png
Binary file added res/drawable-mdpi/pause.png
Binary file added res/drawable-mdpi/stat_notify_alarm.png
Binary file added res/drawable-mdpi/volume.png
Binary file added res/drawable-xhdpi/action_search.png
Binary file added res/drawable-xhdpi/action_search_dark.png
Binary file added res/drawable-xhdpi/albumart_mp_unknown.png
Binary file added res/drawable-xhdpi/content_new.png
Binary file added res/drawable-xhdpi/content_new_dark.png
Binary file added res/drawable-xhdpi/drawer_shadow.9.png
Binary file added res/drawable-xhdpi/ic_drag_queue.9.png
Binary file added res/drawable-xhdpi/ic_drawer.png
Binary file added res/drawable-xhdpi/ic_launcher.png
Binary file added res/drawable-xhdpi/ic_media_next.png
Binary file added res/drawable-xhdpi/ic_media_pause.png
Binary file added res/drawable-xhdpi/ic_media_play.png
Binary file added res/drawable-xhdpi/ic_media_previous.png
Binary file added res/drawable-xhdpi/icn_notification_dismiss.png
Binary file added res/drawable-xhdpi/navigation_accept.png
Binary file added res/drawable-xhdpi/navigation_accept_dark.png
Binary file added res/drawable-xhdpi/navigation_refresh.png
Binary file added res/drawable-xhdpi/navigation_refresh_dark.png
28 changes: 28 additions & 0 deletions res/drawable/add_alarm.xml
@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
* ServeStream: A HTTP stream browser/player for Android
* Copyright 2010 William Seemann
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-->

<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_focused="true" android:state_window_focused="true"
android:drawable="@drawable/ic_clock_add_alarm_selected" />
<item android:state_pressed="true" android:state_window_focused="true"
android:drawable="@drawable/ic_clock_add_alarm_selected" />
<item android:state_focused="false"
android:drawable="@drawable/ic_clock_add_alarm" />
</selector>
13 changes: 13 additions & 0 deletions res/drawable/bg_notification_button.xml
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true">
<shape>
<solid android:color="#ff0091c2" />
</shape>
</item>
<item>
<shape>
<solid android:color="@android:color/transparent" />
</shape>
</item>
</selector>
13 changes: 13 additions & 0 deletions res/drawable/borderless_button.xml
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true"><shape android:shape="rectangle">
<solid android:color="@color/selection_background_color_light" />
</shape></item>
<item android:state_focused="true"><shape android:shape="rectangle">
<solid android:color="@color/selection_background_color_light" />
</shape></item>
<item><shape android:shape="rectangle">
<solid android:color="@android:color/transparent" />
</shape></item>

</selector>
13 changes: 13 additions & 0 deletions res/drawable/borderless_button_dark.xml
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true"><shape android:shape="rectangle">
<solid android:color="@color/selection_background_color_dark" />
</shape></item>
<item android:state_focused="true"><shape android:shape="rectangle">
<solid android:color="@color/selection_background_color_dark" />
</shape></item>
<item><shape android:shape="rectangle">
<solid android:color="@android:color/transparent" />
</shape></item>

</selector>
24 changes: 24 additions & 0 deletions res/drawable/btn_player_next.xml
@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
* ServeStream: A HTTP stream browser/player for Android
* Copyright 2012 William Seemann
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-->

<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/btn_player_next_disabled" android:state_enabled="false"/>
<item android:drawable="@drawable/btn_player_next_normal"/>
</selector>
24 changes: 24 additions & 0 deletions res/drawable/btn_player_prev.xml
@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
* ServeStream: A HTTP stream browser/player for Android
* Copyright 2012 William Seemann
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-->

<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/btn_player_prev_normal" android:state_pressed="true"/>
<item android:drawable="@drawable/btn_player_prev_normal"/>
</selector>
34 changes: 34 additions & 0 deletions res/drawable/btn_strip_trans_right.xml
@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
* ServeStream: A HTTP stream browser/player for Android
* Copyright 2010 William Seemann
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-->

<!-- StateListDrawable used for the small round ImageButtons at the upper
corners of the in-call onscreen touch UI. -->
<selector xmlns:android="http://schemas.android.com/apk/res/android">

<item android:state_pressed="true"
android:drawable="@drawable/btn_strip_trans_right_pressed" />

<item android:state_focused="true"
android:drawable="@drawable/btn_strip_trans_right_selected" />

<item android:state_enabled="true"
android:drawable="@drawable/btn_strip_trans_right_normal" />

</selector>
22 changes: 22 additions & 0 deletions res/drawable/ic_menu_moreoverflow_holo_dark.xml
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
* ServeStream: A HTTP stream browser/player for Android
* Copyright 2014 William Seemann
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/ic_menu_moreoverflow_normal_holo_dark" />
</selector>
22 changes: 22 additions & 0 deletions res/drawable/ic_menu_moreoverflow_holo_light.xml
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
* ServeStream: A HTTP stream browser/player for Android
* Copyright 2014 William Seemann
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/ic_menu_moreoverflow_normal_holo_light" />
</selector>
25 changes: 25 additions & 0 deletions res/drawable/indicator_clock_onoff.xml
@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
* ServeStream: A HTTP stream browser/player for Android
* Copyright 2010 William Seemann
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-->

<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:state_window_focused="true"
android:drawable="@drawable/ic_clock_alarm_selected" />
<item android:drawable="@drawable/ic_clock_alarm_on" />
</selector>
34 changes: 34 additions & 0 deletions res/drawable/player_progress_drawable.xml
@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
* ServeStream: A HTTP stream browser/player for Android
* Copyright 2012 William Seemann
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-->

<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:id="@android:id/background">
<shape>
<solid android:color="#ff484848" />
</shape>
</item>
<item android:id="@android:id/progress">
<clip>
<shape>
<solid android:color="@color/blue" />
</shape>
</clip>
</item>
</layer-list>
56 changes: 56 additions & 0 deletions res/drawable/player_progress_thumb.xml
@@ -0,0 +1,56 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
* ServeStream: A HTTP stream browser/player for Android
* Copyright 2012 William Seemann
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-->

<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:bottom="3.0dip"
android:left="3.0dip"
android:right="3.0dip"
android:top="3.0dip">
<shape android:shape="oval" >
<size
android:height="10.0dip"
android:width="10.0dip" />

<stroke
android:width="1.0dip"
android:color="#3300c8ff" />

<solid android:color="#8800c8ff" />
</shape>
</item>
<item
android:bottom="10.0dip"
android:left="10.0dip"
android:right="10.0dip"
android:top="10.0dip">
<shape android:shape="oval" >
<size
android:height="6.0dip"
android:width="6.0dip" />

<stroke
android:width="1.0dip"
android:color="#ff00c8ff" />

<solid android:color="@color/blue" />
</shape>
</item>
</layer-list>
156 changes: 156 additions & 0 deletions res/layout-land/activity_media_player.xml
@@ -0,0 +1,156 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
* ServeStream: A HTTP stream browser/player for Android
* Copyright 2013 William Seemann
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-->

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center_vertical"
android:orientation="vertical"
android:background="@null" >

<android.support.v4.view.ViewPager
android:id="@+id/pager"
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_weight="1"
android:baselineAligned="false"
android:orientation="horizontal" />

<LinearLayout
android:id="@+id/player_controller"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >

<LinearLayout
android:layout_width="fill_parent"
android:layout_height="40dip"
android:paddingLeft="12dip"
android:paddingRight="12dip"
android:gravity="center_vertical"
android:orientation="horizontal" >

<TextView
android:id="@+id/position_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingRight="6dip"
android:textSize="12sp"
android:textColor="#ffbbbbbb"
android:gravity="right" />

<SeekBar
android:id="@+id/seek_bar"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_vertical"
android:paddingLeft="9dip"
android:paddingRight="9dip"
android:progress="0"
android:progressDrawable="@drawable/player_progress_drawable"
android:thumb="@drawable/player_progress_thumb"
android:thumbOffset="9dip"
android:maxHeight="2dip"
android:minHeight="2dip" />

<TextView
android:id="@+id/duration_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="6dip"
android:textSize="12sp"
android:textColor="#ffbbbbbb"
android:gravity="left" />
</LinearLayout>

<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="60dip"
android:orientation="horizontal" >

<ImageButton
android:id="@+id/shuffle_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:paddingBottom="20dip"
android:paddingLeft="12dip"
android:paddingRight="10dip"
android:paddingTop="8dip"
android:background="@null"
android:src="@drawable/btn_player_shuffle_normal" />

<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_toLeftOf="@+id/repeat_button"
android:layout_toRightOf="@+id/shuffle_button"
android:paddingLeft="10dip"
android:paddingRight="10dip"
android:gravity="center_vertical"
android:orientation="horizontal" >

<net.sourceforge.servestream.button.RepeatingImageButton
android:id="@+id/previous_button"
android:background="@null"
android:paddingBottom="20dip"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1"
android:src="@drawable/btn_player_prev" />

<ImageButton
android:id="@+id/play_pause_button"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1"
android:paddingBottom="20dip"
android:background="@null"
android:src="@drawable/btn_player_play" />

<net.sourceforge.servestream.button.RepeatingImageButton
android:id="@+id/next_button"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1"
android:paddingBottom="20dip"
android:background="@null"
android:src="@drawable/btn_player_next" />

</LinearLayout>

<ImageButton
android:id="@+id/repeat_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:paddingBottom="20dip"
android:paddingLeft="10dip"
android:paddingRight="12dip"
android:paddingTop="8dip"
android:background="@null"
android:src="@drawable/btn_player_repeat_normal" />

</RelativeLayout>

</LinearLayout>

</LinearLayout>
84 changes: 84 additions & 0 deletions res/layout-land/fragment_media_player.xml
@@ -0,0 +1,84 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
* ServeStream: A HTTP stream browser/player for Android
* Copyright 2014 William Seemann
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-->

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:baselineAligned="false"
android:orientation="horizontal" >

<LinearLayout
android:layout_width="0dip"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="@null"
android:padding="10dip" >

<net.sourceforge.servestream.utils.CoverView
android:id="@+id/album_art"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />

</LinearLayout>

<LinearLayout
android:id="@+id/player_info"
android:layout_width="0dip"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:orientation="vertical" >

<TextView
android:id="@+id/track_number_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:textColor="#ffa9a9a9"
android:textSize="13sp"
android:textStyle="normal" />

<TextView
android:id="@+id/trackname"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="18dip"
android:layout_marginRight="18dip"
android:ellipsize="marquee"
android:singleLine="true"
android:textColor="#ffffffff"
android:textSize="17sp"
android:textStyle="bold" />

<TextView
android:id="@+id/artist_and_album"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="18dip"
android:layout_marginRight="18dip"
android:ellipsize="marquee"
android:singleLine="true"
android:textColor="#ffa9a9a9"
android:textSize="13sp"
android:textStyle="normal" />

</LinearLayout>

</LinearLayout>
55 changes: 55 additions & 0 deletions res/layout-land/url_list_item.xml
@@ -0,0 +1,55 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
* ServeStream: A HTTP stream browser/player for Android
* Copyright 2013 William Seemann
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-->

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/content"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="10dip" >

<ImageView
android:id="@+id/overflow_menu_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:src="?attr/list_item_overflow"
android:contentDescription="" />

<TextView
android:id="@android:id/text2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toLeftOf="@+id/overflow_menu_button"
android:layout_centerVertical="true"
android:paddingLeft="10dip"
android:textAppearance="?android:attr/textAppearanceSmall" />

<TextView
android:id="@android:id/text1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_toLeftOf="@android:id/text2"
android:singleLine="true"
android:ellipsize="end"
android:textAppearance="?android:attr/textAppearanceLarge" />

</RelativeLayout>
155 changes: 155 additions & 0 deletions res/layout-port/activity_media_player.xml
@@ -0,0 +1,155 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
* ServeStream: A HTTP stream browser/player for Android
* Copyright 2013 William Seemann
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-->

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center_vertical"
android:orientation="vertical"
android:background="@null" >

<android.support.v4.view.ViewPager
android:id="@+id/pager"
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_weight="1"
android:orientation="vertical" />

<LinearLayout
android:id="@+id/player_controller"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >

<LinearLayout
android:layout_width="fill_parent"
android:layout_height="40dip"
android:paddingLeft="12dip"
android:paddingRight="12dip"
android:gravity="center_vertical"
android:orientation="horizontal" >

<TextView
android:id="@+id/position_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingRight="6dip"
android:textSize="12sp"
android:textColor="#ffbbbbbb"
android:gravity="right" />

<SeekBar
android:id="@+id/seek_bar"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_vertical"
android:paddingLeft="9dip"
android:paddingRight="9dip"
android:progress="0"
android:progressDrawable="@drawable/player_progress_drawable"
android:thumb="@drawable/player_progress_thumb"
android:thumbOffset="9dip"
android:maxHeight="2dip"
android:minHeight="2dip" />

<TextView
android:id="@+id/duration_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="6dip"
android:textSize="12sp"
android:textColor="#ffbbbbbb"
android:gravity="left" />

</LinearLayout>

<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="60dip"
android:orientation="horizontal" >

<ImageButton
android:id="@+id/shuffle_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:paddingBottom="20dip"
android:paddingLeft="12dip"
android:paddingRight="10dip"
android:paddingTop="8dip"
android:background="@null"
android:src="@drawable/btn_player_shuffle_normal" />

<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_toLeftOf="@+id/repeat_button"
android:layout_toRightOf="@+id/shuffle_button"
android:paddingLeft="10dip"
android:paddingRight="10dip"
android:gravity="center_vertical"
android:orientation="horizontal" >

<net.sourceforge.servestream.button.RepeatingImageButton
android:id="@+id/previous_button"
android:background="@null"
android:paddingBottom="20dip"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1"
android:src="@drawable/btn_player_prev" />

<ImageButton
android:id="@+id/play_pause_button"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1"
android:paddingBottom="20dip"
android:background="@null"
android:src="@drawable/btn_player_play" />

<net.sourceforge.servestream.button.RepeatingImageButton
android:id="@+id/next_button"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1"
android:paddingBottom="20dip"
android:background="@null"
android:src="@drawable/btn_player_next" />
</LinearLayout>

<ImageButton
android:id="@+id/repeat_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:paddingBottom="20dip"
android:paddingLeft="10dip"
android:paddingRight="12dip"
android:paddingTop="8dip"
android:background="@null"
android:src="@drawable/btn_player_repeat_normal" />

</RelativeLayout>

</LinearLayout>

</LinearLayout>
84 changes: 84 additions & 0 deletions res/layout-port/fragment_media_player.xml
@@ -0,0 +1,84 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
* ServeStream: A HTTP stream browser/player for Android
* Copyright 2014 William Seemann
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-->

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >

<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight="1"
android:background="@null"
android:padding="10dip" >

<net.sourceforge.servestream.utils.CoverView
android:id="@+id/album_art"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />

</LinearLayout>

<LinearLayout
android:id="@+id/player_info"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dip"
android:gravity="center_horizontal"
android:orientation="vertical" >

<TextView
android:id="@+id/track_number_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingTop="5dip"
android:singleLine="true"
android:textColor="#ffa9a9a9"
android:textSize="13sp"
android:textStyle="normal" />

<TextView
android:id="@+id/trackname"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="12dip"
android:layout_marginRight="12dip"
android:ellipsize="marquee"
android:singleLine="true"
android:textColor="#ffffffff"
android:textSize="17sp"
android:textStyle="bold" />

<TextView
android:id="@+id/artist_and_album"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="12dip"
android:layout_marginRight="12dip"
android:ellipsize="marquee"
android:singleLine="true"
android:textColor="#ffa9a9a9"
android:textSize="13sp"
android:textStyle="normal" />

</LinearLayout>

</LinearLayout>
56 changes: 56 additions & 0 deletions res/layout-port/url_list_item.xml
@@ -0,0 +1,56 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
* ServeStream: A HTTP stream browser/player for Android
* Copyright 2013 William Seemann
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-->

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/content"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="10dip" >

<TextView
android:id="@android:id/text1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingRight="5dip"
android:singleLine="true"
android:ellipsize="end"
android:textAppearance="?android:attr/textAppearanceLarge"
android:layout_alignParentLeft="true"
android:layout_toLeftOf="@+id/overflow_menu_button" />

<TextView
android:id="@android:id/text2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
android:layout_below="@android:id/text1"
android:layout_alignParentLeft="true"
android:layout_toLeftOf="@id/overflow_menu_button" />

<ImageView
android:id="@id/overflow_menu_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:src="?attr/list_item_overflow"
android:contentDescription="" />

</RelativeLayout>
103 changes: 103 additions & 0 deletions res/layout-sw600dp/fragment_nowplaying.xml
@@ -0,0 +1,103 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
* ServeStream: A HTTP stream browser/player for Android
* Copyright 2013 William Seemann
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-->

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/nowplaying"
android:layout_width="fill_parent"
android:layout_height="59.0dip"
android:gravity="bottom"
android:orientation="vertical" >

<View
android:layout_width="fill_parent"
android:layout_height="2dip"
android:background="@drawable/appwidget_divider" />

<LinearLayout
android:layout_width="fill_parent"
android:layout_height="57.0dip"
android:gravity="bottom"
android:orientation="horizontal"
android:background="?attr/borderless_button" >

<ImageView
android:id="@+id/coverart"
android:layout_width="56.0dip"
android:layout_height="56.0dip"
android:scaleType="centerCrop" />

<LinearLayout
android:layout_width="0.0dip"
android:layout_height="fill_parent"
android:layout_weight="1.0"
android:layout_marginLeft="12.0dip"
android:layout_marginRight="15.0dip"
android:gravity="left|center"
android:orientation="vertical" >

<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="16.0dip"
android:textColor="#ffffffff"
android:singleLine="true"
android:ellipsize="marquee" />

<TextView
android:id="@+id/artist"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingTop="2.0dip"
android:textSize="12.0dip"
android:textColor="#ffbbbbbb"
android:singleLine="true"
android:ellipsize="marquee" />

</LinearLayout>

<ImageButton
android:id="@+id/previous_button"
android:layout_width="56.0dip"
android:layout_height="56.0dip"
android:gravity="center"
android:background="?attr/borderless_button" />

<ImageButton
android:id="@+id/play_pause_button"
android:layout_width="56.0dip"
android:layout_height="56.0dip"
android:paddingLeft="5dip"
android:paddingRight="5dip"
android:gravity="center"
android:visibility="gone"
android:background="?attr/borderless_button" />

<ImageButton
android:id="@+id/next_button"
android:layout_width="56.0dip"
android:layout_height="56.0dip"
android:paddingRight="5dip"
android:gravity="center"
android:background="?attr/borderless_button" />

</LinearLayout>

</LinearLayout>
103 changes: 103 additions & 0 deletions res/layout-sw720dp/fragment_nowplaying.xml
@@ -0,0 +1,103 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
* ServeStream: A HTTP stream browser/player for Android
* Copyright 2013 William Seemann
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-->

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/nowplaying"
android:layout_width="fill_parent"
android:layout_height="59.0dip"
android:gravity="bottom"
android:orientation="vertical" >

<View
android:layout_width="fill_parent"
android:layout_height="2dip"
android:background="@drawable/appwidget_divider" />

<LinearLayout
android:layout_width="fill_parent"
android:layout_height="57.0dip"
android:gravity="bottom"
android:orientation="horizontal"
android:background="?attr/borderless_button" >

<ImageView
android:id="@+id/coverart"
android:layout_width="56.0dip"
android:layout_height="56.0dip"
android:scaleType="centerCrop" />

<LinearLayout
android:layout_width="0.0dip"
android:layout_height="fill_parent"
android:layout_weight="1.0"
android:layout_marginLeft="12.0dip"
android:layout_marginRight="15.0dip"
android:gravity="left|center"
android:orientation="vertical" >

<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="16.0dip"
android:textColor="#ffffffff"
android:singleLine="true"
android:ellipsize="marquee" />

<TextView
android:id="@+id/artist"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingTop="2.0dip"
android:textSize="12.0dip"
android:textColor="#ffbbbbbb"
android:singleLine="true"
android:ellipsize="marquee" />

</LinearLayout>

<ImageButton
android:id="@+id/previous_button"
android:layout_width="56.0dip"
android:layout_height="56.0dip"
android:gravity="center"
android:background="?attr/borderless_button" />

<ImageButton
android:id="@+id/play_pause_button"
android:layout_width="56.0dip"
android:layout_height="56.0dip"
android:paddingLeft="5dip"
android:paddingRight="5dip"
android:gravity="center"
android:visibility="gone"
android:background="?attr/borderless_button" />

<ImageButton
android:id="@+id/next_button"
android:layout_width="56.0dip"
android:layout_height="56.0dip"
android:paddingRight="5dip"
android:gravity="center"
android:background="?attr/borderless_button" />

</LinearLayout>

</LinearLayout>
82 changes: 82 additions & 0 deletions res/layout-v14/activity_set_alarm.xml
@@ -0,0 +1,82 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
* ServeStream: A HTTP stream browser/player for Android
* Copyright 2013 William Seemann
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-->

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >

<ListView
android:id="@android:id/list"
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_weight="1" />

<View
android:layout_width="match_parent"
android:layout_height="1dip"
android:background="?android:attr/dividerVertical" />

<LinearLayout
android:layout_width="fill_parent"
android:layout_height="48dip"
android:orientation="horizontal" >

<Button
android:id="@+id/alarm_revert"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="?android:attr/selectableItemBackground"
android:text="@string/revert" />

<View
android:layout_width="1dip"
android:layout_height="fill_parent"
android:layout_marginBottom="4dp"
android:layout_marginTop="4dp"
android:background="?android:attr/dividerVertical" />

<Button
android:id="@+id/alarm_save"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="?android:attr/selectableItemBackground"
android:text="@string/done" />

<View
android:layout_width="1dip"
android:layout_height="fill_parent"
android:layout_marginBottom="4dp"
android:layout_marginTop="4dp"
android:background="?android:attr/dividerVertical" />

<Button
android:id="@+id/alarm_delete"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="?android:attr/selectableItemBackground"
android:text="@string/delete" />

</LinearLayout>

</LinearLayout>
27 changes: 27 additions & 0 deletions res/layout-v14/drawer_list_item.xml
@@ -0,0 +1,27 @@
<!--
Copyright 2013 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->

<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/text1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:gravity="center_vertical"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:textColor="#fff"
android:background="?android:attr/activatedBackgroundIndicator"
android:minHeight="?android:attr/listPreferredItemHeight" />
126 changes: 126 additions & 0 deletions res/layout-v14/fragment_add_uri.xml
@@ -0,0 +1,126 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
* ServeStream: A HTTP stream browser/player for Android
* Copyright 2013 William Seemann
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-->

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >

<RelativeLayout
android:id="@+id/footer"
android:layout_width="fill_parent"
android:layout_height="48dp"
android:layout_alignParentBottom="true" >

<View
android:layout_width="match_parent"
android:layout_height="1dip"
android:layout_alignParentTop="true"
android:background="?android:attr/dividerVertical" />

<View
android:id="@+id/horizontal_divider"
android:layout_width="1dip"
android:layout_height="fill_parent"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="4dp"
android:layout_marginTop="4dp"
android:background="?android:attr/dividerVertical" />

<Button
android:id="@+id/cancel_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_toLeftOf="@id/horizontal_divider"
android:background="?android:attr/selectableItemBackground"
android:text="@android:string/cancel" />

<Button
android:id="@+id/confirm_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_toRightOf="@id/horizontal_divider"
android:background="?android:attr/selectableItemBackground"
android:text="@string/confirm_label" />
</RelativeLayout>

<ScrollView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_above="@id/footer"
android:layout_alignParentTop="true"
android:scrollbars="vertical" >

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >

<TextView
android:id="@+id/url_text"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:focusable="true"
android:focusableInTouchMode="true"
android:text="@string/text_url_label" />

<EditText
android:id="@+id/url_edittext"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:hint="@string/url_hint"
android:inputType="textUri" />

<CheckBox
android:id="@+id/save_playlist_entries_checkbox"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/store_playlist_entries" />

<TextView
android:id="@+id/nickname_text"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:focusable="true"
android:focusableInTouchMode="true"
android:text="@string/text_nickname_label" />

<EditText
android:id="@+id/nickname_edittext"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:inputType="text" />

</LinearLayout>

</ScrollView>

</RelativeLayout>
95 changes: 95 additions & 0 deletions res/layout-v14/notification_coverart_and_text.xml
@@ -0,0 +1,95 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
* ServeStream: A HTTP stream browser/player for Android
* Copyright 2013 William Seemann
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-->

<merge xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >

<ImageView
android:id="@+id/coverart"
android:layout_width="128dip"
android:layout_height="128dip"
android:layout_alignBottom="@id/controls"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:adjustViewBounds="true"
android:scaleType="centerCrop"
android:background="@drawable/albumart_mp_unknown_expanded" />

<ImageButton
android:id="@+id/close"
android:layout_width="42dip"
android:layout_height="42dip"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:scaleType="centerInside"
android:background="@drawable/bg_notification_button"
android:src="@drawable/icn_notification_dismiss" />

<TextView
android:id="@+id/firstLine"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_toLeftOf="@id/close"
android:layout_toRightOf="@id/coverart"
android:duplicateParentState="true"
android:paddingLeft="10dip"
android:paddingRight="10dip"
android:paddingTop="6dip"
android:singleLine="true"
android:textAppearance="@android:style/TextAppearance.StatusBar.EventContent.Title" />

<TextView
android:id="@+id/secondLine"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/firstLine"
android:layout_toLeftOf="@id/close"
android:layout_toRightOf="@id/coverart"
android:duplicateParentState="true"
android:paddingLeft="10dip"
android:paddingRight="10dip"
android:singleLine="true"
android:textAppearance="@android:style/TextAppearance.StatusBar.EventContent" />

<TextView
android:id="@+id/thirdLine"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/secondLine"
android:layout_toLeftOf="@id/close"
android:layout_toRightOf="@id/coverart"
android:duplicateParentState="true"
android:paddingBottom="8dip"
android:paddingLeft="10dip"
android:paddingRight="10dip"
android:singleLine="true"
android:textAppearance="@android:style/TextAppearance.StatusBar.EventContent" />

<TextView
android:layout_width="fill_parent"
android:layout_height="1px"
android:layout_below="@+id/thirdLine"
android:layout_toRightOf="@id/coverart"
android:background="#ff424242" />

</merge>
107 changes: 107 additions & 0 deletions res/layout-v14/notification_small.xml
@@ -0,0 +1,107 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
* ServeStream: A HTTP stream browser/player for Android
* Copyright 2013 William Seemann
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-->

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content" >

<ImageView
android:id="@+id/coverart"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:adjustViewBounds="true"
android:maxHeight="64dip"
android:maxWidth="64dip"
android:scaleType="centerCrop"
android:background="@drawable/albumart_mp_unknown_notification" />

<LinearLayout
android:layout_width="fill_parent"
android:layout_height="64dip"
android:layout_toRightOf="@id/coverart"
android:orientation="horizontal" >

<LinearLayout
android:id="@id/texts"
android:layout_width="0dip"
android:layout_height="64dip"
android:layout_weight="4"
android:gravity="center_vertical"
android:orientation="vertical"
android:paddingBottom="4dip"
android:paddingLeft="10dip"
android:paddingRight="10dip"
android:paddingTop="6dip" >

<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:duplicateParentState="true"
android:singleLine="true"
android:textAppearance="@android:style/TextAppearance.StatusBar.EventContent.Title" />

<TextView
android:id="@+id/subtitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:duplicateParentState="true"
android:singleLine="true"
android:textAppearance="@android:style/TextAppearance.StatusBar.EventContent" />

</LinearLayout>

<ImageButton
android:id="@+id/play_pause"
android:layout_width="0dip"
android:layout_height="64dip"
android:layout_weight="1"
android:paddingLeft="8dip"
android:paddingRight="8dip"
android:scaleType="centerInside"
android:background="@drawable/bg_notification_button"
android:src="@android:drawable/ic_media_pause" />

<ImageButton
android:id="@+id/next"
android:layout_width="0dip"
android:layout_height="64dip"
android:layout_weight="1"
android:paddingLeft="2dip"
android:paddingRight="2dip"
android:scaleType="centerInside"
android:background="@drawable/bg_notification_button"
android:src="@android:drawable/ic_media_next" />

<ImageButton
android:id="@+id/close"
android:layout_width="0dip"
android:layout_height="64dip"
android:layout_weight="1"
android:paddingLeft="2dip"
android:scaleType="centerInside"
android:background="@drawable/bg_notification_button"
android:src="@drawable/icn_notification_dismiss" />

</LinearLayout>

</RelativeLayout>
41 changes: 41 additions & 0 deletions res/layout/action_bar_media_player.xml
@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
* ServeStream: A HTTP stream browser/player for Android
* Copyright 2013 William Seemann
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-->

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >

<SeekBar
android:id="@+id/volume_bar"
android:layout_width="115dip"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:paddingLeft="9dip"
android:paddingRight="9dip"
android:progress="0"
android:progressDrawable="@drawable/player_progress_drawable"
android:thumb="@drawable/player_progress_thumb"
android:thumbOffset="9dip"
android:maxHeight="2dip"
android:minHeight="2dip" />

</RelativeLayout>
31 changes: 31 additions & 0 deletions res/layout/activity_about.xml
@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
* ServeStream: A HTTP stream browser/player for Android
* Copyright 2013 William Seemann
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-->

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >

<WebView
android:id="@+id/about_webview"
android:layout_width="match_parent"
android:layout_height="match_parent" />

</LinearLayout>