Code reformat, fix view reuse, image quality
This commit is contained in:
parent
f841b26023
commit
ecc078e30f
|
@ -0,0 +1,45 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectCodeStyleSettingsManager">
|
||||
<option name="PER_PROJECT_SETTINGS">
|
||||
<value>
|
||||
<option name="CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND" value="99" />
|
||||
<option name="NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND" value="99" />
|
||||
<option name="PACKAGES_TO_USE_IMPORT_ON_DEMAND">
|
||||
<value />
|
||||
</option>
|
||||
<option name="IMPORT_LAYOUT_TABLE">
|
||||
<value>
|
||||
<package name="android" withSubpackages="true" static="false" />
|
||||
<emptyLine />
|
||||
<package name="com" withSubpackages="true" static="false" />
|
||||
<emptyLine />
|
||||
<package name="junit" withSubpackages="true" static="false" />
|
||||
<emptyLine />
|
||||
<package name="net" withSubpackages="true" static="false" />
|
||||
<emptyLine />
|
||||
<package name="org" withSubpackages="true" static="false" />
|
||||
<emptyLine />
|
||||
<package name="java" withSubpackages="true" static="false" />
|
||||
<emptyLine />
|
||||
<package name="javax" withSubpackages="true" static="false" />
|
||||
<emptyLine />
|
||||
<package name="" withSubpackages="true" static="false" />
|
||||
<emptyLine />
|
||||
<package name="" withSubpackages="true" static="true" />
|
||||
<emptyLine />
|
||||
</value>
|
||||
</option>
|
||||
<option name="RIGHT_MARGIN" value="100" />
|
||||
<AndroidXmlCodeStyleSettings>
|
||||
<option name="USE_CUSTOM_SETTINGS" value="true" />
|
||||
</AndroidXmlCodeStyleSettings>
|
||||
<XML>
|
||||
<option name="XML_LEGACY_SETTINGS_IMPORTED" value="true" />
|
||||
</XML>
|
||||
</value>
|
||||
</option>
|
||||
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default (1)" />
|
||||
</component>
|
||||
</project>
|
||||
|
|
@ -4,9 +4,6 @@
|
|||
<option name="DEFAULT_COMPILER" value="Javac" />
|
||||
<excludeFromCompile>
|
||||
<directory url="file://$PROJECT_DIR$/gen" includeSubdirectories="true" />
|
||||
<directory url="file://$PROJECT_DIR$/menudrawer/library/target/generated-sources/r" includeSubdirectories="true" />
|
||||
<directory url="file://$PROJECT_DIR$/menudrawer/samples/target/generated-sources/r" includeSubdirectories="true" />
|
||||
<directory url="file://$PROJECT_DIR$/menudrawer/samples/gen-external-apklibs/com.actionbarsherlock_actionbarsherlock_4.3.1/gen" includeSubdirectories="true" />
|
||||
<directory url="file://$PROJECT_DIR$/menudrawer/library/gen" includeSubdirectories="true" />
|
||||
<directory url="file://$PROJECT_DIR$/pulltorefresh/library/gen" includeSubdirectories="true" />
|
||||
</excludeFromCompile>
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
<component name="ProjectDictionaryState">
|
||||
<dictionary name="Josh">
|
||||
<words>
|
||||
<w>bitrate</w>
|
||||
<w>deserialize</w>
|
||||
<w>deserialized</w>
|
||||
<w>gapless</w>
|
||||
<w>looper</w>
|
||||
<w>playlists</w>
|
||||
<w>transcoded</w>
|
||||
<w>vizualizer</w>
|
||||
</words>
|
||||
</dictionary>
|
||||
</component>
|
|
@ -0,0 +1,20 @@
|
|||
<component name="InspectionProjectProfileManager">
|
||||
<profile version="1.0" is_locked="false">
|
||||
<option name="myName" value="Project Default" />
|
||||
<option name="myLocal" value="false" />
|
||||
<inspection_tool class="ClassReferencesSubclass" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="DeclareCollectionAsInterface" enabled="true" level="WARNING" enabled_by_default="true">
|
||||
<option name="ignoreLocalVariables" value="false" />
|
||||
<option name="ignorePrivateMethodsAndFields" value="false" />
|
||||
</inspection_tool>
|
||||
<inspection_tool class="OverlyStrongTypeCast" enabled="true" level="WARNING" enabled_by_default="true">
|
||||
<option name="ignoreInMatchingInstanceof" value="false" />
|
||||
</inspection_tool>
|
||||
<inspection_tool class="TypeMayBeWeakened" enabled="true" level="WARNING" enabled_by_default="true">
|
||||
<option name="useRighthandTypeAsWeakestTypeInAssignments" value="true" />
|
||||
<option name="useParameterizedTypeForCollectionMethods" value="true" />
|
||||
<option name="doNotWeakenToJavaLangObject" value="true" />
|
||||
<option name="onlyWeakentoInterface" value="true" />
|
||||
</inspection_tool>
|
||||
</profile>
|
||||
</component>
|
|
@ -0,0 +1,7 @@
|
|||
<component name="InspectionProjectProfileManager">
|
||||
<settings>
|
||||
<option name="PROJECT_PROFILE" />
|
||||
<option name="USE_PROJECT_PROFILE" value="false" />
|
||||
<version value="1.0" />
|
||||
</settings>
|
||||
</component>
|
|
@ -2,20 +2,21 @@
|
|||
<manifest xmlns:a="http://schemas.android.com/apk/res/android"
|
||||
package="com.thejoshwa.ultrasonic.androidapp"
|
||||
a:installLocation="auto"
|
||||
a:versionCode="34"
|
||||
a:versionName="1.2.0.7" >
|
||||
a:versionCode="35"
|
||||
a:versionName="1.2.0.8" >
|
||||
|
||||
<uses-permission a:name="android.permission.INTERNET" />
|
||||
<uses-permission a:name="android.permission.READ_PHONE_STATE" />
|
||||
<uses-permission a:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission a:name="android.permission.WAKE_LOCK" />
|
||||
<uses-permission a:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission a:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission a:name="android.permission.RECORD_AUDIO" />
|
||||
<uses-permission a:name="android.permission.MODIFY_AUDIO_SETTINGS" />
|
||||
|
||||
<uses-sdk
|
||||
a:minSdkVersion="14"
|
||||
a:targetSdkVersion="17" />
|
||||
a:targetSdkVersion="19" />
|
||||
|
||||
<supports-screens
|
||||
a:anyDensity="true"
|
||||
|
@ -98,6 +99,7 @@
|
|||
a:launchMode="singleTask" >
|
||||
<intent-filter>
|
||||
<action a:name="android.intent.action.SEARCH" />
|
||||
<category a:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
|
||||
<meta-data
|
||||
|
|
|
@ -17,9 +17,9 @@
|
|||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/gen" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/gen" isTestSource="false" generated="true" />
|
||||
</content>
|
||||
<orderEntry type="jdk" jdkName="Android 4.2.2" jdkType="Android SDK" />
|
||||
<orderEntry type="jdk" jdkName="Android API 19 Platform" jdkType="Android SDK" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="module" module-name="menudrawer" />
|
||||
<orderEntry type="module" module-name="pulltorefresh" />
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
# This file is automatically generated by Android Tools.
|
||||
## This file is automatically generated by Android Studio.
|
||||
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
|
||||
#
|
||||
# This file must *NOT* be checked in Version Control Systems,
|
||||
# This file must *NOT* be checked into Version Control Systems,
|
||||
# as it contains information specific to your local configuration.
|
||||
|
||||
# location of the SDK. This is only used by Ant
|
||||
#
|
||||
# Location of the SDK. This is only used by Gradle.
|
||||
# For customization when using a Version Control System, please read the
|
||||
# header note.
|
||||
sdk.dir=c:/progs/android-sdk-windows
|
||||
#Sat Nov 30 23:46:41 MST 2013
|
||||
sdk.dir=C\:/Program Files (x86)/Android/android-studio/sdk
|
||||
|
|
|
@ -8,6 +8,9 @@
|
|||
<option name="MANIFEST_FILE_RELATIVE_PATH" value="/menudrawer/library/AndroidManifest.xml" />
|
||||
<option name="RES_FOLDER_RELATIVE_PATH" value="/menudrawer/library/res" />
|
||||
<option name="LIBRARY_PROJECT" value="true" />
|
||||
<proGuardCfgFiles>
|
||||
<file>file://D:/Data/Android/adt-bundle-windows/sdk/tools/proguard/proguard-android.txt</file>
|
||||
</proGuardCfgFiles>
|
||||
</configuration>
|
||||
</facet>
|
||||
</component>
|
||||
|
@ -15,7 +18,7 @@
|
|||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$/menudrawer">
|
||||
<sourceFolder url="file://$MODULE_DIR$/menudrawer/library/src" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/menudrawer/library/gen" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/menudrawer/library/gen" isTestSource="false" generated="true" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
# project structure.
|
||||
|
||||
# Project target.
|
||||
target=android-17
|
||||
target=android-19
|
||||
android.library=false
|
||||
android.library.reference.1=menudrawer
|
||||
android.library.reference.2=pulltorefresh
|
||||
|
|
|
@ -8,6 +8,9 @@
|
|||
<option name="MANIFEST_FILE_RELATIVE_PATH" value="/pulltorefresh/library/AndroidManifest.xml" />
|
||||
<option name="RES_FOLDER_RELATIVE_PATH" value="/pulltorefresh/library/res" />
|
||||
<option name="LIBRARY_PROJECT" value="true" />
|
||||
<proGuardCfgFiles>
|
||||
<file>file://D:/Data/Android/adt-bundle-windows/sdk/tools/proguard/proguard-android.txt</file>
|
||||
</proGuardCfgFiles>
|
||||
</configuration>
|
||||
</facet>
|
||||
</component>
|
||||
|
@ -15,7 +18,7 @@
|
|||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$/pulltorefresh">
|
||||
<sourceFolder url="file://$MODULE_DIR$/pulltorefresh/library/src" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/pulltorefresh/library/gen" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/pulltorefresh/library/gen" isTestSource="false" generated="true" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 5.2 KiB |
|
@ -5,8 +5,8 @@
|
|||
|
||||
<ImageView
|
||||
a:id="@+id/select_album_art"
|
||||
a:layout_width="120dip"
|
||||
a:layout_height="120dip"
|
||||
a:layout_width="160dip"
|
||||
a:layout_height="160dip"
|
||||
a:layout_alignParentLeft="true"
|
||||
a:layout_alignParentTop="true"
|
||||
a:layout_marginRight="10dip"
|
||||
|
|
|
@ -45,264 +45,325 @@ import com.thejoshwa.ultrasonic.androidapp.view.EntryAdapter;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class BookmarkActivity extends SubsonicTabActivity {
|
||||
public class BookmarkActivity extends SubsonicTabActivity
|
||||
{
|
||||
|
||||
private PullToRefreshListView refreshAlbumListView;
|
||||
private ListView albumListView;
|
||||
private View albumButtons;
|
||||
private View emptyView;
|
||||
private ImageView playNowButton;
|
||||
private ImageView pinButton;
|
||||
private ImageView unpinButton;
|
||||
private ImageView downloadButton;
|
||||
private ImageView deleteButton;
|
||||
private PullToRefreshListView refreshAlbumListView;
|
||||
private ListView albumListView;
|
||||
private View albumButtons;
|
||||
private View emptyView;
|
||||
private ImageView playNowButton;
|
||||
private ImageView pinButton;
|
||||
private ImageView unpinButton;
|
||||
private ImageView downloadButton;
|
||||
private ImageView deleteButton;
|
||||
|
||||
/**
|
||||
* Called when the activity is first created.
|
||||
*/
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.select_album);
|
||||
|
||||
albumButtons = findViewById(R.id.menu_album);
|
||||
|
||||
refreshAlbumListView = (PullToRefreshListView) findViewById(R.id.select_album_entries);
|
||||
albumListView = refreshAlbumListView.getRefreshableView();
|
||||
|
||||
refreshAlbumListView.setOnRefreshListener(new OnRefreshListener<ListView>() {
|
||||
@Override
|
||||
public void onRefresh(PullToRefreshBase<ListView> refreshView) {
|
||||
new GetDataTask().execute();
|
||||
}
|
||||
});
|
||||
/**
|
||||
* Called when the activity is first created.
|
||||
*/
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.select_album);
|
||||
|
||||
albumListView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
|
||||
|
||||
albumListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
if (position >= 0) {
|
||||
Entry entry = (Entry) parent.getItemAtPosition(position);
|
||||
albumButtons = findViewById(R.id.menu_album);
|
||||
|
||||
if (entry != null) {
|
||||
if (entry.isVideo()) {
|
||||
playVideo(entry);
|
||||
} else {
|
||||
enableButtons();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
refreshAlbumListView = (PullToRefreshListView) findViewById(R.id.select_album_entries);
|
||||
albumListView = refreshAlbumListView.getRefreshableView();
|
||||
|
||||
ImageView selectButton = (ImageView) findViewById(R.id.select_album_select);
|
||||
playNowButton = (ImageView) findViewById(R.id.select_album_play_now);
|
||||
ImageView playNextButton = (ImageView) findViewById(R.id.select_album_play_next);
|
||||
ImageView playLastButton = (ImageView) findViewById(R.id.select_album_play_last);
|
||||
pinButton = (ImageView) findViewById(R.id.select_album_pin);
|
||||
unpinButton = (ImageView) findViewById(R.id.select_album_unpin);
|
||||
downloadButton = (ImageView) findViewById(R.id.select_album_download);
|
||||
deleteButton = (ImageView) findViewById(R.id.select_album_delete);
|
||||
ImageView oreButton = (ImageView) findViewById(R.id.select_album_more);
|
||||
refreshAlbumListView.setOnRefreshListener(new OnRefreshListener<ListView>()
|
||||
{
|
||||
@Override
|
||||
public void onRefresh(PullToRefreshBase<ListView> refreshView)
|
||||
{
|
||||
new GetDataTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}
|
||||
});
|
||||
|
||||
albumListView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
|
||||
|
||||
albumListView.setOnItemClickListener(new AdapterView.OnItemClickListener()
|
||||
{
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
|
||||
{
|
||||
if (position >= 0)
|
||||
{
|
||||
Entry entry = (Entry) parent.getItemAtPosition(position);
|
||||
|
||||
if (entry != null)
|
||||
{
|
||||
if (entry.isVideo())
|
||||
{
|
||||
playVideo(entry);
|
||||
}
|
||||
else
|
||||
{
|
||||
enableButtons();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
ImageView selectButton = (ImageView) findViewById(R.id.select_album_select);
|
||||
playNowButton = (ImageView) findViewById(R.id.select_album_play_now);
|
||||
ImageView playNextButton = (ImageView) findViewById(R.id.select_album_play_next);
|
||||
ImageView playLastButton = (ImageView) findViewById(R.id.select_album_play_last);
|
||||
pinButton = (ImageView) findViewById(R.id.select_album_pin);
|
||||
unpinButton = (ImageView) findViewById(R.id.select_album_unpin);
|
||||
downloadButton = (ImageView) findViewById(R.id.select_album_download);
|
||||
deleteButton = (ImageView) findViewById(R.id.select_album_delete);
|
||||
ImageView oreButton = (ImageView) findViewById(R.id.select_album_more);
|
||||
emptyView = findViewById(R.id.select_album_empty);
|
||||
|
||||
|
||||
selectButton.setVisibility(View.GONE);
|
||||
playNextButton.setVisibility(View.GONE);
|
||||
playLastButton.setVisibility(View.GONE);
|
||||
oreButton.setVisibility(View.GONE);
|
||||
|
||||
playNowButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
playNow(getSelectedSongs(albumListView));
|
||||
}
|
||||
});
|
||||
|
||||
selectButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
selectAllOrNone();
|
||||
}
|
||||
});
|
||||
pinButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
downloadBackground(true);
|
||||
selectAll(false, false);
|
||||
}
|
||||
});
|
||||
unpinButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
unpin();
|
||||
selectAll(false, false);
|
||||
}
|
||||
});
|
||||
downloadButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
downloadBackground(false);
|
||||
selectAll(false, false);
|
||||
}
|
||||
});
|
||||
deleteButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
delete();
|
||||
selectAll(false, false);
|
||||
}
|
||||
});
|
||||
playNowButton.setOnClickListener(new View.OnClickListener()
|
||||
{
|
||||
@Override
|
||||
public void onClick(View view)
|
||||
{
|
||||
playNow(getSelectedSongs(albumListView));
|
||||
}
|
||||
});
|
||||
|
||||
registerForContextMenu(albumListView);
|
||||
selectButton.setOnClickListener(new View.OnClickListener()
|
||||
{
|
||||
@Override
|
||||
public void onClick(View view)
|
||||
{
|
||||
selectAllOrNone();
|
||||
}
|
||||
});
|
||||
pinButton.setOnClickListener(new View.OnClickListener()
|
||||
{
|
||||
@Override
|
||||
public void onClick(View view)
|
||||
{
|
||||
downloadBackground(true);
|
||||
selectAll(false, false);
|
||||
}
|
||||
});
|
||||
unpinButton.setOnClickListener(new View.OnClickListener()
|
||||
{
|
||||
@Override
|
||||
public void onClick(View view)
|
||||
{
|
||||
unpin();
|
||||
selectAll(false, false);
|
||||
}
|
||||
});
|
||||
downloadButton.setOnClickListener(new View.OnClickListener()
|
||||
{
|
||||
@Override
|
||||
public void onClick(View view)
|
||||
{
|
||||
downloadBackground(false);
|
||||
selectAll(false, false);
|
||||
}
|
||||
});
|
||||
deleteButton.setOnClickListener(new View.OnClickListener()
|
||||
{
|
||||
@Override
|
||||
public void onClick(View view)
|
||||
{
|
||||
delete();
|
||||
selectAll(false, false);
|
||||
}
|
||||
});
|
||||
|
||||
enableButtons();
|
||||
registerForContextMenu(albumListView);
|
||||
|
||||
View browseMenuItem = findViewById(R.id.menu_bookmarks);
|
||||
menuDrawer.setActiveView(browseMenuItem);
|
||||
|
||||
getBookmarks();
|
||||
|
||||
}
|
||||
|
||||
private void getBookmarks() {
|
||||
setActionBarSubtitle(R.string.button_bar_bookmarks);
|
||||
enableButtons();
|
||||
|
||||
new LoadTask() {
|
||||
@Override
|
||||
protected MusicDirectory load(MusicService service) throws Exception {
|
||||
return Util.getSongsFromBookmarks(service.getBookmarks(BookmarkActivity.this, this));
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
|
||||
private void playNow(List<Entry> songs) {
|
||||
if(getSelectedSongs(albumListView).size() > 0) {
|
||||
View browseMenuItem = findViewById(R.id.menu_bookmarks);
|
||||
menuDrawer.setActiveView(browseMenuItem);
|
||||
|
||||
getBookmarks();
|
||||
|
||||
}
|
||||
|
||||
private void getBookmarks()
|
||||
{
|
||||
setActionBarSubtitle(R.string.button_bar_bookmarks);
|
||||
|
||||
new LoadTask()
|
||||
{
|
||||
@Override
|
||||
protected MusicDirectory load(MusicService service) throws Exception
|
||||
{
|
||||
return Util.getSongsFromBookmarks(service.getBookmarks(BookmarkActivity.this, this));
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
|
||||
private void playNow(List<Entry> songs)
|
||||
{
|
||||
if (getSelectedSongs(albumListView).size() > 0)
|
||||
{
|
||||
int position = songs.get(0).getBookmarkPosition();
|
||||
getDownloadService().restore(songs, 0, position, true, true);
|
||||
selectAll(false, false);
|
||||
}
|
||||
}
|
||||
|
||||
private List<MusicDirectory.Entry> getSelectedSongs(ListView albumListView) {
|
||||
|
||||
private static List<MusicDirectory.Entry> getSelectedSongs(ListView albumListView)
|
||||
{
|
||||
List<MusicDirectory.Entry> songs = new ArrayList<MusicDirectory.Entry>(10);
|
||||
|
||||
if (albumListView != null) {
|
||||
int count = albumListView.getCount();
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (albumListView.isItemChecked(i)) {
|
||||
songs.add((MusicDirectory.Entry) albumListView.getItemAtPosition(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return songs;
|
||||
}
|
||||
|
||||
private void refresh() {
|
||||
finish();
|
||||
Intent intent = getIntent();
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_REFRESH, true);
|
||||
Util.startActivityWithoutTransition(this, intent);
|
||||
}
|
||||
if (albumListView != null)
|
||||
{
|
||||
int count = albumListView.getCount();
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
if (albumListView.isItemChecked(i))
|
||||
{
|
||||
songs.add((MusicDirectory.Entry) albumListView.getItemAtPosition(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
return songs;
|
||||
}
|
||||
|
||||
private void refresh()
|
||||
{
|
||||
finish();
|
||||
Intent intent = getIntent();
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_REFRESH, true);
|
||||
Util.startActivityWithoutTransition(this, intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item)
|
||||
{
|
||||
switch (item.getItemId())
|
||||
{
|
||||
case android.R.id.home:
|
||||
menuDrawer.toggleMenu();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void selectAllOrNone() {
|
||||
boolean someUnselected = false;
|
||||
int count = albumListView.getCount();
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (!albumListView.isItemChecked(i) && albumListView.getItemAtPosition(i) instanceof MusicDirectory.Entry) {
|
||||
someUnselected = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
selectAll(someUnselected, true);
|
||||
}
|
||||
|
||||
private void selectAll(boolean selected, boolean toast) {
|
||||
int count = albumListView.getCount();
|
||||
int selectedCount = 0;
|
||||
for (int i = 0; i < count; i++) {
|
||||
MusicDirectory.Entry entry = (MusicDirectory.Entry) albumListView.getItemAtPosition(i);
|
||||
if (entry != null && !entry.isDirectory() && !entry.isVideo()) {
|
||||
albumListView.setItemChecked(i, selected);
|
||||
selectedCount++;
|
||||
}
|
||||
}
|
||||
|
||||
// Display toast: N tracks selected / N tracks unselected
|
||||
if (toast) {
|
||||
int toastResId = selected ? R.string.select_album_n_selected : R.string.select_album_n_unselected;
|
||||
Util.toast(this, getString(toastResId, selectedCount));
|
||||
}
|
||||
|
||||
enableButtons();
|
||||
}
|
||||
|
||||
private void enableButtons() {
|
||||
if (getDownloadService() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<MusicDirectory.Entry> selection = getSelectedSongs(albumListView);
|
||||
boolean enabled = !selection.isEmpty();
|
||||
boolean unpinEnabled = false;
|
||||
boolean deleteEnabled = false;
|
||||
|
||||
int pinnedCount = 0;
|
||||
|
||||
for (MusicDirectory.Entry song : selection) {
|
||||
DownloadFile downloadFile = getDownloadService().forSong(song);
|
||||
if (downloadFile.isWorkDone()) {
|
||||
deleteEnabled = true;
|
||||
}
|
||||
|
||||
if (downloadFile.isSaved()) {
|
||||
pinnedCount++;
|
||||
unpinEnabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
playNowButton.setVisibility(enabled && deleteEnabled ? View.VISIBLE : View.GONE);
|
||||
pinButton.setVisibility((enabled && !Util.isOffline(this) && selection.size() > pinnedCount) ? View.VISIBLE : View.GONE);
|
||||
unpinButton.setVisibility(enabled && unpinEnabled ? View.VISIBLE : View.GONE);
|
||||
downloadButton.setVisibility(enabled && !deleteEnabled && !Util.isOffline(this) ? View.VISIBLE : View.GONE);
|
||||
deleteButton.setVisibility(enabled && deleteEnabled ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
|
||||
private void downloadBackground(final boolean save) {
|
||||
List<MusicDirectory.Entry> songs = getSelectedSongs(albumListView);
|
||||
if(songs.isEmpty()) {
|
||||
selectAll(true, false);
|
||||
songs = getSelectedSongs(albumListView);
|
||||
return true;
|
||||
}
|
||||
downloadBackground(save, songs);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void downloadBackground(final boolean save, final List<MusicDirectory.Entry> songs) {
|
||||
if (getDownloadService() == null) {
|
||||
|
||||
private void selectAllOrNone()
|
||||
{
|
||||
boolean someUnselected = false;
|
||||
int count = albumListView.getCount();
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
if (!albumListView.isItemChecked(i) && albumListView.getItemAtPosition(i) instanceof MusicDirectory.Entry)
|
||||
{
|
||||
someUnselected = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
selectAll(someUnselected, true);
|
||||
}
|
||||
|
||||
private void selectAll(boolean selected, boolean toast)
|
||||
{
|
||||
int count = albumListView.getCount();
|
||||
int selectedCount = 0;
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
MusicDirectory.Entry entry = (MusicDirectory.Entry) albumListView.getItemAtPosition(i);
|
||||
if (entry != null && !entry.isDirectory() && !entry.isVideo())
|
||||
{
|
||||
albumListView.setItemChecked(i, selected);
|
||||
selectedCount++;
|
||||
}
|
||||
}
|
||||
|
||||
// Display toast: N tracks selected / N tracks unselected
|
||||
if (toast)
|
||||
{
|
||||
int toastResId = selected ? R.string.select_album_n_selected : R.string.select_album_n_unselected;
|
||||
Util.toast(this, getString(toastResId, selectedCount));
|
||||
}
|
||||
|
||||
enableButtons();
|
||||
}
|
||||
|
||||
private void enableButtons()
|
||||
{
|
||||
if (getDownloadService() == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Runnable onValid = new Runnable() {
|
||||
List<MusicDirectory.Entry> selection = getSelectedSongs(albumListView);
|
||||
boolean enabled = !selection.isEmpty();
|
||||
boolean unpinEnabled = false;
|
||||
boolean deleteEnabled = false;
|
||||
|
||||
int pinnedCount = 0;
|
||||
|
||||
for (MusicDirectory.Entry song : selection)
|
||||
{
|
||||
DownloadFile downloadFile = getDownloadService().forSong(song);
|
||||
if (downloadFile.isWorkDone())
|
||||
{
|
||||
deleteEnabled = true;
|
||||
}
|
||||
|
||||
if (downloadFile.isSaved())
|
||||
{
|
||||
pinnedCount++;
|
||||
unpinEnabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
playNowButton.setVisibility(enabled && deleteEnabled ? View.VISIBLE : View.GONE);
|
||||
pinButton.setVisibility((enabled && !Util.isOffline(this) && selection.size() > pinnedCount) ? View.VISIBLE : View.GONE);
|
||||
unpinButton.setVisibility(enabled && unpinEnabled ? View.VISIBLE : View.GONE);
|
||||
downloadButton.setVisibility(enabled && !deleteEnabled && !Util.isOffline(this) ? View.VISIBLE : View.GONE);
|
||||
deleteButton.setVisibility(enabled && deleteEnabled ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
|
||||
private void downloadBackground(final boolean save)
|
||||
{
|
||||
List<MusicDirectory.Entry> songs = getSelectedSongs(albumListView);
|
||||
|
||||
if (songs.isEmpty())
|
||||
{
|
||||
selectAll(true, false);
|
||||
songs = getSelectedSongs(albumListView);
|
||||
}
|
||||
|
||||
downloadBackground(save, songs);
|
||||
}
|
||||
|
||||
private void downloadBackground(final boolean save, final List<MusicDirectory.Entry> songs)
|
||||
{
|
||||
if (getDownloadService() == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Runnable onValid = new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run() {
|
||||
public void run()
|
||||
{
|
||||
warnIfNetworkOrStorageUnavailable();
|
||||
getDownloadService().downloadBackground(songs, save);
|
||||
|
||||
if (save) {
|
||||
if (save)
|
||||
{
|
||||
Util.toast(BookmarkActivity.this, getResources().getQuantityString(R.plurals.select_album_n_songs_pinned, songs.size(), songs.size()));
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
Util.toast(BookmarkActivity.this, getResources().getQuantityString(R.plurals.select_album_n_songs_downloaded, songs.size(), songs.size()));
|
||||
}
|
||||
}
|
||||
|
@ -310,94 +371,114 @@ public class BookmarkActivity extends SubsonicTabActivity {
|
|||
|
||||
checkLicenseAndTrialPeriod(onValid);
|
||||
}
|
||||
|
||||
private void delete() {
|
||||
|
||||
private void delete()
|
||||
{
|
||||
List<MusicDirectory.Entry> songs = getSelectedSongs(albumListView);
|
||||
if(songs.isEmpty()) {
|
||||
|
||||
if (songs.isEmpty())
|
||||
{
|
||||
selectAll(true, false);
|
||||
songs = getSelectedSongs(albumListView);
|
||||
}
|
||||
if (getDownloadService() != null) {
|
||||
getDownloadService().delete(songs);
|
||||
}
|
||||
}
|
||||
|
||||
private void unpin() {
|
||||
if (getDownloadService() != null) {
|
||||
List<MusicDirectory.Entry> songs = getSelectedSongs(albumListView);
|
||||
Util.toast(BookmarkActivity.this, getResources().getQuantityString(R.plurals.select_album_n_songs_unpinned, songs.size(), songs.size()));
|
||||
getDownloadService().unpin(songs);
|
||||
}
|
||||
}
|
||||
if (getDownloadService() != null)
|
||||
{
|
||||
getDownloadService().delete(songs);
|
||||
}
|
||||
}
|
||||
|
||||
private abstract class LoadTask extends TabActivityBackgroundTask<Pair<MusicDirectory, Boolean>> {
|
||||
private void unpin()
|
||||
{
|
||||
if (getDownloadService() != null)
|
||||
{
|
||||
List<MusicDirectory.Entry> songs = getSelectedSongs(albumListView);
|
||||
Util.toast(BookmarkActivity.this, getResources().getQuantityString(R.plurals.select_album_n_songs_unpinned, songs.size(), songs.size()));
|
||||
getDownloadService().unpin(songs);
|
||||
}
|
||||
}
|
||||
|
||||
public LoadTask() {
|
||||
super(BookmarkActivity.this, true);
|
||||
}
|
||||
private abstract class LoadTask extends TabActivityBackgroundTask<Pair<MusicDirectory, Boolean>>
|
||||
{
|
||||
|
||||
protected abstract MusicDirectory load(MusicService service) throws Exception;
|
||||
public LoadTask()
|
||||
{
|
||||
super(BookmarkActivity.this, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Pair<MusicDirectory, Boolean> doInBackground() throws Throwable {
|
||||
MusicService musicService = MusicServiceFactory.getMusicService(BookmarkActivity.this);
|
||||
MusicDirectory dir = load(musicService);
|
||||
boolean valid = musicService.isLicenseValid(BookmarkActivity.this, this);
|
||||
return new Pair<MusicDirectory, Boolean>(dir, valid);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void done(Pair<MusicDirectory, Boolean> result) {
|
||||
MusicDirectory musicDirectory = result.getFirst();
|
||||
List<MusicDirectory.Entry> entries = musicDirectory.getChildren();
|
||||
|
||||
int songCount = 0;
|
||||
for (MusicDirectory.Entry entry : entries) {
|
||||
if (!entry.isDirectory()) {
|
||||
songCount++;
|
||||
}
|
||||
}
|
||||
|
||||
final int listSize = getIntent().getIntExtra(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_SIZE, 0);
|
||||
|
||||
if (songCount > 0) {
|
||||
pinButton.setVisibility(View.VISIBLE);
|
||||
unpinButton.setVisibility(View.VISIBLE);
|
||||
downloadButton.setVisibility(View.VISIBLE);
|
||||
deleteButton.setVisibility(View.VISIBLE);
|
||||
playNowButton.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
pinButton.setVisibility(View.GONE);
|
||||
unpinButton.setVisibility(View.GONE);
|
||||
downloadButton.setVisibility(View.GONE);
|
||||
deleteButton.setVisibility(View.GONE);
|
||||
playNowButton.setVisibility(View.GONE);
|
||||
|
||||
if (listSize == 0 || result.getFirst().getChildren().size() < listSize) {
|
||||
albumButtons.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
enableButtons();
|
||||
|
||||
emptyView.setVisibility(entries.isEmpty() ? View.VISIBLE : View.GONE);
|
||||
|
||||
albumListView.setAdapter(new EntryAdapter(BookmarkActivity.this, getImageLoader(), entries, true));
|
||||
licenseValid = result.getSecond();
|
||||
}
|
||||
}
|
||||
|
||||
private class GetDataTask extends AsyncTask<Void, Void, String[]> {
|
||||
@Override
|
||||
protected void onPostExecute(String[] result) {
|
||||
refreshAlbumListView.onRefreshComplete();
|
||||
super.onPostExecute(result);
|
||||
}
|
||||
protected abstract MusicDirectory load(MusicService service) throws Exception;
|
||||
|
||||
@Override
|
||||
protected String[] doInBackground(Void... params) {
|
||||
protected Pair<MusicDirectory, Boolean> doInBackground() throws Throwable
|
||||
{
|
||||
MusicService musicService = MusicServiceFactory.getMusicService(BookmarkActivity.this);
|
||||
MusicDirectory dir = load(musicService);
|
||||
boolean valid = musicService.isLicenseValid(BookmarkActivity.this, this);
|
||||
return new Pair<MusicDirectory, Boolean>(dir, valid);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void done(Pair<MusicDirectory, Boolean> result)
|
||||
{
|
||||
MusicDirectory musicDirectory = result.getFirst();
|
||||
List<MusicDirectory.Entry> entries = musicDirectory.getChildren();
|
||||
|
||||
int songCount = 0;
|
||||
for (MusicDirectory.Entry entry : entries)
|
||||
{
|
||||
if (!entry.isDirectory())
|
||||
{
|
||||
songCount++;
|
||||
}
|
||||
}
|
||||
|
||||
final int listSize = getIntent().getIntExtra(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_SIZE, 0);
|
||||
|
||||
if (songCount > 0)
|
||||
{
|
||||
pinButton.setVisibility(View.VISIBLE);
|
||||
unpinButton.setVisibility(View.VISIBLE);
|
||||
downloadButton.setVisibility(View.VISIBLE);
|
||||
deleteButton.setVisibility(View.VISIBLE);
|
||||
playNowButton.setVisibility(View.VISIBLE);
|
||||
}
|
||||
else
|
||||
{
|
||||
pinButton.setVisibility(View.GONE);
|
||||
unpinButton.setVisibility(View.GONE);
|
||||
downloadButton.setVisibility(View.GONE);
|
||||
deleteButton.setVisibility(View.GONE);
|
||||
playNowButton.setVisibility(View.GONE);
|
||||
|
||||
if (listSize == 0 || result.getFirst().getChildren().size() < listSize)
|
||||
{
|
||||
albumButtons.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
enableButtons();
|
||||
|
||||
emptyView.setVisibility(entries.isEmpty() ? View.VISIBLE : View.GONE);
|
||||
|
||||
albumListView.setAdapter(new EntryAdapter(BookmarkActivity.this, getImageLoader(), entries, true));
|
||||
licenseValid = result.getSecond();
|
||||
}
|
||||
}
|
||||
|
||||
private class GetDataTask extends AsyncTask<Void, Void, String[]>
|
||||
{
|
||||
@Override
|
||||
protected void onPostExecute(String[] result)
|
||||
{
|
||||
refreshAlbumListView.onRefreshComplete();
|
||||
super.onPostExecute(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String[] doInBackground(Void... params)
|
||||
{
|
||||
refresh();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,5 @@
|
|||
package com.thejoshwa.ultrasonic.androidapp.activity;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.text.Editable;
|
||||
|
@ -15,13 +9,14 @@ import android.view.View;
|
|||
import android.view.inputmethod.EditorInfo;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.ListAdapter;
|
||||
import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.handmark.pulltorefresh.library.PullToRefreshBase;
|
||||
import com.handmark.pulltorefresh.library.PullToRefreshBase.Mode;
|
||||
import com.handmark.pulltorefresh.library.PullToRefreshListView;
|
||||
import com.handmark.pulltorefresh.library.PullToRefreshBase.OnRefreshListener;
|
||||
import com.handmark.pulltorefresh.library.PullToRefreshListView;
|
||||
import com.thejoshwa.ultrasonic.androidapp.R;
|
||||
import com.thejoshwa.ultrasonic.androidapp.domain.ChatMessage;
|
||||
import com.thejoshwa.ultrasonic.androidapp.service.MusicService;
|
||||
|
@ -31,133 +26,164 @@ import com.thejoshwa.ultrasonic.androidapp.util.TabActivityBackgroundTask;
|
|||
import com.thejoshwa.ultrasonic.androidapp.util.Util;
|
||||
import com.thejoshwa.ultrasonic.androidapp.view.ChatAdapter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
/**
|
||||
* @author Joshua Bahnsen
|
||||
*/
|
||||
public final class ChatActivity extends SubsonicTabActivity {
|
||||
private PullToRefreshListView refreshChatListView;
|
||||
private ListView chatListView;
|
||||
private EditText messageEditText;
|
||||
private ImageButton sendButton;
|
||||
private Timer timer = null;
|
||||
private volatile static Long lastChatMessageTime = (long) 0;
|
||||
private volatile static ArrayList<ChatMessage> messageList = new ArrayList<ChatMessage>();
|
||||
public final class ChatActivity extends SubsonicTabActivity
|
||||
{
|
||||
private PullToRefreshListView refreshChatListView;
|
||||
private ListView chatListView;
|
||||
private EditText messageEditText;
|
||||
private ImageButton sendButton;
|
||||
private Timer timer;
|
||||
private volatile static Long lastChatMessageTime = (long) 0;
|
||||
private volatile static ArrayList<ChatMessage> messageList = new ArrayList<ChatMessage>();
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle bundle) {
|
||||
super.onCreate(bundle);
|
||||
setContentView(R.layout.chat);
|
||||
|
||||
refreshChatListView = (PullToRefreshListView) findViewById(R.id.chat_entries);
|
||||
refreshChatListView.setMode(Mode.PULL_FROM_END);
|
||||
@Override
|
||||
protected void onCreate(Bundle bundle)
|
||||
{
|
||||
super.onCreate(bundle);
|
||||
setContentView(R.layout.chat);
|
||||
|
||||
messageEditText = (EditText) findViewById(R.id.chat_edittext);
|
||||
sendButton = (ImageButton) findViewById(R.id.chat_send);
|
||||
|
||||
sendButton.setOnClickListener(new View.OnClickListener() {
|
||||
refreshChatListView = (PullToRefreshListView) findViewById(R.id.chat_entries);
|
||||
refreshChatListView.setMode(Mode.PULL_FROM_END);
|
||||
|
||||
messageEditText = (EditText) findViewById(R.id.chat_edittext);
|
||||
sendButton = (ImageButton) findViewById(R.id.chat_send);
|
||||
|
||||
sendButton.setOnClickListener(new View.OnClickListener()
|
||||
{
|
||||
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
public void onClick(View view)
|
||||
{
|
||||
sendMessage();
|
||||
}
|
||||
});
|
||||
|
||||
chatListView = refreshChatListView.getRefreshableView();
|
||||
chatListView.setTranscriptMode(ListView.TRANSCRIPT_MODE_ALWAYS_SCROLL);
|
||||
chatListView.setStackFromBottom(true);
|
||||
|
||||
String serverName = Util.getServerName(this, Util.getActiveServer(this));
|
||||
String userName = Util.getUserName(this, Util.getActiveServer(this));
|
||||
String title = String.format("%s [%s@%s]", getResources().getString(R.string.button_bar_chat), userName, serverName);
|
||||
});
|
||||
|
||||
setActionBarSubtitle(title);
|
||||
chatListView = refreshChatListView.getRefreshableView();
|
||||
chatListView.setTranscriptMode(ListView.TRANSCRIPT_MODE_ALWAYS_SCROLL);
|
||||
chatListView.setStackFromBottom(true);
|
||||
|
||||
messageEditText.setImeActionLabel("Send", KeyEvent.KEYCODE_ENTER);
|
||||
|
||||
messageEditText.addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
|
||||
}
|
||||
String serverName = Util.getServerName(this, Util.getActiveServer(this));
|
||||
String userName = Util.getUserName(this, Util.getActiveServer(this));
|
||||
String title = String.format("%s [%s@%s]", getResources().getString(R.string.button_bar_chat), userName, serverName);
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
|
||||
}
|
||||
setActionBarSubtitle(title);
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable editable) {
|
||||
sendButton.setEnabled(!Util.isNullOrWhiteSpace(editable.toString()));
|
||||
}
|
||||
});
|
||||
|
||||
messageEditText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
|
||||
messageEditText.setImeActionLabel("Send", KeyEvent.KEYCODE_ENTER);
|
||||
|
||||
messageEditText.addTextChangedListener(new TextWatcher()
|
||||
{
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
|
||||
if (actionId == EditorInfo.IME_ACTION_DONE || (actionId == EditorInfo.IME_NULL && event.getAction() == KeyEvent.ACTION_DOWN)) {
|
||||
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable editable)
|
||||
{
|
||||
sendButton.setEnabled(!Util.isNullOrWhiteSpace(editable.toString()));
|
||||
}
|
||||
});
|
||||
|
||||
messageEditText.setOnEditorActionListener(new TextView.OnEditorActionListener()
|
||||
{
|
||||
|
||||
@Override
|
||||
public boolean onEditorAction(TextView v, int actionId, KeyEvent event)
|
||||
{
|
||||
if (actionId == EditorInfo.IME_ACTION_DONE || (actionId == EditorInfo.IME_NULL && event.getAction() == KeyEvent.ACTION_DOWN))
|
||||
{
|
||||
sendMessage();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
refreshChatListView.setOnRefreshListener(new OnRefreshListener<ListView>() {
|
||||
@Override
|
||||
public void onRefresh(PullToRefreshBase<ListView> refreshView) {
|
||||
new GetDataTask().execute();
|
||||
}
|
||||
});
|
||||
|
||||
View chatMenuItem = findViewById(R.id.menu_chat);
|
||||
menuDrawer.setActiveView(chatMenuItem);
|
||||
|
||||
load();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
refreshChatListView.setOnRefreshListener(new OnRefreshListener<ListView>()
|
||||
{
|
||||
@Override
|
||||
public void onRefresh(PullToRefreshBase<ListView> refreshView)
|
||||
{
|
||||
new GetDataTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}
|
||||
});
|
||||
|
||||
View chatMenuItem = findViewById(R.id.menu_chat);
|
||||
menuDrawer.setActiveView(chatMenuItem);
|
||||
|
||||
load();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostCreate(Bundle bundle) {
|
||||
protected void onPostCreate(Bundle bundle)
|
||||
{
|
||||
super.onPostCreate(bundle);
|
||||
|
||||
|
||||
timerMethod();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
|
||||
if (!messageList.isEmpty()) {
|
||||
ChatAdapter chatAdapter = new ChatAdapter(ChatActivity.this, messageList);
|
||||
chatListView.setAdapter(chatAdapter);
|
||||
}
|
||||
|
||||
if (timer == null) {
|
||||
timerMethod();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
protected void onResume()
|
||||
{
|
||||
super.onResume();
|
||||
|
||||
if (!messageList.isEmpty())
|
||||
{
|
||||
ListAdapter chatAdapter = new ChatAdapter(ChatActivity.this, messageList);
|
||||
chatListView.setAdapter(chatAdapter);
|
||||
}
|
||||
|
||||
if (timer == null)
|
||||
{
|
||||
timerMethod();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause()
|
||||
{
|
||||
super.onPause();
|
||||
|
||||
if (timer != null) {
|
||||
|
||||
if (timer != null)
|
||||
{
|
||||
timer.cancel();
|
||||
timer = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void timerMethod()
|
||||
{
|
||||
int refreshInterval = Util.getChatRefreshInterval(this);
|
||||
|
||||
if (refreshInterval > 0) {
|
||||
if (refreshInterval > 0)
|
||||
{
|
||||
timer = new Timer();
|
||||
|
||||
timer.schedule(new TimerTask() {
|
||||
public void run() {
|
||||
ChatActivity.this.runOnUiThread(new Runnable() {
|
||||
timer.schedule(new TimerTask()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
ChatActivity.this.runOnUiThread(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run() {
|
||||
public void run()
|
||||
{
|
||||
load();
|
||||
}
|
||||
});
|
||||
|
@ -166,81 +192,98 @@ public final class ChatActivity extends SubsonicTabActivity {
|
|||
}
|
||||
}
|
||||
|
||||
private void sendMessage() {
|
||||
if (messageEditText != null) {
|
||||
final String message;
|
||||
Editable text = messageEditText.getText();
|
||||
private void sendMessage()
|
||||
{
|
||||
if (messageEditText != null)
|
||||
{
|
||||
final String message;
|
||||
Editable text = messageEditText.getText();
|
||||
|
||||
if (text == null) {
|
||||
return;
|
||||
}
|
||||
if (text == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
message = text.toString();
|
||||
message = text.toString();
|
||||
|
||||
if (!Util.isNullOrWhiteSpace(message)) {
|
||||
messageEditText.setText("");
|
||||
if (!Util.isNullOrWhiteSpace(message))
|
||||
{
|
||||
messageEditText.setText("");
|
||||
|
||||
BackgroundTask<Void> task = new TabActivityBackgroundTask<Void>(ChatActivity.this, false) {
|
||||
@Override
|
||||
protected Void doInBackground() throws Throwable {
|
||||
MusicService musicService = MusicServiceFactory.getMusicService(ChatActivity.this);
|
||||
musicService.addChatMessage(message, ChatActivity.this, this);
|
||||
return null;
|
||||
}
|
||||
BackgroundTask<Void> task = new TabActivityBackgroundTask<Void>(ChatActivity.this, false)
|
||||
{
|
||||
@Override
|
||||
protected Void doInBackground() throws Throwable
|
||||
{
|
||||
MusicService musicService = MusicServiceFactory.getMusicService(ChatActivity.this);
|
||||
musicService.addChatMessage(message, ChatActivity.this, this);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void done(Void result) {
|
||||
load();
|
||||
}
|
||||
};
|
||||
@Override
|
||||
protected void done(Void result)
|
||||
{
|
||||
load();
|
||||
}
|
||||
};
|
||||
|
||||
task.execute();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void load() {
|
||||
BackgroundTask<List<ChatMessage>> task = new TabActivityBackgroundTask<List<ChatMessage>>(this, false) {
|
||||
@Override
|
||||
protected List<ChatMessage> doInBackground() throws Throwable {
|
||||
MusicService musicService = MusicServiceFactory.getMusicService(ChatActivity.this);
|
||||
return musicService.getChatMessages(lastChatMessageTime, ChatActivity.this, this);
|
||||
}
|
||||
task.execute();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void done(List<ChatMessage> result) {
|
||||
if (result != null && !result.isEmpty()) {
|
||||
// Reset lastChatMessageTime if we have a newer message
|
||||
for (ChatMessage message : result) {
|
||||
if (message.getTime() > lastChatMessageTime) {
|
||||
lastChatMessageTime = message.getTime();
|
||||
}
|
||||
}
|
||||
|
||||
// Reverse results to show them on the bottom
|
||||
Collections.reverse(result);
|
||||
messageList.addAll(result);
|
||||
|
||||
ChatAdapter chatAdapter = new ChatAdapter(ChatActivity.this, messageList);
|
||||
chatListView.setAdapter(chatAdapter);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
task.execute();
|
||||
}
|
||||
|
||||
private class GetDataTask extends AsyncTask<Void, Void, String[]> {
|
||||
@Override
|
||||
protected void onPostExecute(String[] result) {
|
||||
load();
|
||||
refreshChatListView.onRefreshComplete();
|
||||
super.onPostExecute(result);
|
||||
}
|
||||
private synchronized void load()
|
||||
{
|
||||
BackgroundTask<List<ChatMessage>> task = new TabActivityBackgroundTask<List<ChatMessage>>(this, false)
|
||||
{
|
||||
@Override
|
||||
protected List<ChatMessage> doInBackground() throws Throwable
|
||||
{
|
||||
MusicService musicService = MusicServiceFactory.getMusicService(ChatActivity.this);
|
||||
return musicService.getChatMessages(lastChatMessageTime, ChatActivity.this, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void done(List<ChatMessage> result)
|
||||
{
|
||||
if (result != null && !result.isEmpty())
|
||||
{
|
||||
// Reset lastChatMessageTime if we have a newer message
|
||||
for (ChatMessage message : result)
|
||||
{
|
||||
if (message.getTime() > lastChatMessageTime)
|
||||
{
|
||||
lastChatMessageTime = message.getTime();
|
||||
}
|
||||
}
|
||||
|
||||
// Reverse results to show them on the bottom
|
||||
Collections.reverse(result);
|
||||
messageList.addAll(result);
|
||||
|
||||
ListAdapter chatAdapter = new ChatAdapter(ChatActivity.this, messageList);
|
||||
chatListView.setAdapter(chatAdapter);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
task.execute();
|
||||
}
|
||||
|
||||
private class GetDataTask extends AsyncTask<Void, Void, String[]>
|
||||
{
|
||||
@Override
|
||||
protected void onPostExecute(String[] result)
|
||||
{
|
||||
load();
|
||||
refreshChatListView.onRefreshComplete();
|
||||
super.onPostExecute(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String[] doInBackground(Void... params) {
|
||||
protected String[] doInBackground(Void... params)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -33,6 +33,7 @@ import android.widget.CompoundButton;
|
|||
import android.widget.LinearLayout;
|
||||
import android.widget.SeekBar;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.thejoshwa.ultrasonic.androidapp.R;
|
||||
import com.thejoshwa.ultrasonic.androidapp.audiofx.EqualizerController;
|
||||
import com.thejoshwa.ultrasonic.androidapp.service.DownloadServiceImpl;
|
||||
|
@ -43,150 +44,179 @@ import com.thejoshwa.ultrasonic.androidapp.service.DownloadServiceImpl;
|
|||
* @author Sindre Mehus
|
||||
* @version $Id$
|
||||
*/
|
||||
public class EqualizerActivity extends Activity {
|
||||
public class EqualizerActivity extends Activity
|
||||
{
|
||||
|
||||
private static final int MENU_GROUP_PRESET = 100;
|
||||
private static final int MENU_GROUP_PRESET = 100;
|
||||
|
||||
private final Map<Short, SeekBar> bars = new HashMap<Short, SeekBar>();
|
||||
private EqualizerController equalizerController;
|
||||
private Equalizer equalizer;
|
||||
private final Map<Short, SeekBar> bars = new HashMap<Short, SeekBar>();
|
||||
private EqualizerController equalizerController;
|
||||
private Equalizer equalizer;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle bundle) {
|
||||
super.onCreate(bundle);
|
||||
setContentView(R.layout.equalizer);
|
||||
equalizerController = DownloadServiceImpl.getInstance().getEqualizerController();
|
||||
equalizer = equalizerController.getEqualizer();
|
||||
@Override
|
||||
public void onCreate(Bundle bundle)
|
||||
{
|
||||
super.onCreate(bundle);
|
||||
setContentView(R.layout.equalizer);
|
||||
equalizerController = DownloadServiceImpl.getInstance().getEqualizerController();
|
||||
equalizer = equalizerController.getEqualizer();
|
||||
|
||||
initEqualizer();
|
||||
initEqualizer();
|
||||
|
||||
final View presetButton = findViewById(R.id.equalizer_preset);
|
||||
registerForContextMenu(presetButton);
|
||||
presetButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
presetButton.showContextMenu();
|
||||
}
|
||||
});
|
||||
final View presetButton = findViewById(R.id.equalizer_preset);
|
||||
registerForContextMenu(presetButton);
|
||||
presetButton.setOnClickListener(new View.OnClickListener()
|
||||
{
|
||||
@Override
|
||||
public void onClick(View view)
|
||||
{
|
||||
presetButton.showContextMenu();
|
||||
}
|
||||
});
|
||||
|
||||
CheckBox enabledCheckBox = (CheckBox) findViewById(R.id.equalizer_enabled);
|
||||
enabledCheckBox.setChecked(equalizer.getEnabled());
|
||||
enabledCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
||||
@Override
|
||||
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
|
||||
setEqualizerEnabled(b);
|
||||
}
|
||||
});
|
||||
}
|
||||
CheckBox enabledCheckBox = (CheckBox) findViewById(R.id.equalizer_enabled);
|
||||
enabledCheckBox.setChecked(equalizer.getEnabled());
|
||||
enabledCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener()
|
||||
{
|
||||
@Override
|
||||
public void onCheckedChanged(CompoundButton compoundButton, boolean b)
|
||||
{
|
||||
setEqualizerEnabled(b);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
equalizerController.saveSettings();
|
||||
}
|
||||
@Override
|
||||
protected void onPause()
|
||||
{
|
||||
super.onPause();
|
||||
equalizerController.saveSettings();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) {
|
||||
super.onCreateContextMenu(menu, view, menuInfo);
|
||||
@Override
|
||||
public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo)
|
||||
{
|
||||
super.onCreateContextMenu(menu, view, menuInfo);
|
||||
|
||||
short currentPreset;
|
||||
try {
|
||||
currentPreset = equalizer.getCurrentPreset();
|
||||
} catch (Exception x) {
|
||||
currentPreset = -1;
|
||||
}
|
||||
short currentPreset;
|
||||
try
|
||||
{
|
||||
currentPreset = equalizer.getCurrentPreset();
|
||||
}
|
||||
catch (Exception x)
|
||||
{
|
||||
currentPreset = -1;
|
||||
}
|
||||
|
||||
for (short preset = 0; preset < equalizer.getNumberOfPresets(); preset++) {
|
||||
MenuItem menuItem = menu.add(MENU_GROUP_PRESET, preset, preset, equalizer.getPresetName(preset));
|
||||
if (preset == currentPreset) {
|
||||
menuItem.setChecked(true);
|
||||
}
|
||||
}
|
||||
menu.setGroupCheckable(MENU_GROUP_PRESET, true, true);
|
||||
}
|
||||
for (short preset = 0; preset < equalizer.getNumberOfPresets(); preset++)
|
||||
{
|
||||
MenuItem menuItem = menu.add(MENU_GROUP_PRESET, preset, preset, equalizer.getPresetName(preset));
|
||||
if (preset == currentPreset)
|
||||
{
|
||||
menuItem.setChecked(true);
|
||||
}
|
||||
}
|
||||
menu.setGroupCheckable(MENU_GROUP_PRESET, true, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onContextItemSelected(MenuItem menuItem) {
|
||||
short preset = (short) menuItem.getItemId();
|
||||
equalizer.usePreset(preset);
|
||||
updateBars();
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public boolean onContextItemSelected(MenuItem menuItem)
|
||||
{
|
||||
short preset = (short) menuItem.getItemId();
|
||||
equalizer.usePreset(preset);
|
||||
updateBars();
|
||||
return true;
|
||||
}
|
||||
|
||||
private void setEqualizerEnabled(boolean enabled) {
|
||||
equalizer.setEnabled(enabled);
|
||||
updateBars();
|
||||
}
|
||||
private void setEqualizerEnabled(boolean enabled)
|
||||
{
|
||||
equalizer.setEnabled(enabled);
|
||||
updateBars();
|
||||
}
|
||||
|
||||
private void updateBars() {
|
||||
private void updateBars()
|
||||
{
|
||||
|
||||
for (Map.Entry<Short, SeekBar> entry : bars.entrySet()) {
|
||||
short band = entry.getKey();
|
||||
SeekBar bar = entry.getValue();
|
||||
bar.setEnabled(equalizer.getEnabled());
|
||||
short minEQLevel = equalizer.getBandLevelRange()[0];
|
||||
bar.setProgress(equalizer.getBandLevel(band) - minEQLevel);
|
||||
}
|
||||
}
|
||||
for (Map.Entry<Short, SeekBar> entry : bars.entrySet())
|
||||
{
|
||||
short band = entry.getKey();
|
||||
SeekBar bar = entry.getValue();
|
||||
bar.setEnabled(equalizer.getEnabled());
|
||||
short minEQLevel = equalizer.getBandLevelRange()[0];
|
||||
bar.setProgress(equalizer.getBandLevel(band) - minEQLevel);
|
||||
}
|
||||
}
|
||||
|
||||
private void initEqualizer() {
|
||||
LinearLayout layout = (LinearLayout) findViewById(R.id.equalizer_layout);
|
||||
private void initEqualizer()
|
||||
{
|
||||
LinearLayout layout = (LinearLayout) findViewById(R.id.equalizer_layout);
|
||||
|
||||
try {
|
||||
short[] bandLevelRange = equalizer.getBandLevelRange();
|
||||
short numberOfBands = equalizer.getNumberOfBands();
|
||||
|
||||
final short minEQLevel = bandLevelRange[0];
|
||||
final short maxEQLevel = bandLevelRange[1];
|
||||
try
|
||||
{
|
||||
short[] bandLevelRange = equalizer.getBandLevelRange();
|
||||
short numberOfBands = equalizer.getNumberOfBands();
|
||||
|
||||
for (short i = 0; i < numberOfBands; i++) {
|
||||
final short band = i;
|
||||
final short minEQLevel = bandLevelRange[0];
|
||||
final short maxEQLevel = bandLevelRange[1];
|
||||
|
||||
View bandBar = LayoutInflater.from(this).inflate(R.layout.equalizer_bar, null);
|
||||
TextView freqTextView;
|
||||
for (short i = 0; i < numberOfBands; i++)
|
||||
{
|
||||
final short band = i;
|
||||
|
||||
if (bandBar != null) {
|
||||
freqTextView = (TextView) bandBar.findViewById(R.id.equalizer_frequency);
|
||||
final TextView levelTextView = (TextView) bandBar.findViewById(R.id.equalizer_level);
|
||||
SeekBar bar = (SeekBar) bandBar.findViewById(R.id.equalizer_bar);
|
||||
View bandBar = LayoutInflater.from(this).inflate(R.layout.equalizer_bar, null);
|
||||
TextView freqTextView;
|
||||
|
||||
freqTextView.setText((equalizer.getCenterFreq(band) / 1000) + " Hz");
|
||||
if (bandBar != null)
|
||||
{
|
||||
freqTextView = (TextView) bandBar.findViewById(R.id.equalizer_frequency);
|
||||
final TextView levelTextView = (TextView) bandBar.findViewById(R.id.equalizer_level);
|
||||
SeekBar bar = (SeekBar) bandBar.findViewById(R.id.equalizer_bar);
|
||||
|
||||
bars.put(band, bar);
|
||||
bar.setMax(maxEQLevel - minEQLevel);
|
||||
short level = equalizer.getBandLevel(band);
|
||||
bar.setProgress(level - minEQLevel);
|
||||
bar.setEnabled(equalizer.getEnabled());
|
||||
updateLevelText(levelTextView, level);
|
||||
freqTextView.setText((equalizer.getCenterFreq(band) / 1000) + " Hz");
|
||||
|
||||
bar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
|
||||
@Override
|
||||
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
|
||||
short level = (short) (progress + minEQLevel);
|
||||
if (fromUser) {
|
||||
equalizer.setBandLevel(band, level);
|
||||
}
|
||||
updateLevelText(levelTextView, level);
|
||||
}
|
||||
bars.put(band, bar);
|
||||
bar.setMax(maxEQLevel - minEQLevel);
|
||||
short level = equalizer.getBandLevel(band);
|
||||
bar.setProgress(level - minEQLevel);
|
||||
bar.setEnabled(equalizer.getEnabled());
|
||||
updateLevelText(levelTextView, level);
|
||||
|
||||
@Override
|
||||
public void onStartTrackingTouch(SeekBar seekBar) {
|
||||
}
|
||||
bar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener()
|
||||
{
|
||||
@Override
|
||||
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser)
|
||||
{
|
||||
short level = (short) (progress + minEQLevel);
|
||||
if (fromUser)
|
||||
{
|
||||
equalizer.setBandLevel(band, level);
|
||||
}
|
||||
updateLevelText(levelTextView, level);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStopTrackingTouch(SeekBar seekBar) {
|
||||
}
|
||||
});
|
||||
layout.addView(bandBar);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
//TODO: Show a dialog
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void onStartTrackingTouch(SeekBar seekBar)
|
||||
{
|
||||
}
|
||||
|
||||
private void updateLevelText(TextView levelTextView, short level) {
|
||||
levelTextView.setText((level > 0 ? "+" : "") + level / 100 + " dB");
|
||||
}
|
||||
@Override
|
||||
public void onStopTrackingTouch(SeekBar seekBar)
|
||||
{
|
||||
}
|
||||
});
|
||||
layout.addView(bandBar);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
//TODO: Show a dialog
|
||||
}
|
||||
}
|
||||
|
||||
private static void updateLevelText(TextView levelTextView, short level)
|
||||
{
|
||||
levelTextView.setText((level > 0 ? "+" : "") + level / 100 + " dB");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -45,251 +45,286 @@ import net.simonvt.menudrawer.Position;
|
|||
*
|
||||
* @author Sindre Mehus
|
||||
*/
|
||||
public final class HelpActivity extends Activity implements OnClickListener {
|
||||
private WebView webView;
|
||||
private ImageView backButton;
|
||||
private ImageView forwardButton;
|
||||
|
||||
private static final String STATE_MENUDRAWER = "com.thejoshwa.ultrasonic.androidapp.menuDrawer";
|
||||
private static final String STATE_ACTIVE_VIEW_ID = "com.thejoshwa.ultrasonic.androidapp.activeViewId";
|
||||
private static final String STATE_ACTIVE_POSITION = "com.thejoshwa.ultrasonic.androidapp.activePosition";
|
||||
|
||||
public MenuDrawer menuDrawer;
|
||||
private int activePosition = 1;
|
||||
private int menuActiveViewId;
|
||||
View chatMenuItem = null;
|
||||
View bookmarksMenuItem = null;
|
||||
public final class HelpActivity extends Activity implements OnClickListener
|
||||
{
|
||||
private WebView webView;
|
||||
private ImageView backButton;
|
||||
private ImageView forwardButton;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle bundle) {
|
||||
applyTheme();
|
||||
super.onCreate(bundle);
|
||||
getWindow().requestFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
|
||||
private static final String STATE_MENUDRAWER = "com.thejoshwa.ultrasonic.androidapp.menuDrawer";
|
||||
private static final String STATE_ACTIVE_VIEW_ID = "com.thejoshwa.ultrasonic.androidapp.activeViewId";
|
||||
private static final String STATE_ACTIVE_POSITION = "com.thejoshwa.ultrasonic.androidapp.activePosition";
|
||||
|
||||
setContentView(R.layout.help);
|
||||
|
||||
if (bundle != null) {
|
||||
activePosition = bundle.getInt(STATE_ACTIVE_POSITION);
|
||||
menuActiveViewId = bundle.getInt(STATE_ACTIVE_VIEW_ID);
|
||||
}
|
||||
|
||||
menuDrawer = MenuDrawer.attach(this, MenuDrawer.Type.BEHIND, Position.LEFT, MenuDrawer.MENU_DRAG_WINDOW);
|
||||
menuDrawer.setMenuView(R.layout.menu_main);
|
||||
|
||||
chatMenuItem = findViewById(R.id.menu_chat);
|
||||
bookmarksMenuItem = findViewById(R.id.menu_bookmarks);
|
||||
|
||||
findViewById(R.id.menu_home).setOnClickListener(this);
|
||||
findViewById(R.id.menu_browse).setOnClickListener(this);
|
||||
findViewById(R.id.menu_search).setOnClickListener(this);
|
||||
findViewById(R.id.menu_playlists).setOnClickListener(this);
|
||||
chatMenuItem.setOnClickListener(this);
|
||||
bookmarksMenuItem.setOnClickListener(this);
|
||||
findViewById(R.id.menu_now_playing).setOnClickListener(this);
|
||||
findViewById(R.id.menu_settings).setOnClickListener(this);
|
||||
findViewById(R.id.menu_about).setOnClickListener(this);
|
||||
findViewById(R.id.menu_exit).setOnClickListener(this);
|
||||
public MenuDrawer menuDrawer;
|
||||
private int activePosition = 1;
|
||||
private int menuActiveViewId;
|
||||
View chatMenuItem;
|
||||
View bookmarksMenuItem;
|
||||
|
||||
ActionBar actionBar = getActionBar();
|
||||
|
||||
if (actionBar != null) {
|
||||
actionBar.setDisplayHomeAsUpEnabled(true);
|
||||
}
|
||||
|
||||
View aboutMenuItem = findViewById(R.id.menu_about);
|
||||
menuDrawer.setActiveView(aboutMenuItem);
|
||||
|
||||
webView = (WebView) findViewById(R.id.help_contents);
|
||||
webView.getSettings().setJavaScriptEnabled(true);
|
||||
webView.setWebViewClient(new HelpClient());
|
||||
|
||||
if (bundle != null) {
|
||||
webView.restoreState(bundle);
|
||||
} else {
|
||||
webView.loadUrl(getResources().getString(R.string.help_url));
|
||||
}
|
||||
|
||||
backButton = (ImageView) findViewById(R.id.help_back);
|
||||
backButton.setOnClickListener(new Button.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
webView.goBack();
|
||||
}
|
||||
});
|
||||
|
||||
ImageView stopButton = (ImageView) findViewById(R.id.help_stop);
|
||||
stopButton.setOnClickListener(new Button.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
webView.stopLoading();
|
||||
setProgressBarIndeterminateVisibility(false);
|
||||
}
|
||||
});
|
||||
|
||||
forwardButton = (ImageView) findViewById(R.id.help_forward);
|
||||
forwardButton.setOnClickListener(new Button.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
webView.goForward();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostCreate(Bundle bundle) {
|
||||
super.onPostCreate(bundle);
|
||||
|
||||
int visibility = Util.isOffline(this) ? View.GONE : View.VISIBLE;
|
||||
chatMenuItem.setVisibility(visibility);
|
||||
bookmarksMenuItem.setVisibility(visibility);
|
||||
protected void onCreate(Bundle bundle)
|
||||
{
|
||||
applyTheme();
|
||||
super.onCreate(bundle);
|
||||
getWindow().requestFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
|
||||
|
||||
setContentView(R.layout.help);
|
||||
|
||||
if (bundle != null)
|
||||
{
|
||||
activePosition = bundle.getInt(STATE_ACTIVE_POSITION);
|
||||
menuActiveViewId = bundle.getInt(STATE_ACTIVE_VIEW_ID);
|
||||
}
|
||||
|
||||
menuDrawer = MenuDrawer.attach(this, MenuDrawer.Type.BEHIND, Position.LEFT, MenuDrawer.MENU_DRAG_WINDOW);
|
||||
menuDrawer.setMenuView(R.layout.menu_main);
|
||||
|
||||
chatMenuItem = findViewById(R.id.menu_chat);
|
||||
bookmarksMenuItem = findViewById(R.id.menu_bookmarks);
|
||||
View aboutMenuItem = findViewById(R.id.menu_about);
|
||||
|
||||
findViewById(R.id.menu_home).setOnClickListener(this);
|
||||
findViewById(R.id.menu_browse).setOnClickListener(this);
|
||||
findViewById(R.id.menu_search).setOnClickListener(this);
|
||||
findViewById(R.id.menu_playlists).setOnClickListener(this);
|
||||
chatMenuItem.setOnClickListener(this);
|
||||
bookmarksMenuItem.setOnClickListener(this);
|
||||
findViewById(R.id.menu_now_playing).setOnClickListener(this);
|
||||
findViewById(R.id.menu_settings).setOnClickListener(this);
|
||||
aboutMenuItem.setOnClickListener(this);
|
||||
findViewById(R.id.menu_exit).setOnClickListener(this);
|
||||
|
||||
ActionBar actionBar = getActionBar();
|
||||
|
||||
if (actionBar != null)
|
||||
{
|
||||
actionBar.setDisplayHomeAsUpEnabled(true);
|
||||
}
|
||||
|
||||
menuDrawer.setActiveView(aboutMenuItem);
|
||||
|
||||
webView = (WebView) findViewById(R.id.help_contents);
|
||||
webView.getSettings().setJavaScriptEnabled(true);
|
||||
webView.setWebViewClient(new HelpClient());
|
||||
|
||||
if (bundle != null)
|
||||
{
|
||||
webView.restoreState(bundle);
|
||||
}
|
||||
else
|
||||
{
|
||||
webView.loadUrl(getResources().getString(R.string.help_url));
|
||||
}
|
||||
|
||||
backButton = (ImageView) findViewById(R.id.help_back);
|
||||
backButton.setOnClickListener(new Button.OnClickListener()
|
||||
{
|
||||
@Override
|
||||
public void onClick(View view)
|
||||
{
|
||||
webView.goBack();
|
||||
}
|
||||
});
|
||||
|
||||
ImageView stopButton = (ImageView) findViewById(R.id.help_stop);
|
||||
stopButton.setOnClickListener(new Button.OnClickListener()
|
||||
{
|
||||
@Override
|
||||
public void onClick(View view)
|
||||
{
|
||||
webView.stopLoading();
|
||||
setProgressBarIndeterminateVisibility(false);
|
||||
}
|
||||
});
|
||||
|
||||
forwardButton = (ImageView) findViewById(R.id.help_forward);
|
||||
forwardButton.setOnClickListener(new Button.OnClickListener()
|
||||
{
|
||||
@Override
|
||||
public void onClick(View view)
|
||||
{
|
||||
webView.goForward();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
}
|
||||
@Override
|
||||
protected void onPostCreate(Bundle bundle)
|
||||
{
|
||||
super.onPostCreate(bundle);
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle state) {
|
||||
webView.saveState(state);
|
||||
super.onSaveInstanceState(state);
|
||||
state.putParcelable(STATE_MENUDRAWER, menuDrawer.saveState());
|
||||
state.putInt(STATE_ACTIVE_VIEW_ID, menuActiveViewId);
|
||||
state.putInt(STATE_ACTIVE_POSITION, activePosition);
|
||||
}
|
||||
int visibility = Util.isOffline(this) ? View.GONE : View.VISIBLE;
|
||||
chatMenuItem.setVisibility(visibility);
|
||||
bookmarksMenuItem.setVisibility(visibility);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK) {
|
||||
if (webView.canGoBack()) {
|
||||
webView.goBack();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return super.onKeyDown(keyCode, event);
|
||||
}
|
||||
|
||||
private void applyTheme() {
|
||||
String theme = Util.getTheme(this);
|
||||
|
||||
if ("dark".equalsIgnoreCase(theme) || "fullscreen".equalsIgnoreCase(theme)) {
|
||||
setTheme(R.style.UltraSonicTheme);
|
||||
} else if ("light".equalsIgnoreCase(theme) || "fullscreenlight".equalsIgnoreCase(theme)) {
|
||||
setTheme(R.style.UltraSonicTheme_Light);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case android.R.id.home:
|
||||
menuDrawer.toggleMenu();
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public void onResume()
|
||||
{
|
||||
super.onResume();
|
||||
}
|
||||
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRestoreInstanceState(Bundle state) {
|
||||
super.onRestoreInstanceState(state);
|
||||
menuDrawer.restoreState(state.getParcelable(STATE_MENUDRAWER));
|
||||
}
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle state)
|
||||
{
|
||||
webView.saveState(state);
|
||||
super.onSaveInstanceState(state);
|
||||
state.putParcelable(STATE_MENUDRAWER, menuDrawer.saveState());
|
||||
state.putInt(STATE_ACTIVE_VIEW_ID, menuActiveViewId);
|
||||
state.putInt(STATE_ACTIVE_POSITION, activePosition);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
final int drawerState = menuDrawer.getDrawerState();
|
||||
|
||||
if (drawerState == MenuDrawer.STATE_OPEN || drawerState == MenuDrawer.STATE_OPENING) {
|
||||
menuDrawer.closeMenu(true);
|
||||
return;
|
||||
}
|
||||
|
||||
finish();
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event)
|
||||
{
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK)
|
||||
{
|
||||
if (webView.canGoBack())
|
||||
{
|
||||
webView.goBack();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return super.onKeyDown(keyCode, event);
|
||||
}
|
||||
|
||||
super.onBackPressed();
|
||||
}
|
||||
private void applyTheme()
|
||||
{
|
||||
String theme = Util.getTheme(this);
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
menuActiveViewId = v.getId();
|
||||
menuDrawer.setActiveView(v);
|
||||
|
||||
Intent intent;
|
||||
|
||||
switch (menuActiveViewId) {
|
||||
case R.id.menu_home:
|
||||
|
||||
intent = new Intent(this, MainActivity.class);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||
Util.startActivityWithoutTransition(this, intent);
|
||||
break;
|
||||
case R.id.menu_browse:
|
||||
intent = new Intent(this, SelectArtistActivity.class);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||
Util.startActivityWithoutTransition(this, intent);
|
||||
break;
|
||||
case R.id.menu_search:
|
||||
intent = new Intent(this, SearchActivity.class);
|
||||
intent.putExtra(Constants.INTENT_EXTRA_REQUEST_SEARCH, true);
|
||||
Util.startActivityWithoutTransition(this, intent);
|
||||
break;
|
||||
case R.id.menu_playlists:
|
||||
intent = new Intent(this, SelectPlaylistActivity.class);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||
Util.startActivityWithoutTransition(this, intent);
|
||||
break;
|
||||
case R.id.menu_chat:
|
||||
Util.startActivityWithoutTransition(this, ChatActivity.class);
|
||||
break;
|
||||
case R.id.menu_bookmarks:
|
||||
Util.startActivityWithoutTransition(this, BookmarkActivity.class);
|
||||
break;
|
||||
case R.id.menu_now_playing:
|
||||
Util.startActivityWithoutTransition(this, DownloadActivity.class);
|
||||
break;
|
||||
case R.id.menu_settings:
|
||||
Util.startActivityWithoutTransition(this, SettingsActivity.class);
|
||||
break;
|
||||
case R.id.menu_about:
|
||||
Util.startActivityWithoutTransition(this, HelpActivity.class);
|
||||
break;
|
||||
case R.id.menu_exit:
|
||||
intent = new Intent(this, MainActivity.class);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_EXIT, true);
|
||||
Util.startActivityWithoutTransition(this, intent);
|
||||
break;
|
||||
}
|
||||
|
||||
menuDrawer.closeMenu(true);
|
||||
}
|
||||
if ("dark".equalsIgnoreCase(theme) || "fullscreen".equalsIgnoreCase(theme))
|
||||
{
|
||||
setTheme(R.style.UltraSonicTheme);
|
||||
}
|
||||
else if ("light".equalsIgnoreCase(theme) || "fullscreenlight".equalsIgnoreCase(theme))
|
||||
{
|
||||
setTheme(R.style.UltraSonicTheme_Light);
|
||||
}
|
||||
}
|
||||
|
||||
private final class HelpClient extends WebViewClient {
|
||||
@Override
|
||||
public void onLoadResource(WebView webView, String url) {
|
||||
setProgressBarIndeterminateVisibility(true);
|
||||
super.onLoadResource(webView, url);
|
||||
}
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item)
|
||||
{
|
||||
switch (item.getItemId())
|
||||
{
|
||||
case android.R.id.home:
|
||||
menuDrawer.toggleMenu();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageFinished(WebView view, String url) {
|
||||
setProgressBarIndeterminateVisibility(false);
|
||||
String versionName = Util.getVersionName(HelpActivity.this);
|
||||
String title = view.getTitle() + " (" + versionName + ")";
|
||||
ActionBar actionBar = getActionBar();
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
if (actionBar != null) {
|
||||
actionBar.setSubtitle(title);
|
||||
}
|
||||
@Override
|
||||
protected void onRestoreInstanceState(Bundle state)
|
||||
{
|
||||
super.onRestoreInstanceState(state);
|
||||
menuDrawer.restoreState(state.getParcelable(STATE_MENUDRAWER));
|
||||
}
|
||||
|
||||
backButton.setEnabled(view.canGoBack());
|
||||
forwardButton.setEnabled(view.canGoForward());
|
||||
}
|
||||
@Override
|
||||
public void onBackPressed()
|
||||
{
|
||||
final int drawerState = menuDrawer.getDrawerState();
|
||||
|
||||
@Override
|
||||
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
|
||||
Util.toast(HelpActivity.this, description);
|
||||
}
|
||||
}
|
||||
if (drawerState == MenuDrawer.STATE_OPEN || drawerState == MenuDrawer.STATE_OPENING)
|
||||
{
|
||||
menuDrawer.closeMenu(true);
|
||||
return;
|
||||
}
|
||||
|
||||
finish();
|
||||
|
||||
super.onBackPressed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v)
|
||||
{
|
||||
menuActiveViewId = v.getId();
|
||||
menuDrawer.setActiveView(v);
|
||||
|
||||
Intent intent;
|
||||
|
||||
switch (menuActiveViewId)
|
||||
{
|
||||
case R.id.menu_home:
|
||||
|
||||
intent = new Intent(this, MainActivity.class);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||
Util.startActivityWithoutTransition(this, intent);
|
||||
break;
|
||||
case R.id.menu_browse:
|
||||
intent = new Intent(this, SelectArtistActivity.class);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||
Util.startActivityWithoutTransition(this, intent);
|
||||
break;
|
||||
case R.id.menu_search:
|
||||
intent = new Intent(this, SearchActivity.class);
|
||||
intent.putExtra(Constants.INTENT_EXTRA_REQUEST_SEARCH, true);
|
||||
Util.startActivityWithoutTransition(this, intent);
|
||||
break;
|
||||
case R.id.menu_playlists:
|
||||
intent = new Intent(this, SelectPlaylistActivity.class);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||
Util.startActivityWithoutTransition(this, intent);
|
||||
break;
|
||||
case R.id.menu_chat:
|
||||
Util.startActivityWithoutTransition(this, ChatActivity.class);
|
||||
break;
|
||||
case R.id.menu_bookmarks:
|
||||
Util.startActivityWithoutTransition(this, BookmarkActivity.class);
|
||||
break;
|
||||
case R.id.menu_now_playing:
|
||||
Util.startActivityWithoutTransition(this, DownloadActivity.class);
|
||||
break;
|
||||
case R.id.menu_settings:
|
||||
Util.startActivityWithoutTransition(this, SettingsActivity.class);
|
||||
break;
|
||||
case R.id.menu_about:
|
||||
Util.startActivityWithoutTransition(this, HelpActivity.class);
|
||||
break;
|
||||
case R.id.menu_exit:
|
||||
intent = new Intent(this, MainActivity.class);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_EXIT, true);
|
||||
Util.startActivityWithoutTransition(this, intent);
|
||||
break;
|
||||
}
|
||||
|
||||
menuDrawer.closeMenu(true);
|
||||
}
|
||||
|
||||
private final class HelpClient extends WebViewClient
|
||||
{
|
||||
@Override
|
||||
public void onLoadResource(WebView webView, String url)
|
||||
{
|
||||
setProgressBarIndeterminateVisibility(true);
|
||||
super.onLoadResource(webView, url);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageFinished(WebView view, String url)
|
||||
{
|
||||
setProgressBarIndeterminateVisibility(false);
|
||||
String versionName = Util.getVersionName(HelpActivity.this);
|
||||
String title = String.format("%s (%s)", view.getTitle(), versionName);
|
||||
ActionBar actionBar = getActionBar();
|
||||
|
||||
if (actionBar != null)
|
||||
{
|
||||
actionBar.setSubtitle(title);
|
||||
}
|
||||
|
||||
backButton.setEnabled(view.canGoBack());
|
||||
forwardButton.setEnabled(view.canGoForward());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl)
|
||||
{
|
||||
Util.toast(HelpActivity.this, description);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ package com.thejoshwa.ultrasonic.androidapp.activity;
|
|||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.thejoshwa.ultrasonic.androidapp.R;
|
||||
import com.thejoshwa.ultrasonic.androidapp.domain.Lyrics;
|
||||
import com.thejoshwa.ultrasonic.androidapp.service.MusicService;
|
||||
|
@ -35,45 +36,54 @@ import com.thejoshwa.ultrasonic.androidapp.util.TabActivityBackgroundTask;
|
|||
*
|
||||
* @author Sindre Mehus
|
||||
*/
|
||||
public final class LyricsActivity extends SubsonicTabActivity {
|
||||
public final class LyricsActivity extends SubsonicTabActivity
|
||||
{
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle bundle) {
|
||||
super.onCreate(bundle);
|
||||
setContentView(R.layout.lyrics);
|
||||
@Override
|
||||
protected void onCreate(Bundle bundle)
|
||||
{
|
||||
super.onCreate(bundle);
|
||||
setContentView(R.layout.lyrics);
|
||||
|
||||
View nowPlayingMenuItem = findViewById(R.id.menu_now_playing);
|
||||
menuDrawer.setActiveView(nowPlayingMenuItem);
|
||||
|
||||
load();
|
||||
}
|
||||
View nowPlayingMenuItem = findViewById(R.id.menu_now_playing);
|
||||
menuDrawer.setActiveView(nowPlayingMenuItem);
|
||||
|
||||
private void load() {
|
||||
BackgroundTask<Lyrics> task = new TabActivityBackgroundTask<Lyrics>(this, true) {
|
||||
@Override
|
||||
protected Lyrics doInBackground() throws Throwable {
|
||||
String artist = getIntent().getStringExtra(Constants.INTENT_EXTRA_NAME_ARTIST);
|
||||
String title = getIntent().getStringExtra(Constants.INTENT_EXTRA_NAME_TITLE);
|
||||
MusicService musicService = MusicServiceFactory.getMusicService(LyricsActivity.this);
|
||||
return musicService.getLyrics(artist, title, LyricsActivity.this, this);
|
||||
}
|
||||
load();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void done(Lyrics result) {
|
||||
TextView artistView = (TextView) findViewById(R.id.lyrics_artist);
|
||||
TextView titleView = (TextView) findViewById(R.id.lyrics_title);
|
||||
TextView textView = (TextView) findViewById(R.id.lyrics_text);
|
||||
|
||||
if (result != null && result.getArtist() != null) {
|
||||
artistView.setText(result.getArtist());
|
||||
titleView.setText(result.getTitle());
|
||||
textView.setText(result.getText());
|
||||
} else {
|
||||
artistView.setText(R.string.lyrics_nomatch);
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
task.execute();
|
||||
}
|
||||
private void load()
|
||||
{
|
||||
BackgroundTask<Lyrics> task = new TabActivityBackgroundTask<Lyrics>(this, true)
|
||||
{
|
||||
@Override
|
||||
protected Lyrics doInBackground() throws Throwable
|
||||
{
|
||||
String artist = getIntent().getStringExtra(Constants.INTENT_EXTRA_NAME_ARTIST);
|
||||
String title = getIntent().getStringExtra(Constants.INTENT_EXTRA_NAME_TITLE);
|
||||
MusicService musicService = MusicServiceFactory.getMusicService(LyricsActivity.this);
|
||||
return musicService.getLyrics(artist, title, LyricsActivity.this, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void done(Lyrics result)
|
||||
{
|
||||
TextView artistView = (TextView) findViewById(R.id.lyrics_artist);
|
||||
TextView titleView = (TextView) findViewById(R.id.lyrics_title);
|
||||
TextView textView = (TextView) findViewById(R.id.lyrics_text);
|
||||
|
||||
if (result != null && result.getArtist() != null)
|
||||
{
|
||||
artistView.setText(result.getArtist());
|
||||
titleView.setText(result.getTitle());
|
||||
textView.setText(result.getText());
|
||||
}
|
||||
else
|
||||
{
|
||||
artistView.setText(R.string.lyrics_nomatch);
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
task.execute();
|
||||
}
|
||||
}
|
|
@ -23,10 +23,16 @@ import android.content.Intent;
|
|||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.view.*;
|
||||
import android.view.ContextMenu;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.thejoshwa.ultrasonic.androidapp.R;
|
||||
import com.thejoshwa.ultrasonic.androidapp.service.DownloadService;
|
||||
import com.thejoshwa.ultrasonic.androidapp.service.DownloadServiceImpl;
|
||||
|
@ -35,406 +41,484 @@ import com.thejoshwa.ultrasonic.androidapp.util.FileUtil;
|
|||
import com.thejoshwa.ultrasonic.androidapp.util.MergeAdapter;
|
||||
import com.thejoshwa.ultrasonic.androidapp.util.Util;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
public class MainActivity extends SubsonicTabActivity {
|
||||
import static java.util.Arrays.asList;
|
||||
|
||||
private static final int MENU_GROUP_SERVER = 10;
|
||||
private static final int MENU_ITEM_OFFLINE = 111;
|
||||
private static final int MENU_ITEM_SERVER_1 = 101;
|
||||
private static final int MENU_ITEM_SERVER_2 = 102;
|
||||
private static final int MENU_ITEM_SERVER_3 = 103;
|
||||
private static final int MENU_ITEM_SERVER_4 = 104;
|
||||
private static final int MENU_ITEM_SERVER_5 = 105;
|
||||
private static final int MENU_ITEM_SERVER_6 = 106;
|
||||
private static final int MENU_ITEM_SERVER_7 = 107;
|
||||
private static final int MENU_ITEM_SERVER_8 = 108;
|
||||
private static final int MENU_ITEM_SERVER_9 = 109;
|
||||
private static final int MENU_ITEM_SERVER_10 = 110;
|
||||
public class MainActivity extends SubsonicTabActivity
|
||||
{
|
||||
|
||||
private static boolean infoDialogDisplayed;
|
||||
private static boolean shouldUseId3;
|
||||
|
||||
/**
|
||||
* Called when the activity is first created.
|
||||
*/
|
||||
@Override
|
||||
public void onCreate(final Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
if (getIntent().hasExtra(Constants.INTENT_EXTRA_NAME_EXIT)) {
|
||||
exit();
|
||||
return;
|
||||
}
|
||||
|
||||
setContentView(R.layout.main);
|
||||
private static final int MENU_GROUP_SERVER = 10;
|
||||
private static final int MENU_ITEM_OFFLINE = 111;
|
||||
private static final int MENU_ITEM_SERVER_1 = 101;
|
||||
private static final int MENU_ITEM_SERVER_2 = 102;
|
||||
private static final int MENU_ITEM_SERVER_3 = 103;
|
||||
private static final int MENU_ITEM_SERVER_4 = 104;
|
||||
private static final int MENU_ITEM_SERVER_5 = 105;
|
||||
private static final int MENU_ITEM_SERVER_6 = 106;
|
||||
private static final int MENU_ITEM_SERVER_7 = 107;
|
||||
private static final int MENU_ITEM_SERVER_8 = 108;
|
||||
private static final int MENU_ITEM_SERVER_9 = 109;
|
||||
private static final int MENU_ITEM_SERVER_10 = 110;
|
||||
|
||||
loadSettings();
|
||||
|
||||
final View buttons = LayoutInflater.from(this).inflate(R.layout.main_buttons, null);
|
||||
final View serverButton = buttons.findViewById(R.id.main_select_server);
|
||||
final TextView serverTextView = (TextView) serverButton.findViewById(R.id.main_select_server_2);
|
||||
final View musicTitle = buttons.findViewById(R.id.main_music);
|
||||
final View artistsButton = buttons.findViewById(R.id.main_artists_button);
|
||||
final View albumsButton = buttons.findViewById(R.id.main_albums_button);
|
||||
final View genresButton = buttons.findViewById(R.id.main_genres_button);
|
||||
final View videosTitle = buttons.findViewById(R.id.main_videos_title);
|
||||
final View songsTitle = buttons.findViewById(R.id.main_songs);
|
||||
final View randomSongsButton = buttons.findViewById(R.id.main_songs_button);
|
||||
final View songsStarredButton = buttons.findViewById(R.id.main_songs_starred);
|
||||
final View albumsTitle = buttons.findViewById(R.id.main_albums);
|
||||
final View albumsNewestButton = buttons.findViewById(R.id.main_albums_newest);
|
||||
final View albumsRandomButton = buttons.findViewById(R.id.main_albums_random);
|
||||
final View albumsHighestButton = buttons.findViewById(R.id.main_albums_highest);
|
||||
final View albumsStarredButton = buttons.findViewById(R.id.main_albums_starred);
|
||||
final View albumsRecentButton = buttons.findViewById(R.id.main_albums_recent);
|
||||
final View albumsFrequentButton = buttons.findViewById(R.id.main_albums_frequent);
|
||||
final View albumsAlphaByNameButton = buttons.findViewById(R.id.main_albums_alphaByName);
|
||||
final View albumsAlphaByArtistButton = buttons.findViewById(R.id.main_albums_alphaByArtist);
|
||||
final View videosButton = buttons.findViewById(R.id.main_videos);
|
||||
final View dummyView = findViewById(R.id.main_dummy);
|
||||
private static boolean infoDialogDisplayed;
|
||||
private static boolean shouldUseId3;
|
||||
|
||||
boolean shouldShowDialog = false;
|
||||
|
||||
if (!getActiveServerEnabled()) {
|
||||
shouldShowDialog = true;
|
||||
Util.setActiveServer(this, 0);
|
||||
}
|
||||
/**
|
||||
* Called when the activity is first created.
|
||||
*/
|
||||
@Override
|
||||
public void onCreate(final Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
int instance = Util.getActiveServer(this);
|
||||
String name = Util.getServerName(this, instance);
|
||||
|
||||
if (name == null) {
|
||||
shouldShowDialog = true;
|
||||
Util.setActiveServer(this, 0);
|
||||
instance = Util.getActiveServer(this);
|
||||
name = Util.getServerName(this, instance);
|
||||
}
|
||||
|
||||
serverTextView.setText(name);
|
||||
if (getIntent().hasExtra(Constants.INTENT_EXTRA_NAME_EXIT))
|
||||
{
|
||||
exit();
|
||||
return;
|
||||
}
|
||||
|
||||
final ListView list = (ListView) findViewById(R.id.main_list);
|
||||
|
||||
final MergeAdapter adapter = new MergeAdapter();
|
||||
adapter.addViews(Arrays.asList(serverButton), true);
|
||||
|
||||
if (!Util.isOffline(this)) {
|
||||
adapter.addView(musicTitle, false);
|
||||
adapter.addViews(Arrays.asList(artistsButton, albumsButton, genresButton), true);
|
||||
adapter.addView(songsTitle, false);
|
||||
adapter.addViews(Arrays.asList(randomSongsButton, songsStarredButton), true);
|
||||
adapter.addView(albumsTitle, false);
|
||||
|
||||
if (Util.getShouldUseId3Tags(MainActivity.this)) {
|
||||
shouldUseId3 = true;
|
||||
adapter.addViews(Arrays.asList(albumsNewestButton, albumsRecentButton, albumsFrequentButton, albumsRandomButton, albumsStarredButton, albumsAlphaByNameButton, albumsAlphaByArtistButton), true);
|
||||
} else {
|
||||
shouldUseId3 = false;
|
||||
adapter.addViews(Arrays.asList(albumsNewestButton, albumsRecentButton, albumsFrequentButton, albumsHighestButton, albumsRandomButton, albumsStarredButton, albumsAlphaByNameButton, albumsAlphaByArtistButton), true);
|
||||
}
|
||||
|
||||
adapter.addView(videosTitle, false);
|
||||
adapter.addViews(Arrays.asList(videosButton), true);
|
||||
}
|
||||
|
||||
list.setAdapter(adapter);
|
||||
registerForContextMenu(dummyView);
|
||||
setContentView(R.layout.main);
|
||||
|
||||
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
if (view == serverButton) {
|
||||
dummyView.showContextMenu();
|
||||
} else if (view == albumsNewestButton) {
|
||||
showAlbumList("newest", R.string.main_albums_newest);
|
||||
} else if (view == albumsRandomButton) {
|
||||
showAlbumList("random", R.string.main_albums_random);
|
||||
} else if (view == albumsHighestButton) {
|
||||
showAlbumList("highest", R.string.main_albums_highest);
|
||||
} else if (view == albumsRecentButton) {
|
||||
showAlbumList("recent", R.string.main_albums_recent);
|
||||
} else if (view == albumsFrequentButton) {
|
||||
showAlbumList("frequent", R.string.main_albums_frequent);
|
||||
} else if (view == albumsStarredButton) {
|
||||
showAlbumList(Constants.STARRED, R.string.main_albums_starred);
|
||||
} else if (view == albumsAlphaByNameButton) {
|
||||
showAlbumList(Constants.ALPHABETICAL_BY_NAME, R.string.main_albums_alphaByName);
|
||||
} else if (view == albumsAlphaByArtistButton) {
|
||||
showAlbumList("alphabeticalByArtist", R.string.main_albums_alphaByArtist);
|
||||
} else if (view == songsStarredButton) {
|
||||
showStarredSongs();
|
||||
} else if (view == artistsButton) {
|
||||
showArtists();
|
||||
} else if (view == albumsButton) {
|
||||
showAlbumList(Constants.ALPHABETICAL_BY_NAME, R.string.main_albums_title);
|
||||
} else if (view == randomSongsButton) {
|
||||
showRandomSongs();
|
||||
} else if (view == genresButton) {
|
||||
showGenres();
|
||||
} else if (view == videosButton) {
|
||||
showVideos();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
final View homeMenuItem = findViewById(R.id.menu_home);
|
||||
menuDrawer.setActiveView(homeMenuItem);
|
||||
loadSettings();
|
||||
|
||||
setActionBarTitle(R.string.common_appname);
|
||||
setTitle(R.string.common_appname);
|
||||
final View buttons = LayoutInflater.from(this).inflate(R.layout.main_buttons, null);
|
||||
final View serverButton = buttons.findViewById(R.id.main_select_server);
|
||||
final TextView serverTextView = (TextView) serverButton.findViewById(R.id.main_select_server_2);
|
||||
final View musicTitle = buttons.findViewById(R.id.main_music);
|
||||
final View artistsButton = buttons.findViewById(R.id.main_artists_button);
|
||||
final View albumsButton = buttons.findViewById(R.id.main_albums_button);
|
||||
final View genresButton = buttons.findViewById(R.id.main_genres_button);
|
||||
final View videosTitle = buttons.findViewById(R.id.main_videos_title);
|
||||
final View songsTitle = buttons.findViewById(R.id.main_songs);
|
||||
final View randomSongsButton = buttons.findViewById(R.id.main_songs_button);
|
||||
final View songsStarredButton = buttons.findViewById(R.id.main_songs_starred);
|
||||
final View albumsTitle = buttons.findViewById(R.id.main_albums);
|
||||
final View albumsNewestButton = buttons.findViewById(R.id.main_albums_newest);
|
||||
final View albumsRandomButton = buttons.findViewById(R.id.main_albums_random);
|
||||
final View albumsHighestButton = buttons.findViewById(R.id.main_albums_highest);
|
||||
final View albumsStarredButton = buttons.findViewById(R.id.main_albums_starred);
|
||||
final View albumsRecentButton = buttons.findViewById(R.id.main_albums_recent);
|
||||
final View albumsFrequentButton = buttons.findViewById(R.id.main_albums_frequent);
|
||||
final View albumsAlphaByNameButton = buttons.findViewById(R.id.main_albums_alphaByName);
|
||||
final View albumsAlphaByArtistButton = buttons.findViewById(R.id.main_albums_alphaByArtist);
|
||||
final View videosButton = buttons.findViewById(R.id.main_videos);
|
||||
final View dummyView = findViewById(R.id.main_dummy);
|
||||
|
||||
// Remember the current theme.
|
||||
theme = Util.getTheme(this);
|
||||
boolean shouldShowDialog = false;
|
||||
|
||||
showInfoDialog(shouldShowDialog);
|
||||
}
|
||||
if (!getActiveServerEnabled())
|
||||
{
|
||||
shouldShowDialog = true;
|
||||
Util.setActiveServer(this, 0);
|
||||
}
|
||||
|
||||
private void loadSettings() {
|
||||
PreferenceManager.setDefaultValues(this, R.xml.settings, false);
|
||||
final SharedPreferences preferences = Util.getPreferences(this);
|
||||
|
||||
if (!preferences.contains(Constants.PREFERENCES_KEY_CACHE_LOCATION)) {
|
||||
final SharedPreferences.Editor editor = preferences.edit();
|
||||
editor.putString(Constants.PREFERENCES_KEY_CACHE_LOCATION, FileUtil.getDefaultMusicDirectory().getPath());
|
||||
editor.commit();
|
||||
}
|
||||
}
|
||||
int instance = Util.getActiveServer(this);
|
||||
String name = Util.getServerName(this, instance);
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
if (name == null)
|
||||
{
|
||||
shouldShowDialog = true;
|
||||
Util.setActiveServer(this, 0);
|
||||
instance = Util.getActiveServer(this);
|
||||
name = Util.getServerName(this, instance);
|
||||
}
|
||||
|
||||
boolean id3 = Util.getShouldUseId3Tags(MainActivity.this);
|
||||
|
||||
if (id3 != shouldUseId3) {
|
||||
shouldUseId3 = id3;
|
||||
restart();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(final Menu menu) {
|
||||
final MenuInflater menuInflater = getMenuInflater();
|
||||
menuInflater.inflate(R.menu.main, menu);
|
||||
super.onCreateOptionsMenu(menu);
|
||||
|
||||
return true;
|
||||
}
|
||||
serverTextView.setText(name);
|
||||
|
||||
@Override
|
||||
public void onCreateContextMenu(final ContextMenu menu, final View view, final ContextMenu.ContextMenuInfo menuInfo) {
|
||||
super.onCreateContextMenu(menu, view, menuInfo);
|
||||
final ListView list = (ListView) findViewById(R.id.main_list);
|
||||
|
||||
final int activeServer = Util.getActiveServer(this);
|
||||
boolean checked = false;
|
||||
|
||||
for (int i = 0; i <= Util.getActiveServers(this); i++) {
|
||||
final String serverName = Util.getServerName(this, i);
|
||||
|
||||
if (serverName == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Util.getServerEnabled(this, i)) {
|
||||
final int menuItemNum = getMenuItem(i);
|
||||
|
||||
final MenuItem menuItem = menu.add(MENU_GROUP_SERVER, menuItemNum, menuItemNum, serverName);
|
||||
|
||||
if (activeServer == i) {
|
||||
checked = true;
|
||||
menuItem.setChecked(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
final MergeAdapter adapter = new MergeAdapter();
|
||||
adapter.addViews(Collections.singletonList(serverButton), true);
|
||||
|
||||
if (!checked) {
|
||||
MenuItem menuItem = menu.findItem(getMenuItem(0));
|
||||
if (!Util.isOffline(this))
|
||||
{
|
||||
adapter.addView(musicTitle, false);
|
||||
adapter.addViews(asList(artistsButton, albumsButton, genresButton), true);
|
||||
adapter.addView(songsTitle, false);
|
||||
adapter.addViews(asList(randomSongsButton, songsStarredButton), true);
|
||||
adapter.addView(albumsTitle, false);
|
||||
|
||||
if (menuItem != null) {
|
||||
menuItem.setChecked(true);
|
||||
}
|
||||
}
|
||||
|
||||
menu.setGroupCheckable(MENU_GROUP_SERVER, true, true);
|
||||
menu.setHeaderTitle(R.string.main_select_server);
|
||||
}
|
||||
|
||||
private boolean getActiveServerEnabled() {
|
||||
if (Util.getShouldUseId3Tags(MainActivity.this))
|
||||
{
|
||||
shouldUseId3 = true;
|
||||
adapter.addViews(asList(albumsNewestButton, albumsRecentButton, albumsFrequentButton, albumsRandomButton, albumsStarredButton, albumsAlphaByNameButton, albumsAlphaByArtistButton), true);
|
||||
}
|
||||
else
|
||||
{
|
||||
shouldUseId3 = false;
|
||||
adapter.addViews(asList(albumsNewestButton, albumsRecentButton, albumsFrequentButton, albumsHighestButton, albumsRandomButton, albumsStarredButton, albumsAlphaByNameButton, albumsAlphaByArtistButton), true);
|
||||
}
|
||||
|
||||
adapter.addView(videosTitle, false);
|
||||
adapter.addViews(Collections.singletonList(videosButton), true);
|
||||
}
|
||||
|
||||
list.setAdapter(adapter);
|
||||
registerForContextMenu(dummyView);
|
||||
|
||||
list.setOnItemClickListener(new AdapterView.OnItemClickListener()
|
||||
{
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
|
||||
{
|
||||
if (view == serverButton)
|
||||
{
|
||||
dummyView.showContextMenu();
|
||||
}
|
||||
else if (view == albumsNewestButton)
|
||||
{
|
||||
showAlbumList("newest", R.string.main_albums_newest);
|
||||
}
|
||||
else if (view == albumsRandomButton)
|
||||
{
|
||||
showAlbumList("random", R.string.main_albums_random);
|
||||
}
|
||||
else if (view == albumsHighestButton)
|
||||
{
|
||||
showAlbumList("highest", R.string.main_albums_highest);
|
||||
}
|
||||
else if (view == albumsRecentButton)
|
||||
{
|
||||
showAlbumList("recent", R.string.main_albums_recent);
|
||||
}
|
||||
else if (view == albumsFrequentButton)
|
||||
{
|
||||
showAlbumList("frequent", R.string.main_albums_frequent);
|
||||
}
|
||||
else if (view == albumsStarredButton)
|
||||
{
|
||||
showAlbumList(Constants.STARRED, R.string.main_albums_starred);
|
||||
}
|
||||
else if (view == albumsAlphaByNameButton)
|
||||
{
|
||||
showAlbumList(Constants.ALPHABETICAL_BY_NAME, R.string.main_albums_alphaByName);
|
||||
}
|
||||
else if (view == albumsAlphaByArtistButton)
|
||||
{
|
||||
showAlbumList("alphabeticalByArtist", R.string.main_albums_alphaByArtist);
|
||||
}
|
||||
else if (view == songsStarredButton)
|
||||
{
|
||||
showStarredSongs();
|
||||
}
|
||||
else if (view == artistsButton)
|
||||
{
|
||||
showArtists();
|
||||
}
|
||||
else if (view == albumsButton)
|
||||
{
|
||||
showAlbumList(Constants.ALPHABETICAL_BY_NAME, R.string.main_albums_title);
|
||||
}
|
||||
else if (view == randomSongsButton)
|
||||
{
|
||||
showRandomSongs();
|
||||
}
|
||||
else if (view == genresButton)
|
||||
{
|
||||
showGenres();
|
||||
}
|
||||
else if (view == videosButton)
|
||||
{
|
||||
showVideos();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
final View homeMenuItem = findViewById(R.id.menu_home);
|
||||
menuDrawer.setActiveView(homeMenuItem);
|
||||
|
||||
setActionBarTitle(R.string.common_appname);
|
||||
setTitle(R.string.common_appname);
|
||||
|
||||
// Remember the current theme.
|
||||
theme = Util.getTheme(this);
|
||||
|
||||
showInfoDialog(shouldShowDialog);
|
||||
}
|
||||
|
||||
private void loadSettings()
|
||||
{
|
||||
PreferenceManager.setDefaultValues(this, R.xml.settings, false);
|
||||
final SharedPreferences preferences = Util.getPreferences(this);
|
||||
|
||||
if (!preferences.contains(Constants.PREFERENCES_KEY_CACHE_LOCATION))
|
||||
{
|
||||
final SharedPreferences.Editor editor = preferences.edit();
|
||||
editor.putString(Constants.PREFERENCES_KEY_CACHE_LOCATION, FileUtil.getDefaultMusicDirectory().getPath());
|
||||
editor.commit();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume()
|
||||
{
|
||||
super.onResume();
|
||||
|
||||
boolean id3 = Util.getShouldUseId3Tags(MainActivity.this);
|
||||
|
||||
if (id3 != shouldUseId3)
|
||||
{
|
||||
shouldUseId3 = id3;
|
||||
restart();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(final Menu menu)
|
||||
{
|
||||
final MenuInflater menuInflater = getMenuInflater();
|
||||
menuInflater.inflate(R.menu.main, menu);
|
||||
super.onCreateOptionsMenu(menu);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateContextMenu(final ContextMenu menu, final View view, final ContextMenu.ContextMenuInfo menuInfo)
|
||||
{
|
||||
super.onCreateContextMenu(menu, view, menuInfo);
|
||||
|
||||
final int activeServer = Util.getActiveServer(this);
|
||||
boolean checked = false;
|
||||
|
||||
for (int i = 0; i <= Util.getActiveServers(this); i++)
|
||||
{
|
||||
final String serverName = Util.getServerName(this, i);
|
||||
|
||||
if (serverName == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Util.getServerEnabled(this, i))
|
||||
{
|
||||
final int menuItemNum = getMenuItem(i);
|
||||
|
||||
final MenuItem menuItem = menu.add(MENU_GROUP_SERVER, menuItemNum, menuItemNum, serverName);
|
||||
|
||||
if (activeServer == i)
|
||||
{
|
||||
checked = true;
|
||||
menuItem.setChecked(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!checked)
|
||||
{
|
||||
MenuItem menuItem = menu.findItem(getMenuItem(0));
|
||||
|
||||
if (menuItem != null)
|
||||
{
|
||||
menuItem.setChecked(true);
|
||||
}
|
||||
}
|
||||
|
||||
menu.setGroupCheckable(MENU_GROUP_SERVER, true, true);
|
||||
menu.setHeaderTitle(R.string.main_select_server);
|
||||
}
|
||||
|
||||
private boolean getActiveServerEnabled()
|
||||
{
|
||||
|
||||
final int activeServer = Util.getActiveServer(this);
|
||||
boolean activeServerEnabled = false;
|
||||
|
||||
for (int i = 0; i <= Util.getActiveServers(this); i++) {
|
||||
if (Util.getServerEnabled(this, i)) {
|
||||
if (activeServer == i) {
|
||||
for (int i = 0; i <= Util.getActiveServers(this); i++)
|
||||
{
|
||||
if (Util.getServerEnabled(this, i))
|
||||
{
|
||||
if (activeServer == i)
|
||||
{
|
||||
activeServerEnabled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return activeServerEnabled;
|
||||
}
|
||||
|
||||
private static int getMenuItem(final int serverInstance) {
|
||||
switch (serverInstance) {
|
||||
case 0:
|
||||
return MENU_ITEM_OFFLINE;
|
||||
case 1:
|
||||
return MENU_ITEM_SERVER_1;
|
||||
case 2:
|
||||
return MENU_ITEM_SERVER_2;
|
||||
case 3:
|
||||
return MENU_ITEM_SERVER_3;
|
||||
case 4:
|
||||
return MENU_ITEM_SERVER_4;
|
||||
case 5:
|
||||
return MENU_ITEM_SERVER_5;
|
||||
case 6:
|
||||
return MENU_ITEM_SERVER_6;
|
||||
case 7:
|
||||
return MENU_ITEM_SERVER_7;
|
||||
case 8:
|
||||
return MENU_ITEM_SERVER_8;
|
||||
case 9:
|
||||
return MENU_ITEM_SERVER_9;
|
||||
case 10:
|
||||
return MENU_ITEM_SERVER_10;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static int getMenuItem(final int serverInstance)
|
||||
{
|
||||
switch (serverInstance)
|
||||
{
|
||||
case 0:
|
||||
return MENU_ITEM_OFFLINE;
|
||||
case 1:
|
||||
return MENU_ITEM_SERVER_1;
|
||||
case 2:
|
||||
return MENU_ITEM_SERVER_2;
|
||||
case 3:
|
||||
return MENU_ITEM_SERVER_3;
|
||||
case 4:
|
||||
return MENU_ITEM_SERVER_4;
|
||||
case 5:
|
||||
return MENU_ITEM_SERVER_5;
|
||||
case 6:
|
||||
return MENU_ITEM_SERVER_6;
|
||||
case 7:
|
||||
return MENU_ITEM_SERVER_7;
|
||||
case 8:
|
||||
return MENU_ITEM_SERVER_8;
|
||||
case 9:
|
||||
return MENU_ITEM_SERVER_9;
|
||||
case 10:
|
||||
return MENU_ITEM_SERVER_10;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onContextItemSelected(final MenuItem menuItem) {
|
||||
switch (menuItem.getItemId()) {
|
||||
case MENU_ITEM_OFFLINE:
|
||||
setActiveServer(0);
|
||||
break;
|
||||
case MENU_ITEM_SERVER_1:
|
||||
setActiveServer(1);
|
||||
break;
|
||||
case MENU_ITEM_SERVER_2:
|
||||
setActiveServer(2);
|
||||
break;
|
||||
case MENU_ITEM_SERVER_3:
|
||||
setActiveServer(3);
|
||||
break;
|
||||
case MENU_ITEM_SERVER_4:
|
||||
setActiveServer(4);
|
||||
break;
|
||||
case MENU_ITEM_SERVER_5:
|
||||
setActiveServer(5);
|
||||
break;
|
||||
case MENU_ITEM_SERVER_6:
|
||||
setActiveServer(6);
|
||||
break;
|
||||
case MENU_ITEM_SERVER_7:
|
||||
setActiveServer(7);
|
||||
break;
|
||||
case MENU_ITEM_SERVER_8:
|
||||
setActiveServer(8);
|
||||
break;
|
||||
case MENU_ITEM_SERVER_9:
|
||||
setActiveServer(9);
|
||||
break;
|
||||
case MENU_ITEM_SERVER_10:
|
||||
setActiveServer(10);
|
||||
break;
|
||||
default:
|
||||
return super.onContextItemSelected(menuItem);
|
||||
}
|
||||
}
|
||||
|
||||
// Restart activity
|
||||
restart();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(final MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case android.R.id.home:
|
||||
menuDrawer.toggleMenu();
|
||||
return true;
|
||||
case R.id.main_shuffle:
|
||||
final Intent intent1 = new Intent(this, DownloadActivity.class);
|
||||
intent1.putExtra(Constants.INTENT_EXTRA_NAME_SHUFFLE, true);
|
||||
Util.startActivityWithoutTransition(this, intent1);
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public boolean onContextItemSelected(final MenuItem menuItem)
|
||||
{
|
||||
switch (menuItem.getItemId())
|
||||
{
|
||||
case MENU_ITEM_OFFLINE:
|
||||
setActiveServer(0);
|
||||
break;
|
||||
case MENU_ITEM_SERVER_1:
|
||||
setActiveServer(1);
|
||||
break;
|
||||
case MENU_ITEM_SERVER_2:
|
||||
setActiveServer(2);
|
||||
break;
|
||||
case MENU_ITEM_SERVER_3:
|
||||
setActiveServer(3);
|
||||
break;
|
||||
case MENU_ITEM_SERVER_4:
|
||||
setActiveServer(4);
|
||||
break;
|
||||
case MENU_ITEM_SERVER_5:
|
||||
setActiveServer(5);
|
||||
break;
|
||||
case MENU_ITEM_SERVER_6:
|
||||
setActiveServer(6);
|
||||
break;
|
||||
case MENU_ITEM_SERVER_7:
|
||||
setActiveServer(7);
|
||||
break;
|
||||
case MENU_ITEM_SERVER_8:
|
||||
setActiveServer(8);
|
||||
break;
|
||||
case MENU_ITEM_SERVER_9:
|
||||
setActiveServer(9);
|
||||
break;
|
||||
case MENU_ITEM_SERVER_10:
|
||||
setActiveServer(10);
|
||||
break;
|
||||
default:
|
||||
return super.onContextItemSelected(menuItem);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void setActiveServer(final int instance) {
|
||||
final DownloadService service = getDownloadService();
|
||||
|
||||
if (Util.getActiveServer(this) != instance) {
|
||||
if (service != null) {
|
||||
service.clearIncomplete();
|
||||
}
|
||||
}
|
||||
|
||||
Util.setActiveServer(this, instance);
|
||||
|
||||
if (service != null) {
|
||||
service.setJukeboxEnabled(Util.getJukeboxEnabled(this, instance));
|
||||
}
|
||||
}
|
||||
// Restart activity
|
||||
restart();
|
||||
return true;
|
||||
}
|
||||
|
||||
private void exit() {
|
||||
stopService(new Intent(this, DownloadServiceImpl.class));
|
||||
Util.unregisterMediaButtonEventReceiver(this);
|
||||
finish();
|
||||
}
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(final MenuItem item)
|
||||
{
|
||||
switch (item.getItemId())
|
||||
{
|
||||
case android.R.id.home:
|
||||
menuDrawer.toggleMenu();
|
||||
return true;
|
||||
case R.id.main_shuffle:
|
||||
final Intent intent1 = new Intent(this, DownloadActivity.class);
|
||||
intent1.putExtra(Constants.INTENT_EXTRA_NAME_SHUFFLE, true);
|
||||
Util.startActivityWithoutTransition(this, intent1);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void showInfoDialog(final boolean show) {
|
||||
if (!infoDialogDisplayed) {
|
||||
infoDialogDisplayed = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (show || Util.getRestUrl(this, null).contains("yourhost")) {
|
||||
Util.info(this, R.string.main_welcome_title, R.string.main_welcome_text);
|
||||
}
|
||||
}
|
||||
}
|
||||
private void setActiveServer(final int instance)
|
||||
{
|
||||
final DownloadService service = getDownloadService();
|
||||
|
||||
private void showAlbumList(final String type, final int title) {
|
||||
final Intent intent = new Intent(this, SelectAlbumActivity.class);
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_TYPE, type);
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_TITLE, title);
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_SIZE, Util.getMaxAlbums(this));
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_OFFSET, 0);
|
||||
if (Util.getActiveServer(this) != instance)
|
||||
{
|
||||
if (service != null)
|
||||
{
|
||||
service.clearIncomplete();
|
||||
}
|
||||
}
|
||||
|
||||
Util.setActiveServer(this, instance);
|
||||
|
||||
if (service != null)
|
||||
{
|
||||
service.setJukeboxEnabled(Util.getJukeboxEnabled(this, instance));
|
||||
}
|
||||
}
|
||||
|
||||
private void exit()
|
||||
{
|
||||
stopService(new Intent(this, DownloadServiceImpl.class));
|
||||
Util.unregisterMediaButtonEventReceiver(this);
|
||||
finish();
|
||||
}
|
||||
|
||||
private void showInfoDialog(final boolean show)
|
||||
{
|
||||
if (!infoDialogDisplayed)
|
||||
{
|
||||
infoDialogDisplayed = true;
|
||||
|
||||
if (show || Util.getRestUrl(this, null).contains("yourhost"))
|
||||
{
|
||||
Util.info(this, R.string.main_welcome_title, R.string.main_welcome_text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void showAlbumList(final String type, final int title)
|
||||
{
|
||||
final Intent intent = new Intent(this, SelectAlbumActivity.class);
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_TYPE, type);
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_TITLE, title);
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_SIZE, Util.getMaxAlbums(this));
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_OFFSET, 0);
|
||||
Util.startActivityWithoutTransition(this, intent);
|
||||
}
|
||||
|
||||
private void showStarredSongs()
|
||||
{
|
||||
final Intent intent = new Intent(this, SelectAlbumActivity.class);
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_STARRED, 1);
|
||||
Util.startActivityWithoutTransition(this, intent);
|
||||
}
|
||||
|
||||
private void showRandomSongs()
|
||||
{
|
||||
final Intent intent = new Intent(this, SelectAlbumActivity.class);
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_RANDOM, 1);
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_SIZE, Util.getMaxSongs(this));
|
||||
Util.startActivityWithoutTransition(this, intent);
|
||||
}
|
||||
|
||||
private void showArtists()
|
||||
{
|
||||
final Intent intent = new Intent(this, SelectArtistActivity.class);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_TITLE, getResources().getString(R.string.main_artists_title));
|
||||
Util.startActivityWithoutTransition(this, intent);
|
||||
}
|
||||
|
||||
private void showGenres()
|
||||
{
|
||||
final Intent intent = new Intent(this, SelectGenreActivity.class);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||
Util.startActivityWithoutTransition(this, intent);
|
||||
}
|
||||
|
||||
private void showVideos()
|
||||
{
|
||||
final Intent intent = new Intent(this, SelectAlbumActivity.class);
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_VIDEOS, 1);
|
||||
Util.startActivityWithoutTransition(this, intent);
|
||||
}
|
||||
|
||||
private void showStarredSongs() {
|
||||
final Intent intent = new Intent(this, SelectAlbumActivity.class);
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_STARRED, 1);
|
||||
Util.startActivityWithoutTransition(this, intent);
|
||||
}
|
||||
|
||||
private void showRandomSongs() {
|
||||
final Intent intent = new Intent(this, SelectAlbumActivity.class);
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_RANDOM, 1);
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_SIZE, Util.getMaxSongs(this));
|
||||
Util.startActivityWithoutTransition(this, intent);
|
||||
}
|
||||
|
||||
private void showArtists() {
|
||||
final Intent intent = new Intent(this, SelectArtistActivity.class);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_TITLE, getResources().getString(R.string.main_artists_title));
|
||||
Util.startActivityWithoutTransition(this, intent);
|
||||
}
|
||||
|
||||
private void showGenres() {
|
||||
final Intent intent = new Intent(this, SelectGenreActivity.class);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||
Util.startActivityWithoutTransition(this, intent);
|
||||
}
|
||||
|
||||
private void showVideos() {
|
||||
final Intent intent = new Intent(this, SelectAlbumActivity.class);
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_VIDEOS, 1);
|
||||
Util.startActivityWithoutTransition(this, intent);
|
||||
}
|
||||
}
|
|
@ -24,6 +24,7 @@ import android.app.SearchManager;
|
|||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.provider.SearchRecentSuggestions;
|
||||
|
||||
import com.thejoshwa.ultrasonic.androidapp.util.Constants;
|
||||
import com.thejoshwa.ultrasonic.androidapp.util.Util;
|
||||
import com.thejoshwa.ultrasonic.androidapp.provider.SearchSuggestionProvider;
|
||||
|
@ -33,24 +34,26 @@ import com.thejoshwa.ultrasonic.androidapp.provider.SearchSuggestionProvider;
|
|||
*
|
||||
* @author Sindre Mehus
|
||||
*/
|
||||
public class QueryReceiverActivity extends Activity {
|
||||
public class QueryReceiverActivity extends Activity
|
||||
{
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
String query = getIntent().getStringExtra(SearchManager.QUERY);
|
||||
String query = getIntent().getStringExtra(SearchManager.QUERY);
|
||||
|
||||
if (query != null) {
|
||||
SearchRecentSuggestions suggestions = new SearchRecentSuggestions(this, SearchSuggestionProvider.AUTHORITY,
|
||||
SearchSuggestionProvider.MODE);
|
||||
suggestions.saveRecentQuery(query, null);
|
||||
if (query != null)
|
||||
{
|
||||
SearchRecentSuggestions suggestions = new SearchRecentSuggestions(this, SearchSuggestionProvider.AUTHORITY, SearchSuggestionProvider.MODE);
|
||||
suggestions.saveRecentQuery(query, null);
|
||||
|
||||
Intent intent = new Intent(QueryReceiverActivity.this, SearchActivity.class);
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_QUERY, query);
|
||||
Util.startActivityWithoutTransition(QueryReceiverActivity.this, intent);
|
||||
}
|
||||
finish();
|
||||
Util.disablePendingTransition(this);
|
||||
}
|
||||
Intent intent = new Intent(QueryReceiverActivity.this, SearchActivity.class);
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_QUERY, query);
|
||||
Util.startActivityWithoutTransition(QueryReceiverActivity.this, intent);
|
||||
}
|
||||
finish();
|
||||
Util.disablePendingTransition(this);
|
||||
}
|
||||
}
|
|
@ -19,30 +19,27 @@
|
|||
|
||||
package com.thejoshwa.ultrasonic.androidapp.activity;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Arrays;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.view.ContextMenu;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.View;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.ListAdapter;
|
||||
import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.thejoshwa.ultrasonic.androidapp.R;
|
||||
import com.thejoshwa.ultrasonic.androidapp.domain.Artist;
|
||||
import com.thejoshwa.ultrasonic.androidapp.domain.MusicDirectory;
|
||||
import com.thejoshwa.ultrasonic.androidapp.domain.MusicDirectory.Entry;
|
||||
import com.thejoshwa.ultrasonic.androidapp.domain.SearchCriteria;
|
||||
import com.thejoshwa.ultrasonic.androidapp.domain.SearchResult;
|
||||
import com.thejoshwa.ultrasonic.androidapp.service.DownloadService;
|
||||
import com.thejoshwa.ultrasonic.androidapp.service.MusicService;
|
||||
import com.thejoshwa.ultrasonic.androidapp.service.MusicServiceFactory;
|
||||
import com.thejoshwa.ultrasonic.androidapp.service.DownloadService;
|
||||
import com.thejoshwa.ultrasonic.androidapp.util.BackgroundTask;
|
||||
import com.thejoshwa.ultrasonic.androidapp.util.Constants;
|
||||
import com.thejoshwa.ultrasonic.androidapp.util.MergeAdapter;
|
||||
|
@ -51,397 +48,474 @@ import com.thejoshwa.ultrasonic.androidapp.util.Util;
|
|||
import com.thejoshwa.ultrasonic.androidapp.view.ArtistAdapter;
|
||||
import com.thejoshwa.ultrasonic.androidapp.view.EntryAdapter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Performs searches and displays the matching artists, albums and songs.
|
||||
*
|
||||
* @author Sindre Mehus
|
||||
*/
|
||||
public class SearchActivity extends SubsonicTabActivity {
|
||||
public class SearchActivity extends SubsonicTabActivity
|
||||
{
|
||||
|
||||
private static int DEFAULT_ARTISTS;
|
||||
private static int DEFAULT_ALBUMS;
|
||||
private static int DEFAULT_SONGS;
|
||||
private static int DEFAULT_ARTISTS;
|
||||
private static int DEFAULT_ALBUMS;
|
||||
private static int DEFAULT_SONGS;
|
||||
|
||||
private ListView list;
|
||||
private ListView list;
|
||||
|
||||
private View artistsHeading;
|
||||
private View albumsHeading;
|
||||
private View songsHeading;
|
||||
private TextView searchButton;
|
||||
private View moreArtistsButton;
|
||||
private View moreAlbumsButton;
|
||||
private View moreSongsButton;
|
||||
private SearchResult searchResult;
|
||||
private MergeAdapter mergeAdapter;
|
||||
private ArtistAdapter artistAdapter;
|
||||
private ListAdapter moreArtistsAdapter;
|
||||
private EntryAdapter albumAdapter;
|
||||
private ListAdapter moreAlbumsAdapter;
|
||||
private ListAdapter moreSongsAdapter;
|
||||
private EntryAdapter songAdapter;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.search);
|
||||
private View artistsHeading;
|
||||
private View albumsHeading;
|
||||
private View songsHeading;
|
||||
private TextView searchButton;
|
||||
private View moreArtistsButton;
|
||||
private View moreAlbumsButton;
|
||||
private View moreSongsButton;
|
||||
private SearchResult searchResult;
|
||||
private MergeAdapter mergeAdapter;
|
||||
private ArtistAdapter artistAdapter;
|
||||
private ListAdapter moreArtistsAdapter;
|
||||
private EntryAdapter albumAdapter;
|
||||
private ListAdapter moreAlbumsAdapter;
|
||||
private ListAdapter moreSongsAdapter;
|
||||
private EntryAdapter songAdapter;
|
||||
|
||||
setActionBarTitle(R.string.common_appname);
|
||||
setActionBarSubtitle(R.string.search_title);
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.search);
|
||||
|
||||
View searchMenuItem = findViewById(R.id.menu_search);
|
||||
menuDrawer.setActiveView(searchMenuItem);
|
||||
setActionBarTitle(R.string.common_appname);
|
||||
setActionBarSubtitle(R.string.search_title);
|
||||
|
||||
DEFAULT_ARTISTS = Util.getDefaultArtists(this);
|
||||
DEFAULT_ALBUMS = Util.getDefaultAlbums(this);
|
||||
DEFAULT_SONGS = Util.getDefaultSongs(this);
|
||||
|
||||
View buttons = LayoutInflater.from(this).inflate(R.layout.search_buttons, null);
|
||||
View searchMenuItem = findViewById(R.id.menu_search);
|
||||
menuDrawer.setActiveView(searchMenuItem);
|
||||
|
||||
artistsHeading = buttons.findViewById(R.id.search_artists);
|
||||
albumsHeading = buttons.findViewById(R.id.search_albums);
|
||||
songsHeading = buttons.findViewById(R.id.search_songs);
|
||||
DEFAULT_ARTISTS = Util.getDefaultArtists(this);
|
||||
DEFAULT_ALBUMS = Util.getDefaultAlbums(this);
|
||||
DEFAULT_SONGS = Util.getDefaultSongs(this);
|
||||
|
||||
searchButton = (TextView) buttons.findViewById(R.id.search_search);
|
||||
moreArtistsButton = buttons.findViewById(R.id.search_more_artists);
|
||||
moreAlbumsButton = buttons.findViewById(R.id.search_more_albums);
|
||||
moreSongsButton = buttons.findViewById(R.id.search_more_songs);
|
||||
View buttons = LayoutInflater.from(this).inflate(R.layout.search_buttons, null);
|
||||
|
||||
list = (ListView) findViewById(R.id.search_list);
|
||||
artistsHeading = buttons.findViewById(R.id.search_artists);
|
||||
albumsHeading = buttons.findViewById(R.id.search_albums);
|
||||
songsHeading = buttons.findViewById(R.id.search_songs);
|
||||
|
||||
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
if (view == searchButton) {
|
||||
onSearchRequested();
|
||||
} else if (view == moreArtistsButton) {
|
||||
expandArtists();
|
||||
} else if (view == moreAlbumsButton) {
|
||||
expandAlbums();
|
||||
} else if (view == moreSongsButton) {
|
||||
expandSongs();
|
||||
} else {
|
||||
Object item = parent.getItemAtPosition(position);
|
||||
if (item instanceof Artist) {
|
||||
onArtistSelected((Artist) item);
|
||||
} else if (item instanceof MusicDirectory.Entry) {
|
||||
MusicDirectory.Entry entry = (MusicDirectory.Entry) item;
|
||||
if (entry.isDirectory()) {
|
||||
onAlbumSelected(entry, false);
|
||||
} else if (entry.isVideo()) {
|
||||
onVideoSelected(entry);
|
||||
} else {
|
||||
onSongSelected(entry, false, true, true, false);
|
||||
}
|
||||
searchButton = (TextView) buttons.findViewById(R.id.search_search);
|
||||
moreArtistsButton = buttons.findViewById(R.id.search_more_artists);
|
||||
moreAlbumsButton = buttons.findViewById(R.id.search_more_albums);
|
||||
moreSongsButton = buttons.findViewById(R.id.search_more_songs);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
registerForContextMenu(list);
|
||||
list = (ListView) findViewById(R.id.search_list);
|
||||
|
||||
onNewIntent(getIntent());
|
||||
}
|
||||
list.setOnItemClickListener(new AdapterView.OnItemClickListener()
|
||||
{
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
|
||||
{
|
||||
if (view == searchButton)
|
||||
{
|
||||
onSearchRequested();
|
||||
}
|
||||
else if (view == moreArtistsButton)
|
||||
{
|
||||
expandArtists();
|
||||
}
|
||||
else if (view == moreAlbumsButton)
|
||||
{
|
||||
expandAlbums();
|
||||
}
|
||||
else if (view == moreSongsButton)
|
||||
{
|
||||
expandSongs();
|
||||
}
|
||||
else
|
||||
{
|
||||
Object item = parent.getItemAtPosition(position);
|
||||
if (item instanceof Artist)
|
||||
{
|
||||
onArtistSelected((Artist) item);
|
||||
}
|
||||
else if (item instanceof MusicDirectory.Entry)
|
||||
{
|
||||
MusicDirectory.Entry entry = (MusicDirectory.Entry) item;
|
||||
if (entry.isDirectory())
|
||||
{
|
||||
onAlbumSelected(entry, false);
|
||||
}
|
||||
else if (entry.isVideo())
|
||||
{
|
||||
onVideoSelected(entry);
|
||||
}
|
||||
else
|
||||
{
|
||||
onSongSelected(entry, false, true, true, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onNewIntent(Intent intent) {
|
||||
super.onNewIntent(intent);
|
||||
String query = intent.getStringExtra(Constants.INTENT_EXTRA_NAME_QUERY);
|
||||
boolean autoplay = intent.getBooleanExtra(Constants.INTENT_EXTRA_NAME_AUTOPLAY, false);
|
||||
boolean requestsearch = intent.getBooleanExtra(Constants.INTENT_EXTRA_REQUEST_SEARCH, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (query != null) {
|
||||
mergeAdapter = new MergeAdapter();
|
||||
list.setAdapter(mergeAdapter);
|
||||
search(query, autoplay);
|
||||
} else {
|
||||
populateList();
|
||||
if (requestsearch)
|
||||
onSearchRequested();
|
||||
}
|
||||
}
|
||||
registerForContextMenu(list);
|
||||
|
||||
@Override
|
||||
public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) {
|
||||
super.onCreateContextMenu(menu, view, menuInfo);
|
||||
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;
|
||||
Object selectedItem = list.getItemAtPosition(info.position);
|
||||
onNewIntent(getIntent());
|
||||
}
|
||||
|
||||
boolean isArtist = selectedItem instanceof Artist;
|
||||
boolean isAlbum = selectedItem instanceof MusicDirectory.Entry && ((MusicDirectory.Entry) selectedItem).isDirectory();
|
||||
|
||||
if (!isArtist && !isAlbum) {
|
||||
MenuInflater inflater = getMenuInflater();
|
||||
inflater.inflate(R.menu.select_song_context, menu);
|
||||
} else {
|
||||
MenuInflater inflater = getMenuInflater();
|
||||
inflater.inflate(R.menu.select_album_context, menu);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
protected void onNewIntent(Intent intent)
|
||||
{
|
||||
super.onNewIntent(intent);
|
||||
String query = intent.getStringExtra(Constants.INTENT_EXTRA_NAME_QUERY);
|
||||
boolean autoplay = intent.getBooleanExtra(Constants.INTENT_EXTRA_NAME_AUTOPLAY, false);
|
||||
boolean requestsearch = intent.getBooleanExtra(Constants.INTENT_EXTRA_REQUEST_SEARCH, false);
|
||||
|
||||
@Override
|
||||
public boolean onContextItemSelected(MenuItem menuItem) {
|
||||
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuItem.getMenuInfo();
|
||||
if (query != null)
|
||||
{
|
||||
mergeAdapter = new MergeAdapter();
|
||||
list.setAdapter(mergeAdapter);
|
||||
search(query, autoplay);
|
||||
}
|
||||
else
|
||||
{
|
||||
populateList();
|
||||
if (requestsearch) onSearchRequested();
|
||||
}
|
||||
}
|
||||
|
||||
if (info == null) {
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo)
|
||||
{
|
||||
super.onCreateContextMenu(menu, view, menuInfo);
|
||||
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;
|
||||
Object selectedItem = list.getItemAtPosition(info.position);
|
||||
|
||||
Object selectedItem = list.getItemAtPosition(info.position);
|
||||
boolean isArtist = selectedItem instanceof Artist;
|
||||
boolean isAlbum = selectedItem instanceof MusicDirectory.Entry && ((MusicDirectory.Entry) selectedItem).isDirectory();
|
||||
|
||||
Artist artist = selectedItem instanceof Artist ? (Artist) selectedItem : null;
|
||||
Entry entry = selectedItem instanceof Entry ? (Entry) selectedItem : null;
|
||||
if (!isArtist && !isAlbum)
|
||||
{
|
||||
MenuInflater inflater = getMenuInflater();
|
||||
inflater.inflate(R.menu.select_song_context, menu);
|
||||
}
|
||||
else
|
||||
{
|
||||
MenuInflater inflater = getMenuInflater();
|
||||
inflater.inflate(R.menu.select_album_context, menu);
|
||||
}
|
||||
}
|
||||
|
||||
String entryId = null;
|
||||
@Override
|
||||
public boolean onContextItemSelected(MenuItem menuItem)
|
||||
{
|
||||
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuItem.getMenuInfo();
|
||||
|
||||
if (entry != null) {
|
||||
entryId = entry.getId();
|
||||
}
|
||||
if (info == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
String id = artist != null ? artist.getId() : entryId;
|
||||
Object selectedItem = list.getItemAtPosition(info.position);
|
||||
|
||||
if (id == null ){
|
||||
return true;
|
||||
}
|
||||
Artist artist = selectedItem instanceof Artist ? (Artist) selectedItem : null;
|
||||
Entry entry = selectedItem instanceof Entry ? (Entry) selectedItem : null;
|
||||
|
||||
List<Entry> songs = new ArrayList<Entry>(1);
|
||||
String entryId = null;
|
||||
|
||||
switch (menuItem.getItemId()) {
|
||||
case R.id.album_menu_play_now:
|
||||
downloadRecursively(id, false, false, true, false, false, false, false, false);
|
||||
break;
|
||||
case R.id.album_menu_play_next:
|
||||
downloadRecursively(id, false, true, false, true, false, true, false, false);
|
||||
break;
|
||||
case R.id.album_menu_play_last:
|
||||
downloadRecursively(id, false, true, false, false, false, false, false, false);
|
||||
break;
|
||||
case R.id.album_menu_pin:
|
||||
downloadRecursively(id, true, true, false, false, false, false, false, false);
|
||||
break;
|
||||
case R.id.album_menu_unpin:
|
||||
downloadRecursively(id, false, false, false, false, false, false, true, false);
|
||||
break;
|
||||
case R.id.album_menu_download:
|
||||
downloadRecursively(id, false, false, false, false, true, false, false, false);
|
||||
break;
|
||||
case R.id.song_menu_play_now:
|
||||
if (entry != null) {
|
||||
songs = new ArrayList<MusicDirectory.Entry>(1);
|
||||
songs.add(entry);
|
||||
download(false, false, true, false, false, songs);
|
||||
}
|
||||
break;
|
||||
case R.id.song_menu_play_next:
|
||||
if (entry != null) {
|
||||
songs = new ArrayList<MusicDirectory.Entry>(1);
|
||||
songs.add(entry);
|
||||
download(true, false, false, true, false, songs);
|
||||
}
|
||||
break;
|
||||
case R.id.song_menu_play_last:
|
||||
if (entry != null) {
|
||||
songs = new ArrayList<MusicDirectory.Entry>(1);
|
||||
songs.add(entry);
|
||||
download(true, false, false, false, false, songs);
|
||||
}
|
||||
break;
|
||||
case R.id.song_menu_pin:
|
||||
if (entry != null) {
|
||||
songs.add(entry);
|
||||
Util.toast(SearchActivity.this, getResources().getQuantityString(R.plurals.select_album_n_songs_pinned, songs.size(), songs.size()));
|
||||
downloadBackground(true, songs);
|
||||
}
|
||||
break;
|
||||
case R.id.song_menu_download:
|
||||
if (entry != null) {
|
||||
songs.add(entry);
|
||||
Util.toast(SearchActivity.this, getResources().getQuantityString(R.plurals.select_album_n_songs_downloaded, songs.size(), songs.size()));
|
||||
downloadBackground(false, songs);
|
||||
}
|
||||
break;
|
||||
case R.id.song_menu_unpin:
|
||||
if (entry != null) {
|
||||
songs.add(entry);
|
||||
Util.toast(SearchActivity.this, getResources().getQuantityString(R.plurals.select_album_n_songs_unpinned, songs.size(), songs.size()));
|
||||
getDownloadService().unpin(songs);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return super.onContextItemSelected(menuItem);
|
||||
}
|
||||
if (entry != null)
|
||||
{
|
||||
entryId = entry.getId();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void downloadBackground(final boolean save, final List<MusicDirectory.Entry> songs) {
|
||||
if (getDownloadService() == null) {
|
||||
String id = artist != null ? artist.getId() : entryId;
|
||||
|
||||
if (id == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
List<Entry> songs = new ArrayList<Entry>(1);
|
||||
|
||||
switch (menuItem.getItemId())
|
||||
{
|
||||
case R.id.album_menu_play_now:
|
||||
downloadRecursively(id, false, false, true, false, false, false, false, false);
|
||||
break;
|
||||
case R.id.album_menu_play_next:
|
||||
downloadRecursively(id, false, true, false, true, false, true, false, false);
|
||||
break;
|
||||
case R.id.album_menu_play_last:
|
||||
downloadRecursively(id, false, true, false, false, false, false, false, false);
|
||||
break;
|
||||
case R.id.album_menu_pin:
|
||||
downloadRecursively(id, true, true, false, false, false, false, false, false);
|
||||
break;
|
||||
case R.id.album_menu_unpin:
|
||||
downloadRecursively(id, false, false, false, false, false, false, true, false);
|
||||
break;
|
||||
case R.id.album_menu_download:
|
||||
downloadRecursively(id, false, false, false, false, true, false, false, false);
|
||||
break;
|
||||
case R.id.song_menu_play_now:
|
||||
if (entry != null)
|
||||
{
|
||||
songs = new ArrayList<MusicDirectory.Entry>(1);
|
||||
songs.add(entry);
|
||||
download(false, false, true, false, false, songs);
|
||||
}
|
||||
break;
|
||||
case R.id.song_menu_play_next:
|
||||
if (entry != null)
|
||||
{
|
||||
songs = new ArrayList<MusicDirectory.Entry>(1);
|
||||
songs.add(entry);
|
||||
download(true, false, false, true, false, songs);
|
||||
}
|
||||
break;
|
||||
case R.id.song_menu_play_last:
|
||||
if (entry != null)
|
||||
{
|
||||
songs = new ArrayList<MusicDirectory.Entry>(1);
|
||||
songs.add(entry);
|
||||
download(true, false, false, false, false, songs);
|
||||
}
|
||||
break;
|
||||
case R.id.song_menu_pin:
|
||||
if (entry != null)
|
||||
{
|
||||
songs.add(entry);
|
||||
Util.toast(SearchActivity.this, getResources().getQuantityString(R.plurals.select_album_n_songs_pinned, songs.size(), songs.size()));
|
||||
downloadBackground(true, songs);
|
||||
}
|
||||
break;
|
||||
case R.id.song_menu_download:
|
||||
if (entry != null)
|
||||
{
|
||||
songs.add(entry);
|
||||
Util.toast(SearchActivity.this, getResources().getQuantityString(R.plurals.select_album_n_songs_downloaded, songs.size(), songs.size()));
|
||||
downloadBackground(false, songs);
|
||||
}
|
||||
break;
|
||||
case R.id.song_menu_unpin:
|
||||
if (entry != null)
|
||||
{
|
||||
songs.add(entry);
|
||||
Util.toast(SearchActivity.this, getResources().getQuantityString(R.plurals.select_album_n_songs_unpinned, songs.size(), songs.size()));
|
||||
getDownloadService().unpin(songs);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return super.onContextItemSelected(menuItem);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void downloadBackground(final boolean save, final List<MusicDirectory.Entry> songs)
|
||||
{
|
||||
if (getDownloadService() == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Runnable onValid = new Runnable() {
|
||||
Runnable onValid = new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run() {
|
||||
public void run()
|
||||
{
|
||||
warnIfNetworkOrStorageUnavailable();
|
||||
getDownloadService().downloadBackground(songs, save);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
checkLicenseAndTrialPeriod(onValid);
|
||||
}
|
||||
|
||||
private void search(final String query, final boolean autoplay) {
|
||||
final int maxArtists = Util.getMaxArtists(this);
|
||||
final int maxAlbums = Util.getMaxAlbums(this);
|
||||
final int maxSongs = Util.getMaxSongs(this);
|
||||
|
||||
BackgroundTask<SearchResult> task = new TabActivityBackgroundTask<SearchResult>(this, true) {
|
||||
@Override
|
||||
protected SearchResult doInBackground() throws Throwable {
|
||||
SearchCriteria criteria = new SearchCriteria(query, maxArtists, maxAlbums, maxSongs);
|
||||
MusicService service = MusicServiceFactory.getMusicService(SearchActivity.this);
|
||||
licenseValid = service.isLicenseValid(SearchActivity.this, this);
|
||||
return service.search(criteria, SearchActivity.this, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void done(SearchResult result) {
|
||||
searchResult = result;
|
||||
|
||||
populateList();
|
||||
|
||||
if (autoplay) {
|
||||
autoplay();
|
||||
}
|
||||
private void search(final String query, final boolean autoplay)
|
||||
{
|
||||
final int maxArtists = Util.getMaxArtists(this);
|
||||
final int maxAlbums = Util.getMaxAlbums(this);
|
||||
final int maxSongs = Util.getMaxSongs(this);
|
||||
|
||||
}
|
||||
};
|
||||
task.execute();
|
||||
}
|
||||
BackgroundTask<SearchResult> task = new TabActivityBackgroundTask<SearchResult>(this, true)
|
||||
{
|
||||
@Override
|
||||
protected SearchResult doInBackground() throws Throwable
|
||||
{
|
||||
SearchCriteria criteria = new SearchCriteria(query, maxArtists, maxAlbums, maxSongs);
|
||||
MusicService service = MusicServiceFactory.getMusicService(SearchActivity.this);
|
||||
licenseValid = service.isLicenseValid(SearchActivity.this, this);
|
||||
return service.search(criteria, SearchActivity.this, this);
|
||||
}
|
||||
|
||||
private void populateList() {
|
||||
mergeAdapter = new MergeAdapter();
|
||||
mergeAdapter.addView(searchButton, true);
|
||||
@Override
|
||||
protected void done(SearchResult result)
|
||||
{
|
||||
searchResult = result;
|
||||
|
||||
if (searchResult != null) {
|
||||
List<Artist> artists = searchResult.getArtists();
|
||||
if (!artists.isEmpty()) {
|
||||
mergeAdapter.addView(artistsHeading);
|
||||
List<Artist> displayedArtists = new ArrayList<Artist>(artists.subList(0, Math.min(DEFAULT_ARTISTS, artists.size())));
|
||||
artistAdapter = new ArtistAdapter(this, displayedArtists);
|
||||
mergeAdapter.addAdapter(artistAdapter);
|
||||
if (artists.size() > DEFAULT_ARTISTS) {
|
||||
moreArtistsAdapter = mergeAdapter.addView(moreArtistsButton, true);
|
||||
}
|
||||
}
|
||||
populateList();
|
||||
|
||||
List<MusicDirectory.Entry> albums = searchResult.getAlbums();
|
||||
if (!albums.isEmpty()) {
|
||||
mergeAdapter.addView(albumsHeading);
|
||||
List<MusicDirectory.Entry> displayedAlbums = new ArrayList<MusicDirectory.Entry>(albums.subList(0, Math.min(DEFAULT_ALBUMS, albums.size())));
|
||||
albumAdapter = new EntryAdapter(this, getImageLoader(), displayedAlbums, false);
|
||||
mergeAdapter.addAdapter(albumAdapter);
|
||||
if (albums.size() > DEFAULT_ALBUMS) {
|
||||
moreAlbumsAdapter = mergeAdapter.addView(moreAlbumsButton, true);
|
||||
}
|
||||
}
|
||||
if (autoplay)
|
||||
{
|
||||
autoplay();
|
||||
}
|
||||
|
||||
List<MusicDirectory.Entry> songs = searchResult.getSongs();
|
||||
if (!songs.isEmpty()) {
|
||||
mergeAdapter.addView(songsHeading);
|
||||
List<MusicDirectory.Entry> displayedSongs = new ArrayList<MusicDirectory.Entry>(songs.subList(0, Math.min(DEFAULT_SONGS, songs.size())));
|
||||
songAdapter = new EntryAdapter(this, getImageLoader(), displayedSongs, false);
|
||||
mergeAdapter.addAdapter(songAdapter);
|
||||
if (songs.size() > DEFAULT_SONGS) {
|
||||
moreSongsAdapter = mergeAdapter.addView(moreSongsButton, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
task.execute();
|
||||
}
|
||||
|
||||
boolean empty = searchResult.getArtists().isEmpty() && searchResult.getAlbums().isEmpty() && searchResult.getSongs().isEmpty();
|
||||
searchButton.setText(empty ? R.string.search_no_match : R.string.search_search);
|
||||
}
|
||||
private void populateList()
|
||||
{
|
||||
mergeAdapter = new MergeAdapter();
|
||||
mergeAdapter.addView(searchButton, true);
|
||||
|
||||
list.setAdapter(mergeAdapter);
|
||||
}
|
||||
if (searchResult != null)
|
||||
{
|
||||
List<Artist> artists = searchResult.getArtists();
|
||||
if (!artists.isEmpty())
|
||||
{
|
||||
mergeAdapter.addView(artistsHeading);
|
||||
List<Artist> displayedArtists = new ArrayList<Artist>(artists.subList(0, Math.min(DEFAULT_ARTISTS, artists.size())));
|
||||
artistAdapter = new ArtistAdapter(this, displayedArtists);
|
||||
mergeAdapter.addAdapter(artistAdapter);
|
||||
if (artists.size() > DEFAULT_ARTISTS)
|
||||
{
|
||||
moreArtistsAdapter = mergeAdapter.addView(moreArtistsButton, true);
|
||||
}
|
||||
}
|
||||
|
||||
private void expandArtists() {
|
||||
artistAdapter.clear();
|
||||
|
||||
for (Artist artist : searchResult.getArtists()) {
|
||||
artistAdapter.add(artist);
|
||||
}
|
||||
|
||||
artistAdapter.notifyDataSetChanged();
|
||||
mergeAdapter.removeAdapter(moreArtistsAdapter);
|
||||
mergeAdapter.notifyDataSetChanged();
|
||||
}
|
||||
List<MusicDirectory.Entry> albums = searchResult.getAlbums();
|
||||
if (!albums.isEmpty())
|
||||
{
|
||||
mergeAdapter.addView(albumsHeading);
|
||||
List<MusicDirectory.Entry> displayedAlbums = new ArrayList<MusicDirectory.Entry>(albums.subList(0, Math.min(DEFAULT_ALBUMS, albums.size())));
|
||||
albumAdapter = new EntryAdapter(this, getImageLoader(), displayedAlbums, false);
|
||||
mergeAdapter.addAdapter(albumAdapter);
|
||||
if (albums.size() > DEFAULT_ALBUMS)
|
||||
{
|
||||
moreAlbumsAdapter = mergeAdapter.addView(moreAlbumsButton, true);
|
||||
}
|
||||
}
|
||||
|
||||
private void expandAlbums() {
|
||||
albumAdapter.clear();
|
||||
|
||||
for (MusicDirectory.Entry album : searchResult.getAlbums()) {
|
||||
albumAdapter.add(album);
|
||||
}
|
||||
|
||||
albumAdapter.notifyDataSetChanged();
|
||||
mergeAdapter.removeAdapter(moreAlbumsAdapter);
|
||||
mergeAdapter.notifyDataSetChanged();
|
||||
}
|
||||
List<MusicDirectory.Entry> songs = searchResult.getSongs();
|
||||
if (!songs.isEmpty())
|
||||
{
|
||||
mergeAdapter.addView(songsHeading);
|
||||
List<MusicDirectory.Entry> displayedSongs = new ArrayList<MusicDirectory.Entry>(songs.subList(0, Math.min(DEFAULT_SONGS, songs.size())));
|
||||
songAdapter = new EntryAdapter(this, getImageLoader(), displayedSongs, false);
|
||||
mergeAdapter.addAdapter(songAdapter);
|
||||
if (songs.size() > DEFAULT_SONGS)
|
||||
{
|
||||
moreSongsAdapter = mergeAdapter.addView(moreSongsButton, true);
|
||||
}
|
||||
}
|
||||
|
||||
private void expandSongs() {
|
||||
songAdapter.clear();
|
||||
|
||||
for (MusicDirectory.Entry song : searchResult.getSongs()) {
|
||||
songAdapter.add(song);
|
||||
}
|
||||
|
||||
songAdapter.notifyDataSetChanged();
|
||||
mergeAdapter.removeAdapter(moreSongsAdapter);
|
||||
mergeAdapter.notifyDataSetChanged();
|
||||
}
|
||||
boolean empty = searchResult.getArtists().isEmpty() && searchResult.getAlbums().isEmpty() && searchResult.getSongs().isEmpty();
|
||||
searchButton.setText(empty ? R.string.search_no_match : R.string.search_search);
|
||||
}
|
||||
|
||||
private void onArtistSelected(Artist artist) {
|
||||
Intent intent = new Intent(this, SelectAlbumActivity.class);
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_ID, artist.getId());
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_NAME, artist.getName());
|
||||
Util.startActivityWithoutTransition(this, intent);
|
||||
}
|
||||
list.setAdapter(mergeAdapter);
|
||||
}
|
||||
|
||||
private void onAlbumSelected(MusicDirectory.Entry album, boolean autoplay) {
|
||||
Intent intent = new Intent(SearchActivity.this, SelectAlbumActivity.class);
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_ID, album.getId());
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_NAME, album.getTitle());
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_IS_ALBUM, album.isDirectory());
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_AUTOPLAY, autoplay);
|
||||
Util.startActivityWithoutTransition(SearchActivity.this, intent);
|
||||
}
|
||||
private void expandArtists()
|
||||
{
|
||||
artistAdapter.clear();
|
||||
|
||||
private void onSongSelected(MusicDirectory.Entry song, boolean save, boolean append, boolean autoplay, boolean playNext) {
|
||||
DownloadService downloadService = getDownloadService();
|
||||
if (downloadService != null) {
|
||||
if (!append && !playNext) {
|
||||
downloadService.clear();
|
||||
}
|
||||
|
||||
downloadService.download(Arrays.asList(song), save, false, playNext, false, false);
|
||||
|
||||
if (autoplay) {
|
||||
downloadService.play(downloadService.size() - 1);
|
||||
}
|
||||
for (Artist artist : searchResult.getArtists())
|
||||
{
|
||||
artistAdapter.add(artist);
|
||||
}
|
||||
|
||||
Util.toast(SearchActivity.this, getResources().getQuantityString(R.plurals.select_album_n_songs_added, 1, 1));
|
||||
}
|
||||
}
|
||||
artistAdapter.notifyDataSetChanged();
|
||||
mergeAdapter.removeAdapter(moreArtistsAdapter);
|
||||
mergeAdapter.notifyDataSetChanged();
|
||||
}
|
||||
|
||||
private void onVideoSelected(MusicDirectory.Entry entry) {
|
||||
playVideo(entry);
|
||||
}
|
||||
private void expandAlbums()
|
||||
{
|
||||
albumAdapter.clear();
|
||||
|
||||
private void autoplay() {
|
||||
if (!searchResult.getSongs().isEmpty()) {
|
||||
onSongSelected(searchResult.getSongs().get(0), false, false, true, false);
|
||||
} else if (!searchResult.getAlbums().isEmpty()) {
|
||||
onAlbumSelected(searchResult.getAlbums().get(0), true);
|
||||
}
|
||||
}
|
||||
for (MusicDirectory.Entry album : searchResult.getAlbums())
|
||||
{
|
||||
albumAdapter.add(album);
|
||||
}
|
||||
|
||||
albumAdapter.notifyDataSetChanged();
|
||||
mergeAdapter.removeAdapter(moreAlbumsAdapter);
|
||||
mergeAdapter.notifyDataSetChanged();
|
||||
}
|
||||
|
||||
private void expandSongs()
|
||||
{
|
||||
songAdapter.clear();
|
||||
|
||||
for (MusicDirectory.Entry song : searchResult.getSongs())
|
||||
{
|
||||
songAdapter.add(song);
|
||||
}
|
||||
|
||||
songAdapter.notifyDataSetChanged();
|
||||
mergeAdapter.removeAdapter(moreSongsAdapter);
|
||||
mergeAdapter.notifyDataSetChanged();
|
||||
}
|
||||
|
||||
private void onArtistSelected(Artist artist)
|
||||
{
|
||||
Intent intent = new Intent(this, SelectAlbumActivity.class);
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_ID, artist.getId());
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_NAME, artist.getName());
|
||||
Util.startActivityWithoutTransition(this, intent);
|
||||
}
|
||||
|
||||
private void onAlbumSelected(MusicDirectory.Entry album, boolean autoplay)
|
||||
{
|
||||
Intent intent = new Intent(SearchActivity.this, SelectAlbumActivity.class);
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_ID, album.getId());
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_NAME, album.getTitle());
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_IS_ALBUM, album.isDirectory());
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_AUTOPLAY, autoplay);
|
||||
Util.startActivityWithoutTransition(SearchActivity.this, intent);
|
||||
}
|
||||
|
||||
private void onSongSelected(MusicDirectory.Entry song, boolean save, boolean append, boolean autoplay, boolean playNext)
|
||||
{
|
||||
DownloadService downloadService = getDownloadService();
|
||||
if (downloadService != null)
|
||||
{
|
||||
if (!append && !playNext)
|
||||
{
|
||||
downloadService.clear();
|
||||
}
|
||||
|
||||
downloadService.download(Collections.singletonList(song), save, false, playNext, false, false);
|
||||
|
||||
if (autoplay)
|
||||
{
|
||||
downloadService.play(downloadService.size() - 1);
|
||||
}
|
||||
|
||||
Util.toast(SearchActivity.this, getResources().getQuantityString(R.plurals.select_album_n_songs_added, 1, 1));
|
||||
}
|
||||
}
|
||||
|
||||
private void onVideoSelected(MusicDirectory.Entry entry)
|
||||
{
|
||||
playVideo(entry);
|
||||
}
|
||||
|
||||
private void autoplay()
|
||||
{
|
||||
if (!searchResult.getSongs().isEmpty())
|
||||
{
|
||||
onSongSelected(searchResult.getSongs().get(0), false, false, true, false);
|
||||
}
|
||||
else if (!searchResult.getAlbums().isEmpty())
|
||||
{
|
||||
onAlbumSelected(searchResult.getAlbums().get(0), true);
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -50,255 +50,304 @@ import com.thejoshwa.ultrasonic.androidapp.view.ArtistAdapter;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class SelectArtistActivity extends SubsonicTabActivity implements AdapterView.OnItemClickListener {
|
||||
public class SelectArtistActivity extends SubsonicTabActivity implements AdapterView.OnItemClickListener
|
||||
{
|
||||
|
||||
private static final int MENU_GROUP_MUSIC_FOLDER = 10;
|
||||
private static final int MENU_GROUP_MUSIC_FOLDER = 10;
|
||||
|
||||
private PullToRefreshListView refreshArtistListView;
|
||||
private ListView artistListView;
|
||||
private View folderButton;
|
||||
private TextView folderName;
|
||||
private List<MusicFolder> musicFolders;
|
||||
private PullToRefreshListView refreshArtistListView;
|
||||
private ListView artistListView;
|
||||
private View folderButton;
|
||||
private TextView folderName;
|
||||
private List<MusicFolder> musicFolders;
|
||||
|
||||
/**
|
||||
* Called when the activity is first created.
|
||||
*/
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.select_artist);
|
||||
/**
|
||||
* Called when the activity is first created.
|
||||
*/
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.select_artist);
|
||||
|
||||
refreshArtistListView = (PullToRefreshListView) findViewById(R.id.select_artist_list);
|
||||
artistListView = refreshArtistListView.getRefreshableView();
|
||||
refreshArtistListView = (PullToRefreshListView) findViewById(R.id.select_artist_list);
|
||||
artistListView = refreshArtistListView.getRefreshableView();
|
||||
|
||||
refreshArtistListView.setOnRefreshListener(new OnRefreshListener<ListView>() {
|
||||
@Override
|
||||
public void onRefresh(PullToRefreshBase<ListView> refreshView) {
|
||||
new GetDataTask().execute();
|
||||
}
|
||||
});
|
||||
refreshArtistListView.setOnRefreshListener(new OnRefreshListener<ListView>()
|
||||
{
|
||||
@Override
|
||||
public void onRefresh(PullToRefreshBase<ListView> refreshView)
|
||||
{
|
||||
new GetDataTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}
|
||||
});
|
||||
|
||||
artistListView.setOnItemClickListener(this);
|
||||
artistListView.setOnItemClickListener(this);
|
||||
|
||||
folderButton = LayoutInflater.from(this).inflate(R.layout.select_artist_header, artistListView, false);
|
||||
folderButton = LayoutInflater.from(this).inflate(R.layout.select_artist_header, artistListView, false);
|
||||
|
||||
if (folderButton != null) {
|
||||
folderName = (TextView) folderButton.findViewById(R.id.select_artist_folder_2);
|
||||
}
|
||||
if (folderButton != null)
|
||||
{
|
||||
folderName = (TextView) folderButton.findViewById(R.id.select_artist_folder_2);
|
||||
}
|
||||
|
||||
if (!Util.isOffline(this) && !Util.getShouldUseId3Tags(this)) {
|
||||
artistListView.addHeaderView(folderButton);
|
||||
}
|
||||
if (!Util.isOffline(this) && !Util.getShouldUseId3Tags(this))
|
||||
{
|
||||
artistListView.addHeaderView(folderButton);
|
||||
}
|
||||
|
||||
registerForContextMenu(artistListView);
|
||||
registerForContextMenu(artistListView);
|
||||
|
||||
String title = getIntent().getStringExtra(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_TITLE);
|
||||
if (title == null) {
|
||||
setActionBarSubtitle(Util.isOffline(this) ? R.string.music_library_label_offline : R.string.music_library_label);
|
||||
} else {
|
||||
setActionBarSubtitle(title);
|
||||
}
|
||||
String title = getIntent().getStringExtra(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_TITLE);
|
||||
if (title == null)
|
||||
{
|
||||
setActionBarSubtitle(Util.isOffline(this) ? R.string.music_library_label_offline : R.string.music_library_label);
|
||||
}
|
||||
else
|
||||
{
|
||||
setActionBarSubtitle(title);
|
||||
}
|
||||
|
||||
View browseMenuItem = findViewById(R.id.menu_browse);
|
||||
menuDrawer.setActiveView(browseMenuItem);
|
||||
View browseMenuItem = findViewById(R.id.menu_browse);
|
||||
menuDrawer.setActiveView(browseMenuItem);
|
||||
|
||||
musicFolders = null;
|
||||
load();
|
||||
}
|
||||
musicFolders = null;
|
||||
load();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
super.onCreateOptionsMenu(menu);
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu)
|
||||
{
|
||||
super.onCreateOptionsMenu(menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void refresh() {
|
||||
finish();
|
||||
Intent intent = getIntent();
|
||||
String title = getIntent().getStringExtra(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_TITLE);
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_TITLE, title);
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_REFRESH, true);
|
||||
Util.startActivityWithoutTransition(this, intent);
|
||||
}
|
||||
private void refresh()
|
||||
{
|
||||
finish();
|
||||
Intent intent = getIntent();
|
||||
String title = getIntent().getStringExtra(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_TITLE);
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_TITLE, title);
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_REFRESH, true);
|
||||
Util.startActivityWithoutTransition(this, intent);
|
||||
}
|
||||
|
||||
private void selectFolder() {
|
||||
folderButton.showContextMenu();
|
||||
}
|
||||
private void selectFolder()
|
||||
{
|
||||
folderButton.showContextMenu();
|
||||
}
|
||||
|
||||
private void load() {
|
||||
BackgroundTask<Indexes> task = new TabActivityBackgroundTask<Indexes>(this, true) {
|
||||
@Override
|
||||
protected Indexes doInBackground() throws Throwable {
|
||||
boolean refresh = getIntent().getBooleanExtra(Constants.INTENT_EXTRA_NAME_REFRESH, false);
|
||||
MusicService musicService = MusicServiceFactory.getMusicService(SelectArtistActivity.this);
|
||||
private void load()
|
||||
{
|
||||
BackgroundTask<Indexes> task = new TabActivityBackgroundTask<Indexes>(this, true)
|
||||
{
|
||||
@Override
|
||||
protected Indexes doInBackground() throws Throwable
|
||||
{
|
||||
boolean refresh = getIntent().getBooleanExtra(Constants.INTENT_EXTRA_NAME_REFRESH, false);
|
||||
MusicService musicService = MusicServiceFactory.getMusicService(SelectArtistActivity.this);
|
||||
|
||||
boolean isOffline = Util.isOffline(SelectArtistActivity.this);
|
||||
boolean useId3Tags = Util.getShouldUseId3Tags(SelectArtistActivity.this);
|
||||
boolean isOffline = Util.isOffline(SelectArtistActivity.this);
|
||||
boolean useId3Tags = Util.getShouldUseId3Tags(SelectArtistActivity.this);
|
||||
|
||||
if (!isOffline && !useId3Tags) {
|
||||
musicFolders = musicService.getMusicFolders(refresh, SelectArtistActivity.this, this);
|
||||
}
|
||||
if (!isOffline && !useId3Tags)
|
||||
{
|
||||
musicFolders = musicService.getMusicFolders(refresh, SelectArtistActivity.this, this);
|
||||
}
|
||||
|
||||
String musicFolderId = Util.getSelectedMusicFolderId(SelectArtistActivity.this);
|
||||
String musicFolderId = Util.getSelectedMusicFolderId(SelectArtistActivity.this);
|
||||
|
||||
if (!isOffline && useId3Tags) {
|
||||
return musicService.getArtists(refresh, SelectArtistActivity.this, this);
|
||||
} else {
|
||||
return musicService.getIndexes(musicFolderId, refresh, SelectArtistActivity.this, this);
|
||||
}
|
||||
}
|
||||
return !isOffline && useId3Tags ? musicService.getArtists(refresh, SelectArtistActivity.this, this) : musicService.getIndexes(musicFolderId, refresh, SelectArtistActivity.this, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void done(Indexes result) {
|
||||
if (result != null) {
|
||||
List<Artist> artists = new ArrayList<Artist>(result.getShortcuts().size() + result.getArtists().size());
|
||||
artists.addAll(result.getShortcuts());
|
||||
artists.addAll(result.getArtists());
|
||||
artistListView.setAdapter(new ArtistAdapter(SelectArtistActivity.this, artists));
|
||||
}
|
||||
@Override
|
||||
protected void done(Indexes result)
|
||||
{
|
||||
if (result != null)
|
||||
{
|
||||
List<Artist> artists = new ArrayList<Artist>(result.getShortcuts().size() + result.getArtists().size());
|
||||
artists.addAll(result.getShortcuts());
|
||||
artists.addAll(result.getArtists());
|
||||
artistListView.setAdapter(new ArtistAdapter(SelectArtistActivity.this, artists));
|
||||
}
|
||||
|
||||
// Display selected music folder
|
||||
if (musicFolders != null) {
|
||||
String musicFolderId = Util.getSelectedMusicFolderId(SelectArtistActivity.this);
|
||||
if (musicFolderId == null) {
|
||||
if (folderName != null) {
|
||||
folderName.setText(R.string.select_artist_all_folders);
|
||||
}
|
||||
} else {
|
||||
for (MusicFolder musicFolder : musicFolders) {
|
||||
if (musicFolder.getId().equals(musicFolderId)) {
|
||||
if (folderName != null) {
|
||||
folderName.setText(musicFolder.getName());
|
||||
}
|
||||
// Display selected music folder
|
||||
if (musicFolders != null)
|
||||
{
|
||||
String musicFolderId = Util.getSelectedMusicFolderId(SelectArtistActivity.this);
|
||||
if (musicFolderId == null)
|
||||
{
|
||||
if (folderName != null)
|
||||
{
|
||||
folderName.setText(R.string.select_artist_all_folders);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (MusicFolder musicFolder : musicFolders)
|
||||
{
|
||||
if (musicFolder.getId().equals(musicFolderId))
|
||||
{
|
||||
if (folderName != null)
|
||||
{
|
||||
folderName.setText(musicFolder.getName());
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
task.execute();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
task.execute();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
if (view == folderButton) {
|
||||
selectFolder();
|
||||
} else {
|
||||
Artist artist = (Artist) parent.getItemAtPosition(position);
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
|
||||
{
|
||||
if (view == folderButton)
|
||||
{
|
||||
selectFolder();
|
||||
}
|
||||
else
|
||||
{
|
||||
Artist artist = (Artist) parent.getItemAtPosition(position);
|
||||
|
||||
if (artist != null) {
|
||||
Intent intent = new Intent(this, SelectAlbumActivity.class);
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_ID, artist.getId());
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_NAME, artist.getName());
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_ARTIST, true);
|
||||
Util.startActivityWithoutTransition(this, intent);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (artist != null)
|
||||
{
|
||||
Intent intent = new Intent(this, SelectAlbumActivity.class);
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_ID, artist.getId());
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_NAME, artist.getName());
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_ARTIST, true);
|
||||
Util.startActivityWithoutTransition(this, intent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) {
|
||||
super.onCreateContextMenu(menu, view, menuInfo);
|
||||
@Override
|
||||
public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo)
|
||||
{
|
||||
super.onCreateContextMenu(menu, view, menuInfo);
|
||||
|
||||
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;
|
||||
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;
|
||||
|
||||
if (artistListView.getItemAtPosition(info.position) instanceof Artist) {
|
||||
MenuInflater inflater = getMenuInflater();
|
||||
inflater.inflate(R.menu.select_artist_context, menu);
|
||||
} else if (info.position == 1) {
|
||||
String musicFolderId = Util.getSelectedMusicFolderId(this);
|
||||
MenuItem menuItem = menu.add(MENU_GROUP_MUSIC_FOLDER, -1, 0, R.string.select_artist_all_folders);
|
||||
if (musicFolderId == null) {
|
||||
menuItem.setChecked(true);
|
||||
}
|
||||
if (musicFolders != null) {
|
||||
for (int i = 0; i < musicFolders.size(); i++) {
|
||||
MusicFolder musicFolder = musicFolders.get(i);
|
||||
menuItem = menu.add(MENU_GROUP_MUSIC_FOLDER, i, i + 1, musicFolder.getName());
|
||||
if (musicFolder.getId().equals(musicFolderId)) {
|
||||
menuItem.setChecked(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (artistListView.getItemAtPosition(info.position) instanceof Artist)
|
||||
{
|
||||
MenuInflater inflater = getMenuInflater();
|
||||
inflater.inflate(R.menu.select_artist_context, menu);
|
||||
}
|
||||
else if (info.position == 1)
|
||||
{
|
||||
String musicFolderId = Util.getSelectedMusicFolderId(this);
|
||||
MenuItem menuItem = menu.add(MENU_GROUP_MUSIC_FOLDER, -1, 0, R.string.select_artist_all_folders);
|
||||
|
||||
menu.setGroupCheckable(MENU_GROUP_MUSIC_FOLDER, true, true);
|
||||
}
|
||||
}
|
||||
if (musicFolderId == null)
|
||||
{
|
||||
menuItem.setChecked(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onContextItemSelected(MenuItem menuItem) {
|
||||
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuItem.getMenuInfo();
|
||||
if (musicFolders != null)
|
||||
{
|
||||
for (int i = 0; i < musicFolders.size(); i++)
|
||||
{
|
||||
MusicFolder musicFolder = musicFolders.get(i);
|
||||
menuItem = menu.add(MENU_GROUP_MUSIC_FOLDER, i, i + 1, musicFolder.getName());
|
||||
|
||||
if (info == null) {
|
||||
return true;
|
||||
}
|
||||
if (musicFolder.getId().equals(musicFolderId))
|
||||
{
|
||||
menuItem.setChecked(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Artist artist = (Artist) artistListView.getItemAtPosition(info.position);
|
||||
menu.setGroupCheckable(MENU_GROUP_MUSIC_FOLDER, true, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (artist != null) {
|
||||
switch (menuItem.getItemId()) {
|
||||
case R.id.artist_menu_play_now:
|
||||
downloadRecursively(artist.getId(), false, false, true, false, false, false, false, true);
|
||||
break;
|
||||
case R.id.artist_menu_play_next:
|
||||
downloadRecursively(artist.getId(), false, false, true, true, false, true, false, true);
|
||||
break;
|
||||
case R.id.artist_menu_play_last:
|
||||
downloadRecursively(artist.getId(), false, true, false, false, false, false, false, true);
|
||||
break;
|
||||
case R.id.artist_menu_pin:
|
||||
downloadRecursively(artist.getId(), true, true, false, false, false, false, false, true);
|
||||
break;
|
||||
case R.id.artist_menu_unpin:
|
||||
downloadRecursively(artist.getId(), false, false, false, false, false, false, true, true);
|
||||
break;
|
||||
case R.id.artist_menu_download:
|
||||
downloadRecursively(artist.getId(), false, false, false, false, true, false, false, true);
|
||||
break;
|
||||
default:
|
||||
return super.onContextItemSelected(menuItem);
|
||||
}
|
||||
} else if (info.position == 1) {
|
||||
MusicFolder selectedFolder = menuItem.getItemId() == -1 ? null : musicFolders.get(menuItem.getItemId());
|
||||
String musicFolderId = selectedFolder == null ? null : selectedFolder.getId();
|
||||
String musicFolderName = selectedFolder == null ? getString(R.string.select_artist_all_folders) : selectedFolder.getName();
|
||||
Util.setSelectedMusicFolderId(this, musicFolderId);
|
||||
folderName.setText(musicFolderName);
|
||||
refresh();
|
||||
}
|
||||
@Override
|
||||
public boolean onContextItemSelected(MenuItem menuItem)
|
||||
{
|
||||
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuItem.getMenuInfo();
|
||||
|
||||
return true;
|
||||
}
|
||||
if (info == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case android.R.id.home:
|
||||
menuDrawer.toggleMenu();
|
||||
return true;
|
||||
case R.id.main_shuffle:
|
||||
Intent intent = new Intent(this, DownloadActivity.class);
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_SHUFFLE, true);
|
||||
Util.startActivityWithoutTransition(this, intent);
|
||||
return true;
|
||||
}
|
||||
Artist artist = (Artist) artistListView.getItemAtPosition(info.position);
|
||||
|
||||
return false;
|
||||
}
|
||||
if (artist != null)
|
||||
{
|
||||
switch (menuItem.getItemId())
|
||||
{
|
||||
case R.id.artist_menu_play_now:
|
||||
downloadRecursively(artist.getId(), false, false, true, false, false, false, false, true);
|
||||
break;
|
||||
case R.id.artist_menu_play_next:
|
||||
downloadRecursively(artist.getId(), false, false, true, true, false, true, false, true);
|
||||
break;
|
||||
case R.id.artist_menu_play_last:
|
||||
downloadRecursively(artist.getId(), false, true, false, false, false, false, false, true);
|
||||
break;
|
||||
case R.id.artist_menu_pin:
|
||||
downloadRecursively(artist.getId(), true, true, false, false, false, false, false, true);
|
||||
break;
|
||||
case R.id.artist_menu_unpin:
|
||||
downloadRecursively(artist.getId(), false, false, false, false, false, false, true, true);
|
||||
break;
|
||||
case R.id.artist_menu_download:
|
||||
downloadRecursively(artist.getId(), false, false, false, false, true, false, false, true);
|
||||
break;
|
||||
default:
|
||||
return super.onContextItemSelected(menuItem);
|
||||
}
|
||||
}
|
||||
else if (info.position == 1)
|
||||
{
|
||||
MusicFolder selectedFolder = menuItem.getItemId() == -1 ? null : musicFolders.get(menuItem.getItemId());
|
||||
String musicFolderId = selectedFolder == null ? null : selectedFolder.getId();
|
||||
String musicFolderName = selectedFolder == null ? getString(R.string.select_artist_all_folders) : selectedFolder.getName();
|
||||
Util.setSelectedMusicFolderId(this, musicFolderId);
|
||||
folderName.setText(musicFolderName);
|
||||
refresh();
|
||||
}
|
||||
|
||||
private class GetDataTask extends AsyncTask<Void, Void, String[]> {
|
||||
@Override
|
||||
protected void onPostExecute(String[] result) {
|
||||
refreshArtistListView.onRefreshComplete();
|
||||
super.onPostExecute(result);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String[] doInBackground(Void... params) {
|
||||
refresh();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item)
|
||||
{
|
||||
switch (item.getItemId())
|
||||
{
|
||||
case android.R.id.home:
|
||||
menuDrawer.toggleMenu();
|
||||
return true;
|
||||
case R.id.main_shuffle:
|
||||
Intent intent = new Intent(this, DownloadActivity.class);
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_SHUFFLE, true);
|
||||
Util.startActivityWithoutTransition(this, intent);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private class GetDataTask extends AsyncTask<Void, Void, String[]>
|
||||
{
|
||||
@Override
|
||||
protected void onPostExecute(String[] result)
|
||||
{
|
||||
refreshArtistListView.onRefreshComplete();
|
||||
super.onPostExecute(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String[] doInBackground(Void... params)
|
||||
{
|
||||
refresh();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -45,130 +45,151 @@ import com.thejoshwa.ultrasonic.androidapp.view.GenreAdapter;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class SelectGenreActivity extends SubsonicTabActivity implements AdapterView.OnItemClickListener {
|
||||
public class SelectGenreActivity extends SubsonicTabActivity implements AdapterView.OnItemClickListener
|
||||
{
|
||||
|
||||
private static final String TAG = SelectGenreActivity.class.getSimpleName();
|
||||
|
||||
|
||||
private PullToRefreshListView refreshGenreListView;
|
||||
private ListView genreListView;
|
||||
private View emptyView;
|
||||
private View emptyView;
|
||||
|
||||
/**
|
||||
* Called when the activity is first created.
|
||||
*/
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.select_genre);
|
||||
/**
|
||||
* Called when the activity is first created.
|
||||
*/
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.select_genre);
|
||||
|
||||
refreshGenreListView = (PullToRefreshListView) findViewById(R.id.select_genre_list);
|
||||
genreListView = refreshGenreListView.getRefreshableView();
|
||||
|
||||
refreshGenreListView.setOnRefreshListener(new OnRefreshListener<ListView>() {
|
||||
@Override
|
||||
public void onRefresh(PullToRefreshBase<ListView> refreshView) {
|
||||
new GetDataTask().execute();
|
||||
}
|
||||
});
|
||||
|
||||
genreListView.setOnItemClickListener(this);
|
||||
|
||||
emptyView = findViewById(R.id.select_genre_empty);
|
||||
refreshGenreListView = (PullToRefreshListView) findViewById(R.id.select_genre_list);
|
||||
genreListView = refreshGenreListView.getRefreshableView();
|
||||
|
||||
registerForContextMenu(genreListView);
|
||||
|
||||
View browseMenuItem = findViewById(R.id.menu_browse);
|
||||
menuDrawer.setActiveView(browseMenuItem);
|
||||
refreshGenreListView.setOnRefreshListener(new OnRefreshListener<ListView>()
|
||||
{
|
||||
@Override
|
||||
public void onRefresh(PullToRefreshBase<ListView> refreshView)
|
||||
{
|
||||
new GetDataTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}
|
||||
});
|
||||
|
||||
setActionBarSubtitle(R.string.main_genres_title);
|
||||
genreListView.setOnItemClickListener(this);
|
||||
|
||||
load();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
super.onCreateOptionsMenu(menu);
|
||||
|
||||
return true;
|
||||
}
|
||||
emptyView = findViewById(R.id.select_genre_empty);
|
||||
|
||||
private void refresh() {
|
||||
finish();
|
||||
Intent intent = getIntent();
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_REFRESH, true);
|
||||
Util.startActivityWithoutTransition(this, intent);
|
||||
}
|
||||
registerForContextMenu(genreListView);
|
||||
|
||||
View browseMenuItem = findViewById(R.id.menu_browse);
|
||||
menuDrawer.setActiveView(browseMenuItem);
|
||||
|
||||
setActionBarSubtitle(R.string.main_genres_title);
|
||||
|
||||
load();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu)
|
||||
{
|
||||
super.onCreateOptionsMenu(menu);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void refresh()
|
||||
{
|
||||
finish();
|
||||
Intent intent = getIntent();
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_REFRESH, true);
|
||||
Util.startActivityWithoutTransition(this, intent);
|
||||
}
|
||||
|
||||
private void load()
|
||||
{
|
||||
BackgroundTask<List<Genre>> task = new TabActivityBackgroundTask<List<Genre>>(this, true)
|
||||
{
|
||||
@Override
|
||||
protected List<Genre> doInBackground() throws Throwable
|
||||
{
|
||||
MusicService musicService = MusicServiceFactory.getMusicService(SelectGenreActivity.this);
|
||||
|
||||
List<Genre> genres = new ArrayList<Genre>();
|
||||
|
||||
try
|
||||
{
|
||||
genres = musicService.getGenres(SelectGenreActivity.this, this);
|
||||
}
|
||||
catch (Exception x)
|
||||
{
|
||||
Log.e(TAG, "Failed to load genres", x);
|
||||
}
|
||||
|
||||
private void load() {
|
||||
BackgroundTask<List<Genre>> task = new TabActivityBackgroundTask<List<Genre>>(this, true) {
|
||||
@Override
|
||||
protected List<Genre> doInBackground() throws Throwable {
|
||||
MusicService musicService = MusicServiceFactory.getMusicService(SelectGenreActivity.this);
|
||||
|
||||
List<Genre> genres = new ArrayList<Genre>();
|
||||
|
||||
try {
|
||||
genres = musicService.getGenres(SelectGenreActivity.this, this);
|
||||
} catch (Exception x) {
|
||||
Log.e(TAG, "Failed to load genres", x);
|
||||
}
|
||||
|
||||
return genres;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void done(List<Genre> result) {
|
||||
emptyView.setVisibility(result == null || result.isEmpty() ? View.VISIBLE : View.GONE);
|
||||
|
||||
if (result != null) {
|
||||
genreListView.setAdapter(new GenreAdapter(SelectGenreActivity.this, result));
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
task.execute();
|
||||
}
|
||||
@Override
|
||||
protected void done(List<Genre> result)
|
||||
{
|
||||
emptyView.setVisibility(result == null || result.isEmpty() ? View.VISIBLE : View.GONE);
|
||||
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
Genre genre = (Genre) parent.getItemAtPosition(position);
|
||||
if (result != null)
|
||||
{
|
||||
genreListView.setAdapter(new GenreAdapter(SelectGenreActivity.this, result));
|
||||
}
|
||||
|
||||
if (genre != null) {
|
||||
Intent intent = new Intent(this, SelectAlbumActivity.class);
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_GENRE_NAME, genre.getName());
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_SIZE, Util.getMaxSongs(this));
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_OFFSET, 0);
|
||||
Util.startActivityWithoutTransition(this, intent);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
task.execute();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
|
||||
{
|
||||
Genre genre = (Genre) parent.getItemAtPosition(position);
|
||||
|
||||
if (genre != null)
|
||||
{
|
||||
Intent intent = new Intent(this, SelectAlbumActivity.class);
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_GENRE_NAME, genre.getName());
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_SIZE, Util.getMaxSongs(this));
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_OFFSET, 0);
|
||||
Util.startActivityWithoutTransition(this, intent);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item)
|
||||
{
|
||||
switch (item.getItemId())
|
||||
{
|
||||
case android.R.id.home:
|
||||
menuDrawer.toggleMenu();
|
||||
return true;
|
||||
case R.id.main_shuffle:
|
||||
Intent intent = new Intent(this, DownloadActivity.class);
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_SHUFFLE, true);
|
||||
Util.startActivityWithoutTransition(this, intent);
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
case R.id.main_shuffle:
|
||||
Intent intent = new Intent(this, DownloadActivity.class);
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_SHUFFLE, true);
|
||||
Util.startActivityWithoutTransition(this, intent);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private class GetDataTask extends AsyncTask<Void, Void, String[]> {
|
||||
@Override
|
||||
protected void onPostExecute(String[] result) {
|
||||
refreshGenreListView.onRefreshComplete();
|
||||
super.onPostExecute(result);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private class GetDataTask extends AsyncTask<Void, Void, String[]>
|
||||
{
|
||||
@Override
|
||||
protected void onPostExecute(String[] result)
|
||||
{
|
||||
refreshGenreListView.onRefreshComplete();
|
||||
super.onPostExecute(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String[] doInBackground(Void... params) {
|
||||
protected String[] doInBackground(Void... params)
|
||||
{
|
||||
refresh();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -53,94 +53,105 @@ import com.thejoshwa.ultrasonic.androidapp.view.PlaylistAdapter;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
public class SelectPlaylistActivity extends SubsonicTabActivity implements AdapterView.OnItemClickListener {
|
||||
public class SelectPlaylistActivity extends SubsonicTabActivity implements AdapterView.OnItemClickListener
|
||||
{
|
||||
|
||||
private PullToRefreshListView refreshPlaylistsListView;
|
||||
private ListView playlistsListView;
|
||||
private View emptyTextView;
|
||||
private PlaylistAdapter playlistAdapter;
|
||||
private PullToRefreshListView refreshPlaylistsListView;
|
||||
private ListView playlistsListView;
|
||||
private View emptyTextView;
|
||||
private PlaylistAdapter playlistAdapter;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.select_playlist);
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.select_playlist);
|
||||
|
||||
refreshPlaylistsListView = (PullToRefreshListView) findViewById(R.id.select_playlist_list);
|
||||
playlistsListView = refreshPlaylistsListView.getRefreshableView();
|
||||
|
||||
refreshPlaylistsListView.setOnRefreshListener(new OnRefreshListener<ListView>() {
|
||||
@Override
|
||||
public void onRefresh(PullToRefreshBase<ListView> refreshView) {
|
||||
new GetDataTask().execute();
|
||||
}
|
||||
});
|
||||
|
||||
emptyTextView = findViewById(R.id.select_playlist_empty);
|
||||
playlistsListView.setOnItemClickListener(this);
|
||||
registerForContextMenu(playlistsListView);
|
||||
refreshPlaylistsListView = (PullToRefreshListView) findViewById(R.id.select_playlist_list);
|
||||
playlistsListView = refreshPlaylistsListView.getRefreshableView();
|
||||
|
||||
View playlistsMenuItem = findViewById(R.id.menu_playlists);
|
||||
menuDrawer.setActiveView(playlistsMenuItem);
|
||||
refreshPlaylistsListView.setOnRefreshListener(new OnRefreshListener<ListView>()
|
||||
{
|
||||
@Override
|
||||
public void onRefresh(PullToRefreshBase<ListView> refreshView)
|
||||
{
|
||||
new GetDataTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}
|
||||
});
|
||||
|
||||
setActionBarTitle(R.string.common_appname);
|
||||
setActionBarSubtitle(R.string.playlist_label);
|
||||
emptyTextView = findViewById(R.id.select_playlist_empty);
|
||||
playlistsListView.setOnItemClickListener(this);
|
||||
registerForContextMenu(playlistsListView);
|
||||
|
||||
load();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
super.onCreateOptionsMenu(menu);
|
||||
return true;
|
||||
}
|
||||
View playlistsMenuItem = findViewById(R.id.menu_playlists);
|
||||
menuDrawer.setActiveView(playlistsMenuItem);
|
||||
|
||||
private void refresh() {
|
||||
setActionBarTitle(R.string.common_appname);
|
||||
setActionBarSubtitle(R.string.playlist_label);
|
||||
|
||||
load();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu)
|
||||
{
|
||||
super.onCreateOptionsMenu(menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void refresh()
|
||||
{
|
||||
finish();
|
||||
Intent intent = new Intent(this, SelectPlaylistActivity.class);
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_REFRESH, true);
|
||||
Util.startActivityWithoutTransition(this, intent);
|
||||
}
|
||||
|
||||
private void load() {
|
||||
BackgroundTask<List<Playlist>> task = new TabActivityBackgroundTask<List<Playlist>>(this, true) {
|
||||
@Override
|
||||
protected List<Playlist> doInBackground() throws Throwable {
|
||||
MusicService musicService = MusicServiceFactory.getMusicService(SelectPlaylistActivity.this);
|
||||
boolean refresh = getIntent().getBooleanExtra(Constants.INTENT_EXTRA_NAME_REFRESH, false);
|
||||
List<Playlist> playlists = musicService.getPlaylists(refresh, SelectPlaylistActivity.this, this);
|
||||
|
||||
if(!Util.isOffline(SelectPlaylistActivity.this))
|
||||
private void load()
|
||||
{
|
||||
BackgroundTask<List<Playlist>> task = new TabActivityBackgroundTask<List<Playlist>>(this, true)
|
||||
{
|
||||
@Override
|
||||
protected List<Playlist> doInBackground() throws Throwable
|
||||
{
|
||||
MusicService musicService = MusicServiceFactory.getMusicService(SelectPlaylistActivity.this);
|
||||
boolean refresh = getIntent().getBooleanExtra(Constants.INTENT_EXTRA_NAME_REFRESH, false);
|
||||
List<Playlist> playlists = musicService.getPlaylists(refresh, SelectPlaylistActivity.this, this);
|
||||
|
||||
if (!Util.isOffline(SelectPlaylistActivity.this))
|
||||
new CacheCleaner(SelectPlaylistActivity.this, getDownloadService()).cleanPlaylists(playlists);
|
||||
return playlists;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void done(List<Playlist> result) {
|
||||
playlistsListView.setAdapter(playlistAdapter = new PlaylistAdapter(SelectPlaylistActivity.this, result));
|
||||
emptyTextView.setVisibility(result.isEmpty() ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
};
|
||||
task.execute();
|
||||
}
|
||||
@Override
|
||||
protected void done(List<Playlist> result)
|
||||
{
|
||||
playlistsListView.setAdapter(playlistAdapter = new PlaylistAdapter(SelectPlaylistActivity.this, result));
|
||||
emptyTextView.setVisibility(result.isEmpty() ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
};
|
||||
task.execute();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) {
|
||||
super.onCreateContextMenu(menu, view, menuInfo);
|
||||
@Override
|
||||
public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo)
|
||||
{
|
||||
super.onCreateContextMenu(menu, view, menuInfo);
|
||||
|
||||
MenuInflater inflater = getMenuInflater();
|
||||
if (Util.isOffline(this))
|
||||
inflater.inflate(R.menu.select_playlist_context_offline, menu);
|
||||
else
|
||||
inflater.inflate(R.menu.select_playlist_context, menu);
|
||||
}
|
||||
MenuInflater inflater = getMenuInflater();
|
||||
if (Util.isOffline(this)) inflater.inflate(R.menu.select_playlist_context_offline, menu);
|
||||
else inflater.inflate(R.menu.select_playlist_context, menu);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onContextItemSelected(MenuItem menuItem) {
|
||||
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuItem.getMenuInfo();
|
||||
Playlist playlist = (Playlist) playlistsListView.getItemAtPosition(info.position);
|
||||
@Override
|
||||
public boolean onContextItemSelected(MenuItem menuItem)
|
||||
{
|
||||
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuItem.getMenuInfo();
|
||||
Playlist playlist = (Playlist) playlistsListView.getItemAtPosition(info.position);
|
||||
|
||||
Intent intent;
|
||||
switch (menuItem.getItemId()) {
|
||||
switch (menuItem.getItemId())
|
||||
{
|
||||
case R.id.playlist_menu_pin:
|
||||
downloadPlaylist(playlist.getId(), playlist.getName(), true, true, false, false, true, false, false);
|
||||
break;
|
||||
|
@ -149,22 +160,22 @@ public class SelectPlaylistActivity extends SubsonicTabActivity implements Adapt
|
|||
break;
|
||||
case R.id.playlist_menu_download:
|
||||
downloadPlaylist(playlist.getId(), playlist.getName(), false, false, false, false, true, false, false);
|
||||
break;
|
||||
case R.id.playlist_menu_play_now:
|
||||
intent = new Intent(SelectPlaylistActivity.this, SelectAlbumActivity.class);
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_PLAYLIST_ID, playlist.getId());
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_PLAYLIST_NAME, playlist.getName());
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_AUTOPLAY, true);
|
||||
Util.startActivityWithoutTransition(SelectPlaylistActivity.this, intent);
|
||||
break;
|
||||
break;
|
||||
case R.id.playlist_menu_play_now:
|
||||
intent = new Intent(SelectPlaylistActivity.this, SelectAlbumActivity.class);
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_PLAYLIST_ID, playlist.getId());
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_PLAYLIST_NAME, playlist.getName());
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_AUTOPLAY, true);
|
||||
Util.startActivityWithoutTransition(SelectPlaylistActivity.this, intent);
|
||||
break;
|
||||
case R.id.playlist_menu_play_shuffled:
|
||||
intent = new Intent(SelectPlaylistActivity.this, SelectAlbumActivity.class);
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_PLAYLIST_ID, playlist.getId());
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_PLAYLIST_NAME, playlist.getName());
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_AUTOPLAY, true);
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_PLAYLIST_ID, playlist.getId());
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_PLAYLIST_NAME, playlist.getName());
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_AUTOPLAY, true);
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_SHUFFLE, true);
|
||||
Util.startActivityWithoutTransition(SelectPlaylistActivity.this, intent);
|
||||
break;
|
||||
Util.startActivityWithoutTransition(SelectPlaylistActivity.this, intent);
|
||||
break;
|
||||
case R.id.playlist_menu_delete:
|
||||
deletePlaylist(playlist);
|
||||
break;
|
||||
|
@ -174,64 +185,73 @@ public class SelectPlaylistActivity extends SubsonicTabActivity implements Adapt
|
|||
case R.id.playlist_update_info:
|
||||
updatePlaylistInfo(playlist);
|
||||
break;
|
||||
default:
|
||||
return super.onContextItemSelected(menuItem);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
default:
|
||||
return super.onContextItemSelected(menuItem);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item)
|
||||
{
|
||||
switch (item.getItemId())
|
||||
{
|
||||
case android.R.id.home:
|
||||
menuDrawer.toggleMenu();
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
|
||||
{
|
||||
|
||||
Playlist playlist = (Playlist) parent.getItemAtPosition(position);
|
||||
Playlist playlist = (Playlist) parent.getItemAtPosition(position);
|
||||
|
||||
Intent intent = new Intent(SelectPlaylistActivity.this, SelectAlbumActivity.class);
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_PLAYLIST_ID, playlist.getId());
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_PLAYLIST_NAME, playlist.getName());
|
||||
Util.startActivityWithoutTransition(SelectPlaylistActivity.this, intent);
|
||||
}
|
||||
|
||||
private void deletePlaylist(final Playlist playlist) {
|
||||
new AlertDialog.Builder(this)
|
||||
.setIcon(android.R.drawable.ic_dialog_alert)
|
||||
.setTitle(R.string.common_confirm)
|
||||
.setMessage(getResources().getString(R.string.delete_playlist, playlist.getName()))
|
||||
.setPositiveButton(R.string.common_ok, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
new LoadingTask<Void>(SelectPlaylistActivity.this, false) {
|
||||
Intent intent = new Intent(SelectPlaylistActivity.this, SelectAlbumActivity.class);
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_PLAYLIST_ID, playlist.getId());
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_PLAYLIST_NAME, playlist.getName());
|
||||
Util.startActivityWithoutTransition(SelectPlaylistActivity.this, intent);
|
||||
}
|
||||
|
||||
private void deletePlaylist(final Playlist playlist)
|
||||
{
|
||||
new AlertDialog.Builder(this).setIcon(android.R.drawable.ic_dialog_alert).setTitle(R.string.common_confirm).setMessage(getResources().getString(R.string.delete_playlist, playlist.getName())).setPositiveButton(R.string.common_ok, new DialogInterface.OnClickListener()
|
||||
{
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which)
|
||||
{
|
||||
new LoadingTask<Void>(SelectPlaylistActivity.this, false)
|
||||
{
|
||||
@Override
|
||||
protected Void doInBackground() throws Throwable {
|
||||
protected Void doInBackground() throws Throwable
|
||||
{
|
||||
MusicService musicService = MusicServiceFactory.getMusicService(SelectPlaylistActivity.this);
|
||||
musicService.deletePlaylist(playlist.getId(), SelectPlaylistActivity.this, null);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void done(Void result) {
|
||||
protected void done(Void result)
|
||||
{
|
||||
playlistAdapter.remove(playlist);
|
||||
playlistAdapter.notifyDataSetChanged();
|
||||
Util.toast(SelectPlaylistActivity.this, getResources().getString(R.string.menu_deleted_playlist, playlist.getName()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void error(Throwable error) {
|
||||
protected void error(Throwable error)
|
||||
{
|
||||
String msg;
|
||||
if (error instanceof OfflineException || error instanceof ServerTooOldException) {
|
||||
if (error instanceof OfflineException || error instanceof ServerTooOldException)
|
||||
{
|
||||
msg = getErrorMessage(error);
|
||||
} else {
|
||||
msg = getResources().getString(R.string.menu_deleted_playlist_error, playlist.getName()) + " " + getErrorMessage(error);
|
||||
}
|
||||
else
|
||||
{
|
||||
msg = String.format("%s %s", getResources().getString(R.string.menu_deleted_playlist_error, playlist.getName()), getErrorMessage(error));
|
||||
}
|
||||
|
||||
Util.toast(SelectPlaylistActivity.this, msg, false);
|
||||
|
@ -239,90 +259,92 @@ public class SelectPlaylistActivity extends SubsonicTabActivity implements Adapt
|
|||
}.execute();
|
||||
}
|
||||
|
||||
})
|
||||
.setNegativeButton(R.string.common_cancel, null)
|
||||
.show();
|
||||
}).setNegativeButton(R.string.common_cancel, null).show();
|
||||
}
|
||||
|
||||
private void displayPlaylistInfo(final Playlist playlist) {
|
||||
|
||||
private void displayPlaylistInfo(final Playlist playlist)
|
||||
{
|
||||
String message = "Owner: " + playlist.getOwner() + "\nComments: " +
|
||||
((playlist.getComment() == null) ? "" : playlist.getComment()) +
|
||||
"\nSong Count: " + playlist.getSongCount() +
|
||||
((playlist.getPublic() == null) ? "" : ("\nPublic: " + playlist.getPublic()) +
|
||||
((playlist.getCreated() == null) ? "" : ("\nCreation Date: " + playlist.getCreated().replace('T', ' '))));
|
||||
new AlertDialog.Builder(this)
|
||||
.setIcon(android.R.drawable.ic_dialog_alert)
|
||||
.setTitle(playlist.getName())
|
||||
.setMessage(message)
|
||||
.show();
|
||||
((playlist.getComment() == null) ? "" : playlist.getComment()) +
|
||||
"\nSong Count: " + playlist.getSongCount() +
|
||||
((playlist.getPublic() == null) ? "" : ("\nPublic: " + playlist.getPublic()) + ((playlist.getCreated() == null) ? "" : ("\nCreation Date: " + playlist.getCreated().replace('T', ' '))));
|
||||
new AlertDialog.Builder(this).setIcon(android.R.drawable.ic_dialog_alert).setTitle(playlist.getName()).setMessage(message).show();
|
||||
}
|
||||
|
||||
private void updatePlaylistInfo(final Playlist playlist) {
|
||||
|
||||
private void updatePlaylistInfo(final Playlist playlist)
|
||||
{
|
||||
View dialogView = getLayoutInflater().inflate(R.layout.update_playlist, null);
|
||||
final EditText nameBox = (EditText)dialogView.findViewById(R.id.get_playlist_name);
|
||||
final EditText commentBox = (EditText)dialogView.findViewById(R.id.get_playlist_comment);
|
||||
final CheckBox publicBox = (CheckBox)dialogView.findViewById(R.id.get_playlist_public);
|
||||
|
||||
final EditText nameBox = (EditText) dialogView.findViewById(R.id.get_playlist_name);
|
||||
final EditText commentBox = (EditText) dialogView.findViewById(R.id.get_playlist_comment);
|
||||
final CheckBox publicBox = (CheckBox) dialogView.findViewById(R.id.get_playlist_public);
|
||||
|
||||
nameBox.setText(playlist.getName());
|
||||
commentBox.setText(playlist.getComment());
|
||||
Boolean pub = playlist.getPublic();
|
||||
if(pub == null) {
|
||||
if (pub == null)
|
||||
{
|
||||
publicBox.setEnabled(false);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
publicBox.setChecked(pub);
|
||||
}
|
||||
|
||||
new AlertDialog.Builder(this)
|
||||
.setIcon(android.R.drawable.ic_dialog_alert)
|
||||
.setTitle(R.string.playlist_update_info)
|
||||
.setView(dialogView)
|
||||
.setPositiveButton(R.string.common_ok, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
new LoadingTask<Void>(SelectPlaylistActivity.this, false) {
|
||||
@Override
|
||||
protected Void doInBackground() throws Throwable {
|
||||
MusicService musicService = MusicServiceFactory.getMusicService(SelectPlaylistActivity.this);
|
||||
musicService.updatePlaylist(playlist.getId(), nameBox.getText().toString(), commentBox.getText().toString(), publicBox.isChecked(), SelectPlaylistActivity.this, null);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void done(Void result) {
|
||||
refresh();
|
||||
Util.toast(SelectPlaylistActivity.this, getResources().getString(R.string.playlist_updated_info, playlist.getName()));
|
||||
}
|
||||
new AlertDialog.Builder(this).setIcon(android.R.drawable.ic_dialog_alert);
|
||||
new AlertDialog.Builder(this).setTitle(R.string.playlist_update_info);
|
||||
new AlertDialog.Builder(this).setView(dialogView);
|
||||
new AlertDialog.Builder(this).setPositiveButton(R.string.common_ok, new DialogInterface.OnClickListener()
|
||||
{
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which)
|
||||
{
|
||||
new LoadingTask<Void>(SelectPlaylistActivity.this, false)
|
||||
{
|
||||
@Override
|
||||
protected Void doInBackground() throws Throwable
|
||||
{
|
||||
MusicService musicService = MusicServiceFactory.getMusicService(SelectPlaylistActivity.this);
|
||||
musicService.updatePlaylist(playlist.getId(), nameBox.getText().toString(), commentBox.getText().toString(), publicBox.isChecked(), SelectPlaylistActivity.this, null);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void error(Throwable error) {
|
||||
String msg;
|
||||
if (error instanceof OfflineException || error instanceof ServerTooOldException) {
|
||||
msg = getErrorMessage(error);
|
||||
} else {
|
||||
msg = getResources().getString(R.string.playlist_updated_info_error, playlist.getName()) + " " + getErrorMessage(error);
|
||||
}
|
||||
@Override
|
||||
protected void done(Void result)
|
||||
{
|
||||
refresh();
|
||||
Util.toast(SelectPlaylistActivity.this, getResources().getString(R.string.playlist_updated_info, playlist.getName()));
|
||||
}
|
||||
|
||||
Util.toast(SelectPlaylistActivity.this, msg, false);
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
@Override
|
||||
protected void error(Throwable error)
|
||||
{
|
||||
String msg;
|
||||
msg = error instanceof OfflineException || error instanceof ServerTooOldException ? getErrorMessage(error) : String.format("%s %s", getResources().getString(R.string.playlist_updated_info_error, playlist.getName()), getErrorMessage(error));
|
||||
|
||||
})
|
||||
.setNegativeButton(R.string.common_cancel, null)
|
||||
.show();
|
||||
Util.toast(SelectPlaylistActivity.this, msg, false);
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
|
||||
});
|
||||
new AlertDialog.Builder(this).setNegativeButton(R.string.common_cancel, null);
|
||||
new AlertDialog.Builder(this).show();
|
||||
}
|
||||
|
||||
private class GetDataTask extends AsyncTask<Void, Void, String[]> {
|
||||
@Override
|
||||
protected void onPostExecute(String[] result) {
|
||||
refreshPlaylistsListView.onRefreshComplete();
|
||||
super.onPostExecute(result);
|
||||
}
|
||||
|
||||
private class GetDataTask extends AsyncTask<Void, Void, String[]>
|
||||
{
|
||||
@Override
|
||||
protected void onPostExecute(String[] result)
|
||||
{
|
||||
refreshPlaylistsListView.onRefreshComplete();
|
||||
super.onPostExecute(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String[] doInBackground(Void... params) {
|
||||
protected String[] doInBackground(Void... params)
|
||||
{
|
||||
refresh();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -24,36 +24,39 @@ import android.app.SearchManager;
|
|||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.provider.SearchRecentSuggestions;
|
||||
|
||||
import com.thejoshwa.ultrasonic.androidapp.util.Constants;
|
||||
import com.thejoshwa.ultrasonic.androidapp.util.Util;
|
||||
import com.thejoshwa.ultrasonic.androidapp.provider.SearchSuggestionProvider;
|
||||
|
||||
/**
|
||||
* Receives voice search queries and forwards to the SearchActivity.
|
||||
*
|
||||
* <p/>
|
||||
* http://android-developers.blogspot.com/2010/09/supporting-new-music-voice-action.html
|
||||
*
|
||||
* @author Sindre Mehus
|
||||
*/
|
||||
public class VoiceQueryReceiverActivity extends Activity {
|
||||
public class VoiceQueryReceiverActivity extends Activity
|
||||
{
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
String query = getIntent().getStringExtra(SearchManager.QUERY);
|
||||
String query = getIntent().getStringExtra(SearchManager.QUERY);
|
||||
|
||||
if (query != null) {
|
||||
SearchRecentSuggestions suggestions = new SearchRecentSuggestions(this, SearchSuggestionProvider.AUTHORITY,
|
||||
SearchSuggestionProvider.MODE);
|
||||
suggestions.saveRecentQuery(query, null);
|
||||
if (query != null)
|
||||
{
|
||||
SearchRecentSuggestions suggestions = new SearchRecentSuggestions(this, SearchSuggestionProvider.AUTHORITY, SearchSuggestionProvider.MODE);
|
||||
suggestions.saveRecentQuery(query, null);
|
||||
|
||||
Intent intent = new Intent(VoiceQueryReceiverActivity.this, SearchActivity.class);
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_QUERY, query);
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_AUTOPLAY, true);
|
||||
Util.startActivityWithoutTransition(VoiceQueryReceiverActivity.this, intent);
|
||||
}
|
||||
finish();
|
||||
Util.disablePendingTransition(this);
|
||||
}
|
||||
Intent intent = new Intent(VoiceQueryReceiverActivity.this, SearchActivity.class);
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_QUERY, query);
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_AUTOPLAY, true);
|
||||
Util.startActivityWithoutTransition(VoiceQueryReceiverActivity.this, intent);
|
||||
}
|
||||
finish();
|
||||
Util.disablePendingTransition(this);
|
||||
}
|
||||
}
|
|
@ -18,142 +18,181 @@
|
|||
*/
|
||||
package com.thejoshwa.ultrasonic.androidapp.audiofx;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import android.content.Context;
|
||||
import android.media.MediaPlayer;
|
||||
import android.media.audiofx.Equalizer;
|
||||
import android.util.Log;
|
||||
|
||||
import com.thejoshwa.ultrasonic.androidapp.util.FileUtil;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Backward-compatible wrapper for {@link Equalizer}, which is API Level 9.
|
||||
*
|
||||
* @author Sindre Mehus
|
||||
* @version $Id$
|
||||
*/
|
||||
public class EqualizerController {
|
||||
public class EqualizerController
|
||||
{
|
||||
|
||||
private static final String TAG = EqualizerController.class.getSimpleName();
|
||||
private static final String TAG = EqualizerController.class.getSimpleName();
|
||||
|
||||
private final Context context;
|
||||
private Equalizer equalizer;
|
||||
private boolean released = false;
|
||||
private int audioSessionId = 0;
|
||||
private final Context context;
|
||||
private Equalizer equalizer;
|
||||
private boolean released;
|
||||
private int audioSessionId;
|
||||
|
||||
// Class initialization fails when this throws an exception.
|
||||
static {
|
||||
try {
|
||||
Class.forName("android.media.audiofx.Equalizer");
|
||||
} catch (Exception ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
// Class initialization fails when this throws an exception.
|
||||
static
|
||||
{
|
||||
try
|
||||
{
|
||||
Class.forName("android.media.audiofx.Equalizer");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws an exception if the {@link Equalizer} class is not available.
|
||||
*/
|
||||
public static void checkAvailable() throws Throwable {
|
||||
// Calling here forces class initialization.
|
||||
}
|
||||
/**
|
||||
* Throws an exception if the {@link Equalizer} class is not available.
|
||||
*/
|
||||
public static void checkAvailable() throws Throwable
|
||||
{
|
||||
// Calling here forces class initialization.
|
||||
}
|
||||
|
||||
public EqualizerController(Context context, MediaPlayer mediaPlayer) {
|
||||
this.context = context;
|
||||
|
||||
try {
|
||||
public EqualizerController(Context context, MediaPlayer mediaPlayer)
|
||||
{
|
||||
this.context = context;
|
||||
|
||||
try
|
||||
{
|
||||
audioSessionId = mediaPlayer.getAudioSessionId();
|
||||
equalizer = new Equalizer(0, audioSessionId);
|
||||
} catch (Throwable x) {
|
||||
equalizer = null;
|
||||
Log.w(TAG, "Failed to create equalizer.", x);
|
||||
}
|
||||
}
|
||||
equalizer = new Equalizer(0, audioSessionId);
|
||||
}
|
||||
catch (Throwable x)
|
||||
{
|
||||
equalizer = null;
|
||||
Log.w(TAG, "Failed to create equalizer.", x);
|
||||
}
|
||||
}
|
||||
|
||||
public void saveSettings() {
|
||||
try {
|
||||
if (isAvailable()) {
|
||||
FileUtil.serialize(context, new EqualizerSettings(equalizer), "equalizer.dat");
|
||||
}
|
||||
} catch (Throwable x) {
|
||||
Log.w(TAG, "Failed to save equalizer settings.", x);
|
||||
}
|
||||
}
|
||||
public void saveSettings()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (isAvailable())
|
||||
{
|
||||
FileUtil.serialize(context, new EqualizerSettings(equalizer), "equalizer.dat");
|
||||
}
|
||||
}
|
||||
catch (Throwable x)
|
||||
{
|
||||
Log.w(TAG, "Failed to save equalizer settings.", x);
|
||||
}
|
||||
}
|
||||
|
||||
public void loadSettings() {
|
||||
try {
|
||||
if (isAvailable()) {
|
||||
EqualizerSettings settings = FileUtil.deserialize(context, "equalizer.dat");
|
||||
public void loadSettings()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (isAvailable())
|
||||
{
|
||||
EqualizerSettings settings = FileUtil.deserialize(context, "equalizer.dat");
|
||||
|
||||
if (settings != null) {
|
||||
settings.apply(equalizer);
|
||||
}
|
||||
}
|
||||
} catch (Throwable x) {
|
||||
Log.w(TAG, "Failed to load equalizer settings.", x);
|
||||
}
|
||||
}
|
||||
if (settings != null)
|
||||
{
|
||||
settings.apply(equalizer);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Throwable x)
|
||||
{
|
||||
Log.w(TAG, "Failed to load equalizer settings.", x);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isAvailable() {
|
||||
return equalizer != null;
|
||||
}
|
||||
public boolean isAvailable()
|
||||
{
|
||||
return equalizer != null;
|
||||
}
|
||||
|
||||
public void release() {
|
||||
if (isAvailable()) {
|
||||
public void release()
|
||||
{
|
||||
if (isAvailable())
|
||||
{
|
||||
released = true;
|
||||
equalizer.release();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Equalizer getEqualizer() {
|
||||
if (released) {
|
||||
public Equalizer getEqualizer()
|
||||
{
|
||||
if (released)
|
||||
{
|
||||
released = false;
|
||||
|
||||
try {
|
||||
|
||||
try
|
||||
{
|
||||
equalizer = new Equalizer(0, audioSessionId);
|
||||
} catch (Throwable x) {
|
||||
}
|
||||
catch (Throwable x)
|
||||
{
|
||||
equalizer = null;
|
||||
Log.w(TAG, "Failed to create equalizer.", x);
|
||||
}
|
||||
}
|
||||
|
||||
return equalizer;
|
||||
}
|
||||
|
||||
private static class EqualizerSettings implements Serializable {
|
||||
return equalizer;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
private static class EqualizerSettings implements Serializable
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 626565082425206061L;
|
||||
private final short[] bandLevels;
|
||||
private short preset;
|
||||
private final boolean enabled;
|
||||
private short preset;
|
||||
private final boolean enabled;
|
||||
|
||||
public EqualizerSettings(Equalizer equalizer) {
|
||||
enabled = equalizer.getEnabled();
|
||||
bandLevels = new short[equalizer.getNumberOfBands()];
|
||||
|
||||
for (short i = 0; i < equalizer.getNumberOfBands(); i++) {
|
||||
bandLevels[i] = equalizer.getBandLevel(i);
|
||||
}
|
||||
|
||||
try {
|
||||
preset = equalizer.getCurrentPreset();
|
||||
} catch (Exception x) {
|
||||
preset = -1;
|
||||
}
|
||||
}
|
||||
public EqualizerSettings(Equalizer equalizer)
|
||||
{
|
||||
enabled = equalizer.getEnabled();
|
||||
bandLevels = new short[equalizer.getNumberOfBands()];
|
||||
|
||||
public void apply(Equalizer equalizer) {
|
||||
for (short i = 0; i < bandLevels.length; i++) {
|
||||
equalizer.setBandLevel(i, bandLevels[i]);
|
||||
}
|
||||
|
||||
if (preset >= 0 && preset < equalizer.getNumberOfPresets()) {
|
||||
equalizer.usePreset(preset);
|
||||
}
|
||||
|
||||
equalizer.setEnabled(enabled);
|
||||
}
|
||||
}
|
||||
for (short i = 0; i < equalizer.getNumberOfBands(); i++)
|
||||
{
|
||||
bandLevels[i] = equalizer.getBandLevel(i);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
preset = equalizer.getCurrentPreset();
|
||||
}
|
||||
catch (Exception x)
|
||||
{
|
||||
preset = -1;
|
||||
}
|
||||
}
|
||||
|
||||
public void apply(Equalizer equalizer)
|
||||
{
|
||||
for (short i = 0; i < bandLevels.length; i++)
|
||||
{
|
||||
equalizer.setBandLevel(i, bandLevels[i]);
|
||||
}
|
||||
|
||||
if (preset >= 0 && preset < equalizer.getNumberOfPresets())
|
||||
{
|
||||
equalizer.usePreset(preset);
|
||||
}
|
||||
|
||||
equalizer.setEnabled(enabled);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,70 +28,89 @@ import android.util.Log;
|
|||
* @author Sindre Mehus
|
||||
* @version $Id$
|
||||
*/
|
||||
public class VisualizerController {
|
||||
public class VisualizerController
|
||||
{
|
||||
|
||||
private static final String TAG = VisualizerController.class.getSimpleName();
|
||||
private static final int PREFERRED_CAPTURE_SIZE = 128; // Must be a power of two.
|
||||
private static final String TAG = VisualizerController.class.getSimpleName();
|
||||
private static final int PREFERRED_CAPTURE_SIZE = 128; // Must be a power of two.
|
||||
|
||||
private Visualizer visualizer;
|
||||
private Visualizer visualizer;
|
||||
private boolean released = false;
|
||||
private int audioSessionId = 0;
|
||||
|
||||
// Class initialization fails when this throws an exception.
|
||||
static {
|
||||
try {
|
||||
Class.forName("android.media.audiofx.Visualizer");
|
||||
} catch (Exception ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
// Class initialization fails when this throws an exception.
|
||||
static
|
||||
{
|
||||
try
|
||||
{
|
||||
Class.forName("android.media.audiofx.Visualizer");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws an exception if the {@link Visualizer} class is not available.
|
||||
*/
|
||||
public static void checkAvailable() throws Throwable {
|
||||
// Calling here forces class initialization.
|
||||
}
|
||||
/**
|
||||
* Throws an exception if the {@link Visualizer} class is not available.
|
||||
*/
|
||||
public static void checkAvailable() throws Throwable
|
||||
{
|
||||
// Calling here forces class initialization.
|
||||
}
|
||||
|
||||
public VisualizerController(MediaPlayer mediaPlayer) {
|
||||
try {
|
||||
public VisualizerController(MediaPlayer mediaPlayer)
|
||||
{
|
||||
try
|
||||
{
|
||||
audioSessionId = mediaPlayer.getAudioSessionId();
|
||||
visualizer = new Visualizer(audioSessionId);
|
||||
} catch (Throwable x) {
|
||||
Log.w(TAG, "Failed to create visualizer.", x);
|
||||
}
|
||||
visualizer = new Visualizer(audioSessionId);
|
||||
}
|
||||
catch (Throwable x)
|
||||
{
|
||||
Log.w(TAG, "Failed to create visualizer.", x);
|
||||
}
|
||||
|
||||
if (visualizer != null) {
|
||||
int[] captureSizeRange = Visualizer.getCaptureSizeRange();
|
||||
int captureSize = Math.max(PREFERRED_CAPTURE_SIZE, captureSizeRange[0]);
|
||||
captureSize = Math.min(captureSize, captureSizeRange[1]);
|
||||
visualizer.setCaptureSize(captureSize);
|
||||
}
|
||||
}
|
||||
if (visualizer != null)
|
||||
{
|
||||
int[] captureSizeRange = Visualizer.getCaptureSizeRange();
|
||||
int captureSize = Math.max(PREFERRED_CAPTURE_SIZE, captureSizeRange[0]);
|
||||
captureSize = Math.min(captureSize, captureSizeRange[1]);
|
||||
visualizer.setCaptureSize(captureSize);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isAvailable() {
|
||||
return visualizer != null;
|
||||
}
|
||||
public boolean isAvailable()
|
||||
{
|
||||
return visualizer != null;
|
||||
}
|
||||
|
||||
public void release() {
|
||||
if (isAvailable()) {
|
||||
visualizer.release();
|
||||
public void release()
|
||||
{
|
||||
if (isAvailable())
|
||||
{
|
||||
visualizer.release();
|
||||
released = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Visualizer getVisualizer() {
|
||||
if (released) {
|
||||
public Visualizer getVisualizer()
|
||||
{
|
||||
if (released)
|
||||
{
|
||||
released = false;
|
||||
|
||||
try {
|
||||
|
||||
try
|
||||
{
|
||||
visualizer = new Visualizer(audioSessionId);
|
||||
} catch (Throwable x) {
|
||||
}
|
||||
catch (Throwable x)
|
||||
{
|
||||
visualizer = null;
|
||||
Log.w(TAG, "Failed to create visualizer.", x);
|
||||
}
|
||||
}
|
||||
|
||||
return visualizer;
|
||||
}
|
||||
return visualizer;
|
||||
}
|
||||
}
|
|
@ -23,69 +23,83 @@ import java.io.Serializable;
|
|||
/**
|
||||
* @author Sindre Mehus
|
||||
*/
|
||||
public class Artist implements Serializable {
|
||||
public class Artist implements Serializable
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = -5790532593784846982L;
|
||||
private String id;
|
||||
private String name;
|
||||
private String index;
|
||||
private String coverArt;
|
||||
private Long albumCount;
|
||||
private int closeness;
|
||||
private String name;
|
||||
private String index;
|
||||
private String coverArt;
|
||||
private Long albumCount;
|
||||
private int closeness;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
public String getId()
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
public void setId(String id)
|
||||
{
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
public String getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
public void setName(String name)
|
||||
{
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getIndex() {
|
||||
return index;
|
||||
}
|
||||
public String getIndex()
|
||||
{
|
||||
return index;
|
||||
}
|
||||
|
||||
public void setIndex(String index) {
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
public String getCoverArt() {
|
||||
return coverArt;
|
||||
}
|
||||
public void setIndex(String index)
|
||||
{
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
public void setCoverArt(String coverArt) {
|
||||
this.coverArt = coverArt;
|
||||
}
|
||||
|
||||
public long getAlbumCount() {
|
||||
public String getCoverArt()
|
||||
{
|
||||
return coverArt;
|
||||
}
|
||||
|
||||
public void setCoverArt(String coverArt)
|
||||
{
|
||||
this.coverArt = coverArt;
|
||||
}
|
||||
|
||||
public long getAlbumCount()
|
||||
{
|
||||
return albumCount;
|
||||
}
|
||||
|
||||
public void setAlbumCount(Long albumCount) {
|
||||
public void setAlbumCount(Long albumCount)
|
||||
{
|
||||
this.albumCount = albumCount;
|
||||
}
|
||||
|
||||
public int getCloseness() {
|
||||
|
||||
public int getCloseness()
|
||||
{
|
||||
return closeness;
|
||||
}
|
||||
|
||||
public void setCloseness(int closeness) {
|
||||
public void setCloseness(int closeness)
|
||||
{
|
||||
this.closeness = closeness;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name;
|
||||
}
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
}
|
|
@ -9,79 +9,104 @@ import java.util.Locale;
|
|||
|
||||
import com.thejoshwa.ultrasonic.androidapp.domain.MusicDirectory.Entry;
|
||||
|
||||
public class Bookmark implements Serializable {
|
||||
public class Bookmark implements Serializable
|
||||
{
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 8988990025189807803L;
|
||||
private int position;
|
||||
private String username;
|
||||
private String comment;
|
||||
private Date created;
|
||||
private Date changed;
|
||||
private Entry entry;
|
||||
|
||||
public int getPosition() {
|
||||
return position;
|
||||
}
|
||||
private String comment;
|
||||
private Date created;
|
||||
private Date changed;
|
||||
private Entry entry;
|
||||
|
||||
public void setPosition(int position) {
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
public int getPosition()
|
||||
{
|
||||
return position;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public String getComment() {
|
||||
return comment;
|
||||
}
|
||||
public void setPosition(int position)
|
||||
{
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
public void setComment(String comment) {
|
||||
this.comment = comment;
|
||||
}
|
||||
|
||||
public Date getCreated() {
|
||||
return created;
|
||||
}
|
||||
public String getUsername()
|
||||
{
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setCreated(String created) {
|
||||
if (created != null) {
|
||||
try {
|
||||
public void setUsername(String username)
|
||||
{
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public String getComment()
|
||||
{
|
||||
return comment;
|
||||
}
|
||||
|
||||
public void setComment(String comment)
|
||||
{
|
||||
this.comment = comment;
|
||||
}
|
||||
|
||||
public Date getCreated()
|
||||
{
|
||||
return created;
|
||||
}
|
||||
|
||||
public void setCreated(String created)
|
||||
{
|
||||
if (created != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
this.created = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.ENGLISH).parse(created);
|
||||
} catch (ParseException e) {
|
||||
}
|
||||
catch (ParseException e)
|
||||
{
|
||||
this.created = null;
|
||||
}
|
||||
} else {
|
||||
this.created = null;
|
||||
}
|
||||
}
|
||||
|
||||
public Date getChanged() {
|
||||
return changed;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this.created = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void setChanged(String changed) {
|
||||
if (changed != null) {
|
||||
try {
|
||||
public Date getChanged()
|
||||
{
|
||||
return changed;
|
||||
}
|
||||
|
||||
public void setChanged(String changed)
|
||||
{
|
||||
if (changed != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
this.changed = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.ENGLISH).parse(changed);
|
||||
} catch (ParseException e) {
|
||||
}
|
||||
catch (ParseException e)
|
||||
{
|
||||
this.changed = null;
|
||||
}
|
||||
} else {
|
||||
this.changed = null;
|
||||
}
|
||||
}
|
||||
|
||||
public Entry getEntry() {
|
||||
return this.entry;
|
||||
}
|
||||
|
||||
public void setEntry(Entry entry) {
|
||||
this.entry = entry;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this.changed = null;
|
||||
}
|
||||
}
|
||||
|
||||
public Entry getEntry()
|
||||
{
|
||||
return this.entry;
|
||||
}
|
||||
|
||||
public void setEntry(Entry entry)
|
||||
{
|
||||
this.entry = entry;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,36 +2,43 @@ package com.thejoshwa.ultrasonic.androidapp.domain;
|
|||
|
||||
import java.io.Serializable;
|
||||
|
||||
public class ChatMessage implements Serializable {
|
||||
public class ChatMessage implements Serializable
|
||||
{
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 496544310289324167L;
|
||||
private String username;
|
||||
private Long time;
|
||||
private String message;
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
private Long time;
|
||||
private String message;
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public Long getTime() {
|
||||
return time;
|
||||
}
|
||||
public String getUsername()
|
||||
{
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setTime(Long time) {
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
public void setUsername(String username)
|
||||
{
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
public Long getTime()
|
||||
{
|
||||
return time;
|
||||
}
|
||||
|
||||
public void setTime(Long time)
|
||||
{
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
public String getMessage()
|
||||
{
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(String message)
|
||||
{
|
||||
this.message = message;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,32 +2,38 @@ package com.thejoshwa.ultrasonic.androidapp.domain;
|
|||
|
||||
import java.io.Serializable;
|
||||
|
||||
public class Genre implements Serializable {
|
||||
public class Genre implements Serializable
|
||||
{
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = -3943025175219134028L;
|
||||
private String name;
|
||||
private String index;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
private String index;
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getIndex() {
|
||||
return index;
|
||||
}
|
||||
public String getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setIndex(String index) {
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name;
|
||||
}
|
||||
public void setName(String name)
|
||||
{
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getIndex()
|
||||
{
|
||||
return index;
|
||||
}
|
||||
|
||||
public void setIndex(String index)
|
||||
{
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,31 +24,36 @@ import java.io.Serializable;
|
|||
/**
|
||||
* @author Sindre Mehus
|
||||
*/
|
||||
public class Indexes implements Serializable {
|
||||
public class Indexes implements Serializable
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 8156117238598414701L;
|
||||
private final long lastModified;
|
||||
private final List<com.thejoshwa.ultrasonic.androidapp.domain.Artist> shortcuts;
|
||||
private final List<com.thejoshwa.ultrasonic.androidapp.domain.Artist> artists;
|
||||
private final List<com.thejoshwa.ultrasonic.androidapp.domain.Artist> shortcuts;
|
||||
private final List<com.thejoshwa.ultrasonic.androidapp.domain.Artist> artists;
|
||||
|
||||
public Indexes(long lastModified, List<com.thejoshwa.ultrasonic.androidapp.domain.Artist> shortcuts, List<com.thejoshwa.ultrasonic.androidapp.domain.Artist> artists) {
|
||||
this.lastModified = lastModified;
|
||||
this.shortcuts = shortcuts;
|
||||
this.artists = artists;
|
||||
}
|
||||
public Indexes(long lastModified, List<com.thejoshwa.ultrasonic.androidapp.domain.Artist> shortcuts, List<com.thejoshwa.ultrasonic.androidapp.domain.Artist> artists)
|
||||
{
|
||||
this.lastModified = lastModified;
|
||||
this.shortcuts = shortcuts;
|
||||
this.artists = artists;
|
||||
}
|
||||
|
||||
public long getLastModified() {
|
||||
return lastModified;
|
||||
}
|
||||
public long getLastModified()
|
||||
{
|
||||
return lastModified;
|
||||
}
|
||||
|
||||
public List<com.thejoshwa.ultrasonic.androidapp.domain.Artist> getShortcuts() {
|
||||
return shortcuts;
|
||||
}
|
||||
public List<com.thejoshwa.ultrasonic.androidapp.domain.Artist> getShortcuts()
|
||||
{
|
||||
return shortcuts;
|
||||
}
|
||||
|
||||
public List<com.thejoshwa.ultrasonic.androidapp.domain.Artist> getArtists() {
|
||||
return artists;
|
||||
}
|
||||
public List<com.thejoshwa.ultrasonic.androidapp.domain.Artist> getArtists()
|
||||
{
|
||||
return artists;
|
||||
}
|
||||
}
|
|
@ -22,42 +22,51 @@ package com.thejoshwa.ultrasonic.androidapp.domain;
|
|||
* @author Sindre Mehus
|
||||
* @version $Id$
|
||||
*/
|
||||
public class JukeboxStatus {
|
||||
public class JukeboxStatus
|
||||
{
|
||||
|
||||
private Integer positionSeconds;
|
||||
private Integer currentPlayingIndex;
|
||||
private Float gain;
|
||||
private boolean playing;
|
||||
private Integer positionSeconds;
|
||||
private Integer currentPlayingIndex;
|
||||
private Float gain;
|
||||
private boolean playing;
|
||||
|
||||
public Integer getPositionSeconds() {
|
||||
return positionSeconds;
|
||||
}
|
||||
public Integer getPositionSeconds()
|
||||
{
|
||||
return positionSeconds;
|
||||
}
|
||||
|
||||
public void setPositionSeconds(Integer positionSeconds) {
|
||||
this.positionSeconds = positionSeconds;
|
||||
}
|
||||
public void setPositionSeconds(Integer positionSeconds)
|
||||
{
|
||||
this.positionSeconds = positionSeconds;
|
||||
}
|
||||
|
||||
public Integer getCurrentPlayingIndex() {
|
||||
return currentPlayingIndex;
|
||||
}
|
||||
public Integer getCurrentPlayingIndex()
|
||||
{
|
||||
return currentPlayingIndex;
|
||||
}
|
||||
|
||||
public void setCurrentIndex(Integer currentPlayingIndex) {
|
||||
this.currentPlayingIndex = currentPlayingIndex;
|
||||
}
|
||||
public void setCurrentIndex(Integer currentPlayingIndex)
|
||||
{
|
||||
this.currentPlayingIndex = currentPlayingIndex;
|
||||
}
|
||||
|
||||
public boolean isPlaying() {
|
||||
return playing;
|
||||
}
|
||||
public boolean isPlaying()
|
||||
{
|
||||
return playing;
|
||||
}
|
||||
|
||||
public void setPlaying(boolean playing) {
|
||||
this.playing = playing;
|
||||
}
|
||||
public void setPlaying(boolean playing)
|
||||
{
|
||||
this.playing = playing;
|
||||
}
|
||||
|
||||
public Float getGain() {
|
||||
return gain;
|
||||
}
|
||||
public Float getGain()
|
||||
{
|
||||
return gain;
|
||||
}
|
||||
|
||||
public void setGain(float gain) {
|
||||
this.gain = gain;
|
||||
}
|
||||
public void setGain(float gain)
|
||||
{
|
||||
this.gain = gain;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,33 +23,40 @@ package com.thejoshwa.ultrasonic.androidapp.domain;
|
|||
*
|
||||
* @author Sindre Mehus
|
||||
*/
|
||||
public class Lyrics {
|
||||
public class Lyrics
|
||||
{
|
||||
|
||||
private String artist;
|
||||
private String title;
|
||||
private String text;
|
||||
private String artist;
|
||||
private String title;
|
||||
private String text;
|
||||
|
||||
public String getArtist() {
|
||||
return artist;
|
||||
}
|
||||
public String getArtist()
|
||||
{
|
||||
return artist;
|
||||
}
|
||||
|
||||
public void setArtist(String artist) {
|
||||
this.artist = artist;
|
||||
}
|
||||
public void setArtist(String artist)
|
||||
{
|
||||
this.artist = artist;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
public String getTitle()
|
||||
{
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
public void setTitle(String title)
|
||||
{
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
public String getText()
|
||||
{
|
||||
return text;
|
||||
}
|
||||
|
||||
public void setText(String text) {
|
||||
this.text = text;
|
||||
}
|
||||
public void setText(String text)
|
||||
{
|
||||
this.text = text;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,335 +29,413 @@ import java.io.Serializable;
|
|||
/**
|
||||
* @author Sindre Mehus
|
||||
*/
|
||||
public class MusicDirectory {
|
||||
public class MusicDirectory
|
||||
{
|
||||
|
||||
private String name;
|
||||
private final List<Entry> children = new ArrayList<Entry>();
|
||||
private String name;
|
||||
private final List<Entry> children = new ArrayList<Entry>();
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
public String getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
public void setName(String name)
|
||||
{
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public void addChild(Entry child) {
|
||||
children.add(child);
|
||||
}
|
||||
public void addChild(Entry child)
|
||||
{
|
||||
children.add(child);
|
||||
}
|
||||
|
||||
public List<Entry> getChildren() {
|
||||
return getChildren(true, true);
|
||||
}
|
||||
public List<Entry> getChildren()
|
||||
{
|
||||
return getChildren(true, true);
|
||||
}
|
||||
|
||||
public List<Entry> getChildren(boolean includeDirs, boolean includeFiles) {
|
||||
if (includeDirs && includeFiles) {
|
||||
return children;
|
||||
}
|
||||
public List<Entry> getChildren(boolean includeDirs, boolean includeFiles)
|
||||
{
|
||||
if (includeDirs && includeFiles)
|
||||
{
|
||||
return children;
|
||||
}
|
||||
|
||||
List<Entry> result = new ArrayList<Entry>(children.size());
|
||||
for (Entry child : children) {
|
||||
if (child.isDirectory() && includeDirs || !child.isDirectory() && includeFiles) {
|
||||
result.add(child);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
List<Entry> result = new ArrayList<Entry>(children.size());
|
||||
for (Entry child : children)
|
||||
{
|
||||
if (child.isDirectory() && includeDirs || !child.isDirectory() && includeFiles)
|
||||
{
|
||||
result.add(child);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static class Entry implements Serializable {
|
||||
/**
|
||||
*
|
||||
public static class Entry implements Serializable
|
||||
{
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = -3339106650010798108L;
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
private String id;
|
||||
private String parent;
|
||||
private boolean isDirectory;
|
||||
private String title;
|
||||
private String album;
|
||||
private String albumId;
|
||||
private String artist;
|
||||
private String artistId;
|
||||
private Integer track;
|
||||
private Integer year;
|
||||
private String genre;
|
||||
private String contentType;
|
||||
private String suffix;
|
||||
private String transcodedContentType;
|
||||
private String transcodedSuffix;
|
||||
private String coverArt;
|
||||
private Long size;
|
||||
private Long songCount;
|
||||
private Integer duration;
|
||||
private Integer bitRate;
|
||||
private String path;
|
||||
private boolean isVideo;
|
||||
private boolean isStarred;
|
||||
private Integer discNumber;
|
||||
private String type;
|
||||
private Date created;
|
||||
private int closeness;
|
||||
private int bookmarkPosition;
|
||||
|
||||
public Integer getDiscNumber() {
|
||||
return discNumber;
|
||||
}
|
||||
|
||||
public void setDiscNumber(Integer discNumber) {
|
||||
this.discNumber = discNumber;
|
||||
}
|
||||
private String parent;
|
||||
private boolean isDirectory;
|
||||
private String title;
|
||||
private String album;
|
||||
private String albumId;
|
||||
private String artist;
|
||||
private String artistId;
|
||||
private Integer track;
|
||||
private Integer year;
|
||||
private String genre;
|
||||
private String contentType;
|
||||
private String suffix;
|
||||
private String transcodedContentType;
|
||||
private String transcodedSuffix;
|
||||
private String coverArt;
|
||||
private Long size;
|
||||
private Long songCount;
|
||||
private Integer duration;
|
||||
private Integer bitRate;
|
||||
private String path;
|
||||
private boolean isVideo;
|
||||
private boolean isStarred;
|
||||
private Integer discNumber;
|
||||
private String type;
|
||||
private Date created;
|
||||
private int closeness;
|
||||
private int bookmarkPosition;
|
||||
|
||||
public boolean getStarred() {
|
||||
return isStarred;
|
||||
}
|
||||
|
||||
public void setStarred(boolean starred) {
|
||||
this.isStarred = starred;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
public Integer getDiscNumber()
|
||||
{
|
||||
return discNumber;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
public void setDiscNumber(Integer discNumber)
|
||||
{
|
||||
this.discNumber = discNumber;
|
||||
}
|
||||
|
||||
public String getParent() {
|
||||
return parent;
|
||||
}
|
||||
public boolean getStarred()
|
||||
{
|
||||
return isStarred;
|
||||
}
|
||||
|
||||
public void setParent(String parent) {
|
||||
this.parent = parent;
|
||||
}
|
||||
public void setStarred(boolean starred)
|
||||
{
|
||||
this.isStarred = starred;
|
||||
}
|
||||
|
||||
public boolean isDirectory() {
|
||||
return isDirectory;
|
||||
}
|
||||
public String getId()
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setIsDirectory(boolean directory) {
|
||||
this.isDirectory = directory;
|
||||
}
|
||||
public void setId(String id)
|
||||
{
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
public String getParent()
|
||||
{
|
||||
return parent;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
public void setParent(String parent)
|
||||
{
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
public String getAlbum() {
|
||||
return album;
|
||||
}
|
||||
public boolean isDirectory()
|
||||
{
|
||||
return isDirectory;
|
||||
}
|
||||
|
||||
public void setAlbum(String album) {
|
||||
this.album = album;
|
||||
}
|
||||
|
||||
public String getAlbumId() {
|
||||
return albumId;
|
||||
}
|
||||
public void setIsDirectory(boolean directory)
|
||||
{
|
||||
this.isDirectory = directory;
|
||||
}
|
||||
|
||||
public void setAlbumId(String albumId) {
|
||||
this.albumId = albumId;
|
||||
}
|
||||
public String getTitle()
|
||||
{
|
||||
return title;
|
||||
}
|
||||
|
||||
public String getArtist() {
|
||||
return artist;
|
||||
}
|
||||
public void setTitle(String title)
|
||||
{
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public void setArtist(String artist) {
|
||||
this.artist = artist;
|
||||
}
|
||||
|
||||
public String getArtistId() {
|
||||
return artistId;
|
||||
}
|
||||
public String getAlbum()
|
||||
{
|
||||
return album;
|
||||
}
|
||||
|
||||
public void setArtistId(String artistId) {
|
||||
this.artistId = artistId;
|
||||
}
|
||||
public void setAlbum(String album)
|
||||
{
|
||||
this.album = album;
|
||||
}
|
||||
|
||||
public Integer getTrack() {
|
||||
return track == null ? 0 : track;
|
||||
}
|
||||
public String getAlbumId()
|
||||
{
|
||||
return albumId;
|
||||
}
|
||||
|
||||
public void setTrack(Integer track) {
|
||||
this.track = track;
|
||||
}
|
||||
|
||||
public Long getSongcount() {
|
||||
return songCount;
|
||||
}
|
||||
public void setAlbumId(String albumId)
|
||||
{
|
||||
this.albumId = albumId;
|
||||
}
|
||||
|
||||
public void setSongCount(Long songCount) {
|
||||
this.songCount = songCount;
|
||||
}
|
||||
public String getArtist()
|
||||
{
|
||||
return artist;
|
||||
}
|
||||
|
||||
public Integer getYear() {
|
||||
return year == null ? 0 : year;
|
||||
}
|
||||
public void setArtist(String artist)
|
||||
{
|
||||
this.artist = artist;
|
||||
}
|
||||
|
||||
public void setYear(Integer year) {
|
||||
this.year = year;
|
||||
}
|
||||
public String getArtistId()
|
||||
{
|
||||
return artistId;
|
||||
}
|
||||
|
||||
public String getGenre() {
|
||||
return genre;
|
||||
}
|
||||
public void setArtistId(String artistId)
|
||||
{
|
||||
this.artistId = artistId;
|
||||
}
|
||||
|
||||
public void setGenre(String genre) {
|
||||
this.genre = genre;
|
||||
}
|
||||
public Integer getTrack()
|
||||
{
|
||||
return track == null ? 0 : track;
|
||||
}
|
||||
|
||||
public String getContentType() {
|
||||
return contentType;
|
||||
}
|
||||
public void setTrack(Integer track)
|
||||
{
|
||||
this.track = track;
|
||||
}
|
||||
|
||||
public void setContentType(String contentType) {
|
||||
this.contentType = contentType;
|
||||
}
|
||||
public Long getSongCount()
|
||||
{
|
||||
return songCount;
|
||||
}
|
||||
|
||||
public String getSuffix() {
|
||||
return suffix;
|
||||
}
|
||||
public void setSongCount(Long songCount)
|
||||
{
|
||||
this.songCount = songCount;
|
||||
}
|
||||
|
||||
public void setSuffix(String suffix) {
|
||||
this.suffix = suffix;
|
||||
}
|
||||
public Integer getYear()
|
||||
{
|
||||
return year == null ? 0 : year;
|
||||
}
|
||||
|
||||
public String getTranscodedContentType() {
|
||||
return transcodedContentType;
|
||||
}
|
||||
public void setYear(Integer year)
|
||||
{
|
||||
this.year = year;
|
||||
}
|
||||
|
||||
public void setTranscodedContentType(String transcodedContentType) {
|
||||
this.transcodedContentType = transcodedContentType;
|
||||
}
|
||||
public String getGenre()
|
||||
{
|
||||
return genre;
|
||||
}
|
||||
|
||||
public String getTranscodedSuffix() {
|
||||
return transcodedSuffix;
|
||||
}
|
||||
public void setGenre(String genre)
|
||||
{
|
||||
this.genre = genre;
|
||||
}
|
||||
|
||||
public void setTranscodedSuffix(String transcodedSuffix) {
|
||||
this.transcodedSuffix = transcodedSuffix;
|
||||
}
|
||||
public String getContentType()
|
||||
{
|
||||
return contentType;
|
||||
}
|
||||
|
||||
public Long getSize() {
|
||||
return size;
|
||||
}
|
||||
public void setContentType(String contentType)
|
||||
{
|
||||
this.contentType = contentType;
|
||||
}
|
||||
|
||||
public void setSize(Long size) {
|
||||
this.size = size;
|
||||
}
|
||||
public String getSuffix()
|
||||
{
|
||||
return suffix;
|
||||
}
|
||||
|
||||
public Integer getDuration() {
|
||||
return duration;
|
||||
}
|
||||
public void setSuffix(String suffix)
|
||||
{
|
||||
this.suffix = suffix;
|
||||
}
|
||||
|
||||
public void setDuration(Integer duration) {
|
||||
this.duration = duration;
|
||||
}
|
||||
|
||||
public void setDuration(long duration) {
|
||||
this.duration = (int) duration;
|
||||
}
|
||||
public String getTranscodedContentType()
|
||||
{
|
||||
return transcodedContentType;
|
||||
}
|
||||
|
||||
public Integer getBitRate() {
|
||||
return bitRate;
|
||||
}
|
||||
public void setTranscodedContentType(String transcodedContentType)
|
||||
{
|
||||
this.transcodedContentType = transcodedContentType;
|
||||
}
|
||||
|
||||
public void setBitRate(Integer bitRate) {
|
||||
this.bitRate = bitRate;
|
||||
}
|
||||
public String getTranscodedSuffix()
|
||||
{
|
||||
return transcodedSuffix;
|
||||
}
|
||||
|
||||
public String getCoverArt() {
|
||||
return coverArt;
|
||||
}
|
||||
public void setTranscodedSuffix(String transcodedSuffix)
|
||||
{
|
||||
this.transcodedSuffix = transcodedSuffix;
|
||||
}
|
||||
|
||||
public void setCoverArt(String coverArt) {
|
||||
this.coverArt = coverArt;
|
||||
}
|
||||
public Long getSize()
|
||||
{
|
||||
return size;
|
||||
}
|
||||
|
||||
public String getPath() {
|
||||
return path;
|
||||
}
|
||||
public void setSize(Long size)
|
||||
{
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
public void setPath(String path) {
|
||||
this.path = path;
|
||||
}
|
||||
public Integer getDuration()
|
||||
{
|
||||
return duration;
|
||||
}
|
||||
|
||||
public boolean isVideo() {
|
||||
return isVideo;
|
||||
}
|
||||
public void setDuration(Integer duration)
|
||||
{
|
||||
this.duration = duration;
|
||||
}
|
||||
|
||||
public void setIsVideo(boolean video) {
|
||||
this.isVideo = video;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
public void setDuration(long duration)
|
||||
{
|
||||
this.duration = (int) duration;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public Date getCreated() {
|
||||
return created;
|
||||
}
|
||||
public Integer getBitRate()
|
||||
{
|
||||
return bitRate;
|
||||
}
|
||||
|
||||
public void setCreated(String created) {
|
||||
if (created != null) {
|
||||
try {
|
||||
public void setBitRate(Integer bitRate)
|
||||
{
|
||||
this.bitRate = bitRate;
|
||||
}
|
||||
|
||||
public String getCoverArt()
|
||||
{
|
||||
return coverArt;
|
||||
}
|
||||
|
||||
public void setCoverArt(String coverArt)
|
||||
{
|
||||
this.coverArt = coverArt;
|
||||
}
|
||||
|
||||
public String getPath()
|
||||
{
|
||||
return path;
|
||||
}
|
||||
|
||||
public void setPath(String path)
|
||||
{
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
public boolean isVideo()
|
||||
{
|
||||
return isVideo;
|
||||
}
|
||||
|
||||
public void setIsVideo(boolean video)
|
||||
{
|
||||
this.isVideo = video;
|
||||
}
|
||||
|
||||
public String getType()
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type)
|
||||
{
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public Date getCreated()
|
||||
{
|
||||
return created;
|
||||
}
|
||||
|
||||
public void setCreated(String created)
|
||||
{
|
||||
if (created != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
this.created = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.ENGLISH).parse(created);
|
||||
} catch (ParseException e) {
|
||||
}
|
||||
catch (ParseException e)
|
||||
{
|
||||
this.created = null;
|
||||
}
|
||||
} else {
|
||||
this.created = null;
|
||||
}
|
||||
}
|
||||
|
||||
public int getCloseness() {
|
||||
}
|
||||
else
|
||||
{
|
||||
this.created = null;
|
||||
}
|
||||
}
|
||||
|
||||
public int getCloseness()
|
||||
{
|
||||
return closeness;
|
||||
}
|
||||
|
||||
public void setCloseness(int closeness) {
|
||||
public void setCloseness(int closeness)
|
||||
{
|
||||
this.closeness = closeness;
|
||||
}
|
||||
|
||||
public int getBookmarkPosition() {
|
||||
return bookmarkPosition;
|
||||
}
|
||||
|
||||
public void setBookmarkPosition(int bookmarkPosition) {
|
||||
public int getBookmarkPosition()
|
||||
{
|
||||
return bookmarkPosition;
|
||||
}
|
||||
|
||||
public void setBookmarkPosition(int bookmarkPosition)
|
||||
{
|
||||
this.bookmarkPosition = bookmarkPosition;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
if (this == o)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Entry entry = (Entry) o;
|
||||
return id.equals(entry.id);
|
||||
}
|
||||
Entry entry = (Entry) o;
|
||||
return id.equals(entry.id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return id.hashCode();
|
||||
}
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return id.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return title;
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return title;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -24,21 +24,25 @@ package com.thejoshwa.ultrasonic.androidapp.domain;
|
|||
* @author Sindre Mehus
|
||||
* @version $Id$
|
||||
*/
|
||||
public class MusicFolder {
|
||||
public class MusicFolder
|
||||
{
|
||||
|
||||
private final String id;
|
||||
private final String name;
|
||||
private final String id;
|
||||
private final String name;
|
||||
|
||||
public MusicFolder(String id, String name) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
}
|
||||
public MusicFolder(String id, String name)
|
||||
{
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
public String getId()
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
public String getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,13 +22,14 @@ package com.thejoshwa.ultrasonic.androidapp.domain;
|
|||
* @author Sindre Mehus
|
||||
* @version $Id$
|
||||
*/
|
||||
public enum PlayerState {
|
||||
IDLE,
|
||||
DOWNLOADING,
|
||||
PREPARING,
|
||||
PREPARED,
|
||||
STARTED,
|
||||
STOPPED,
|
||||
PAUSED,
|
||||
COMPLETED
|
||||
public enum PlayerState
|
||||
{
|
||||
IDLE,
|
||||
DOWNLOADING,
|
||||
PREPARING,
|
||||
PREPARED,
|
||||
STARTED,
|
||||
STOPPED,
|
||||
PAUSED,
|
||||
COMPLETED
|
||||
}
|
||||
|
|
|
@ -23,91 +23,111 @@ import java.io.Serializable;
|
|||
/**
|
||||
* @author Sindre Mehus
|
||||
*/
|
||||
public class Playlist implements Serializable {
|
||||
public class Playlist implements Serializable
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = -4160515427075433798L;
|
||||
private String id;
|
||||
private String name;
|
||||
private String name;
|
||||
private String owner;
|
||||
private String comment;
|
||||
private String songCount;
|
||||
private String created;
|
||||
private Boolean pub;
|
||||
|
||||
public Playlist(String id, String name) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
}
|
||||
public Playlist(String id, String name, String owner, String comment, String songCount, String created, String pub) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
public Playlist(String id, String name)
|
||||
{
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Playlist(String id, String name, String owner, String comment, String songCount, String created, String pub)
|
||||
{
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.owner = (owner == null) ? "" : owner;
|
||||
this.comment = (comment == null) ? "" : comment;
|
||||
this.songCount = (songCount == null) ? "" : songCount;
|
||||
this.created = (created == null) ? "" : created;
|
||||
this.pub = (pub == null) ? null : (pub.equals("true"));
|
||||
}
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
public String getId()
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
public void setId(String id)
|
||||
{
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
public String getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getOwner() {
|
||||
public void setName(String name)
|
||||
{
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getOwner()
|
||||
{
|
||||
return this.owner;
|
||||
}
|
||||
|
||||
public void setOwner(String owner) {
|
||||
|
||||
public void setOwner(String owner)
|
||||
{
|
||||
this.owner = owner;
|
||||
}
|
||||
|
||||
public String getComment() {
|
||||
|
||||
public String getComment()
|
||||
{
|
||||
return this.comment;
|
||||
}
|
||||
|
||||
public void setComment(String comment) {
|
||||
|
||||
public void setComment(String comment)
|
||||
{
|
||||
this.comment = comment;
|
||||
}
|
||||
|
||||
public String getSongCount() {
|
||||
|
||||
public String getSongCount()
|
||||
{
|
||||
return this.songCount;
|
||||
}
|
||||
|
||||
public void setSongCount(String songCount) {
|
||||
|
||||
public void setSongCount(String songCount)
|
||||
{
|
||||
this.songCount = songCount;
|
||||
}
|
||||
|
||||
public String getCreated() {
|
||||
|
||||
public String getCreated()
|
||||
{
|
||||
return this.created;
|
||||
}
|
||||
|
||||
public void setCreated(String created) {
|
||||
|
||||
public void setCreated(String created)
|
||||
{
|
||||
this.created = created;
|
||||
}
|
||||
|
||||
public Boolean getPublic() {
|
||||
|
||||
public Boolean getPublic()
|
||||
{
|
||||
return this.pub;
|
||||
}
|
||||
public void setPublic(Boolean pub) {
|
||||
|
||||
public void setPublic(Boolean pub)
|
||||
{
|
||||
this.pub = pub;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name;
|
||||
}
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
}
|
|
@ -4,25 +4,32 @@ package com.thejoshwa.ultrasonic.androidapp.domain;
|
|||
* @author Sindre Mehus
|
||||
* @version $Id$
|
||||
*/
|
||||
public enum RepeatMode {
|
||||
OFF {
|
||||
@Override
|
||||
public RepeatMode next() {
|
||||
return ALL;
|
||||
}
|
||||
},
|
||||
ALL {
|
||||
@Override
|
||||
public RepeatMode next() {
|
||||
return SINGLE;
|
||||
}
|
||||
},
|
||||
SINGLE {
|
||||
@Override
|
||||
public RepeatMode next() {
|
||||
return OFF;
|
||||
}
|
||||
};
|
||||
public enum RepeatMode
|
||||
{
|
||||
OFF
|
||||
{
|
||||
@Override
|
||||
public RepeatMode next()
|
||||
{
|
||||
return ALL;
|
||||
}
|
||||
},
|
||||
ALL
|
||||
{
|
||||
@Override
|
||||
public RepeatMode next()
|
||||
{
|
||||
return SINGLE;
|
||||
}
|
||||
},
|
||||
SINGLE
|
||||
{
|
||||
@Override
|
||||
public RepeatMode next()
|
||||
{
|
||||
return OFF;
|
||||
}
|
||||
};
|
||||
|
||||
public abstract RepeatMode next();
|
||||
public abstract RepeatMode next();
|
||||
}
|
||||
|
|
|
@ -23,33 +23,39 @@ package com.thejoshwa.ultrasonic.androidapp.domain;
|
|||
*
|
||||
* @author Sindre Mehus
|
||||
*/
|
||||
public class SearchCritera {
|
||||
public class SearchCritera
|
||||
{
|
||||
|
||||
private final String query;
|
||||
private final int artistCount;
|
||||
private final int albumCount;
|
||||
private final int songCount;
|
||||
private final String query;
|
||||
private final int artistCount;
|
||||
private final int albumCount;
|
||||
private final int songCount;
|
||||
|
||||
public SearchCritera(String query, int artistCount, int albumCount, int songCount) {
|
||||
this.query = query;
|
||||
this.artistCount = artistCount;
|
||||
this.albumCount = albumCount;
|
||||
this.songCount = songCount;
|
||||
}
|
||||
public SearchCritera(String query, int artistCount, int albumCount, int songCount)
|
||||
{
|
||||
this.query = query;
|
||||
this.artistCount = artistCount;
|
||||
this.albumCount = albumCount;
|
||||
this.songCount = songCount;
|
||||
}
|
||||
|
||||
public String getQuery() {
|
||||
return query;
|
||||
}
|
||||
public String getQuery()
|
||||
{
|
||||
return query;
|
||||
}
|
||||
|
||||
public int getArtistCount() {
|
||||
return artistCount;
|
||||
}
|
||||
public int getArtistCount()
|
||||
{
|
||||
return artistCount;
|
||||
}
|
||||
|
||||
public int getAlbumCount() {
|
||||
return albumCount;
|
||||
}
|
||||
public int getAlbumCount()
|
||||
{
|
||||
return albumCount;
|
||||
}
|
||||
|
||||
public int getSongCount() {
|
||||
return songCount;
|
||||
}
|
||||
public int getSongCount()
|
||||
{
|
||||
return songCount;
|
||||
}
|
||||
}
|
|
@ -23,33 +23,39 @@ package com.thejoshwa.ultrasonic.androidapp.domain;
|
|||
*
|
||||
* @author Sindre Mehus
|
||||
*/
|
||||
public class SearchCriteria {
|
||||
public class SearchCriteria
|
||||
{
|
||||
|
||||
private final String query;
|
||||
private final int artistCount;
|
||||
private final int albumCount;
|
||||
private final int songCount;
|
||||
private final String query;
|
||||
private final int artistCount;
|
||||
private final int albumCount;
|
||||
private final int songCount;
|
||||
|
||||
public SearchCriteria(String query, int artistCount, int albumCount, int songCount) {
|
||||
this.query = query;
|
||||
this.artistCount = artistCount;
|
||||
this.albumCount = albumCount;
|
||||
this.songCount = songCount;
|
||||
}
|
||||
public SearchCriteria(String query, int artistCount, int albumCount, int songCount)
|
||||
{
|
||||
this.query = query;
|
||||
this.artistCount = artistCount;
|
||||
this.albumCount = albumCount;
|
||||
this.songCount = songCount;
|
||||
}
|
||||
|
||||
public String getQuery() {
|
||||
return query;
|
||||
}
|
||||
public String getQuery()
|
||||
{
|
||||
return query;
|
||||
}
|
||||
|
||||
public int getArtistCount() {
|
||||
return artistCount;
|
||||
}
|
||||
public int getArtistCount()
|
||||
{
|
||||
return artistCount;
|
||||
}
|
||||
|
||||
public int getAlbumCount() {
|
||||
return albumCount;
|
||||
}
|
||||
public int getAlbumCount()
|
||||
{
|
||||
return albumCount;
|
||||
}
|
||||
|
||||
public int getSongCount() {
|
||||
return songCount;
|
||||
}
|
||||
public int getSongCount()
|
||||
{
|
||||
return songCount;
|
||||
}
|
||||
}
|
|
@ -25,27 +25,32 @@ import java.util.List;
|
|||
*
|
||||
* @author Sindre Mehus
|
||||
*/
|
||||
public class SearchResult {
|
||||
public class SearchResult
|
||||
{
|
||||
|
||||
private final List<Artist> artists;
|
||||
private final List<MusicDirectory.Entry> albums;
|
||||
private final List<MusicDirectory.Entry> songs;
|
||||
private final List<Artist> artists;
|
||||
private final List<MusicDirectory.Entry> albums;
|
||||
private final List<MusicDirectory.Entry> songs;
|
||||
|
||||
public SearchResult(List<Artist> artists, List<MusicDirectory.Entry> albums, List<MusicDirectory.Entry> songs) {
|
||||
this.artists = artists;
|
||||
this.albums = albums;
|
||||
this.songs = songs;
|
||||
}
|
||||
public SearchResult(List<Artist> artists, List<MusicDirectory.Entry> albums, List<MusicDirectory.Entry> songs)
|
||||
{
|
||||
this.artists = artists;
|
||||
this.albums = albums;
|
||||
this.songs = songs;
|
||||
}
|
||||
|
||||
public List<Artist> getArtists() {
|
||||
return artists;
|
||||
}
|
||||
public List<Artist> getArtists()
|
||||
{
|
||||
return artists;
|
||||
}
|
||||
|
||||
public List<MusicDirectory.Entry> getAlbums() {
|
||||
return albums;
|
||||
}
|
||||
public List<MusicDirectory.Entry> getAlbums()
|
||||
{
|
||||
return albums;
|
||||
}
|
||||
|
||||
public List<MusicDirectory.Entry> getSongs() {
|
||||
return songs;
|
||||
}
|
||||
public List<MusicDirectory.Entry> getSongs()
|
||||
{
|
||||
return songs;
|
||||
}
|
||||
}
|
|
@ -23,24 +23,29 @@ package com.thejoshwa.ultrasonic.androidapp.domain;
|
|||
*
|
||||
* @author Sindre Mehus
|
||||
*/
|
||||
public class ServerInfo {
|
||||
public class ServerInfo
|
||||
{
|
||||
|
||||
private boolean isLicenseValid;
|
||||
private Version restVersion;
|
||||
private boolean isLicenseValid;
|
||||
private Version restVersion;
|
||||
|
||||
public boolean isLicenseValid() {
|
||||
return isLicenseValid;
|
||||
}
|
||||
public boolean isLicenseValid()
|
||||
{
|
||||
return isLicenseValid;
|
||||
}
|
||||
|
||||
public void setLicenseValid(boolean licenseValid) {
|
||||
isLicenseValid = licenseValid;
|
||||
}
|
||||
public void setLicenseValid(boolean licenseValid)
|
||||
{
|
||||
isLicenseValid = licenseValid;
|
||||
}
|
||||
|
||||
public Version getRestVersion() {
|
||||
return restVersion;
|
||||
}
|
||||
public Version getRestVersion()
|
||||
{
|
||||
return restVersion;
|
||||
}
|
||||
|
||||
public void setRestVersion(Version restVersion) {
|
||||
this.restVersion = restVersion;
|
||||
}
|
||||
public void setRestVersion(Version restVersion)
|
||||
{
|
||||
this.restVersion = restVersion;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,115 +10,153 @@ import java.util.Locale;
|
|||
|
||||
import com.thejoshwa.ultrasonic.androidapp.domain.MusicDirectory.Entry;
|
||||
|
||||
public class Share implements Serializable {
|
||||
public class Share implements Serializable
|
||||
{
|
||||
private static final long serialVersionUID = 1487561657691009668L;
|
||||
private String id;
|
||||
private String url;
|
||||
private String description;
|
||||
private String username;
|
||||
private Date created;
|
||||
private Date lastVisited;
|
||||
private Date expires;
|
||||
private Long visitCount;
|
||||
private List<Entry> entries;
|
||||
|
||||
public Share() {
|
||||
entries = new ArrayList<Entry>();
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
private String url;
|
||||
private String description;
|
||||
private String username;
|
||||
private Date created;
|
||||
private Date lastVisited;
|
||||
private Date expires;
|
||||
private Long visitCount;
|
||||
private List<Entry> entries;
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
public Share()
|
||||
{
|
||||
entries = new ArrayList<Entry>();
|
||||
}
|
||||
|
||||
public void setUrl(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
public String getId()
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
public void setId(String id)
|
||||
{
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public Date getCreated() {
|
||||
return created;
|
||||
}
|
||||
public String getUrl()
|
||||
{
|
||||
return url;
|
||||
}
|
||||
|
||||
public void setCreated(String created) {
|
||||
if (created != null) {
|
||||
try {
|
||||
public void setUrl(String url)
|
||||
{
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public String getDescription()
|
||||
{
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description)
|
||||
{
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String getUsername()
|
||||
{
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(String username)
|
||||
{
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public Date getCreated()
|
||||
{
|
||||
return created;
|
||||
}
|
||||
|
||||
public void setCreated(String created)
|
||||
{
|
||||
if (created != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
this.created = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.ENGLISH).parse(created);
|
||||
} catch (ParseException e) {
|
||||
}
|
||||
catch (ParseException e)
|
||||
{
|
||||
this.created = null;
|
||||
}
|
||||
} else {
|
||||
this.created = null;
|
||||
}
|
||||
}
|
||||
|
||||
public Date getLastVisited() {
|
||||
return lastVisited;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this.created = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void setLastVisited(String lastVisited) {
|
||||
if (lastVisited != null) {
|
||||
try {
|
||||
public Date getLastVisited()
|
||||
{
|
||||
return lastVisited;
|
||||
}
|
||||
|
||||
public void setLastVisited(String lastVisited)
|
||||
{
|
||||
if (lastVisited != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
this.lastVisited = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.ENGLISH).parse(lastVisited);
|
||||
} catch (ParseException e) {
|
||||
}
|
||||
catch (ParseException e)
|
||||
{
|
||||
this.lastVisited = null;
|
||||
}
|
||||
} else {
|
||||
this.lastVisited = null;
|
||||
}
|
||||
}
|
||||
|
||||
public Date getExpires() {
|
||||
return expires;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this.lastVisited = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void setExpires(String expires) {
|
||||
if (expires != null) {
|
||||
try {
|
||||
public Date getExpires()
|
||||
{
|
||||
return expires;
|
||||
}
|
||||
|
||||
public void setExpires(String expires)
|
||||
{
|
||||
if (expires != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
this.expires = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.ENGLISH).parse(expires);
|
||||
} catch (ParseException e) {
|
||||
}
|
||||
catch (ParseException e)
|
||||
{
|
||||
this.expires = null;
|
||||
}
|
||||
} else {
|
||||
this.expires = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this.expires = null;
|
||||
}
|
||||
}
|
||||
|
||||
public Long getVisitCount() {
|
||||
return visitCount;
|
||||
}
|
||||
|
||||
public void setVisitCount(Long visitCount) {
|
||||
this.visitCount = visitCount;
|
||||
}
|
||||
|
||||
public List<Entry> getEntries() {
|
||||
return this.entries;
|
||||
}
|
||||
|
||||
public void addEntry(Entry entry) {
|
||||
entries.add(entry);
|
||||
}
|
||||
}
|
||||
public Long getVisitCount()
|
||||
{
|
||||
return visitCount;
|
||||
}
|
||||
|
||||
public void setVisitCount(Long visitCount)
|
||||
{
|
||||
this.visitCount = visitCount;
|
||||
}
|
||||
|
||||
public List<Entry> getEntries()
|
||||
{
|
||||
return this.entries;
|
||||
}
|
||||
|
||||
public void addEntry(Entry entry)
|
||||
{
|
||||
entries.add(entry);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,124 +18,159 @@
|
|||
*/
|
||||
package com.thejoshwa.ultrasonic.androidapp.domain;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Represents the version number of the Subsonic Android app.
|
||||
*
|
||||
* @author Sindre Mehus
|
||||
* @version $Revision: 1.3 $ $Date: 2006/01/20 21:25:16 $
|
||||
*/
|
||||
public class Version implements Comparable<Version> {
|
||||
private int major;
|
||||
private int minor;
|
||||
private int beta;
|
||||
private int bugfix;
|
||||
public class Version implements Comparable<Version>
|
||||
{
|
||||
private static final Pattern COMPILE = Pattern.compile("\\.");
|
||||
private int major;
|
||||
private int minor;
|
||||
private int beta;
|
||||
private int bugfix;
|
||||
|
||||
/**
|
||||
* Creates a new version instance by parsing the given string.
|
||||
* @param version A string of the format "1.27", "1.27.2" or "1.27.beta3".
|
||||
*/
|
||||
public Version(String version) {
|
||||
String[] s = version.split("\\.");
|
||||
major = Integer.valueOf(s[0]);
|
||||
minor = Integer.valueOf(s[1]);
|
||||
/**
|
||||
* Creates a new version instance by parsing the given string.
|
||||
*
|
||||
* @param version A string of the format "1.27", "1.27.2" or "1.27.beta3".
|
||||
*/
|
||||
public Version(String version)
|
||||
{
|
||||
String[] s = COMPILE.split(version);
|
||||
major = Integer.valueOf(s[0]);
|
||||
minor = Integer.valueOf(s[1]);
|
||||
|
||||
if (s.length > 2) {
|
||||
if (s[2].contains("beta")) {
|
||||
beta = Integer.valueOf(s[2].replace("beta", ""));
|
||||
} else {
|
||||
bugfix = Integer.valueOf(s[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (s.length > 2)
|
||||
{
|
||||
if (s[2].contains("beta"))
|
||||
{
|
||||
beta = Integer.valueOf(s[2].replace("beta", ""));
|
||||
}
|
||||
else
|
||||
{
|
||||
bugfix = Integer.valueOf(s[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int getMajor() {
|
||||
return major;
|
||||
}
|
||||
public int getMajor()
|
||||
{
|
||||
return major;
|
||||
}
|
||||
|
||||
public int getMinor() {
|
||||
return minor;
|
||||
}
|
||||
public int getMinor()
|
||||
{
|
||||
return minor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether this object is equal to another.
|
||||
* @param o Object to compare to.
|
||||
* @return Whether this object is equals to another.
|
||||
*/
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
/**
|
||||
* Return whether this object is equal to another.
|
||||
*
|
||||
* @param o Object to compare to.
|
||||
* @return Whether this object is equals to another.
|
||||
*/
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
final Version version = (Version) o;
|
||||
final Version version = (Version) o;
|
||||
|
||||
if (beta != version.beta) return false;
|
||||
if (bugfix != version.bugfix) return false;
|
||||
return major == version.major && minor == version.minor;
|
||||
}
|
||||
if (beta != version.beta) return false;
|
||||
if (bugfix != version.bugfix) return false;
|
||||
return major == version.major && minor == version.minor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a hash code for this object.
|
||||
* @return A hash code for this object.
|
||||
*/
|
||||
public int hashCode() {
|
||||
int result;
|
||||
result = major;
|
||||
result = 29 * result + minor;
|
||||
result = 29 * result + beta;
|
||||
result = 29 * result + bugfix;
|
||||
return result;
|
||||
}
|
||||
/**
|
||||
* Returns a hash code for this object.
|
||||
*
|
||||
* @return A hash code for this object.
|
||||
*/
|
||||
public int hashCode()
|
||||
{
|
||||
int result;
|
||||
result = major;
|
||||
result = 29 * result + minor;
|
||||
result = 29 * result + beta;
|
||||
result = 29 * result + bugfix;
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of the form "1.27", "1.27.2" or "1.27.beta3".
|
||||
* @return A string representation of the form "1.27", "1.27.2" or "1.27.beta3".
|
||||
*/
|
||||
public String toString() {
|
||||
StringBuffer buf = new StringBuffer();
|
||||
buf.append(major).append('.').append(minor);
|
||||
if (beta != 0) {
|
||||
buf.append(".beta").append(beta);
|
||||
} else if (bugfix != 0) {
|
||||
buf.append('.').append(bugfix);
|
||||
}
|
||||
/**
|
||||
* Returns a string representation of the form "1.27", "1.27.2" or "1.27.beta3".
|
||||
*
|
||||
* @return A string representation of the form "1.27", "1.27.2" or "1.27.beta3".
|
||||
*/
|
||||
public String toString()
|
||||
{
|
||||
StringBuffer buf = new StringBuffer();
|
||||
buf.append(major).append('.').append(minor);
|
||||
if (beta != 0)
|
||||
{
|
||||
buf.append(".beta").append(beta);
|
||||
}
|
||||
else if (bugfix != 0)
|
||||
{
|
||||
buf.append('.').append(bugfix);
|
||||
}
|
||||
|
||||
return buf.toString();
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares this object with the specified object for order.
|
||||
* @param version The object to compare to.
|
||||
* @return A negative integer, zero, or a positive integer as this object is less than, equal to, or
|
||||
* greater than the specified object.
|
||||
*/
|
||||
@Override
|
||||
public int compareTo(Version version) {
|
||||
if (major < version.major) {
|
||||
return -1;
|
||||
} else if (major > version.major) {
|
||||
return 1;
|
||||
}
|
||||
/**
|
||||
* Compares this object with the specified object for order.
|
||||
*
|
||||
* @param version The object to compare to.
|
||||
* @return A negative integer, zero, or a positive integer as this object is less than, equal to, or
|
||||
* greater than the specified object.
|
||||
*/
|
||||
@Override
|
||||
public int compareTo(Version version)
|
||||
{
|
||||
if (major < version.major)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else if (major > version.major)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (minor < version.minor) {
|
||||
return -1;
|
||||
} else if (minor > version.minor) {
|
||||
return 1;
|
||||
}
|
||||
if (minor < version.minor)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else if (minor > version.minor)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (bugfix < version.bugfix) {
|
||||
return -1;
|
||||
} else if (bugfix > version.bugfix) {
|
||||
return 1;
|
||||
}
|
||||
if (bugfix < version.bugfix)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else if (bugfix > version.bugfix)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int thisBeta = beta == 0 ? Integer.MAX_VALUE : beta;
|
||||
int otherBeta = version.beta == 0 ? Integer.MAX_VALUE : version.beta;
|
||||
int thisBeta = beta == 0 ? Integer.MAX_VALUE : beta;
|
||||
int otherBeta = version.beta == 0 ? Integer.MAX_VALUE : version.beta;
|
||||
|
||||
if (thisBeta < otherBeta) {
|
||||
return -1;
|
||||
} else if (thisBeta > otherBeta) {
|
||||
return 1;
|
||||
}
|
||||
if (thisBeta < otherBeta)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else if (thisBeta > otherBeta)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
|
@ -25,12 +25,13 @@ import android.content.SearchRecentSuggestionsProvider;
|
|||
*
|
||||
* @author Sindre Mehus
|
||||
*/
|
||||
public class SearchSuggestionProvider extends SearchRecentSuggestionsProvider {
|
||||
public class SearchSuggestionProvider extends SearchRecentSuggestionsProvider
|
||||
{
|
||||
public static final String AUTHORITY = SearchSuggestionProvider.class.getName();
|
||||
public static final int MODE = DATABASE_MODE_QUERIES;
|
||||
|
||||
public static final String AUTHORITY = SearchSuggestionProvider.class.getName();
|
||||
public static final int MODE = DATABASE_MODE_QUERIES;
|
||||
|
||||
public SearchSuggestionProvider() {
|
||||
setupSuggestions(AUTHORITY, MODE);
|
||||
}
|
||||
public SearchSuggestionProvider()
|
||||
{
|
||||
setupSuggestions(AUTHORITY, MODE);
|
||||
}
|
||||
}
|
|
@ -1,13 +1,5 @@
|
|||
package com.thejoshwa.ultrasonic.androidapp.provider;
|
||||
|
||||
import com.thejoshwa.ultrasonic.androidapp.R;
|
||||
import com.thejoshwa.ultrasonic.androidapp.activity.DownloadActivity;
|
||||
import com.thejoshwa.ultrasonic.androidapp.activity.MainActivity;
|
||||
import com.thejoshwa.ultrasonic.androidapp.domain.MusicDirectory;
|
||||
import com.thejoshwa.ultrasonic.androidapp.service.DownloadService;
|
||||
import com.thejoshwa.ultrasonic.androidapp.service.DownloadServiceImpl;
|
||||
import com.thejoshwa.ultrasonic.androidapp.util.FileUtil;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.appwidget.AppWidgetManager;
|
||||
import android.appwidget.AppWidgetProvider;
|
||||
|
@ -22,172 +14,212 @@ import android.util.Log;
|
|||
import android.view.KeyEvent;
|
||||
import android.widget.RemoteViews;
|
||||
|
||||
public class UltraSonicAppWidgetProvider extends AppWidgetProvider {
|
||||
|
||||
private final static String TAG = UltraSonicAppWidgetProvider.class.getSimpleName();
|
||||
import com.thejoshwa.ultrasonic.androidapp.R;
|
||||
import com.thejoshwa.ultrasonic.androidapp.activity.DownloadActivity;
|
||||
import com.thejoshwa.ultrasonic.androidapp.activity.MainActivity;
|
||||
import com.thejoshwa.ultrasonic.androidapp.domain.MusicDirectory;
|
||||
import com.thejoshwa.ultrasonic.androidapp.service.DownloadService;
|
||||
import com.thejoshwa.ultrasonic.androidapp.service.DownloadServiceImpl;
|
||||
import com.thejoshwa.ultrasonic.androidapp.util.FileUtil;
|
||||
|
||||
public class UltraSonicAppWidgetProvider extends AppWidgetProvider
|
||||
{
|
||||
|
||||
private final static String TAG = UltraSonicAppWidgetProvider.class.getSimpleName();
|
||||
protected int layoutId;
|
||||
|
||||
|
||||
@Override
|
||||
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
|
||||
defaultAppWidget(context, appWidgetIds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize given widgets to default state, where we launch UltraSonic on default click
|
||||
* and hide actions if service not running.
|
||||
*/
|
||||
private void defaultAppWidget(Context context, int[] appWidgetIds) {
|
||||
final Resources res = context.getResources();
|
||||
final RemoteViews views = new RemoteViews(context.getPackageName(), this.layoutId);
|
||||
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds)
|
||||
{
|
||||
defaultAppWidget(context, appWidgetIds);
|
||||
}
|
||||
|
||||
views.setTextViewText(R.id.artist, res.getText(R.string.widget_initial_text));
|
||||
|
||||
linkButtons(context, views, false);
|
||||
pushUpdate(context, appWidgetIds, views);
|
||||
}
|
||||
|
||||
private void pushUpdate(Context context, int[] appWidgetIds, RemoteViews views) {
|
||||
// Update specific list of appWidgetIds if given, otherwise default to all
|
||||
final AppWidgetManager manager = AppWidgetManager.getInstance(context);
|
||||
/**
|
||||
* Initialize given widgets to default state, where we launch UltraSonic on default click
|
||||
* and hide actions if service not running.
|
||||
*/
|
||||
private void defaultAppWidget(Context context, int[] appWidgetIds)
|
||||
{
|
||||
final Resources res = context.getResources();
|
||||
final RemoteViews views = new RemoteViews(context.getPackageName(), this.layoutId);
|
||||
|
||||
if (manager != null) {
|
||||
if (appWidgetIds != null) {
|
||||
manager.updateAppWidget(appWidgetIds, views);
|
||||
} else {
|
||||
manager.updateAppWidget(new ComponentName(context, this.getClass()), views);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a change notification coming over from {@link DownloadService}
|
||||
*/
|
||||
public void notifyChange(Context context, DownloadService service, boolean playing, boolean setAlbum) {
|
||||
if (hasInstances(context)) {
|
||||
performUpdate(context, service, null, playing, setAlbum);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check against {@link AppWidgetManager} if there are any instances of this widget.
|
||||
*/
|
||||
private boolean hasInstances(Context context) {
|
||||
AppWidgetManager manager = AppWidgetManager.getInstance(context);
|
||||
int[] appWidgetIds = new int[0];
|
||||
views.setTextViewText(R.id.artist, res.getText(R.string.widget_initial_text));
|
||||
|
||||
if (manager != null) {
|
||||
appWidgetIds = manager.getAppWidgetIds(new ComponentName(context, getClass()));
|
||||
}
|
||||
linkButtons(context, views, false);
|
||||
pushUpdate(context, appWidgetIds, views);
|
||||
}
|
||||
|
||||
return (appWidgetIds.length > 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update all active widget instances by pushing changes
|
||||
*/
|
||||
private void performUpdate(Context context, DownloadService service, int[] appWidgetIds, boolean playing, boolean setAlbum) {
|
||||
final Resources res = context.getResources();
|
||||
final RemoteViews views = new RemoteViews(context.getPackageName(), this.layoutId);
|
||||
private void pushUpdate(Context context, int[] appWidgetIds, RemoteViews views)
|
||||
{
|
||||
// Update specific list of appWidgetIds if given, otherwise default to all
|
||||
final AppWidgetManager manager = AppWidgetManager.getInstance(context);
|
||||
|
||||
MusicDirectory.Entry currentPlaying = service.getCurrentPlaying() == null ? null : service.getCurrentPlaying().getSong();
|
||||
String title = currentPlaying == null ? null : currentPlaying.getTitle();
|
||||
String artist = currentPlaying == null ? null : currentPlaying.getArtist();
|
||||
String album = currentPlaying == null ? null : currentPlaying.getAlbum();
|
||||
CharSequence errorState = null;
|
||||
if (manager != null)
|
||||
{
|
||||
if (appWidgetIds != null)
|
||||
{
|
||||
manager.updateAppWidget(appWidgetIds, views);
|
||||
}
|
||||
else
|
||||
{
|
||||
manager.updateAppWidget(new ComponentName(context, this.getClass()), views);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Show error message?
|
||||
String status = Environment.getExternalStorageState();
|
||||
if (status.equals(Environment.MEDIA_SHARED) ||
|
||||
status.equals(Environment.MEDIA_UNMOUNTED)) {
|
||||
errorState = res.getText(R.string.widget_sdcard_busy);
|
||||
} else if (status.equals(Environment.MEDIA_REMOVED)) {
|
||||
errorState = res.getText(R.string.widget_sdcard_missing);
|
||||
} else if (currentPlaying == null) {
|
||||
errorState = res.getText(R.string.widget_initial_text);
|
||||
}
|
||||
/**
|
||||
* Handle a change notification coming over from {@link DownloadService}
|
||||
*/
|
||||
public void notifyChange(Context context, DownloadService service, boolean playing, boolean setAlbum)
|
||||
{
|
||||
if (hasInstances(context))
|
||||
{
|
||||
performUpdate(context, service, null, playing, setAlbum);
|
||||
}
|
||||
}
|
||||
|
||||
if (errorState != null) {
|
||||
// Show error state to user
|
||||
views.setTextViewText(R.id.title, null);
|
||||
views.setTextViewText(R.id.artist, errorState);
|
||||
if (setAlbum) {
|
||||
views.setTextViewText(R.id.album, null);
|
||||
}
|
||||
views.setImageViewResource(R.id.appwidget_coverart, R.drawable.appwidget_art_default);
|
||||
} else {
|
||||
// No error, so show normal titles
|
||||
views.setTextViewText(R.id.title, title);
|
||||
views.setTextViewText(R.id.artist, artist);
|
||||
if (setAlbum) {
|
||||
views.setTextViewText(R.id.album, album);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Check against {@link AppWidgetManager} if there are any instances of this widget.
|
||||
*/
|
||||
private boolean hasInstances(Context context)
|
||||
{
|
||||
AppWidgetManager manager = AppWidgetManager.getInstance(context);
|
||||
int[] appWidgetIds = new int[0];
|
||||
|
||||
// Set correct drawable for pause state
|
||||
if (playing) {
|
||||
views.setImageViewResource(R.id.control_play, R.drawable.media_pause_normal_dark);
|
||||
} else {
|
||||
views.setImageViewResource(R.id.control_play, R.drawable.media_start_normal_dark);
|
||||
}
|
||||
if (manager != null)
|
||||
{
|
||||
appWidgetIds = manager.getAppWidgetIds(new ComponentName(context, getClass()));
|
||||
}
|
||||
|
||||
// Set the cover art
|
||||
try {
|
||||
int size;
|
||||
Resources resources = context.getResources();
|
||||
Drawable drawable = resources.getDrawable(R.drawable.appwidget_art_default);
|
||||
size = drawable != null ? drawable.getIntrinsicHeight() : 0;
|
||||
return (appWidgetIds.length > 0);
|
||||
}
|
||||
|
||||
Bitmap bitmap = currentPlaying == null ? null : FileUtil.getAlbumArtBitmap(context, currentPlaying, size, true);
|
||||
/**
|
||||
* Update all active widget instances by pushing changes
|
||||
*/
|
||||
private void performUpdate(Context context, DownloadService service, int[] appWidgetIds, boolean playing, boolean setAlbum)
|
||||
{
|
||||
final Resources res = context.getResources();
|
||||
final RemoteViews views = new RemoteViews(context.getPackageName(), this.layoutId);
|
||||
|
||||
if (bitmap == null) {
|
||||
// Set default cover art
|
||||
views.setImageViewResource(R.id.appwidget_coverart, R.drawable.appwidget_art_default);
|
||||
} else {
|
||||
//bitmap = getRoundedCornerBitmap(bitmap);
|
||||
views.setImageViewBitmap(R.id.appwidget_coverart, bitmap);
|
||||
}
|
||||
} catch (Exception x) {
|
||||
Log.e(TAG, "Failed to load cover art", x);
|
||||
views.setImageViewResource(R.id.appwidget_coverart, R.drawable.appwidget_art_default);
|
||||
}
|
||||
MusicDirectory.Entry currentPlaying = service.getCurrentPlaying() == null ? null : service.getCurrentPlaying().getSong();
|
||||
String title = currentPlaying == null ? null : currentPlaying.getTitle();
|
||||
String artist = currentPlaying == null ? null : currentPlaying.getArtist();
|
||||
String album = currentPlaying == null ? null : currentPlaying.getAlbum();
|
||||
CharSequence errorState = null;
|
||||
|
||||
// Link actions buttons to intents
|
||||
linkButtons(context, views, currentPlaying != null);
|
||||
// Show error message?
|
||||
String status = Environment.getExternalStorageState();
|
||||
if (status.equals(Environment.MEDIA_SHARED) || status.equals(Environment.MEDIA_UNMOUNTED))
|
||||
{
|
||||
errorState = res.getText(R.string.widget_sdcard_busy);
|
||||
}
|
||||
else if (status.equals(Environment.MEDIA_REMOVED))
|
||||
{
|
||||
errorState = res.getText(R.string.widget_sdcard_missing);
|
||||
}
|
||||
else if (currentPlaying == null)
|
||||
{
|
||||
errorState = res.getText(R.string.widget_initial_text);
|
||||
}
|
||||
|
||||
pushUpdate(context, appWidgetIds, views);
|
||||
}
|
||||
|
||||
/**
|
||||
* Link up various button actions using {@link PendingIntent}.
|
||||
*
|
||||
* @param playerActive True if player is active in background, which means
|
||||
* widget click will launch {@link DownloadActivity},
|
||||
* otherwise we launch {@link MainActivity}.
|
||||
*/
|
||||
private void linkButtons(Context context, RemoteViews views, boolean playerActive) {
|
||||
if (errorState != null)
|
||||
{
|
||||
// Show error state to user
|
||||
views.setTextViewText(R.id.title, null);
|
||||
views.setTextViewText(R.id.artist, errorState);
|
||||
if (setAlbum)
|
||||
{
|
||||
views.setTextViewText(R.id.album, null);
|
||||
}
|
||||
views.setImageViewResource(R.id.appwidget_coverart, R.drawable.appwidget_art_default);
|
||||
}
|
||||
else
|
||||
{
|
||||
// No error, so show normal titles
|
||||
views.setTextViewText(R.id.title, title);
|
||||
views.setTextViewText(R.id.artist, artist);
|
||||
if (setAlbum)
|
||||
{
|
||||
views.setTextViewText(R.id.album, album);
|
||||
}
|
||||
}
|
||||
|
||||
Intent intent = new Intent(context, playerActive ? DownloadActivity.class : MainActivity.class);
|
||||
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
|
||||
views.setOnClickPendingIntent(R.id.appwidget_coverart, pendingIntent);
|
||||
views.setOnClickPendingIntent(R.id.appwidget_top, pendingIntent);
|
||||
|
||||
// Emulate media button clicks.
|
||||
intent = new Intent("1");
|
||||
intent.setComponent(new ComponentName(context, DownloadServiceImpl.class));
|
||||
intent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE));
|
||||
pendingIntent = PendingIntent.getService(context, 0, intent, 0);
|
||||
views.setOnClickPendingIntent(R.id.control_play, pendingIntent);
|
||||
// Set correct drawable for pause state
|
||||
if (playing)
|
||||
{
|
||||
views.setImageViewResource(R.id.control_play, R.drawable.media_pause_normal_dark);
|
||||
}
|
||||
else
|
||||
{
|
||||
views.setImageViewResource(R.id.control_play, R.drawable.media_start_normal_dark);
|
||||
}
|
||||
|
||||
intent = new Intent("2"); // Use a unique action name to ensure a different PendingIntent to be created.
|
||||
intent.setComponent(new ComponentName(context, DownloadServiceImpl.class));
|
||||
intent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_NEXT));
|
||||
pendingIntent = PendingIntent.getService(context, 0, intent, 0);
|
||||
views.setOnClickPendingIntent(R.id.control_next, pendingIntent);
|
||||
|
||||
intent = new Intent("3"); // Use a unique action name to ensure a different PendingIntent to be created.
|
||||
intent.setComponent(new ComponentName(context, DownloadServiceImpl.class));
|
||||
intent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_PREVIOUS));
|
||||
pendingIntent = PendingIntent.getService(context, 0, intent, 0);
|
||||
views.setOnClickPendingIntent(R.id.control_previous, pendingIntent);
|
||||
}
|
||||
// Set the cover art
|
||||
try
|
||||
{
|
||||
int size;
|
||||
Resources resources = context.getResources();
|
||||
Drawable drawable = resources.getDrawable(R.drawable.appwidget_art_default);
|
||||
size = drawable != null ? drawable.getIntrinsicHeight() : 0;
|
||||
|
||||
Bitmap bitmap = currentPlaying == null ? null : FileUtil.getAlbumArtBitmap(context, currentPlaying, size, true);
|
||||
|
||||
if (bitmap == null)
|
||||
{
|
||||
// Set default cover art
|
||||
views.setImageViewResource(R.id.appwidget_coverart, R.drawable.appwidget_art_default);
|
||||
}
|
||||
else
|
||||
{
|
||||
//bitmap = getRoundedCornerBitmap(bitmap);
|
||||
views.setImageViewBitmap(R.id.appwidget_coverart, bitmap);
|
||||
}
|
||||
}
|
||||
catch (Exception x)
|
||||
{
|
||||
Log.e(TAG, "Failed to load cover art", x);
|
||||
views.setImageViewResource(R.id.appwidget_coverart, R.drawable.appwidget_art_default);
|
||||
}
|
||||
|
||||
// Link actions buttons to intents
|
||||
linkButtons(context, views, currentPlaying != null);
|
||||
|
||||
pushUpdate(context, appWidgetIds, views);
|
||||
}
|
||||
|
||||
/**
|
||||
* Link up various button actions using {@link PendingIntent}.
|
||||
*
|
||||
* @param playerActive True if player is active in background, which means
|
||||
* widget click will launch {@link DownloadActivity},
|
||||
* otherwise we launch {@link MainActivity}.
|
||||
*/
|
||||
private static void linkButtons(Context context, RemoteViews views, boolean playerActive)
|
||||
{
|
||||
|
||||
Intent intent = new Intent(context, playerActive ? DownloadActivity.class : MainActivity.class);
|
||||
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
|
||||
views.setOnClickPendingIntent(R.id.appwidget_coverart, pendingIntent);
|
||||
views.setOnClickPendingIntent(R.id.appwidget_top, pendingIntent);
|
||||
|
||||
// Emulate media button clicks.
|
||||
intent = new Intent("1");
|
||||
intent.setComponent(new ComponentName(context, DownloadServiceImpl.class));
|
||||
intent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE));
|
||||
pendingIntent = PendingIntent.getService(context, 0, intent, 0);
|
||||
views.setOnClickPendingIntent(R.id.control_play, pendingIntent);
|
||||
|
||||
intent = new Intent("2"); // Use a unique action name to ensure a different PendingIntent to be created.
|
||||
intent.setComponent(new ComponentName(context, DownloadServiceImpl.class));
|
||||
intent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_NEXT));
|
||||
pendingIntent = PendingIntent.getService(context, 0, intent, 0);
|
||||
views.setOnClickPendingIntent(R.id.control_next, pendingIntent);
|
||||
|
||||
intent = new Intent("3"); // Use a unique action name to ensure a different PendingIntent to be created.
|
||||
intent.setComponent(new ComponentName(context, DownloadServiceImpl.class));
|
||||
intent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_PREVIOUS));
|
||||
pendingIntent = PendingIntent.getService(context, 0, intent, 0);
|
||||
views.setOnClickPendingIntent(R.id.control_previous, pendingIntent);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,19 +20,23 @@ package com.thejoshwa.ultrasonic.androidapp.provider;
|
|||
|
||||
import com.thejoshwa.ultrasonic.androidapp.R;
|
||||
|
||||
public class UltraSonicAppWidgetProvider4x1 extends UltraSonicAppWidgetProvider {
|
||||
public class UltraSonicAppWidgetProvider4x1 extends UltraSonicAppWidgetProvider
|
||||
{
|
||||
|
||||
public UltraSonicAppWidgetProvider4x1() {
|
||||
public UltraSonicAppWidgetProvider4x1()
|
||||
{
|
||||
super();
|
||||
this.layoutId = R.layout.appwidget4x1;
|
||||
}
|
||||
|
||||
private static UltraSonicAppWidgetProvider4x1 instance;
|
||||
|
||||
public static synchronized UltraSonicAppWidgetProvider4x1 getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new UltraSonicAppWidgetProvider4x1();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
public static synchronized UltraSonicAppWidgetProvider4x1 getInstance()
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
instance = new UltraSonicAppWidgetProvider4x1();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,19 +20,23 @@ package com.thejoshwa.ultrasonic.androidapp.provider;
|
|||
|
||||
import com.thejoshwa.ultrasonic.androidapp.R;
|
||||
|
||||
public class UltraSonicAppWidgetProvider4x2 extends UltraSonicAppWidgetProvider {
|
||||
public class UltraSonicAppWidgetProvider4x2 extends UltraSonicAppWidgetProvider
|
||||
{
|
||||
|
||||
public UltraSonicAppWidgetProvider4x2() {
|
||||
public UltraSonicAppWidgetProvider4x2()
|
||||
{
|
||||
super();
|
||||
this.layoutId = R.layout.appwidget4x2;
|
||||
}
|
||||
|
||||
private static UltraSonicAppWidgetProvider4x2 instance;
|
||||
|
||||
public static synchronized UltraSonicAppWidgetProvider4x2 getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new UltraSonicAppWidgetProvider4x2();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
public static synchronized UltraSonicAppWidgetProvider4x2 getInstance()
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
instance = new UltraSonicAppWidgetProvider4x2();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,19 +20,23 @@ package com.thejoshwa.ultrasonic.androidapp.provider;
|
|||
|
||||
import com.thejoshwa.ultrasonic.androidapp.R;
|
||||
|
||||
public class UltraSonicAppWidgetProvider4x3 extends UltraSonicAppWidgetProvider {
|
||||
public class UltraSonicAppWidgetProvider4x3 extends UltraSonicAppWidgetProvider
|
||||
{
|
||||
|
||||
public UltraSonicAppWidgetProvider4x3() {
|
||||
public UltraSonicAppWidgetProvider4x3()
|
||||
{
|
||||
super();
|
||||
this.layoutId = R.layout.appwidget4x3;
|
||||
}
|
||||
|
||||
private static UltraSonicAppWidgetProvider4x3 instance;
|
||||
|
||||
public static synchronized UltraSonicAppWidgetProvider4x3 getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new UltraSonicAppWidgetProvider4x3();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
public static synchronized UltraSonicAppWidgetProvider4x3 getInstance()
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
instance = new UltraSonicAppWidgetProvider4x3();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,19 +20,23 @@ package com.thejoshwa.ultrasonic.androidapp.provider;
|
|||
|
||||
import com.thejoshwa.ultrasonic.androidapp.R;
|
||||
|
||||
public class UltraSonicAppWidgetProvider4x4 extends UltraSonicAppWidgetProvider {
|
||||
public class UltraSonicAppWidgetProvider4x4 extends UltraSonicAppWidgetProvider
|
||||
{
|
||||
|
||||
public UltraSonicAppWidgetProvider4x4() {
|
||||
public UltraSonicAppWidgetProvider4x4()
|
||||
{
|
||||
super();
|
||||
this.layoutId = R.layout.appwidget4x4;
|
||||
}
|
||||
|
||||
private static UltraSonicAppWidgetProvider4x4 instance;
|
||||
|
||||
public static synchronized UltraSonicAppWidgetProvider4x4 getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new UltraSonicAppWidgetProvider4x4();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
public static synchronized UltraSonicAppWidgetProvider4x4 getInstance()
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
instance = new UltraSonicAppWidgetProvider4x4();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,32 +1,38 @@
|
|||
package com.thejoshwa.ultrasonic.androidapp.receiver;
|
||||
|
||||
import com.thejoshwa.ultrasonic.androidapp.domain.MusicDirectory.Entry;
|
||||
import com.thejoshwa.ultrasonic.androidapp.service.DownloadService;
|
||||
import com.thejoshwa.ultrasonic.androidapp.service.DownloadServiceImpl;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
public class A2dpIntentReceiver extends BroadcastReceiver {
|
||||
import com.thejoshwa.ultrasonic.androidapp.domain.MusicDirectory.Entry;
|
||||
import com.thejoshwa.ultrasonic.androidapp.service.DownloadService;
|
||||
import com.thejoshwa.ultrasonic.androidapp.service.DownloadServiceImpl;
|
||||
|
||||
public class A2dpIntentReceiver extends BroadcastReceiver
|
||||
{
|
||||
|
||||
private static final String PLAYSTATUS_RESPONSE = "com.android.music.playstatusresponse";
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
public void onReceive(Context context, Intent intent)
|
||||
{
|
||||
|
||||
DownloadService downloadService = DownloadServiceImpl.getInstance();
|
||||
|
||||
if (downloadService == null) {
|
||||
if (downloadService == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (downloadService.getCurrentPlaying() == null) {
|
||||
if (downloadService.getCurrentPlaying() == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Entry song = downloadService.getCurrentPlaying().getSong();
|
||||
|
||||
if (song == null) {
|
||||
if (song == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -36,30 +42,32 @@ public class A2dpIntentReceiver extends BroadcastReceiver {
|
|||
Integer playerPosition = downloadService.getPlayerPosition();
|
||||
Integer listSize = downloadService.getDownloads().size();
|
||||
|
||||
if (duration != null) {
|
||||
if (duration != null)
|
||||
{
|
||||
avrcpIntent.putExtra("duration", (long) duration);
|
||||
}
|
||||
|
||||
avrcpIntent.putExtra("position", (long) playerPosition);
|
||||
avrcpIntent.putExtra("ListSize", (long) listSize);
|
||||
avrcpIntent.putExtra("position", (long) playerPosition);
|
||||
avrcpIntent.putExtra("ListSize", (long) listSize);
|
||||
|
||||
switch (downloadService.getPlayerState()) {
|
||||
case STARTED:
|
||||
avrcpIntent.putExtra("playing", true);
|
||||
break;
|
||||
case STOPPED:
|
||||
avrcpIntent.putExtra("playing", false);
|
||||
break;
|
||||
case PAUSED:
|
||||
avrcpIntent.putExtra("playing", false);
|
||||
break;
|
||||
case COMPLETED:
|
||||
avrcpIntent.putExtra("playing", false);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
switch (downloadService.getPlayerState())
|
||||
{
|
||||
case STARTED:
|
||||
avrcpIntent.putExtra("playing", true);
|
||||
break;
|
||||
case STOPPED:
|
||||
avrcpIntent.putExtra("playing", false);
|
||||
break;
|
||||
case PAUSED:
|
||||
avrcpIntent.putExtra("playing", false);
|
||||
break;
|
||||
case COMPLETED:
|
||||
avrcpIntent.putExtra("playing", false);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
context.sendBroadcast(avrcpIntent);
|
||||
}
|
||||
}
|
|
@ -22,45 +22,55 @@ import android.content.BroadcastReceiver;
|
|||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.util.Log;
|
||||
|
||||
import com.thejoshwa.ultrasonic.androidapp.service.DownloadServiceImpl;
|
||||
import com.thejoshwa.ultrasonic.androidapp.util.Util;
|
||||
|
||||
/**
|
||||
* Request media button focus when connected to Bluetooth A2DP.
|
||||
*
|
||||
*
|
||||
* @author Sindre Mehus
|
||||
*/
|
||||
public class BluetoothIntentReceiver extends BroadcastReceiver {
|
||||
public class BluetoothIntentReceiver extends BroadcastReceiver
|
||||
{
|
||||
|
||||
private static final String TAG = BluetoothIntentReceiver.class.getSimpleName();
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
public void onReceive(Context context, Intent intent)
|
||||
{
|
||||
int state = intent.getIntExtra("android.bluetooth.a2dp.extra.SINK_STATE", -1);
|
||||
String action = intent.getAction();
|
||||
|
||||
Log.d(TAG, "Bluetooth Sink State: " + state);
|
||||
Log.d(TAG, "Bluetooth Action: " + action);
|
||||
|
||||
boolean actionConnected = false;
|
||||
boolean actionDisconnected = false;
|
||||
boolean actionConnected = false;
|
||||
boolean actionDisconnected = false;
|
||||
|
||||
if (action != null) {
|
||||
if (action.equals(android.bluetooth.BluetoothDevice.ACTION_ACL_CONNECTED)) {
|
||||
actionConnected = true;
|
||||
if (action != null)
|
||||
{
|
||||
if (action.equals(android.bluetooth.BluetoothDevice.ACTION_ACL_CONNECTED))
|
||||
{
|
||||
actionConnected = true;
|
||||
|
||||
} else if (action.equals(android.bluetooth.BluetoothDevice.ACTION_ACL_DISCONNECTED) || action.equals(android.bluetooth.BluetoothDevice.ACTION_ACL_DISCONNECT_REQUESTED)) {
|
||||
actionDisconnected = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (action.equals(android.bluetooth.BluetoothDevice.ACTION_ACL_DISCONNECTED) || action.equals(android.bluetooth.BluetoothDevice.ACTION_ACL_DISCONNECT_REQUESTED))
|
||||
{
|
||||
actionDisconnected = true;
|
||||
}
|
||||
}
|
||||
|
||||
boolean connected = state == android.bluetooth.BluetoothA2dp.STATE_CONNECTED || actionConnected;
|
||||
boolean disconnected = state == android.bluetooth.BluetoothA2dp.STATE_DISCONNECTED || actionDisconnected;
|
||||
|
||||
if (connected) {
|
||||
if (connected)
|
||||
{
|
||||
Log.i(TAG, "Connected to Bluetooth A2DP, requesting media button focus.");
|
||||
Util.registerMediaButtonEventReceiver(context);
|
||||
} else if (disconnected) {
|
||||
}
|
||||
else if (disconnected)
|
||||
{
|
||||
Log.i(TAG, "Disconnected from Bluetooth A2DP, requesting pause.");
|
||||
context.sendBroadcast(new Intent(DownloadServiceImpl.CMD_PAUSE));
|
||||
}
|
||||
|
|
|
@ -24,44 +24,52 @@ import android.content.Intent;
|
|||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.KeyEvent;
|
||||
|
||||
import com.thejoshwa.ultrasonic.androidapp.service.DownloadServiceImpl;
|
||||
import com.thejoshwa.ultrasonic.androidapp.util.Util;
|
||||
|
||||
/**
|
||||
* @author Sindre Mehus
|
||||
*/
|
||||
public class MediaButtonIntentReceiver extends BroadcastReceiver {
|
||||
public class MediaButtonIntentReceiver extends BroadcastReceiver
|
||||
{
|
||||
|
||||
private static final String TAG = MediaButtonIntentReceiver.class.getSimpleName();
|
||||
private static final String TAG = MediaButtonIntentReceiver.class.getSimpleName();
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (Util.getMediaButtonsPreference(context)) {
|
||||
String intentAction = intent.getAction();
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent)
|
||||
{
|
||||
if (Util.getMediaButtonsPreference(context))
|
||||
{
|
||||
String intentAction = intent.getAction();
|
||||
|
||||
if (!Intent.ACTION_MEDIA_BUTTON.equals(intentAction))
|
||||
return;
|
||||
if (!Intent.ACTION_MEDIA_BUTTON.equals(intentAction)) return;
|
||||
|
||||
Bundle extras = intent.getExtras();
|
||||
Bundle extras = intent.getExtras();
|
||||
|
||||
if (extras == null) {
|
||||
return;
|
||||
}
|
||||
if (extras == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
KeyEvent event = (KeyEvent) extras.get(Intent.EXTRA_KEY_EVENT);
|
||||
Log.i(TAG, "Got MEDIA_BUTTON key event: " + event);
|
||||
KeyEvent event = (KeyEvent) extras.get(Intent.EXTRA_KEY_EVENT);
|
||||
Log.i(TAG, "Got MEDIA_BUTTON key event: " + event);
|
||||
|
||||
Intent serviceIntent = new Intent(context, DownloadServiceImpl.class);
|
||||
serviceIntent.putExtra(Intent.EXTRA_KEY_EVENT, event);
|
||||
context.startService(serviceIntent);
|
||||
Intent serviceIntent = new Intent(context, DownloadServiceImpl.class);
|
||||
serviceIntent.putExtra(Intent.EXTRA_KEY_EVENT, event);
|
||||
context.startService(serviceIntent);
|
||||
|
||||
try {
|
||||
if (isOrderedBroadcast()) {
|
||||
abortBroadcast();
|
||||
}
|
||||
} catch (Exception x) {
|
||||
// Ignored.
|
||||
}
|
||||
}
|
||||
}
|
||||
try
|
||||
{
|
||||
if (isOrderedBroadcast())
|
||||
{
|
||||
abortBroadcast();
|
||||
}
|
||||
}
|
||||
catch (Exception x)
|
||||
{
|
||||
// Ignored.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,11 +18,6 @@
|
|||
*/
|
||||
package com.thejoshwa.ultrasonic.androidapp.service;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.apache.http.HttpResponse;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
|
||||
|
@ -46,359 +41,427 @@ import com.thejoshwa.ultrasonic.androidapp.util.ProgressListener;
|
|||
import com.thejoshwa.ultrasonic.androidapp.util.TimeLimitedCache;
|
||||
import com.thejoshwa.ultrasonic.androidapp.util.Util;
|
||||
|
||||
import org.apache.http.HttpResponse;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* @author Sindre Mehus
|
||||
*/
|
||||
public class CachedMusicService implements MusicService {
|
||||
public class CachedMusicService implements MusicService
|
||||
{
|
||||
|
||||
private static final int MUSIC_DIR_CACHE_SIZE = 100;
|
||||
private static final int MUSIC_DIR_CACHE_SIZE = 100;
|
||||
|
||||
private final MusicService musicService;
|
||||
private final LRUCache<String, TimeLimitedCache<MusicDirectory>> cachedMusicDirectories;
|
||||
private final LRUCache<String, TimeLimitedCache<MusicDirectory>> cachedArtist;
|
||||
private final LRUCache<String, TimeLimitedCache<MusicDirectory>> cachedAlbum;
|
||||
private final TimeLimitedCache<Boolean> cachedLicenseValid = new TimeLimitedCache<Boolean>(120, TimeUnit.SECONDS);
|
||||
private final TimeLimitedCache<Indexes> cachedIndexes = new TimeLimitedCache<Indexes>(60 * 60, TimeUnit.SECONDS);
|
||||
private final TimeLimitedCache<Indexes> cachedArtists = new TimeLimitedCache<Indexes>(60 * 60, TimeUnit.SECONDS);
|
||||
private final TimeLimitedCache<List<Playlist>> cachedPlaylists = new TimeLimitedCache<List<Playlist>>(3600, TimeUnit.SECONDS);
|
||||
private final TimeLimitedCache<List<MusicFolder>> cachedMusicFolders = new TimeLimitedCache<List<MusicFolder>>(10 * 3600, TimeUnit.SECONDS);
|
||||
private final TimeLimitedCache<List<Genre>> cachedGenres = new TimeLimitedCache<List<Genre>>(10 * 3600, TimeUnit.SECONDS);
|
||||
|
||||
private String restUrl;
|
||||
private final MusicService musicService;
|
||||
private final LRUCache<String, TimeLimitedCache<MusicDirectory>> cachedMusicDirectories;
|
||||
private final LRUCache<String, TimeLimitedCache<MusicDirectory>> cachedArtist;
|
||||
private final LRUCache<String, TimeLimitedCache<MusicDirectory>> cachedAlbum;
|
||||
private final TimeLimitedCache<Boolean> cachedLicenseValid = new TimeLimitedCache<Boolean>(120, TimeUnit.SECONDS);
|
||||
private final TimeLimitedCache<Indexes> cachedIndexes = new TimeLimitedCache<Indexes>(60 * 60, TimeUnit.SECONDS);
|
||||
private final TimeLimitedCache<Indexes> cachedArtists = new TimeLimitedCache<Indexes>(60 * 60, TimeUnit.SECONDS);
|
||||
private final TimeLimitedCache<List<Playlist>> cachedPlaylists = new TimeLimitedCache<List<Playlist>>(3600, TimeUnit.SECONDS);
|
||||
private final TimeLimitedCache<List<MusicFolder>> cachedMusicFolders = new TimeLimitedCache<List<MusicFolder>>(10 * 3600, TimeUnit.SECONDS);
|
||||
private final TimeLimitedCache<List<Genre>> cachedGenres = new TimeLimitedCache<List<Genre>>(10 * 3600, TimeUnit.SECONDS);
|
||||
|
||||
public CachedMusicService(MusicService musicService) {
|
||||
this.musicService = musicService;
|
||||
cachedMusicDirectories = new LRUCache<String, TimeLimitedCache<MusicDirectory>>(MUSIC_DIR_CACHE_SIZE);
|
||||
cachedArtist = new LRUCache<String, TimeLimitedCache<MusicDirectory>>(MUSIC_DIR_CACHE_SIZE);
|
||||
cachedAlbum = new LRUCache<String, TimeLimitedCache<MusicDirectory>>(MUSIC_DIR_CACHE_SIZE);
|
||||
}
|
||||
private String restUrl;
|
||||
|
||||
@Override
|
||||
public void ping(Context context, ProgressListener progressListener) throws Exception {
|
||||
checkSettingsChanged(context);
|
||||
musicService.ping(context, progressListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLicenseValid(Context context, ProgressListener progressListener) throws Exception {
|
||||
checkSettingsChanged(context);
|
||||
Boolean result = cachedLicenseValid.get();
|
||||
if (result == null) {
|
||||
result = musicService.isLicenseValid(context, progressListener);
|
||||
cachedLicenseValid.set(result, result ? 30L * 60L : 2L * 60L, TimeUnit.SECONDS);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MusicFolder> getMusicFolders(boolean refresh, Context context, ProgressListener progressListener) throws Exception {
|
||||
checkSettingsChanged(context);
|
||||
if (refresh) {
|
||||
cachedMusicFolders.clear();
|
||||
}
|
||||
List<MusicFolder> result = cachedMusicFolders.get();
|
||||
if (result == null) {
|
||||
result = musicService.getMusicFolders(refresh, context, progressListener);
|
||||
cachedMusicFolders.set(result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Indexes getIndexes(String musicFolderId, boolean refresh, Context context, ProgressListener progressListener) throws Exception {
|
||||
checkSettingsChanged(context);
|
||||
if (refresh) {
|
||||
cachedIndexes.clear();
|
||||
cachedMusicFolders.clear();
|
||||
cachedMusicDirectories.clear();
|
||||
}
|
||||
Indexes result = cachedIndexes.get();
|
||||
if (result == null) {
|
||||
result = musicService.getIndexes(musicFolderId, refresh, context, progressListener);
|
||||
cachedIndexes.set(result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Indexes getArtists(boolean refresh, Context context, ProgressListener progressListener) throws Exception {
|
||||
checkSettingsChanged(context);
|
||||
if (refresh) {
|
||||
cachedArtists.clear();
|
||||
}
|
||||
Indexes result = cachedArtists.get();
|
||||
if (result == null) {
|
||||
result = musicService.getArtists(refresh, context, progressListener);
|
||||
cachedArtists.set(result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MusicDirectory getMusicDirectory(String id, String name, boolean refresh, Context context, ProgressListener progressListener) throws Exception {
|
||||
checkSettingsChanged(context);
|
||||
TimeLimitedCache<MusicDirectory> cache = refresh ? null : cachedMusicDirectories.get(id);
|
||||
|
||||
MusicDirectory dir = cache == null ? null : cache.get();
|
||||
|
||||
if (dir == null) {
|
||||
dir = musicService.getMusicDirectory(id, name, refresh, context, progressListener);
|
||||
cache = new TimeLimitedCache<MusicDirectory>(Util.getDirectoryCacheTime(context), TimeUnit.SECONDS);
|
||||
cache.set(dir);
|
||||
cachedMusicDirectories.put(id, cache);
|
||||
}
|
||||
return dir;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MusicDirectory getArtist(String id, String name, boolean refresh, Context context, ProgressListener progressListener) throws Exception {
|
||||
checkSettingsChanged(context);
|
||||
TimeLimitedCache<MusicDirectory> cache = refresh ? null : cachedArtist.get(id);
|
||||
MusicDirectory dir = cache == null ? null : cache.get();
|
||||
if (dir == null) {
|
||||
dir = musicService.getArtist(id, name, refresh, context, progressListener);
|
||||
cache = new TimeLimitedCache<MusicDirectory>(Util.getDirectoryCacheTime(context), TimeUnit.SECONDS);
|
||||
cache.set(dir);
|
||||
cachedArtist.put(id, cache);
|
||||
}
|
||||
return dir;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MusicDirectory getAlbum(String id, String name, boolean refresh, Context context, ProgressListener progressListener) throws Exception {
|
||||
checkSettingsChanged(context);
|
||||
TimeLimitedCache<MusicDirectory> cache = refresh ? null : cachedAlbum.get(id);
|
||||
MusicDirectory dir = cache == null ? null : cache.get();
|
||||
if (dir == null) {
|
||||
dir = musicService.getAlbum(id, name, refresh, context, progressListener);
|
||||
cache = new TimeLimitedCache<MusicDirectory>(Util.getDirectoryCacheTime(context), TimeUnit.SECONDS);
|
||||
cache.set(dir);
|
||||
cachedAlbum.put(id, cache);
|
||||
}
|
||||
return dir;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SearchResult search(SearchCriteria criteria, Context context, ProgressListener progressListener) throws Exception {
|
||||
return musicService.search(criteria, context, progressListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MusicDirectory getPlaylist(String id, String name, Context context, ProgressListener progressListener) throws Exception {
|
||||
return musicService.getPlaylist(id, name, context, progressListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Playlist> getPlaylists(boolean refresh, Context context, ProgressListener progressListener) throws Exception {
|
||||
checkSettingsChanged(context);
|
||||
List<Playlist> result = refresh ? null : cachedPlaylists.get();
|
||||
if (result == null) {
|
||||
result = musicService.getPlaylists(refresh, context, progressListener);
|
||||
cachedPlaylists.set(result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createPlaylist(String id, String name, List<MusicDirectory.Entry> entries, Context context, ProgressListener progressListener) throws Exception {
|
||||
cachedPlaylists.clear();
|
||||
musicService.createPlaylist(id, name, entries, context, progressListener);
|
||||
}
|
||||
public CachedMusicService(MusicService musicService)
|
||||
{
|
||||
this.musicService = musicService;
|
||||
cachedMusicDirectories = new LRUCache<String, TimeLimitedCache<MusicDirectory>>(MUSIC_DIR_CACHE_SIZE);
|
||||
cachedArtist = new LRUCache<String, TimeLimitedCache<MusicDirectory>>(MUSIC_DIR_CACHE_SIZE);
|
||||
cachedAlbum = new LRUCache<String, TimeLimitedCache<MusicDirectory>>(MUSIC_DIR_CACHE_SIZE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deletePlaylist(String id, Context context, ProgressListener progressListener) throws Exception {
|
||||
public void ping(Context context, ProgressListener progressListener) throws Exception
|
||||
{
|
||||
checkSettingsChanged(context);
|
||||
musicService.ping(context, progressListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLicenseValid(Context context, ProgressListener progressListener) throws Exception
|
||||
{
|
||||
checkSettingsChanged(context);
|
||||
Boolean result = cachedLicenseValid.get();
|
||||
if (result == null)
|
||||
{
|
||||
result = musicService.isLicenseValid(context, progressListener);
|
||||
cachedLicenseValid.set(result, result ? 30L * 60L : 2L * 60L, TimeUnit.SECONDS);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MusicFolder> getMusicFolders(boolean refresh, Context context, ProgressListener progressListener) throws Exception
|
||||
{
|
||||
checkSettingsChanged(context);
|
||||
if (refresh)
|
||||
{
|
||||
cachedMusicFolders.clear();
|
||||
}
|
||||
List<MusicFolder> result = cachedMusicFolders.get();
|
||||
if (result == null)
|
||||
{
|
||||
result = musicService.getMusicFolders(refresh, context, progressListener);
|
||||
cachedMusicFolders.set(result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Indexes getIndexes(String musicFolderId, boolean refresh, Context context, ProgressListener progressListener) throws Exception
|
||||
{
|
||||
checkSettingsChanged(context);
|
||||
if (refresh)
|
||||
{
|
||||
cachedIndexes.clear();
|
||||
cachedMusicFolders.clear();
|
||||
cachedMusicDirectories.clear();
|
||||
}
|
||||
Indexes result = cachedIndexes.get();
|
||||
if (result == null)
|
||||
{
|
||||
result = musicService.getIndexes(musicFolderId, refresh, context, progressListener);
|
||||
cachedIndexes.set(result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Indexes getArtists(boolean refresh, Context context, ProgressListener progressListener) throws Exception
|
||||
{
|
||||
checkSettingsChanged(context);
|
||||
if (refresh)
|
||||
{
|
||||
cachedArtists.clear();
|
||||
}
|
||||
Indexes result = cachedArtists.get();
|
||||
if (result == null)
|
||||
{
|
||||
result = musicService.getArtists(refresh, context, progressListener);
|
||||
cachedArtists.set(result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MusicDirectory getMusicDirectory(String id, String name, boolean refresh, Context context, ProgressListener progressListener) throws Exception
|
||||
{
|
||||
checkSettingsChanged(context);
|
||||
TimeLimitedCache<MusicDirectory> cache = refresh ? null : cachedMusicDirectories.get(id);
|
||||
|
||||
MusicDirectory dir = cache == null ? null : cache.get();
|
||||
|
||||
if (dir == null)
|
||||
{
|
||||
dir = musicService.getMusicDirectory(id, name, refresh, context, progressListener);
|
||||
cache = new TimeLimitedCache<MusicDirectory>(Util.getDirectoryCacheTime(context), TimeUnit.SECONDS);
|
||||
cache.set(dir);
|
||||
cachedMusicDirectories.put(id, cache);
|
||||
}
|
||||
return dir;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MusicDirectory getArtist(String id, String name, boolean refresh, Context context, ProgressListener progressListener) throws Exception
|
||||
{
|
||||
checkSettingsChanged(context);
|
||||
TimeLimitedCache<MusicDirectory> cache = refresh ? null : cachedArtist.get(id);
|
||||
MusicDirectory dir = cache == null ? null : cache.get();
|
||||
if (dir == null)
|
||||
{
|
||||
dir = musicService.getArtist(id, name, refresh, context, progressListener);
|
||||
cache = new TimeLimitedCache<MusicDirectory>(Util.getDirectoryCacheTime(context), TimeUnit.SECONDS);
|
||||
cache.set(dir);
|
||||
cachedArtist.put(id, cache);
|
||||
}
|
||||
return dir;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MusicDirectory getAlbum(String id, String name, boolean refresh, Context context, ProgressListener progressListener) throws Exception
|
||||
{
|
||||
checkSettingsChanged(context);
|
||||
TimeLimitedCache<MusicDirectory> cache = refresh ? null : cachedAlbum.get(id);
|
||||
MusicDirectory dir = cache == null ? null : cache.get();
|
||||
if (dir == null)
|
||||
{
|
||||
dir = musicService.getAlbum(id, name, refresh, context, progressListener);
|
||||
cache = new TimeLimitedCache<MusicDirectory>(Util.getDirectoryCacheTime(context), TimeUnit.SECONDS);
|
||||
cache.set(dir);
|
||||
cachedAlbum.put(id, cache);
|
||||
}
|
||||
return dir;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SearchResult search(SearchCriteria criteria, Context context, ProgressListener progressListener) throws Exception
|
||||
{
|
||||
return musicService.search(criteria, context, progressListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MusicDirectory getPlaylist(String id, String name, Context context, ProgressListener progressListener) throws Exception
|
||||
{
|
||||
return musicService.getPlaylist(id, name, context, progressListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Playlist> getPlaylists(boolean refresh, Context context, ProgressListener progressListener) throws Exception
|
||||
{
|
||||
checkSettingsChanged(context);
|
||||
List<Playlist> result = refresh ? null : cachedPlaylists.get();
|
||||
if (result == null)
|
||||
{
|
||||
result = musicService.getPlaylists(refresh, context, progressListener);
|
||||
cachedPlaylists.set(result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createPlaylist(String id, String name, List<MusicDirectory.Entry> entries, Context context, ProgressListener progressListener) throws Exception
|
||||
{
|
||||
cachedPlaylists.clear();
|
||||
musicService.createPlaylist(id, name, entries, context, progressListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deletePlaylist(String id, Context context, ProgressListener progressListener) throws Exception
|
||||
{
|
||||
musicService.deletePlaylist(id, context, progressListener);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void updatePlaylist(String id, List<MusicDirectory.Entry> toAdd, Context context, ProgressListener progressListener) throws Exception {
|
||||
public void updatePlaylist(String id, List<MusicDirectory.Entry> toAdd, Context context, ProgressListener progressListener) throws Exception
|
||||
{
|
||||
musicService.updatePlaylist(id, toAdd, context, progressListener);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void removeFromPlaylist(String id, List<Integer> toRemove, Context context, ProgressListener progressListener) throws Exception {
|
||||
public void removeFromPlaylist(String id, List<Integer> toRemove, Context context, ProgressListener progressListener) throws Exception
|
||||
{
|
||||
musicService.removeFromPlaylist(id, toRemove, context, progressListener);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void updatePlaylist(String id, String name, String comment, boolean pub, Context context, ProgressListener progressListener) throws Exception {
|
||||
public void updatePlaylist(String id, String name, String comment, boolean pub, Context context, ProgressListener progressListener) throws Exception
|
||||
{
|
||||
musicService.updatePlaylist(id, name, comment, pub, context, progressListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Lyrics getLyrics(String artist, String title, Context context, ProgressListener progressListener) throws Exception {
|
||||
return musicService.getLyrics(artist, title, context, progressListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void scrobble(String id, boolean submission, Context context, ProgressListener progressListener) throws Exception {
|
||||
musicService.scrobble(id, submission, context, progressListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MusicDirectory getAlbumList(String type, int size, int offset, Context context, ProgressListener progressListener) throws Exception {
|
||||
return musicService.getAlbumList(type, size, offset, context, progressListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MusicDirectory getAlbumList2(String type, int size, int offset, Context context, ProgressListener progressListener) throws Exception {
|
||||
return musicService.getAlbumList2(type, size, offset, context, progressListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MusicDirectory getRandomSongs(int size, Context context, ProgressListener progressListener) throws Exception {
|
||||
return musicService.getRandomSongs(size, context, progressListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SearchResult getStarred(Context context, ProgressListener progressListener) throws Exception {
|
||||
return musicService.getStarred(context, progressListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SearchResult getStarred2(Context context, ProgressListener progressListener) throws Exception {
|
||||
return musicService.getStarred2(context, progressListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bitmap getCoverArt(Context context, MusicDirectory.Entry entry, int size, boolean saveToFile, boolean highQuality, ProgressListener progressListener) throws Exception {
|
||||
return musicService.getCoverArt(context, entry, size, saveToFile, highQuality, progressListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpResponse getDownloadInputStream(Context context, MusicDirectory.Entry song, long offset, int maxBitrate, CancellableTask task) throws Exception {
|
||||
return musicService.getDownloadInputStream(context, song, offset, maxBitrate, task);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Version getLocalVersion(Context context) throws Exception {
|
||||
return musicService.getLocalVersion(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Version getLatestVersion(Context context, ProgressListener progressListener) throws Exception {
|
||||
return musicService.getLatestVersion(context, progressListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVideoUrl(Context context, String id, boolean useFlash) throws Exception {
|
||||
public Lyrics getLyrics(String artist, String title, Context context, ProgressListener progressListener) throws Exception
|
||||
{
|
||||
return musicService.getLyrics(artist, title, context, progressListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void scrobble(String id, boolean submission, Context context, ProgressListener progressListener) throws Exception
|
||||
{
|
||||
musicService.scrobble(id, submission, context, progressListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MusicDirectory getAlbumList(String type, int size, int offset, Context context, ProgressListener progressListener) throws Exception
|
||||
{
|
||||
return musicService.getAlbumList(type, size, offset, context, progressListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MusicDirectory getAlbumList2(String type, int size, int offset, Context context, ProgressListener progressListener) throws Exception
|
||||
{
|
||||
return musicService.getAlbumList2(type, size, offset, context, progressListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MusicDirectory getRandomSongs(int size, Context context, ProgressListener progressListener) throws Exception
|
||||
{
|
||||
return musicService.getRandomSongs(size, context, progressListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SearchResult getStarred(Context context, ProgressListener progressListener) throws Exception
|
||||
{
|
||||
return musicService.getStarred(context, progressListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SearchResult getStarred2(Context context, ProgressListener progressListener) throws Exception
|
||||
{
|
||||
return musicService.getStarred2(context, progressListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bitmap getCoverArt(Context context, MusicDirectory.Entry entry, int size, boolean saveToFile, boolean highQuality, ProgressListener progressListener) throws Exception
|
||||
{
|
||||
return musicService.getCoverArt(context, entry, size, saveToFile, highQuality, progressListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpResponse getDownloadInputStream(Context context, MusicDirectory.Entry song, long offset, int maxBitrate, CancellableTask task) throws Exception
|
||||
{
|
||||
return musicService.getDownloadInputStream(context, song, offset, maxBitrate, task);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Version getLocalVersion(Context context) throws Exception
|
||||
{
|
||||
return musicService.getLocalVersion(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Version getLatestVersion(Context context, ProgressListener progressListener) throws Exception
|
||||
{
|
||||
return musicService.getLatestVersion(context, progressListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVideoUrl(Context context, String id, boolean useFlash) throws Exception
|
||||
{
|
||||
return musicService.getVideoUrl(context, id, useFlash);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVideoStreamUrl(int maxBitrate, Context context, String id) {
|
||||
return musicService.getVideoStreamUrl(maxBitrate, context, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JukeboxStatus updateJukeboxPlaylist(List<String> ids, Context context, ProgressListener progressListener) throws Exception {
|
||||
return musicService.updateJukeboxPlaylist(ids, context, progressListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JukeboxStatus skipJukebox(int index, int offsetSeconds, Context context, ProgressListener progressListener) throws Exception {
|
||||
return musicService.skipJukebox(index, offsetSeconds, context, progressListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JukeboxStatus stopJukebox(Context context, ProgressListener progressListener) throws Exception {
|
||||
return musicService.stopJukebox(context, progressListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JukeboxStatus startJukebox(Context context, ProgressListener progressListener) throws Exception {
|
||||
return musicService.startJukebox(context, progressListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JukeboxStatus getJukeboxStatus(Context context, ProgressListener progressListener) throws Exception {
|
||||
return musicService.getJukeboxStatus(context, progressListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JukeboxStatus setJukeboxGain(float gain, Context context, ProgressListener progressListener) throws Exception {
|
||||
return musicService.setJukeboxGain(gain, context, progressListener);
|
||||
}
|
||||
|
||||
private void checkSettingsChanged(Context context) {
|
||||
String newUrl = Util.getRestUrl(context, null);
|
||||
if (!Util.equals(newUrl, restUrl)) {
|
||||
cachedMusicFolders.clear();
|
||||
cachedMusicDirectories.clear();
|
||||
cachedLicenseValid.clear();
|
||||
cachedIndexes.clear();
|
||||
cachedPlaylists.clear();
|
||||
restUrl = newUrl;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void star(String id, String albumId, String artistId, Context context, ProgressListener progressListener) throws Exception {
|
||||
musicService.star(id, albumId, artistId, context, progressListener);
|
||||
|
||||
public String getVideoStreamUrl(int maxBitrate, Context context, String id)
|
||||
{
|
||||
return musicService.getVideoStreamUrl(maxBitrate, context, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unstar(String id, String albumId, String artistId, Context context, ProgressListener progressListener) throws Exception {
|
||||
public JukeboxStatus updateJukeboxPlaylist(List<String> ids, Context context, ProgressListener progressListener) throws Exception
|
||||
{
|
||||
return musicService.updateJukeboxPlaylist(ids, context, progressListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JukeboxStatus skipJukebox(int index, int offsetSeconds, Context context, ProgressListener progressListener) throws Exception
|
||||
{
|
||||
return musicService.skipJukebox(index, offsetSeconds, context, progressListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JukeboxStatus stopJukebox(Context context, ProgressListener progressListener) throws Exception
|
||||
{
|
||||
return musicService.stopJukebox(context, progressListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JukeboxStatus startJukebox(Context context, ProgressListener progressListener) throws Exception
|
||||
{
|
||||
return musicService.startJukebox(context, progressListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JukeboxStatus getJukeboxStatus(Context context, ProgressListener progressListener) throws Exception
|
||||
{
|
||||
return musicService.getJukeboxStatus(context, progressListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JukeboxStatus setJukeboxGain(float gain, Context context, ProgressListener progressListener) throws Exception
|
||||
{
|
||||
return musicService.setJukeboxGain(gain, context, progressListener);
|
||||
}
|
||||
|
||||
private void checkSettingsChanged(Context context)
|
||||
{
|
||||
String newUrl = Util.getRestUrl(context, null);
|
||||
if (!Util.equals(newUrl, restUrl))
|
||||
{
|
||||
cachedMusicFolders.clear();
|
||||
cachedMusicDirectories.clear();
|
||||
cachedLicenseValid.clear();
|
||||
cachedIndexes.clear();
|
||||
cachedPlaylists.clear();
|
||||
restUrl = newUrl;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void star(String id, String albumId, String artistId, Context context, ProgressListener progressListener) throws Exception
|
||||
{
|
||||
musicService.star(id, albumId, artistId, context, progressListener);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unstar(String id, String albumId, String artistId, Context context, ProgressListener progressListener) throws Exception
|
||||
{
|
||||
musicService.unstar(id, albumId, artistId, context, progressListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Genre> getGenres(Context context, ProgressListener progressListener) throws Exception {
|
||||
checkSettingsChanged(context);
|
||||
List<Genre> result = cachedGenres.get();
|
||||
|
||||
if (result == null) {
|
||||
result = musicService.getGenres(context, progressListener);
|
||||
cachedGenres.set(result);
|
||||
}
|
||||
|
||||
return result;
|
||||
public List<Genre> getGenres(Context context, ProgressListener progressListener) throws Exception
|
||||
{
|
||||
checkSettingsChanged(context);
|
||||
List<Genre> result = cachedGenres.get();
|
||||
|
||||
if (result == null)
|
||||
{
|
||||
result = musicService.getGenres(context, progressListener);
|
||||
cachedGenres.set(result);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MusicDirectory getSongsByGenre(String genre, int count, int offset, Context context, ProgressListener progressListener) throws Exception {
|
||||
public MusicDirectory getSongsByGenre(String genre, int count, int offset, Context context, ProgressListener progressListener) throws Exception
|
||||
{
|
||||
return musicService.getSongsByGenre(genre, count, offset, context, progressListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Share> getShares(Context context, ProgressListener progressListener) throws Exception {
|
||||
return musicService.getShares(context, progressListener);
|
||||
public List<Share> getShares(Context context, ProgressListener progressListener) throws Exception
|
||||
{
|
||||
return musicService.getShares(context, progressListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ChatMessage> getChatMessages(Long since, Context context, ProgressListener progressListener) throws Exception {
|
||||
public List<ChatMessage> getChatMessages(Long since, Context context, ProgressListener progressListener) throws Exception
|
||||
{
|
||||
return musicService.getChatMessages(since, context, progressListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addChatMessage(String message, Context context, ProgressListener progressListener) throws Exception {
|
||||
public void addChatMessage(String message, Context context, ProgressListener progressListener) throws Exception
|
||||
{
|
||||
musicService.addChatMessage(message, context, progressListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Bookmark> getBookmarks(Context context, ProgressListener progressListener) throws Exception {
|
||||
public List<Bookmark> getBookmarks(Context context, ProgressListener progressListener) throws Exception
|
||||
{
|
||||
return musicService.getBookmarks(context, progressListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteBookmark(String id, Context context, ProgressListener progressListener) throws Exception {
|
||||
public void deleteBookmark(String id, Context context, ProgressListener progressListener) throws Exception
|
||||
{
|
||||
musicService.deleteBookmark(id, context, progressListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createBookmark(String id, int position, Context context, ProgressListener progressListener) throws Exception {
|
||||
public void createBookmark(String id, int position, Context context, ProgressListener progressListener) throws Exception
|
||||
{
|
||||
musicService.createBookmark(id, position, context, progressListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MusicDirectory getVideos(boolean refresh, Context context, ProgressListener progressListener) throws Exception {
|
||||
public MusicDirectory getVideos(boolean refresh, Context context, ProgressListener progressListener) throws Exception
|
||||
{
|
||||
checkSettingsChanged(context);
|
||||
TimeLimitedCache<MusicDirectory> cache = refresh ? null : cachedMusicDirectories.get(Constants.INTENT_EXTRA_NAME_VIDEOS);
|
||||
|
||||
MusicDirectory dir = cache == null ? null : cache.get();
|
||||
|
||||
if (dir == null) {
|
||||
if (dir == null)
|
||||
{
|
||||
dir = musicService.getVideos(refresh, context, progressListener);
|
||||
cache = new TimeLimitedCache<MusicDirectory>(Util.getDirectoryCacheTime(context), TimeUnit.SECONDS);
|
||||
cache.set(dir);
|
||||
|
|
|
@ -18,281 +18,369 @@
|
|||
*/
|
||||
package com.thejoshwa.ultrasonic.androidapp.service;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.wifi.WifiManager;
|
||||
import android.os.PowerManager;
|
||||
import android.util.Log;
|
||||
|
||||
import com.thejoshwa.ultrasonic.androidapp.domain.MusicDirectory;
|
||||
import com.thejoshwa.ultrasonic.androidapp.util.CacheCleaner;
|
||||
import com.thejoshwa.ultrasonic.androidapp.util.CancellableTask;
|
||||
import com.thejoshwa.ultrasonic.androidapp.util.FileUtil;
|
||||
import com.thejoshwa.ultrasonic.androidapp.util.Util;
|
||||
import com.thejoshwa.ultrasonic.androidapp.util.CacheCleaner;
|
||||
|
||||
import org.apache.http.Header;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.HttpStatus;
|
||||
import org.apache.http.Header;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.RandomAccessFile;
|
||||
|
||||
import static android.content.Context.POWER_SERVICE;
|
||||
import static android.os.PowerManager.ON_AFTER_RELEASE;
|
||||
import static android.os.PowerManager.SCREEN_DIM_WAKE_LOCK;
|
||||
|
||||
/**
|
||||
* @author Sindre Mehus
|
||||
* @version $Id$
|
||||
*/
|
||||
public class DownloadFile {
|
||||
public class DownloadFile
|
||||
{
|
||||
|
||||
private static final String TAG = DownloadFile.class.getSimpleName();
|
||||
private final Context context;
|
||||
private final MusicDirectory.Entry song;
|
||||
private final File partialFile;
|
||||
private final File completeFile;
|
||||
private final File saveFile;
|
||||
private static final String TAG = DownloadFile.class.getSimpleName();
|
||||
private final Context context;
|
||||
private final MusicDirectory.Entry song;
|
||||
private final File partialFile;
|
||||
private final File completeFile;
|
||||
private final File saveFile;
|
||||
|
||||
private final MediaStoreService mediaStoreService;
|
||||
private CancellableTask downloadTask;
|
||||
private boolean save;
|
||||
private boolean failed;
|
||||
private int bitRate;
|
||||
private volatile boolean isPlaying = false;
|
||||
private volatile boolean saveWhenDone = false;
|
||||
private volatile boolean completeWhenDone = false;
|
||||
private Integer contentLength = null;
|
||||
private final MediaStoreService mediaStoreService;
|
||||
private CancellableTask downloadTask;
|
||||
private boolean save;
|
||||
private boolean failed;
|
||||
private int bitRate;
|
||||
private volatile boolean isPlaying;
|
||||
private volatile boolean saveWhenDone;
|
||||
private volatile boolean completeWhenDone;
|
||||
private Integer contentLength;
|
||||
|
||||
public DownloadFile(Context context, MusicDirectory.Entry song, boolean save) {
|
||||
this.context = context;
|
||||
this.song = song;
|
||||
this.save = save;
|
||||
|
||||
saveFile = FileUtil.getSongFile(context, song);
|
||||
bitRate = Util.getMaxBitRate(context);
|
||||
partialFile = new File(saveFile.getParent(), FileUtil.getBaseName(saveFile.getName()) + ".partial." + FileUtil.getExtension(saveFile.getName()));
|
||||
completeFile = new File(saveFile.getParent(), FileUtil.getBaseName(saveFile.getName()) + ".complete." + FileUtil.getExtension(saveFile.getName()));
|
||||
mediaStoreService = new MediaStoreService(context);
|
||||
}
|
||||
public DownloadFile(Context context, MusicDirectory.Entry song, boolean save)
|
||||
{
|
||||
super();
|
||||
this.context = context;
|
||||
this.song = song;
|
||||
this.save = save;
|
||||
|
||||
public MusicDirectory.Entry getSong() {
|
||||
return song;
|
||||
}
|
||||
saveFile = FileUtil.getSongFile(context, song);
|
||||
bitRate = Util.getMaxBitRate(context);
|
||||
partialFile = new File(saveFile.getParent(), String.format("%s.partial.%s", FileUtil.getBaseName(saveFile.getName()), FileUtil.getExtension(saveFile.getName())));
|
||||
completeFile = new File(saveFile.getParent(), String.format("%s.complete.%s", FileUtil.getBaseName(saveFile.getName()), FileUtil.getExtension(saveFile.getName())));
|
||||
mediaStoreService = new MediaStoreService(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the effective bit rate.
|
||||
*/
|
||||
public int getBitRate() {
|
||||
if (!partialFile.exists()) {
|
||||
public MusicDirectory.Entry getSong()
|
||||
{
|
||||
return song;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the effective bit rate.
|
||||
*/
|
||||
public int getBitRate()
|
||||
{
|
||||
if (!partialFile.exists())
|
||||
{
|
||||
bitRate = Util.getMaxBitRate(context);
|
||||
}
|
||||
|
||||
if (bitRate > 0) {
|
||||
return bitRate;
|
||||
}
|
||||
|
||||
return song.getBitRate() == null ? 160 : song.getBitRate();
|
||||
}
|
||||
|
||||
public Integer getContentLength() {
|
||||
if (bitRate > 0)
|
||||
{
|
||||
return bitRate;
|
||||
}
|
||||
|
||||
return song.getBitRate() == null ? 160 : song.getBitRate();
|
||||
}
|
||||
|
||||
public Integer getContentLength()
|
||||
{
|
||||
return contentLength;
|
||||
}
|
||||
|
||||
public synchronized void download() {
|
||||
FileUtil.createDirectoryForParent(saveFile);
|
||||
failed = false;
|
||||
|
||||
if (!partialFile.exists()) {
|
||||
public synchronized void download()
|
||||
{
|
||||
FileUtil.createDirectoryForParent(saveFile);
|
||||
failed = false;
|
||||
|
||||
if (!partialFile.exists())
|
||||
{
|
||||
bitRate = Util.getMaxBitRate(context);
|
||||
}
|
||||
|
||||
downloadTask = new DownloadTask();
|
||||
downloadTask.start();
|
||||
}
|
||||
|
||||
public synchronized void cancelDownload() {
|
||||
if (downloadTask != null) {
|
||||
downloadTask.cancel();
|
||||
}
|
||||
}
|
||||
downloadTask = new DownloadTask();
|
||||
downloadTask.start();
|
||||
}
|
||||
|
||||
public File getCompleteFile() {
|
||||
if (saveFile.exists()) {
|
||||
return saveFile;
|
||||
}
|
||||
public synchronized void cancelDownload()
|
||||
{
|
||||
if (downloadTask != null)
|
||||
{
|
||||
downloadTask.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
if (completeFile.exists()) {
|
||||
return completeFile;
|
||||
}
|
||||
public File getCompleteFile()
|
||||
{
|
||||
if (saveFile.exists())
|
||||
{
|
||||
return saveFile;
|
||||
}
|
||||
|
||||
return saveFile;
|
||||
}
|
||||
if (completeFile.exists())
|
||||
{
|
||||
return completeFile;
|
||||
}
|
||||
|
||||
public File getPartialFile() {
|
||||
return partialFile;
|
||||
}
|
||||
return saveFile;
|
||||
}
|
||||
|
||||
public boolean isSaved() {
|
||||
return saveFile.exists();
|
||||
}
|
||||
public File getPartialFile()
|
||||
{
|
||||
return partialFile;
|
||||
}
|
||||
|
||||
public synchronized boolean isCompleteFileAvailable() {
|
||||
return saveFile.exists() || completeFile.exists();
|
||||
}
|
||||
public boolean isSaved()
|
||||
{
|
||||
return saveFile.exists();
|
||||
}
|
||||
|
||||
public synchronized boolean isWorkDone() {
|
||||
return saveFile.exists() || (completeFile.exists() && !save) || saveWhenDone || completeWhenDone;
|
||||
}
|
||||
public synchronized boolean isCompleteFileAvailable()
|
||||
{
|
||||
return saveFile.exists() || completeFile.exists();
|
||||
}
|
||||
|
||||
public synchronized boolean isDownloading() {
|
||||
return downloadTask != null && downloadTask.isRunning();
|
||||
}
|
||||
public synchronized boolean isWorkDone()
|
||||
{
|
||||
return saveFile.exists() || (completeFile.exists() && !save) || saveWhenDone || completeWhenDone;
|
||||
}
|
||||
|
||||
public synchronized boolean isDownloadCancelled() {
|
||||
return downloadTask != null && downloadTask.isCancelled();
|
||||
}
|
||||
public synchronized boolean isDownloading()
|
||||
{
|
||||
return downloadTask != null && downloadTask.isRunning();
|
||||
}
|
||||
|
||||
public boolean shouldSave() {
|
||||
return save;
|
||||
}
|
||||
public synchronized boolean isDownloadCancelled()
|
||||
{
|
||||
return downloadTask != null && downloadTask.isCancelled();
|
||||
}
|
||||
|
||||
public boolean isFailed() {
|
||||
return failed;
|
||||
}
|
||||
public boolean shouldSave()
|
||||
{
|
||||
return save;
|
||||
}
|
||||
|
||||
public void delete() {
|
||||
cancelDownload();
|
||||
Util.delete(partialFile);
|
||||
Util.delete(completeFile);
|
||||
Util.delete(saveFile);
|
||||
mediaStoreService.deleteFromMediaStore(this);
|
||||
}
|
||||
public boolean isFailed()
|
||||
{
|
||||
return failed;
|
||||
}
|
||||
|
||||
public void unpin() {
|
||||
if (saveFile.exists()) {
|
||||
saveFile.renameTo(completeFile);
|
||||
}
|
||||
}
|
||||
public void delete()
|
||||
{
|
||||
cancelDownload();
|
||||
Util.delete(partialFile);
|
||||
Util.delete(completeFile);
|
||||
Util.delete(saveFile);
|
||||
mediaStoreService.deleteFromMediaStore(this);
|
||||
}
|
||||
|
||||
public boolean cleanup() {
|
||||
boolean ok = true;
|
||||
if (completeFile.exists() || saveFile.exists()) {
|
||||
ok = Util.delete(partialFile);
|
||||
}
|
||||
if (saveFile.exists()) {
|
||||
ok &= Util.delete(completeFile);
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
public void unpin()
|
||||
{
|
||||
if (saveFile.exists())
|
||||
{
|
||||
saveFile.renameTo(completeFile);
|
||||
}
|
||||
}
|
||||
|
||||
// In support of LRU caching.
|
||||
public void updateModificationDate() {
|
||||
updateModificationDate(saveFile);
|
||||
updateModificationDate(partialFile);
|
||||
updateModificationDate(completeFile);
|
||||
}
|
||||
public boolean cleanup()
|
||||
{
|
||||
boolean ok = true;
|
||||
|
||||
private void updateModificationDate(File file) {
|
||||
if (file.exists()) {
|
||||
boolean ok = file.setLastModified(System.currentTimeMillis());
|
||||
if (!ok) {
|
||||
Log.w(TAG, "Failed to set last-modified date on " + file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setPlaying(boolean isPlaying) {
|
||||
try {
|
||||
if (saveWhenDone && !isPlaying) {
|
||||
if (completeFile.exists() || saveFile.exists())
|
||||
{
|
||||
ok = Util.delete(partialFile);
|
||||
}
|
||||
|
||||
if (saveFile.exists())
|
||||
{
|
||||
ok &= Util.delete(completeFile);
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
// In support of LRU caching.
|
||||
public void updateModificationDate()
|
||||
{
|
||||
updateModificationDate(saveFile);
|
||||
updateModificationDate(partialFile);
|
||||
updateModificationDate(completeFile);
|
||||
}
|
||||
|
||||
private static void updateModificationDate(File file)
|
||||
{
|
||||
if (file.exists())
|
||||
{
|
||||
boolean ok = file.setLastModified(System.currentTimeMillis());
|
||||
|
||||
if (!ok)
|
||||
{
|
||||
Log.i(TAG, String.format("Failed to set last-modified date on %s, trying alternate method", file));
|
||||
|
||||
try
|
||||
{
|
||||
// Try alternate method to update last modified date to current time
|
||||
// Found at https://code.google.com/p/android/issues/detail?id=18624
|
||||
RandomAccessFile raf = new RandomAccessFile(file, "rw");
|
||||
long length = raf.length();
|
||||
raf.setLength(length + 1);
|
||||
raf.setLength(length);
|
||||
raf.close();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.w(TAG, String.format("Failed to set last-modified date on %s", file));
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setPlaying(boolean isPlaying)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (saveWhenDone && !isPlaying)
|
||||
{
|
||||
Util.renameFile(completeFile, saveFile);
|
||||
saveWhenDone = false;
|
||||
} else if (completeWhenDone && !isPlaying) {
|
||||
if (save) {
|
||||
}
|
||||
else if (completeWhenDone && !isPlaying)
|
||||
{
|
||||
if (save)
|
||||
{
|
||||
Util.renameFile(partialFile, saveFile);
|
||||
mediaStoreService.saveInMediaStore(DownloadFile.this);
|
||||
} else {
|
||||
mediaStoreService.saveInMediaStore(DownloadFile.this);
|
||||
}
|
||||
else
|
||||
{
|
||||
Util.renameFile(partialFile, completeFile);
|
||||
}
|
||||
|
||||
|
||||
completeWhenDone = false;
|
||||
}
|
||||
} catch(IOException ex) {
|
||||
Log.w(TAG, "Failed to rename file " + completeFile + " to " + saveFile);
|
||||
}
|
||||
|
||||
catch (IOException ex)
|
||||
{
|
||||
Log.w(TAG, String.format("Failed to rename file %s to %s", completeFile, saveFile));
|
||||
}
|
||||
|
||||
this.isPlaying = isPlaying;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DownloadFile (" + song + ")";
|
||||
}
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return String.format("DownloadFile (%s)", song);
|
||||
}
|
||||
|
||||
private class DownloadTask extends CancellableTask {
|
||||
private class DownloadTask extends CancellableTask
|
||||
{
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
@Override
|
||||
public void execute()
|
||||
{
|
||||
|
||||
InputStream in = null;
|
||||
FileOutputStream out = null;
|
||||
PowerManager.WakeLock wakeLock = null;
|
||||
InputStream in = null;
|
||||
FileOutputStream out = null;
|
||||
PowerManager.WakeLock wakeLock = null;
|
||||
WifiManager.WifiLock wifiLock = null;
|
||||
|
||||
try {
|
||||
if (Util.isScreenLitOnDownload(context)) {
|
||||
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
|
||||
wakeLock = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE, toString());
|
||||
wakeLock.acquire();
|
||||
Log.i(TAG, "Acquired wake lock " + wakeLock);
|
||||
}
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
if (Util.isScreenLitOnDownload(context))
|
||||
{
|
||||
PowerManager pm = (PowerManager) context.getSystemService(POWER_SERVICE);
|
||||
wakeLock = pm.newWakeLock(SCREEN_DIM_WAKE_LOCK | ON_AFTER_RELEASE, toString());
|
||||
wakeLock.acquire();
|
||||
Log.i(TAG, String.format("Acquired wake lock %s", wakeLock));
|
||||
}
|
||||
|
||||
wifiLock = Util.createWifiLock(context, toString());
|
||||
wifiLock.acquire();
|
||||
|
||||
if (saveFile.exists()) {
|
||||
Log.i(TAG, saveFile + " already exists. Skipping.");
|
||||
return;
|
||||
}
|
||||
if (completeFile.exists()) {
|
||||
if (save) {
|
||||
if (isPlaying) {
|
||||
if (saveFile.exists())
|
||||
{
|
||||
Log.i(TAG, String.format("%s already exists. Skipping.", saveFile));
|
||||
return;
|
||||
}
|
||||
if (completeFile.exists())
|
||||
{
|
||||
if (save)
|
||||
{
|
||||
if (isPlaying)
|
||||
{
|
||||
saveWhenDone = true;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
Util.renameFile(completeFile, saveFile);
|
||||
}
|
||||
} else {
|
||||
Log.i(TAG, completeFile + " already exists. Skipping.");
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.i(TAG, String.format("%s already exists. Skipping.", completeFile));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
MusicService musicService = MusicServiceFactory.getMusicService(context);
|
||||
MusicService musicService = MusicServiceFactory.getMusicService(context);
|
||||
|
||||
// Some devices seem to throw error on partial file which doesn't exist
|
||||
boolean compare;
|
||||
|
||||
|
||||
Integer duration = song.getDuration();
|
||||
long fileLength = 0;
|
||||
|
||||
if (!partialFile.exists()) {
|
||||
|
||||
if (!partialFile.exists())
|
||||
{
|
||||
fileLength = partialFile.length();
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
try
|
||||
{
|
||||
compare = (bitRate == 0) || (duration == null || duration == 0) || (fileLength == 0);
|
||||
//(bitRate * song.getDuration() * 1000 / 8) > partialFile.length();
|
||||
} catch(Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
compare = true;
|
||||
}
|
||||
|
||||
if (compare) {
|
||||
|
||||
if (compare)
|
||||
{
|
||||
// Attempt partial HTTP GET, appending to the file if it exists.
|
||||
HttpResponse response = musicService.getDownloadInputStream(context, song, partialFile.length(), bitRate, DownloadTask.this);
|
||||
Header contentLengthHeader = response.getFirstHeader("Content-Length");
|
||||
|
||||
if (contentLengthHeader != null) {
|
||||
if (contentLengthHeader != null)
|
||||
{
|
||||
String contentLengthString = contentLengthHeader.getValue();
|
||||
|
||||
if (contentLengthString != null) {
|
||||
if (contentLengthString != null)
|
||||
{
|
||||
Log.i(TAG, "Content Length: " + contentLengthString);
|
||||
contentLength = Integer.parseInt(contentLengthString);
|
||||
}
|
||||
|
@ -300,113 +388,144 @@ public class DownloadFile {
|
|||
|
||||
in = response.getEntity().getContent();
|
||||
boolean partial = response.getStatusLine().getStatusCode() == HttpStatus.SC_PARTIAL_CONTENT;
|
||||
|
||||
if (partial) {
|
||||
Log.i(TAG, "Executed partial HTTP GET, skipping " + partialFile.length() + " bytes");
|
||||
|
||||
if (partial)
|
||||
{
|
||||
Log.i(TAG, String.format("Executed partial HTTP GET, skipping %d bytes", partialFile.length()));
|
||||
}
|
||||
|
||||
out = new FileOutputStream(partialFile, partial);
|
||||
long n = copy(in, out);
|
||||
Log.i(TAG, "Downloaded " + n + " bytes to " + partialFile);
|
||||
Log.i(TAG, String.format("Downloaded %d bytes to %s", n, partialFile));
|
||||
out.flush();
|
||||
out.close();
|
||||
|
||||
if (isCancelled()) {
|
||||
throw new Exception("Download of '" + song + "' was cancelled");
|
||||
if (isCancelled())
|
||||
{
|
||||
throw new Exception(String.format("Download of '%s' was cancelled", song));
|
||||
}
|
||||
|
||||
downloadAndSaveCoverArt(musicService);
|
||||
}
|
||||
|
||||
if (isPlaying) {
|
||||
if (isPlaying)
|
||||
{
|
||||
completeWhenDone = true;
|
||||
} else {
|
||||
if (save) {
|
||||
}
|
||||
else
|
||||
{
|
||||
if (save)
|
||||
{
|
||||
Util.renameFile(partialFile, saveFile);
|
||||
mediaStoreService.saveInMediaStore(DownloadFile.this);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
Util.renameFile(partialFile, completeFile);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception x) {
|
||||
Util.close(out);
|
||||
Util.delete(completeFile);
|
||||
Util.delete(saveFile);
|
||||
if (!isCancelled()) {
|
||||
failed = true;
|
||||
Log.w(TAG, "Failed to download '" + song + "'.", x);
|
||||
}
|
||||
}
|
||||
catch (Exception x)
|
||||
{
|
||||
Util.close(out);
|
||||
Util.delete(completeFile);
|
||||
Util.delete(saveFile);
|
||||
if (!isCancelled())
|
||||
{
|
||||
failed = true;
|
||||
Log.w(TAG, String.format("Failed to download '%s'.", song), x);
|
||||
}
|
||||
|
||||
} finally {
|
||||
Util.close(in);
|
||||
Util.close(out);
|
||||
if (wakeLock != null) {
|
||||
wakeLock.release();
|
||||
Log.i(TAG, "Released wake lock " + wakeLock);
|
||||
}
|
||||
if (wifiLock != null) {
|
||||
}
|
||||
finally
|
||||
{
|
||||
Util.close(in);
|
||||
Util.close(out);
|
||||
if (wakeLock != null)
|
||||
{
|
||||
wakeLock.release();
|
||||
Log.i(TAG, String.format("Released wake lock %s", wakeLock));
|
||||
}
|
||||
if (wifiLock != null)
|
||||
{
|
||||
wifiLock.release();
|
||||
}
|
||||
new CacheCleaner(context, DownloadServiceImpl.getInstance()).cleanSpace();
|
||||
if(DownloadServiceImpl.getInstance() != null) {
|
||||
((DownloadServiceImpl)DownloadServiceImpl.getInstance()).checkDownloads();
|
||||
new CacheCleaner(context, DownloadServiceImpl.getInstance()).cleanSpace();
|
||||
if (DownloadServiceImpl.getInstance() != null)
|
||||
{
|
||||
((DownloadServiceImpl) DownloadServiceImpl.getInstance()).checkDownloads();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DownloadTask (" + song + ")";
|
||||
}
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return String.format("DownloadTask (%s)", song);
|
||||
}
|
||||
|
||||
private void downloadAndSaveCoverArt(MusicService musicService) throws Exception {
|
||||
try {
|
||||
if (song.getCoverArt() != null) {
|
||||
int size = Util.getMinDisplayMetric(context);
|
||||
musicService.getCoverArt(context, song, size, true, true, null);
|
||||
}
|
||||
} catch (Exception x) {
|
||||
Log.e(TAG, "Failed to get cover art.", x);
|
||||
}
|
||||
}
|
||||
private void downloadAndSaveCoverArt(MusicService musicService) throws Exception
|
||||
{
|
||||
try
|
||||
{
|
||||
if (song.getCoverArt() != null)
|
||||
{
|
||||
int size = Util.getMinDisplayMetric(context);
|
||||
musicService.getCoverArt(context, song, size, true, true, null);
|
||||
}
|
||||
}
|
||||
catch (Exception x)
|
||||
{
|
||||
Log.e(TAG, "Failed to get cover art.", x);
|
||||
}
|
||||
}
|
||||
|
||||
private long copy(final InputStream in, OutputStream out) throws IOException, InterruptedException {
|
||||
private long copy(final InputStream in, OutputStream out) throws IOException
|
||||
{
|
||||
// Start a thread that will close the input stream if the task is
|
||||
// cancelled, thus causing the copy() method to return.
|
||||
new Thread()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
Util.sleepQuietly(3000L);
|
||||
|
||||
// Start a thread that will close the input stream if the task is
|
||||
// cancelled, thus causing the copy() method to return.
|
||||
new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
while (true) {
|
||||
Util.sleepQuietly(3000L);
|
||||
if (isCancelled()) {
|
||||
Util.close(in);
|
||||
return;
|
||||
}
|
||||
if (!isRunning()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
if (isCancelled())
|
||||
{
|
||||
Util.close(in);
|
||||
return;
|
||||
}
|
||||
|
||||
byte[] buffer = new byte[1024 * 16];
|
||||
long count = 0;
|
||||
int n;
|
||||
long lastLog = System.currentTimeMillis();
|
||||
if (!isRunning())
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
|
||||
while (!isCancelled() && (n = in.read(buffer)) != -1) {
|
||||
out.write(buffer, 0, n);
|
||||
count += n;
|
||||
byte[] buffer = new byte[1024 * 16];
|
||||
long count = 0;
|
||||
int n;
|
||||
long lastLog = System.currentTimeMillis();
|
||||
|
||||
long now = System.currentTimeMillis();
|
||||
if (now - lastLog > 3000L) { // Only every so often.
|
||||
Log.i(TAG, "Downloaded " + Util.formatBytes(count) + " of " + song);
|
||||
lastLog = now;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
}
|
||||
while (!isCancelled() && (n = in.read(buffer)) != -1)
|
||||
{
|
||||
out.write(buffer, 0, n);
|
||||
count += n;
|
||||
|
||||
long now = System.currentTimeMillis();
|
||||
if (now - lastLog > 3000L)
|
||||
{ // Only every so often.
|
||||
Log.i(TAG, String.format("Downloaded %s of %s", Util.formatBytes(count), song));
|
||||
lastLog = now;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -18,121 +18,122 @@
|
|||
*/
|
||||
package com.thejoshwa.ultrasonic.androidapp.service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.thejoshwa.ultrasonic.androidapp.audiofx.EqualizerController;
|
||||
import com.thejoshwa.ultrasonic.androidapp.audiofx.VisualizerController;
|
||||
import com.thejoshwa.ultrasonic.androidapp.domain.MusicDirectory.Entry;
|
||||
import com.thejoshwa.ultrasonic.androidapp.domain.PlayerState;
|
||||
import com.thejoshwa.ultrasonic.androidapp.domain.RepeatMode;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Sindre Mehus
|
||||
* @version $Id$
|
||||
*/
|
||||
public interface DownloadService {
|
||||
public interface DownloadService
|
||||
{
|
||||
|
||||
void download(List<Entry> songs, boolean save, boolean autoplay, boolean playNext, boolean shuffle, boolean newPlaylist);
|
||||
|
||||
void downloadBackground(List<Entry> songs, boolean save);
|
||||
|
||||
void setShufflePlayEnabled(boolean enabled);
|
||||
void downloadBackground(List<Entry> songs, boolean save);
|
||||
|
||||
boolean isShufflePlayEnabled();
|
||||
void setShufflePlayEnabled(boolean enabled);
|
||||
|
||||
void shuffle();
|
||||
boolean isShufflePlayEnabled();
|
||||
|
||||
RepeatMode getRepeatMode();
|
||||
void shuffle();
|
||||
|
||||
void setRepeatMode(RepeatMode repeatMode);
|
||||
RepeatMode getRepeatMode();
|
||||
|
||||
boolean getKeepScreenOn();
|
||||
void setRepeatMode(RepeatMode repeatMode);
|
||||
|
||||
void setKeepScreenOn(boolean screenOn);
|
||||
boolean getKeepScreenOn();
|
||||
|
||||
boolean getShowVisualization();
|
||||
|
||||
boolean getEqualizerAvailable();
|
||||
|
||||
boolean getVisualizerAvailable();
|
||||
void setKeepScreenOn(boolean screenOn);
|
||||
|
||||
void setShowVisualization(boolean showVisualization);
|
||||
boolean getShowVisualization();
|
||||
|
||||
void clear();
|
||||
boolean getEqualizerAvailable();
|
||||
|
||||
boolean getVisualizerAvailable();
|
||||
|
||||
void setShowVisualization(boolean showVisualization);
|
||||
|
||||
void clear();
|
||||
|
||||
void clearBackground();
|
||||
|
||||
void clearIncomplete();
|
||||
void clearIncomplete();
|
||||
|
||||
int size();
|
||||
|
||||
int size();
|
||||
|
||||
void remove(int which);
|
||||
|
||||
void remove(DownloadFile downloadFile);
|
||||
|
||||
long getDownloadListDuration();
|
||||
|
||||
void remove(DownloadFile downloadFile);
|
||||
|
||||
long getDownloadListDuration();
|
||||
|
||||
List<DownloadFile> getSongs();
|
||||
|
||||
List<DownloadFile> getDownloads();
|
||||
|
||||
List<DownloadFile> getDownloads();
|
||||
|
||||
List<DownloadFile> getBackgroundDownloads();
|
||||
|
||||
int getCurrentPlayingIndex();
|
||||
int getCurrentPlayingIndex();
|
||||
|
||||
DownloadFile getCurrentPlaying();
|
||||
DownloadFile getCurrentPlaying();
|
||||
|
||||
DownloadFile getCurrentDownloading();
|
||||
DownloadFile getCurrentDownloading();
|
||||
|
||||
void play(int index);
|
||||
void play(int index);
|
||||
|
||||
void seekTo(int position);
|
||||
void seekTo(int position);
|
||||
|
||||
void previous();
|
||||
void previous();
|
||||
|
||||
void next();
|
||||
void next();
|
||||
|
||||
void pause();
|
||||
|
||||
void stop();
|
||||
void pause();
|
||||
|
||||
void start();
|
||||
void stop();
|
||||
|
||||
void reset();
|
||||
void start();
|
||||
|
||||
PlayerState getPlayerState();
|
||||
void reset();
|
||||
|
||||
int getPlayerPosition();
|
||||
PlayerState getPlayerState();
|
||||
|
||||
int getPlayerDuration();
|
||||
int getPlayerPosition();
|
||||
|
||||
void delete(List<Entry> songs);
|
||||
int getPlayerDuration();
|
||||
|
||||
void unpin(List<Entry> songs);
|
||||
void delete(List<Entry> songs);
|
||||
|
||||
DownloadFile forSong(Entry song);
|
||||
void unpin(List<Entry> songs);
|
||||
|
||||
long getDownloadListUpdateRevision();
|
||||
DownloadFile forSong(Entry song);
|
||||
|
||||
void setSuggestedPlaylistName(String name);
|
||||
long getDownloadListUpdateRevision();
|
||||
|
||||
String getSuggestedPlaylistName();
|
||||
void setSuggestedPlaylistName(String name);
|
||||
|
||||
EqualizerController getEqualizerController();
|
||||
String getSuggestedPlaylistName();
|
||||
|
||||
VisualizerController getVisualizerController();
|
||||
EqualizerController getEqualizerController();
|
||||
|
||||
boolean isJukeboxEnabled();
|
||||
VisualizerController getVisualizerController();
|
||||
|
||||
void setJukeboxEnabled(boolean b);
|
||||
boolean isJukeboxEnabled();
|
||||
|
||||
void adjustJukeboxVolume(boolean up);
|
||||
|
||||
void togglePlayPause();
|
||||
|
||||
void setVolume(float volume);
|
||||
|
||||
void swap(boolean mainList, int from, int to);
|
||||
|
||||
void restore(List<Entry> songs, int currentPlayingIndex, int currentPlayingPosition, boolean autoPlay, boolean newPlaylist);
|
||||
void setJukeboxEnabled(boolean b);
|
||||
|
||||
void adjustJukeboxVolume(boolean up);
|
||||
|
||||
void togglePlayPause();
|
||||
|
||||
void setVolume(float volume);
|
||||
|
||||
void swap(boolean mainList, int from, int to);
|
||||
|
||||
void restore(List<Entry> songs, int currentPlayingIndex, int currentPlayingPosition, boolean autoPlay, boolean newPlaylist);
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -18,15 +18,6 @@
|
|||
*/
|
||||
package com.thejoshwa.ultrasonic.androidapp.service;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
@ -36,169 +27,218 @@ import android.telephony.PhoneStateListener;
|
|||
import android.telephony.TelephonyManager;
|
||||
import android.util.Log;
|
||||
import android.view.KeyEvent;
|
||||
|
||||
import com.thejoshwa.ultrasonic.androidapp.domain.MusicDirectory;
|
||||
import com.thejoshwa.ultrasonic.androidapp.domain.PlayerState;
|
||||
import com.thejoshwa.ultrasonic.androidapp.util.CacheCleaner;
|
||||
import com.thejoshwa.ultrasonic.androidapp.util.FileUtil;
|
||||
import com.thejoshwa.ultrasonic.androidapp.util.Util;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
/**
|
||||
* @author Sindre Mehus
|
||||
*/
|
||||
public class DownloadServiceLifecycleSupport {
|
||||
public class DownloadServiceLifecycleSupport
|
||||
{
|
||||
|
||||
private static final String TAG = DownloadServiceLifecycleSupport.class.getSimpleName();
|
||||
private static final String FILENAME_DOWNLOADS_SER = "downloadstate.ser";
|
||||
private static final String TAG = DownloadServiceLifecycleSupport.class.getSimpleName();
|
||||
private static final String FILENAME_DOWNLOADS_SER = "downloadstate.ser";
|
||||
|
||||
private final DownloadServiceImpl downloadService;
|
||||
private ScheduledExecutorService executorService;
|
||||
private BroadcastReceiver headsetEventReceiver;
|
||||
private BroadcastReceiver ejectEventReceiver;
|
||||
private PhoneStateListener phoneStateListener;
|
||||
private boolean externalStorageAvailable= true;
|
||||
private ReentrantLock lock = new ReentrantLock();
|
||||
private final DownloadServiceImpl downloadService;
|
||||
private ScheduledExecutorService executorService;
|
||||
private BroadcastReceiver headsetEventReceiver;
|
||||
private BroadcastReceiver ejectEventReceiver;
|
||||
private PhoneStateListener phoneStateListener;
|
||||
private boolean externalStorageAvailable = true;
|
||||
private ReentrantLock lock = new ReentrantLock();
|
||||
private final AtomicBoolean setup = new AtomicBoolean(false);
|
||||
|
||||
/**
|
||||
* This receiver manages the intent that could come from other applications.
|
||||
*/
|
||||
private BroadcastReceiver intentReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
String action = intent.getAction();
|
||||
Log.i(TAG, "intentReceiver.onReceive: " + action);
|
||||
if (DownloadServiceImpl.CMD_PLAY.equals(action)) {
|
||||
downloadService.play();
|
||||
} else if (DownloadServiceImpl.CMD_NEXT.equals(action)) {
|
||||
downloadService.next();
|
||||
} else if (DownloadServiceImpl.CMD_PREVIOUS.equals(action)) {
|
||||
downloadService.previous();
|
||||
} else if (DownloadServiceImpl.CMD_TOGGLEPAUSE.equals(action)) {
|
||||
downloadService.togglePlayPause();
|
||||
} else if (DownloadServiceImpl.CMD_PAUSE.equals(action)) {
|
||||
downloadService.pause();
|
||||
} else if (DownloadServiceImpl.CMD_STOP.equals(action)) {
|
||||
downloadService.pause();
|
||||
downloadService.seekTo(0);
|
||||
}
|
||||
}
|
||||
};
|
||||
/**
|
||||
* This receiver manages the intent that could come from other applications.
|
||||
*/
|
||||
private BroadcastReceiver intentReceiver = new BroadcastReceiver()
|
||||
{
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent)
|
||||
{
|
||||
String action = intent.getAction();
|
||||
Log.i(TAG, "intentReceiver.onReceive: " + action);
|
||||
if (DownloadServiceImpl.CMD_PLAY.equals(action))
|
||||
{
|
||||
downloadService.play();
|
||||
}
|
||||
else if (DownloadServiceImpl.CMD_NEXT.equals(action))
|
||||
{
|
||||
downloadService.next();
|
||||
}
|
||||
else if (DownloadServiceImpl.CMD_PREVIOUS.equals(action))
|
||||
{
|
||||
downloadService.previous();
|
||||
}
|
||||
else if (DownloadServiceImpl.CMD_TOGGLEPAUSE.equals(action))
|
||||
{
|
||||
downloadService.togglePlayPause();
|
||||
}
|
||||
else if (DownloadServiceImpl.CMD_PAUSE.equals(action))
|
||||
{
|
||||
downloadService.pause();
|
||||
}
|
||||
else if (DownloadServiceImpl.CMD_STOP.equals(action))
|
||||
{
|
||||
downloadService.pause();
|
||||
downloadService.seekTo(0);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
public DownloadServiceLifecycleSupport(DownloadServiceImpl downloadService) {
|
||||
this.downloadService = downloadService;
|
||||
}
|
||||
public DownloadServiceLifecycleSupport(DownloadServiceImpl downloadService)
|
||||
{
|
||||
this.downloadService = downloadService;
|
||||
}
|
||||
|
||||
public void onCreate() {
|
||||
Runnable downloadChecker = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
downloadService.checkDownloads();
|
||||
} catch (Throwable x) {
|
||||
Log.e(TAG, "checkDownloads() failed.", x);
|
||||
}
|
||||
}
|
||||
};
|
||||
public void onCreate()
|
||||
{
|
||||
Runnable downloadChecker = new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
downloadService.checkDownloads();
|
||||
}
|
||||
catch (Throwable x)
|
||||
{
|
||||
Log.e(TAG, "checkDownloads() failed.", x);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
executorService = Executors.newSingleThreadScheduledExecutor();
|
||||
executorService.scheduleWithFixedDelay(downloadChecker, 5, 5, TimeUnit.SECONDS);
|
||||
executorService = Executors.newSingleThreadScheduledExecutor();
|
||||
executorService.scheduleWithFixedDelay(downloadChecker, 5, 5, TimeUnit.SECONDS);
|
||||
|
||||
// Pause when headset is unplugged.
|
||||
headsetEventReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
Log.i(TAG, "Headset event for: " + intent.getExtras().get("name"));
|
||||
if (intent.getExtras().getInt("state") == 0) {
|
||||
if(!downloadService.isJukeboxEnabled()) {
|
||||
// Pause when headset is unplugged.
|
||||
headsetEventReceiver = new BroadcastReceiver()
|
||||
{
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent)
|
||||
{
|
||||
Log.i(TAG, String.format("Headset event for: %s", intent.getExtras().get("name")));
|
||||
if (intent.getExtras().getInt("state") == 0)
|
||||
{
|
||||
if (!downloadService.isJukeboxEnabled())
|
||||
{
|
||||
downloadService.pause();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
downloadService.registerReceiver(headsetEventReceiver, new IntentFilter(Intent.ACTION_HEADSET_PLUG));
|
||||
}
|
||||
}
|
||||
};
|
||||
downloadService.registerReceiver(headsetEventReceiver, new IntentFilter(Intent.ACTION_HEADSET_PLUG));
|
||||
|
||||
// Stop when SD card is ejected.
|
||||
ejectEventReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
externalStorageAvailable = Intent.ACTION_MEDIA_MOUNTED.equals(intent.getAction());
|
||||
if (!externalStorageAvailable) {
|
||||
Log.i(TAG, "External media is ejecting. Stopping playback.");
|
||||
downloadService.reset();
|
||||
} else {
|
||||
Log.i(TAG, "External media is available.");
|
||||
}
|
||||
}
|
||||
};
|
||||
IntentFilter ejectFilter = new IntentFilter(Intent.ACTION_MEDIA_EJECT);
|
||||
ejectFilter.addAction(Intent.ACTION_MEDIA_MOUNTED);
|
||||
ejectFilter.addDataScheme("file");
|
||||
downloadService.registerReceiver(ejectEventReceiver, ejectFilter);
|
||||
// Stop when SD card is ejected.
|
||||
ejectEventReceiver = new BroadcastReceiver()
|
||||
{
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent)
|
||||
{
|
||||
externalStorageAvailable = Intent.ACTION_MEDIA_MOUNTED.equals(intent.getAction());
|
||||
if (!externalStorageAvailable)
|
||||
{
|
||||
Log.i(TAG, "External media is ejecting. Stopping playback.");
|
||||
downloadService.reset();
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.i(TAG, "External media is available.");
|
||||
}
|
||||
}
|
||||
};
|
||||
IntentFilter ejectFilter = new IntentFilter(Intent.ACTION_MEDIA_EJECT);
|
||||
ejectFilter.addAction(Intent.ACTION_MEDIA_MOUNTED);
|
||||
ejectFilter.addDataScheme("file");
|
||||
downloadService.registerReceiver(ejectEventReceiver, ejectFilter);
|
||||
|
||||
// React to media buttons.
|
||||
Util.registerMediaButtonEventReceiver(downloadService);
|
||||
// React to media buttons.
|
||||
Util.registerMediaButtonEventReceiver(downloadService);
|
||||
|
||||
// Pause temporarily on incoming phone calls.
|
||||
phoneStateListener = new MyPhoneStateListener();
|
||||
TelephonyManager telephonyManager = (TelephonyManager) downloadService.getSystemService(Context.TELEPHONY_SERVICE);
|
||||
telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
|
||||
// Pause temporarily on incoming phone calls.
|
||||
phoneStateListener = new MyPhoneStateListener();
|
||||
TelephonyManager telephonyManager = (TelephonyManager) downloadService.getSystemService(Context.TELEPHONY_SERVICE);
|
||||
telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
|
||||
|
||||
// Register the handler for outside intents.
|
||||
IntentFilter commandFilter = new IntentFilter();
|
||||
commandFilter.addAction(DownloadServiceImpl.CMD_PLAY);
|
||||
commandFilter.addAction(DownloadServiceImpl.CMD_TOGGLEPAUSE);
|
||||
commandFilter.addAction(DownloadServiceImpl.CMD_PAUSE);
|
||||
commandFilter.addAction(DownloadServiceImpl.CMD_STOP);
|
||||
commandFilter.addAction(DownloadServiceImpl.CMD_PREVIOUS);
|
||||
commandFilter.addAction(DownloadServiceImpl.CMD_NEXT);
|
||||
downloadService.registerReceiver(intentReceiver, commandFilter);
|
||||
|
||||
int instance = Util.getActiveServer(downloadService);
|
||||
downloadService.setJukeboxEnabled(Util.getJukeboxEnabled(downloadService, instance));
|
||||
// Register the handler for outside intents.
|
||||
IntentFilter commandFilter = new IntentFilter();
|
||||
commandFilter.addAction(DownloadServiceImpl.CMD_PLAY);
|
||||
commandFilter.addAction(DownloadServiceImpl.CMD_TOGGLEPAUSE);
|
||||
commandFilter.addAction(DownloadServiceImpl.CMD_PAUSE);
|
||||
commandFilter.addAction(DownloadServiceImpl.CMD_STOP);
|
||||
commandFilter.addAction(DownloadServiceImpl.CMD_PREVIOUS);
|
||||
commandFilter.addAction(DownloadServiceImpl.CMD_NEXT);
|
||||
downloadService.registerReceiver(intentReceiver, commandFilter);
|
||||
|
||||
deserializeDownloadQueue();
|
||||
int instance = Util.getActiveServer(downloadService);
|
||||
downloadService.setJukeboxEnabled(Util.getJukeboxEnabled(downloadService, instance));
|
||||
|
||||
new CacheCleaner(downloadService, downloadService).clean();
|
||||
}
|
||||
deserializeDownloadQueue();
|
||||
|
||||
public void onStart(Intent intent) {
|
||||
if (intent != null && intent.getExtras() != null) {
|
||||
KeyEvent event = (KeyEvent) intent.getExtras().get(Intent.EXTRA_KEY_EVENT);
|
||||
if (event != null) {
|
||||
handleKeyEvent(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
new CacheCleaner(downloadService, downloadService).clean();
|
||||
}
|
||||
|
||||
public void onDestroy() {
|
||||
executorService.shutdown();
|
||||
serializeDownloadQueueNow();
|
||||
downloadService.clear(false);
|
||||
downloadService.unregisterReceiver(ejectEventReceiver);
|
||||
downloadService.unregisterReceiver(headsetEventReceiver);
|
||||
downloadService.unregisterReceiver(intentReceiver);
|
||||
public void onStart(Intent intent)
|
||||
{
|
||||
if (intent != null && intent.getExtras() != null)
|
||||
{
|
||||
KeyEvent event = (KeyEvent) intent.getExtras().get(Intent.EXTRA_KEY_EVENT);
|
||||
if (event != null)
|
||||
{
|
||||
handleKeyEvent(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TelephonyManager telephonyManager = (TelephonyManager) downloadService.getSystemService(Context.TELEPHONY_SERVICE);
|
||||
telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_NONE);
|
||||
}
|
||||
public void onDestroy()
|
||||
{
|
||||
executorService.shutdown();
|
||||
serializeDownloadQueueNow();
|
||||
downloadService.clear(false);
|
||||
downloadService.unregisterReceiver(ejectEventReceiver);
|
||||
downloadService.unregisterReceiver(headsetEventReceiver);
|
||||
downloadService.unregisterReceiver(intentReceiver);
|
||||
|
||||
public boolean isExternalStorageAvailable() {
|
||||
return externalStorageAvailable;
|
||||
}
|
||||
TelephonyManager telephonyManager = (TelephonyManager) downloadService.getSystemService(Context.TELEPHONY_SERVICE);
|
||||
telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_NONE);
|
||||
}
|
||||
|
||||
public void serializeDownloadQueue() {
|
||||
if(!setup.get()) {
|
||||
public boolean isExternalStorageAvailable()
|
||||
{
|
||||
return externalStorageAvailable;
|
||||
}
|
||||
|
||||
public void serializeDownloadQueue()
|
||||
{
|
||||
if (!setup.get())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
new SerializeTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}
|
||||
|
||||
public void serializeDownloadQueueNow() {
|
||||
List<DownloadFile> songs = new ArrayList<DownloadFile>(downloadService.getSongs());
|
||||
new SerializeTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}
|
||||
|
||||
public void serializeDownloadQueueNow()
|
||||
{
|
||||
List<DownloadFile> songs = new ArrayList<DownloadFile>(downloadService.getSongs());
|
||||
State state = new State();
|
||||
for (DownloadFile downloadFile : songs) {
|
||||
for (DownloadFile downloadFile : songs)
|
||||
{
|
||||
state.songs.add(downloadFile.getSong());
|
||||
}
|
||||
state.currentPlayingIndex = downloadService.getCurrentPlayingIndex();
|
||||
|
@ -206,29 +246,36 @@ public class DownloadServiceLifecycleSupport {
|
|||
|
||||
Log.i(TAG, "Serialized currentPlayingIndex: " + state.currentPlayingIndex + ", currentPlayingPosition: " + state.currentPlayingPosition);
|
||||
FileUtil.serialize(downloadService, state, FILENAME_DOWNLOADS_SER);
|
||||
}
|
||||
}
|
||||
|
||||
private void deserializeDownloadQueue() {
|
||||
private void deserializeDownloadQueue()
|
||||
{
|
||||
new DeserializeTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}
|
||||
private void deserializeDownloadQueueNow() {
|
||||
State state = FileUtil.deserialize(downloadService, FILENAME_DOWNLOADS_SER);
|
||||
if (state == null) {
|
||||
return;
|
||||
}
|
||||
Log.i(TAG, "Deserialized currentPlayingIndex: " + state.currentPlayingIndex + ", currentPlayingPosition: " + state.currentPlayingPosition);
|
||||
downloadService.restore(state.songs, state.currentPlayingIndex, state.currentPlayingPosition, false, false);
|
||||
|
||||
// Work-around: Serialize again, as the restore() method creates a serialization without current playing info.
|
||||
serializeDownloadQueue();
|
||||
}
|
||||
|
||||
private void handleKeyEvent(KeyEvent event) {
|
||||
if (event.getAction() != KeyEvent.ACTION_DOWN || event.getRepeatCount() > 0) {
|
||||
return;
|
||||
}
|
||||
private void deserializeDownloadQueueNow()
|
||||
{
|
||||
State state = FileUtil.deserialize(downloadService, FILENAME_DOWNLOADS_SER);
|
||||
if (state == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
Log.i(TAG, "Deserialized currentPlayingIndex: " + state.currentPlayingIndex + ", currentPlayingPosition: " + state.currentPlayingPosition);
|
||||
downloadService.restore(state.songs, state.currentPlayingIndex, state.currentPlayingPosition, false, false);
|
||||
|
||||
switch (event.getKeyCode()) {
|
||||
// Work-around: Serialize again, as the restore() method creates a serialization without current playing info.
|
||||
serializeDownloadQueue();
|
||||
}
|
||||
|
||||
private void handleKeyEvent(KeyEvent event)
|
||||
{
|
||||
if (event.getAction() != KeyEvent.ACTION_DOWN || event.getRepeatCount() > 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch (event.getKeyCode())
|
||||
{
|
||||
case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
|
||||
case KeyEvent.KEYCODE_HEADSETHOOK:
|
||||
downloadService.togglePlayPause();
|
||||
|
@ -237,7 +284,8 @@ public class DownloadServiceLifecycleSupport {
|
|||
downloadService.previous();
|
||||
break;
|
||||
case KeyEvent.KEYCODE_MEDIA_NEXT:
|
||||
if (downloadService.getCurrentPlayingIndex() < downloadService.size() - 1) {
|
||||
if (downloadService.getCurrentPlayingIndex() < downloadService.size() - 1)
|
||||
{
|
||||
downloadService.next();
|
||||
}
|
||||
break;
|
||||
|
@ -245,76 +293,95 @@ public class DownloadServiceLifecycleSupport {
|
|||
downloadService.stop();
|
||||
break;
|
||||
case KeyEvent.KEYCODE_MEDIA_PLAY:
|
||||
if(downloadService.getPlayerState() != PlayerState.STARTED) {
|
||||
if (downloadService.getPlayerState() != PlayerState.STARTED)
|
||||
{
|
||||
downloadService.start();
|
||||
}
|
||||
break;
|
||||
case KeyEvent.KEYCODE_MEDIA_PAUSE:
|
||||
downloadService.pause();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Logic taken from packages/apps/Music. Will pause when an incoming
|
||||
* call rings or if a call (incoming or outgoing) is connected.
|
||||
*/
|
||||
private class MyPhoneStateListener extends PhoneStateListener {
|
||||
private boolean resumeAfterCall;
|
||||
/**
|
||||
* Logic taken from packages/apps/Music. Will pause when an incoming
|
||||
* call rings or if a call (incoming or outgoing) is connected.
|
||||
*/
|
||||
private class MyPhoneStateListener extends PhoneStateListener
|
||||
{
|
||||
private boolean resumeAfterCall;
|
||||
|
||||
@Override
|
||||
public void onCallStateChanged(int state, String incomingNumber) {
|
||||
switch (state) {
|
||||
case TelephonyManager.CALL_STATE_RINGING:
|
||||
case TelephonyManager.CALL_STATE_OFFHOOK:
|
||||
if (downloadService.getPlayerState() == PlayerState.STARTED && !downloadService.isJukeboxEnabled()) {
|
||||
resumeAfterCall = true;
|
||||
downloadService.pause();
|
||||
}
|
||||
break;
|
||||
case TelephonyManager.CALL_STATE_IDLE:
|
||||
if (resumeAfterCall) {
|
||||
resumeAfterCall = false;
|
||||
downloadService.start();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class State implements Serializable {
|
||||
private static final long serialVersionUID = -6346438781062572270L;
|
||||
|
||||
private List<MusicDirectory.Entry> songs = new ArrayList<MusicDirectory.Entry>();
|
||||
private int currentPlayingIndex;
|
||||
private int currentPlayingPosition;
|
||||
}
|
||||
|
||||
private class SerializeTask extends AsyncTask<Void, Void, Void> {
|
||||
@Override
|
||||
protected Void doInBackground(Void... params) {
|
||||
if(lock.tryLock()) {
|
||||
try {
|
||||
public void onCallStateChanged(int state, String incomingNumber)
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case TelephonyManager.CALL_STATE_RINGING:
|
||||
case TelephonyManager.CALL_STATE_OFFHOOK:
|
||||
if (downloadService.getPlayerState() == PlayerState.STARTED && !downloadService.isJukeboxEnabled())
|
||||
{
|
||||
resumeAfterCall = true;
|
||||
downloadService.pause();
|
||||
}
|
||||
break;
|
||||
case TelephonyManager.CALL_STATE_IDLE:
|
||||
if (resumeAfterCall)
|
||||
{
|
||||
resumeAfterCall = false;
|
||||
downloadService.start();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class State implements Serializable
|
||||
{
|
||||
private static final long serialVersionUID = -6346438781062572270L;
|
||||
|
||||
private List<MusicDirectory.Entry> songs = new ArrayList<MusicDirectory.Entry>();
|
||||
private int currentPlayingIndex;
|
||||
private int currentPlayingPosition;
|
||||
}
|
||||
|
||||
private class SerializeTask extends AsyncTask<Void, Void, Void>
|
||||
{
|
||||
@Override
|
||||
protected Void doInBackground(Void... params)
|
||||
{
|
||||
if (lock.tryLock())
|
||||
{
|
||||
try
|
||||
{
|
||||
serializeDownloadQueueNow();
|
||||
} finally {
|
||||
}
|
||||
finally
|
||||
{
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
private class DeserializeTask extends AsyncTask<Void, Void, Void> {
|
||||
|
||||
private class DeserializeTask extends AsyncTask<Void, Void, Void>
|
||||
{
|
||||
@Override
|
||||
protected Void doInBackground(Void... params) {
|
||||
try {
|
||||
protected Void doInBackground(Void... params)
|
||||
{
|
||||
try
|
||||
{
|
||||
lock.lock();
|
||||
deserializeDownloadQueueNow();
|
||||
setup.set(true);
|
||||
} finally {
|
||||
}
|
||||
finally
|
||||
{
|
||||
lock.unlock();
|
||||
}
|
||||
return null;
|
||||
|
|
|
@ -26,6 +26,7 @@ import android.view.LayoutInflater;
|
|||
import android.view.View;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.thejoshwa.ultrasonic.androidapp.R;
|
||||
import com.thejoshwa.ultrasonic.androidapp.domain.JukeboxStatus;
|
||||
import com.thejoshwa.ultrasonic.androidapp.domain.PlayerState;
|
||||
|
@ -48,312 +49,383 @@ import java.util.concurrent.atomic.AtomicLong;
|
|||
* @author Sindre Mehus
|
||||
* @version $Id$
|
||||
*/
|
||||
public class JukeboxService {
|
||||
public class JukeboxService
|
||||
{
|
||||
|
||||
private static final String TAG = JukeboxService.class.getSimpleName();
|
||||
private static final long STATUS_UPDATE_INTERVAL_SECONDS = 5L;
|
||||
private static final String TAG = JukeboxService.class.getSimpleName();
|
||||
private static final long STATUS_UPDATE_INTERVAL_SECONDS = 5L;
|
||||
|
||||
private final Handler handler = new Handler();
|
||||
private final TaskQueue tasks = new TaskQueue();
|
||||
private final DownloadServiceImpl downloadService;
|
||||
private final ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
|
||||
private ScheduledFuture<?> statusUpdateFuture;
|
||||
private final AtomicLong timeOfLastUpdate = new AtomicLong();
|
||||
private JukeboxStatus jukeboxStatus;
|
||||
private float gain = 0.5f;
|
||||
private VolumeToast volumeToast;
|
||||
private final Handler handler = new Handler();
|
||||
private final TaskQueue tasks = new TaskQueue();
|
||||
private final DownloadServiceImpl downloadService;
|
||||
private final ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
|
||||
private ScheduledFuture<?> statusUpdateFuture;
|
||||
private final AtomicLong timeOfLastUpdate = new AtomicLong();
|
||||
private JukeboxStatus jukeboxStatus;
|
||||
private float gain = 0.5f;
|
||||
private VolumeToast volumeToast;
|
||||
|
||||
// TODO: Report warning if queue fills up.
|
||||
// TODO: Create shutdown method?
|
||||
// TODO: Disable repeat.
|
||||
// TODO: Persist RC state?
|
||||
// TODO: Minimize status updates.
|
||||
// TODO: Report warning if queue fills up.
|
||||
// TODO: Create shutdown method?
|
||||
// TODO: Disable repeat.
|
||||
// TODO: Persist RC state?
|
||||
// TODO: Minimize status updates.
|
||||
|
||||
public JukeboxService(DownloadServiceImpl downloadService) {
|
||||
this.downloadService = downloadService;
|
||||
new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
processTasks();
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
public JukeboxService(DownloadServiceImpl downloadService)
|
||||
{
|
||||
this.downloadService = downloadService;
|
||||
new Thread()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
processTasks();
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
|
||||
private synchronized void startStatusUpdate() {
|
||||
stopStatusUpdate();
|
||||
Runnable updateTask = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
tasks.remove(GetStatus.class);
|
||||
tasks.add(new GetStatus());
|
||||
}
|
||||
};
|
||||
statusUpdateFuture = executorService.scheduleWithFixedDelay(updateTask, STATUS_UPDATE_INTERVAL_SECONDS,
|
||||
STATUS_UPDATE_INTERVAL_SECONDS, TimeUnit.SECONDS);
|
||||
}
|
||||
private synchronized void startStatusUpdate()
|
||||
{
|
||||
stopStatusUpdate();
|
||||
Runnable updateTask = new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
tasks.remove(GetStatus.class);
|
||||
tasks.add(new GetStatus());
|
||||
}
|
||||
};
|
||||
statusUpdateFuture = executorService.scheduleWithFixedDelay(updateTask, STATUS_UPDATE_INTERVAL_SECONDS, STATUS_UPDATE_INTERVAL_SECONDS, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
private synchronized void stopStatusUpdate() {
|
||||
if (statusUpdateFuture != null) {
|
||||
statusUpdateFuture.cancel(false);
|
||||
statusUpdateFuture = null;
|
||||
}
|
||||
}
|
||||
private synchronized void stopStatusUpdate()
|
||||
{
|
||||
if (statusUpdateFuture != null)
|
||||
{
|
||||
statusUpdateFuture.cancel(false);
|
||||
statusUpdateFuture = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void processTasks() {
|
||||
while (true) {
|
||||
JukeboxTask task = null;
|
||||
try {
|
||||
if (!Util.isOffline(downloadService)) {
|
||||
task = tasks.take();
|
||||
JukeboxStatus status = task.execute();
|
||||
onStatusUpdate(status);
|
||||
}
|
||||
} catch (Throwable x) {
|
||||
onError(task, x);
|
||||
}
|
||||
}
|
||||
}
|
||||
private void processTasks()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
JukeboxTask task = null;
|
||||
try
|
||||
{
|
||||
if (!Util.isOffline(downloadService))
|
||||
{
|
||||
task = tasks.take();
|
||||
JukeboxStatus status = task.execute();
|
||||
onStatusUpdate(status);
|
||||
}
|
||||
}
|
||||
catch (Throwable x)
|
||||
{
|
||||
onError(task, x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void onStatusUpdate(JukeboxStatus jukeboxStatus) {
|
||||
timeOfLastUpdate.set(System.currentTimeMillis());
|
||||
this.jukeboxStatus = jukeboxStatus;
|
||||
private void onStatusUpdate(JukeboxStatus jukeboxStatus)
|
||||
{
|
||||
timeOfLastUpdate.set(System.currentTimeMillis());
|
||||
this.jukeboxStatus = jukeboxStatus;
|
||||
|
||||
// Track change?
|
||||
Integer index = jukeboxStatus.getCurrentPlayingIndex();
|
||||
if (index != null && index != -1 && index != downloadService.getCurrentPlayingIndex()) {
|
||||
downloadService.setCurrentPlaying(index);
|
||||
}
|
||||
}
|
||||
// Track change?
|
||||
Integer index = jukeboxStatus.getCurrentPlayingIndex();
|
||||
if (index != null && index != -1 && index != downloadService.getCurrentPlayingIndex())
|
||||
{
|
||||
downloadService.setCurrentPlaying(index);
|
||||
}
|
||||
}
|
||||
|
||||
private void onError(JukeboxTask task, Throwable x) {
|
||||
if (x instanceof ServerTooOldException && !(task instanceof Stop)) {
|
||||
disableJukeboxOnError(x, R.string.download_jukebox_server_too_old);
|
||||
} else if (x instanceof OfflineException && !(task instanceof Stop)) {
|
||||
disableJukeboxOnError(x, R.string.download_jukebox_offline);
|
||||
} else if (x instanceof SubsonicRESTException && ((SubsonicRESTException) x).getCode() == 50 && !(task instanceof Stop)) {
|
||||
disableJukeboxOnError(x, R.string.download_jukebox_not_authorized);
|
||||
} else {
|
||||
Log.e(TAG, "Failed to process jukebox task: " + x, x);
|
||||
}
|
||||
}
|
||||
private void onError(JukeboxTask task, Throwable x)
|
||||
{
|
||||
if (x instanceof ServerTooOldException && !(task instanceof Stop))
|
||||
{
|
||||
disableJukeboxOnError(x, R.string.download_jukebox_server_too_old);
|
||||
}
|
||||
else if (x instanceof OfflineException && !(task instanceof Stop))
|
||||
{
|
||||
disableJukeboxOnError(x, R.string.download_jukebox_offline);
|
||||
}
|
||||
else if (x instanceof SubsonicRESTException && ((SubsonicRESTException) x).getCode() == 50 && !(task instanceof Stop))
|
||||
{
|
||||
disableJukeboxOnError(x, R.string.download_jukebox_not_authorized);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.e(TAG, "Failed to process jukebox task: " + x, x);
|
||||
}
|
||||
}
|
||||
|
||||
private void disableJukeboxOnError(Throwable x, final int resourceId) {
|
||||
Log.w(TAG, x.toString());
|
||||
handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Util.toast(downloadService, resourceId, false);
|
||||
}
|
||||
});
|
||||
downloadService.setJukeboxEnabled(false);
|
||||
}
|
||||
private void disableJukeboxOnError(Throwable x, final int resourceId)
|
||||
{
|
||||
Log.w(TAG, x.toString());
|
||||
handler.post(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
Util.toast(downloadService, resourceId, false);
|
||||
}
|
||||
});
|
||||
downloadService.setJukeboxEnabled(false);
|
||||
}
|
||||
|
||||
public void updatePlaylist() {
|
||||
tasks.remove(Skip.class);
|
||||
tasks.remove(Stop.class);
|
||||
tasks.remove(Start.class);
|
||||
public void updatePlaylist()
|
||||
{
|
||||
tasks.remove(Skip.class);
|
||||
tasks.remove(Stop.class);
|
||||
tasks.remove(Start.class);
|
||||
|
||||
List<String> ids = new ArrayList<String>();
|
||||
for (DownloadFile file : downloadService.getDownloads()) {
|
||||
ids.add(file.getSong().getId());
|
||||
}
|
||||
tasks.add(new SetPlaylist(ids));
|
||||
}
|
||||
List<String> ids = new ArrayList<String>();
|
||||
for (DownloadFile file : downloadService.getDownloads())
|
||||
{
|
||||
ids.add(file.getSong().getId());
|
||||
}
|
||||
tasks.add(new SetPlaylist(ids));
|
||||
}
|
||||
|
||||
public void skip(final int index, final int offsetSeconds) {
|
||||
tasks.remove(Skip.class);
|
||||
tasks.remove(Stop.class);
|
||||
tasks.remove(Start.class);
|
||||
public void skip(final int index, final int offsetSeconds)
|
||||
{
|
||||
tasks.remove(Skip.class);
|
||||
tasks.remove(Stop.class);
|
||||
tasks.remove(Start.class);
|
||||
|
||||
startStatusUpdate();
|
||||
|
||||
if (jukeboxStatus != null) {
|
||||
jukeboxStatus.setPositionSeconds(offsetSeconds);
|
||||
}
|
||||
|
||||
tasks.add(new Skip(index, offsetSeconds));
|
||||
downloadService.setPlayerState(PlayerState.STARTED);
|
||||
}
|
||||
startStatusUpdate();
|
||||
|
||||
public void stop() {
|
||||
tasks.remove(Stop.class);
|
||||
tasks.remove(Start.class);
|
||||
if (jukeboxStatus != null)
|
||||
{
|
||||
jukeboxStatus.setPositionSeconds(offsetSeconds);
|
||||
}
|
||||
|
||||
stopStatusUpdate();
|
||||
tasks.add(new Stop());
|
||||
}
|
||||
tasks.add(new Skip(index, offsetSeconds));
|
||||
downloadService.setPlayerState(PlayerState.STARTED);
|
||||
}
|
||||
|
||||
public void start() {
|
||||
tasks.remove(Stop.class);
|
||||
tasks.remove(Start.class);
|
||||
public void stop()
|
||||
{
|
||||
tasks.remove(Stop.class);
|
||||
tasks.remove(Start.class);
|
||||
|
||||
startStatusUpdate();
|
||||
tasks.add(new Start());
|
||||
}
|
||||
stopStatusUpdate();
|
||||
tasks.add(new Stop());
|
||||
}
|
||||
|
||||
public synchronized void adjustVolume(boolean up) {
|
||||
float delta = up ? 0.05f : -0.05f;
|
||||
gain += delta;
|
||||
gain = Math.max(gain, 0.0f);
|
||||
gain = Math.min(gain, 1.0f);
|
||||
public void start()
|
||||
{
|
||||
tasks.remove(Stop.class);
|
||||
tasks.remove(Start.class);
|
||||
|
||||
tasks.remove(SetGain.class);
|
||||
tasks.add(new SetGain(gain));
|
||||
startStatusUpdate();
|
||||
tasks.add(new Start());
|
||||
}
|
||||
|
||||
if (volumeToast == null) {
|
||||
volumeToast = new VolumeToast(downloadService);
|
||||
}
|
||||
volumeToast.setVolume(gain);
|
||||
}
|
||||
public synchronized void adjustVolume(boolean up)
|
||||
{
|
||||
float delta = up ? 0.05f : -0.05f;
|
||||
gain += delta;
|
||||
gain = Math.max(gain, 0.0f);
|
||||
gain = Math.min(gain, 1.0f);
|
||||
|
||||
private MusicService getMusicService() {
|
||||
return MusicServiceFactory.getMusicService(downloadService);
|
||||
}
|
||||
tasks.remove(SetGain.class);
|
||||
tasks.add(new SetGain(gain));
|
||||
|
||||
public int getPositionSeconds() {
|
||||
if (jukeboxStatus == null || jukeboxStatus.getPositionSeconds() == null || timeOfLastUpdate.get() == 0) {
|
||||
return 0;
|
||||
}
|
||||
if (volumeToast == null)
|
||||
{
|
||||
volumeToast = new VolumeToast(downloadService);
|
||||
}
|
||||
volumeToast.setVolume(gain);
|
||||
}
|
||||
|
||||
if (jukeboxStatus.isPlaying()) {
|
||||
int secondsSinceLastUpdate = (int) ((System.currentTimeMillis() - timeOfLastUpdate.get()) / 1000L);
|
||||
return jukeboxStatus.getPositionSeconds() + secondsSinceLastUpdate;
|
||||
}
|
||||
private MusicService getMusicService()
|
||||
{
|
||||
return MusicServiceFactory.getMusicService(downloadService);
|
||||
}
|
||||
|
||||
return jukeboxStatus.getPositionSeconds();
|
||||
}
|
||||
public int getPositionSeconds()
|
||||
{
|
||||
if (jukeboxStatus == null || jukeboxStatus.getPositionSeconds() == null || timeOfLastUpdate.get() == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
tasks.clear();
|
||||
if (enabled) {
|
||||
updatePlaylist();
|
||||
}
|
||||
stop();
|
||||
downloadService.setPlayerState(PlayerState.IDLE);
|
||||
}
|
||||
if (jukeboxStatus.isPlaying())
|
||||
{
|
||||
int secondsSinceLastUpdate = (int) ((System.currentTimeMillis() - timeOfLastUpdate.get()) / 1000L);
|
||||
return jukeboxStatus.getPositionSeconds() + secondsSinceLastUpdate;
|
||||
}
|
||||
|
||||
private static class TaskQueue {
|
||||
return jukeboxStatus.getPositionSeconds();
|
||||
}
|
||||
|
||||
private final LinkedBlockingQueue<JukeboxTask> queue = new LinkedBlockingQueue<JukeboxTask>();
|
||||
public void setEnabled(boolean enabled)
|
||||
{
|
||||
tasks.clear();
|
||||
if (enabled)
|
||||
{
|
||||
updatePlaylist();
|
||||
}
|
||||
stop();
|
||||
downloadService.setPlayerState(PlayerState.IDLE);
|
||||
}
|
||||
|
||||
void add(JukeboxTask jukeboxTask) {
|
||||
queue.add(jukeboxTask);
|
||||
}
|
||||
private static class TaskQueue
|
||||
{
|
||||
|
||||
JukeboxTask take() throws InterruptedException {
|
||||
return queue.take();
|
||||
}
|
||||
private final LinkedBlockingQueue<JukeboxTask> queue = new LinkedBlockingQueue<JukeboxTask>();
|
||||
|
||||
void remove(Class<? extends JukeboxTask> clazz) {
|
||||
try {
|
||||
Iterator<JukeboxTask> iterator = queue.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
JukeboxTask task = iterator.next();
|
||||
if (clazz.equals(task.getClass())) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
} catch (Throwable x) {
|
||||
Log.w(TAG, "Failed to clean-up task queue.", x);
|
||||
}
|
||||
}
|
||||
void add(JukeboxTask jukeboxTask)
|
||||
{
|
||||
queue.add(jukeboxTask);
|
||||
}
|
||||
|
||||
void clear() {
|
||||
queue.clear();
|
||||
}
|
||||
}
|
||||
JukeboxTask take() throws InterruptedException
|
||||
{
|
||||
return queue.take();
|
||||
}
|
||||
|
||||
private abstract class JukeboxTask {
|
||||
void remove(Class<? extends JukeboxTask> clazz)
|
||||
{
|
||||
try
|
||||
{
|
||||
Iterator<JukeboxTask> iterator = queue.iterator();
|
||||
while (iterator.hasNext())
|
||||
{
|
||||
JukeboxTask task = iterator.next();
|
||||
if (clazz.equals(task.getClass()))
|
||||
{
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Throwable x)
|
||||
{
|
||||
Log.w(TAG, "Failed to clean-up task queue.", x);
|
||||
}
|
||||
}
|
||||
|
||||
abstract JukeboxStatus execute() throws Exception;
|
||||
void clear()
|
||||
{
|
||||
queue.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getClass().getSimpleName();
|
||||
}
|
||||
}
|
||||
private abstract class JukeboxTask
|
||||
{
|
||||
|
||||
private class GetStatus extends JukeboxTask {
|
||||
@Override
|
||||
JukeboxStatus execute() throws Exception {
|
||||
return getMusicService().getJukeboxStatus(downloadService, null);
|
||||
}
|
||||
}
|
||||
abstract JukeboxStatus execute() throws Exception;
|
||||
|
||||
private class SetPlaylist extends JukeboxTask {
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return getClass().getSimpleName();
|
||||
}
|
||||
}
|
||||
|
||||
private final List<String> ids;
|
||||
private class GetStatus extends JukeboxTask
|
||||
{
|
||||
@Override
|
||||
JukeboxStatus execute() throws Exception
|
||||
{
|
||||
return getMusicService().getJukeboxStatus(downloadService, null);
|
||||
}
|
||||
}
|
||||
|
||||
SetPlaylist(List<String> ids) {
|
||||
this.ids = ids;
|
||||
}
|
||||
private class SetPlaylist extends JukeboxTask
|
||||
{
|
||||
|
||||
@Override
|
||||
JukeboxStatus execute() throws Exception {
|
||||
return getMusicService().updateJukeboxPlaylist(ids, downloadService, null);
|
||||
}
|
||||
}
|
||||
private final List<String> ids;
|
||||
|
||||
private class Skip extends JukeboxTask {
|
||||
private final int index;
|
||||
private final int offsetSeconds;
|
||||
SetPlaylist(List<String> ids)
|
||||
{
|
||||
this.ids = ids;
|
||||
}
|
||||
|
||||
Skip(int index, int offsetSeconds) {
|
||||
this.index = index;
|
||||
this.offsetSeconds = offsetSeconds;
|
||||
}
|
||||
@Override
|
||||
JukeboxStatus execute() throws Exception
|
||||
{
|
||||
return getMusicService().updateJukeboxPlaylist(ids, downloadService, null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
JukeboxStatus execute() throws Exception {
|
||||
return getMusicService().skipJukebox(index, offsetSeconds, downloadService, null);
|
||||
}
|
||||
}
|
||||
private class Skip extends JukeboxTask
|
||||
{
|
||||
private final int index;
|
||||
private final int offsetSeconds;
|
||||
|
||||
private class Stop extends JukeboxTask {
|
||||
@Override
|
||||
JukeboxStatus execute() throws Exception {
|
||||
return getMusicService().stopJukebox(downloadService, null);
|
||||
}
|
||||
}
|
||||
Skip(int index, int offsetSeconds)
|
||||
{
|
||||
this.index = index;
|
||||
this.offsetSeconds = offsetSeconds;
|
||||
}
|
||||
|
||||
private class Start extends JukeboxTask {
|
||||
@Override
|
||||
JukeboxStatus execute() throws Exception {
|
||||
return getMusicService().startJukebox(downloadService, null);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
JukeboxStatus execute() throws Exception
|
||||
{
|
||||
return getMusicService().skipJukebox(index, offsetSeconds, downloadService, null);
|
||||
}
|
||||
}
|
||||
|
||||
private class SetGain extends JukeboxTask {
|
||||
private class Stop extends JukeboxTask
|
||||
{
|
||||
@Override
|
||||
JukeboxStatus execute() throws Exception
|
||||
{
|
||||
return getMusicService().stopJukebox(downloadService, null);
|
||||
}
|
||||
}
|
||||
|
||||
private final float gain;
|
||||
private class Start extends JukeboxTask
|
||||
{
|
||||
@Override
|
||||
JukeboxStatus execute() throws Exception
|
||||
{
|
||||
return getMusicService().startJukebox(downloadService, null);
|
||||
}
|
||||
}
|
||||
|
||||
private SetGain(float gain) {
|
||||
this.gain = gain;
|
||||
}
|
||||
private class SetGain extends JukeboxTask
|
||||
{
|
||||
|
||||
@Override
|
||||
JukeboxStatus execute() throws Exception {
|
||||
return getMusicService().setJukeboxGain(gain, downloadService, null);
|
||||
}
|
||||
}
|
||||
private final float gain;
|
||||
|
||||
private static class VolumeToast extends Toast {
|
||||
private SetGain(float gain)
|
||||
{
|
||||
this.gain = gain;
|
||||
}
|
||||
|
||||
private final ProgressBar progressBar;
|
||||
@Override
|
||||
JukeboxStatus execute() throws Exception
|
||||
{
|
||||
return getMusicService().setJukeboxGain(gain, downloadService, null);
|
||||
}
|
||||
}
|
||||
|
||||
public VolumeToast(Context context) {
|
||||
super(context);
|
||||
setDuration(Toast.LENGTH_SHORT);
|
||||
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
View view = inflater.inflate(R.layout.jukebox_volume, null);
|
||||
progressBar = (ProgressBar) view.findViewById(R.id.jukebox_volume_progress_bar);
|
||||
setView(view);
|
||||
setGravity(Gravity.TOP, 0, 0);
|
||||
}
|
||||
private static class VolumeToast extends Toast
|
||||
{
|
||||
|
||||
public void setVolume(float volume) {
|
||||
progressBar.setProgress(Math.round(100 * volume));
|
||||
show();
|
||||
}
|
||||
}
|
||||
private final ProgressBar progressBar;
|
||||
|
||||
public VolumeToast(Context context)
|
||||
{
|
||||
super(context);
|
||||
setDuration(Toast.LENGTH_SHORT);
|
||||
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
View view = inflater.inflate(R.layout.jukebox_volume, null);
|
||||
progressBar = (ProgressBar) view.findViewById(R.id.jukebox_volume_progress_bar);
|
||||
setView(view);
|
||||
setGravity(Gravity.TOP, 0, 0);
|
||||
}
|
||||
|
||||
public void setVolume(float volume)
|
||||
{
|
||||
progressBar.setProgress(Math.round(100 * volume));
|
||||
show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,91 +27,101 @@ import android.database.Cursor;
|
|||
import android.net.Uri;
|
||||
import android.provider.MediaStore;
|
||||
import android.util.Log;
|
||||
|
||||
import com.thejoshwa.ultrasonic.androidapp.domain.MusicDirectory;
|
||||
import com.thejoshwa.ultrasonic.androidapp.util.FileUtil;
|
||||
|
||||
/**
|
||||
* @author Sindre Mehus
|
||||
*/
|
||||
public class MediaStoreService {
|
||||
public class MediaStoreService
|
||||
{
|
||||
|
||||
private static final String TAG = MediaStoreService.class.getSimpleName();
|
||||
private static final Uri ALBUM_ART_URI = Uri.parse("content://media/external/audio/albumart");
|
||||
private static final String TAG = MediaStoreService.class.getSimpleName();
|
||||
private static final Uri ALBUM_ART_URI = Uri.parse("content://media/external/audio/albumart");
|
||||
|
||||
private final Context context;
|
||||
private final Context context;
|
||||
|
||||
public MediaStoreService(Context context) {
|
||||
this.context = context;
|
||||
}
|
||||
public MediaStoreService(Context context)
|
||||
{
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
public void saveInMediaStore(DownloadFile downloadFile) {
|
||||
MusicDirectory.Entry song = downloadFile.getSong();
|
||||
File songFile = downloadFile.getCompleteFile();
|
||||
public void saveInMediaStore(DownloadFile downloadFile)
|
||||
{
|
||||
MusicDirectory.Entry song = downloadFile.getSong();
|
||||
File songFile = downloadFile.getCompleteFile();
|
||||
|
||||
// Delete existing row in case the song has been downloaded before.
|
||||
deleteFromMediaStore(downloadFile);
|
||||
// Delete existing row in case the song has been downloaded before.
|
||||
deleteFromMediaStore(downloadFile);
|
||||
|
||||
ContentResolver contentResolver = context.getContentResolver();
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(MediaStore.MediaColumns.TITLE, song.getTitle());
|
||||
values.put(MediaStore.Audio.AudioColumns.ARTIST, song.getArtist());
|
||||
values.put(MediaStore.Audio.AudioColumns.ALBUM, song.getAlbum());
|
||||
values.put(MediaStore.Audio.AudioColumns.TRACK, song.getTrack());
|
||||
values.put(MediaStore.Audio.AudioColumns.YEAR, song.getYear());
|
||||
values.put(MediaStore.MediaColumns.DATA, songFile.getAbsolutePath());
|
||||
values.put(MediaStore.MediaColumns.MIME_TYPE, song.getContentType());
|
||||
values.put(MediaStore.Audio.AudioColumns.IS_MUSIC, 1);
|
||||
ContentResolver contentResolver = context.getContentResolver();
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(MediaStore.MediaColumns.TITLE, song.getTitle());
|
||||
values.put(MediaStore.Audio.AudioColumns.ARTIST, song.getArtist());
|
||||
values.put(MediaStore.Audio.AudioColumns.ALBUM, song.getAlbum());
|
||||
values.put(MediaStore.Audio.AudioColumns.TRACK, song.getTrack());
|
||||
values.put(MediaStore.Audio.AudioColumns.YEAR, song.getYear());
|
||||
values.put(MediaStore.MediaColumns.DATA, songFile.getAbsolutePath());
|
||||
values.put(MediaStore.MediaColumns.MIME_TYPE, song.getContentType());
|
||||
values.put(MediaStore.Audio.AudioColumns.IS_MUSIC, 1);
|
||||
|
||||
Uri uri = contentResolver.insert(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, values);
|
||||
Uri uri = contentResolver.insert(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, values);
|
||||
|
||||
if (uri != null) {
|
||||
// Look up album, and add cover art if found.
|
||||
Cursor cursor = contentResolver.query(uri, new String[]{MediaStore.Audio.AudioColumns.ALBUM_ID}, null, null, null);
|
||||
if (uri != null)
|
||||
{
|
||||
// Look up album, and add cover art if found.
|
||||
Cursor cursor = contentResolver.query(uri, new String[]{MediaStore.Audio.AudioColumns.ALBUM_ID}, null, null, null);
|
||||
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
int albumId = cursor.getInt(0);
|
||||
insertAlbumArt(albumId, downloadFile);
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cursor != null && cursor.moveToFirst())
|
||||
{
|
||||
int albumId = cursor.getInt(0);
|
||||
insertAlbumArt(albumId, downloadFile);
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void deleteFromMediaStore(DownloadFile downloadFile) {
|
||||
ContentResolver contentResolver = context.getContentResolver();
|
||||
MusicDirectory.Entry song = downloadFile.getSong();
|
||||
File file = downloadFile.getCompleteFile();
|
||||
public void deleteFromMediaStore(DownloadFile downloadFile)
|
||||
{
|
||||
ContentResolver contentResolver = context.getContentResolver();
|
||||
MusicDirectory.Entry song = downloadFile.getSong();
|
||||
File file = downloadFile.getCompleteFile();
|
||||
|
||||
int n = contentResolver.delete(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
|
||||
MediaStore.Audio.AudioColumns.TITLE_KEY + "=? AND " +
|
||||
MediaStore.MediaColumns.DATA + "=?",
|
||||
new String[]{MediaStore.Audio.keyFor(song.getTitle()), file.getAbsolutePath()});
|
||||
if (n > 0) {
|
||||
Log.i(TAG, "Deleting media store row for " + song);
|
||||
}
|
||||
}
|
||||
int n = contentResolver.delete(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, MediaStore.Audio.AudioColumns.TITLE_KEY + "=? AND " +
|
||||
MediaStore.MediaColumns.DATA + "=?", new String[]{MediaStore.Audio.keyFor(song.getTitle()), file.getAbsolutePath()});
|
||||
if (n > 0)
|
||||
{
|
||||
Log.i(TAG, "Deleting media store row for " + song);
|
||||
}
|
||||
}
|
||||
|
||||
private void insertAlbumArt(int albumId, DownloadFile downloadFile) {
|
||||
ContentResolver contentResolver = context.getContentResolver();
|
||||
Uri uri = Uri.withAppendedPath(ALBUM_ART_URI, String.valueOf(albumId));
|
||||
private void insertAlbumArt(int albumId, DownloadFile downloadFile)
|
||||
{
|
||||
ContentResolver contentResolver = context.getContentResolver();
|
||||
Uri uri = Uri.withAppendedPath(ALBUM_ART_URI, String.valueOf(albumId));
|
||||
|
||||
if (uri == null) {
|
||||
return;
|
||||
}
|
||||
if (uri == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Cursor cursor = contentResolver.query(uri, null, null, null, null);
|
||||
Cursor cursor = contentResolver.query(uri, null, null, null, null);
|
||||
|
||||
if (cursor != null && !cursor.moveToFirst()) {
|
||||
// No album art found, add it.
|
||||
File albumArtFile = FileUtil.getAlbumArtFile(context, downloadFile.getSong());
|
||||
if (albumArtFile.exists()) {
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(MediaStore.Audio.AlbumColumns.ALBUM_ID, albumId);
|
||||
values.put(MediaStore.MediaColumns.DATA, albumArtFile.getPath());
|
||||
contentResolver.insert(ALBUM_ART_URI, values);
|
||||
Log.i(TAG, "Added album art: " + albumArtFile);
|
||||
}
|
||||
if (cursor != null && !cursor.moveToFirst())
|
||||
{
|
||||
// No album art found, add it.
|
||||
File albumArtFile = FileUtil.getAlbumArtFile(context, downloadFile.getSong());
|
||||
if (albumArtFile.exists())
|
||||
{
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(MediaStore.Audio.AlbumColumns.ALBUM_ID, albumId);
|
||||
values.put(MediaStore.MediaColumns.DATA, albumArtFile.getPath());
|
||||
contentResolver.insert(ALBUM_ART_URI, values);
|
||||
Log.i(TAG, "Added album art: " + albumArtFile);
|
||||
}
|
||||
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -18,10 +18,6 @@
|
|||
*/
|
||||
package com.thejoshwa.ultrasonic.androidapp.service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.http.HttpResponse;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
|
||||
|
@ -41,100 +37,105 @@ import com.thejoshwa.ultrasonic.androidapp.domain.Version;
|
|||
import com.thejoshwa.ultrasonic.androidapp.util.CancellableTask;
|
||||
import com.thejoshwa.ultrasonic.androidapp.util.ProgressListener;
|
||||
|
||||
import org.apache.http.HttpResponse;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Sindre Mehus
|
||||
*/
|
||||
public interface MusicService {
|
||||
public interface MusicService
|
||||
{
|
||||
|
||||
void ping(Context context, ProgressListener progressListener) throws Exception;
|
||||
void ping(Context context, ProgressListener progressListener) throws Exception;
|
||||
|
||||
boolean isLicenseValid(Context context, ProgressListener progressListener) throws Exception;
|
||||
boolean isLicenseValid(Context context, ProgressListener progressListener) throws Exception;
|
||||
|
||||
List<Genre> getGenres(Context context, ProgressListener progressListener) throws Exception;
|
||||
|
||||
void star(String id, String albumId, String artistId, Context context, ProgressListener progressListener) throws Exception;
|
||||
|
||||
void unstar(String id, String albumId, String artistId, Context context, ProgressListener progressListener) throws Exception;
|
||||
List<Genre> getGenres(Context context, ProgressListener progressListener) throws Exception;
|
||||
|
||||
List<MusicFolder> getMusicFolders(boolean refresh, Context context, ProgressListener progressListener) throws Exception;
|
||||
|
||||
Indexes getIndexes(String musicFolderId, boolean refresh, Context context, ProgressListener progressListener) throws Exception;
|
||||
|
||||
Indexes getArtists(boolean refresh, Context context, ProgressListener progressListener) throws Exception;
|
||||
void star(String id, String albumId, String artistId, Context context, ProgressListener progressListener) throws Exception;
|
||||
|
||||
MusicDirectory getMusicDirectory(String id, String name, boolean refresh, Context context, ProgressListener progressListener) throws Exception;
|
||||
|
||||
MusicDirectory getArtist(String id, String name, boolean refresh, Context context, ProgressListener progressListener) throws Exception;
|
||||
|
||||
MusicDirectory getAlbum(String id, String name, boolean refresh, Context context, ProgressListener progressListener) throws Exception;
|
||||
void unstar(String id, String albumId, String artistId, Context context, ProgressListener progressListener) throws Exception;
|
||||
|
||||
SearchResult search(SearchCriteria criteria, Context context, ProgressListener progressListener) throws Exception;
|
||||
List<MusicFolder> getMusicFolders(boolean refresh, Context context, ProgressListener progressListener) throws Exception;
|
||||
|
||||
MusicDirectory getPlaylist(String id, String name, Context context, ProgressListener progressListener) throws Exception;
|
||||
|
||||
List<Playlist> getPlaylists(boolean refresh, Context context, ProgressListener progressListener) throws Exception;
|
||||
Indexes getIndexes(String musicFolderId, boolean refresh, Context context, ProgressListener progressListener) throws Exception;
|
||||
|
||||
void createPlaylist(String id, String name, List<MusicDirectory.Entry> entries, Context context, ProgressListener progressListener) throws Exception;
|
||||
Indexes getArtists(boolean refresh, Context context, ProgressListener progressListener) throws Exception;
|
||||
|
||||
void deletePlaylist(String id, Context context, ProgressListener progressListener) throws Exception;
|
||||
MusicDirectory getMusicDirectory(String id, String name, boolean refresh, Context context, ProgressListener progressListener) throws Exception;
|
||||
|
||||
MusicDirectory getArtist(String id, String name, boolean refresh, Context context, ProgressListener progressListener) throws Exception;
|
||||
|
||||
MusicDirectory getAlbum(String id, String name, boolean refresh, Context context, ProgressListener progressListener) throws Exception;
|
||||
|
||||
SearchResult search(SearchCriteria criteria, Context context, ProgressListener progressListener) throws Exception;
|
||||
|
||||
MusicDirectory getPlaylist(String id, String name, Context context, ProgressListener progressListener) throws Exception;
|
||||
|
||||
List<Playlist> getPlaylists(boolean refresh, Context context, ProgressListener progressListener) throws Exception;
|
||||
|
||||
void createPlaylist(String id, String name, List<MusicDirectory.Entry> entries, Context context, ProgressListener progressListener) throws Exception;
|
||||
|
||||
void deletePlaylist(String id, Context context, ProgressListener progressListener) throws Exception;
|
||||
|
||||
void updatePlaylist(String id, List<MusicDirectory.Entry> toAdd, Context context, ProgressListener progressListener) throws Exception;
|
||||
|
||||
void removeFromPlaylist(String id, List<Integer> toRemove, Context context, ProgressListener progressListener) throws Exception;
|
||||
|
||||
void updatePlaylist(String id, String name, String comment, boolean pub, Context context, ProgressListener progressListener) throws Exception;
|
||||
|
||||
Lyrics getLyrics(String artist, String title, Context context, ProgressListener progressListener) throws Exception;
|
||||
|
||||
void scrobble(String id, boolean submission, Context context, ProgressListener progressListener) throws Exception;
|
||||
Lyrics getLyrics(String artist, String title, Context context, ProgressListener progressListener) throws Exception;
|
||||
|
||||
MusicDirectory getAlbumList(String type, int size, int offset, Context context, ProgressListener progressListener) throws Exception;
|
||||
|
||||
MusicDirectory getAlbumList2(String type, int size, int offset, Context context, ProgressListener progressListener) throws Exception;
|
||||
void scrobble(String id, boolean submission, Context context, ProgressListener progressListener) throws Exception;
|
||||
|
||||
MusicDirectory getRandomSongs(int size, Context context, ProgressListener progressListener) throws Exception;
|
||||
|
||||
MusicDirectory getSongsByGenre(String genre, int count, int offset, Context context, ProgressListener progressListener) throws Exception;
|
||||
|
||||
SearchResult getStarred(Context context, ProgressListener progressListener) throws Exception;
|
||||
|
||||
SearchResult getStarred2(Context context, ProgressListener progressListener) throws Exception;
|
||||
MusicDirectory getAlbumList(String type, int size, int offset, Context context, ProgressListener progressListener) throws Exception;
|
||||
|
||||
Bitmap getCoverArt(Context context, MusicDirectory.Entry entry, int size, boolean saveToFile, boolean highQuality, ProgressListener progressListener) throws Exception;
|
||||
MusicDirectory getAlbumList2(String type, int size, int offset, Context context, ProgressListener progressListener) throws Exception;
|
||||
|
||||
HttpResponse getDownloadInputStream(Context context, MusicDirectory.Entry song, long offset, int maxBitrate, CancellableTask task) throws Exception;
|
||||
MusicDirectory getRandomSongs(int size, Context context, ProgressListener progressListener) throws Exception;
|
||||
|
||||
Version getLocalVersion(Context context) throws Exception;
|
||||
MusicDirectory getSongsByGenre(String genre, int count, int offset, Context context, ProgressListener progressListener) throws Exception;
|
||||
|
||||
Version getLatestVersion(Context context, ProgressListener progressListener) throws Exception;
|
||||
SearchResult getStarred(Context context, ProgressListener progressListener) throws Exception;
|
||||
|
||||
String getVideoUrl(Context context, String id, boolean useFlash) throws Exception;
|
||||
SearchResult getStarred2(Context context, ProgressListener progressListener) throws Exception;
|
||||
|
||||
Bitmap getCoverArt(Context context, MusicDirectory.Entry entry, int size, boolean saveToFile, boolean highQuality, ProgressListener progressListener) throws Exception;
|
||||
|
||||
HttpResponse getDownloadInputStream(Context context, MusicDirectory.Entry song, long offset, int maxBitrate, CancellableTask task) throws Exception;
|
||||
|
||||
Version getLocalVersion(Context context) throws Exception;
|
||||
|
||||
Version getLatestVersion(Context context, ProgressListener progressListener) throws Exception;
|
||||
|
||||
String getVideoUrl(Context context, String id, boolean useFlash) throws Exception;
|
||||
|
||||
String getVideoStreamUrl(int Bitrate, Context context, String id);
|
||||
|
||||
JukeboxStatus updateJukeboxPlaylist(List<String> ids, Context context, ProgressListener progressListener) throws Exception;
|
||||
JukeboxStatus updateJukeboxPlaylist(List<String> ids, Context context, ProgressListener progressListener) throws Exception;
|
||||
|
||||
JukeboxStatus skipJukebox(int index, int offsetSeconds, Context context, ProgressListener progressListener) throws Exception;
|
||||
JukeboxStatus skipJukebox(int index, int offsetSeconds, Context context, ProgressListener progressListener) throws Exception;
|
||||
|
||||
JukeboxStatus stopJukebox(Context context, ProgressListener progressListener) throws Exception;
|
||||
JukeboxStatus stopJukebox(Context context, ProgressListener progressListener) throws Exception;
|
||||
|
||||
JukeboxStatus startJukebox(Context context, ProgressListener progressListener) throws Exception;
|
||||
JukeboxStatus startJukebox(Context context, ProgressListener progressListener) throws Exception;
|
||||
|
||||
JukeboxStatus getJukeboxStatus(Context context, ProgressListener progressListener) throws Exception;
|
||||
JukeboxStatus getJukeboxStatus(Context context, ProgressListener progressListener) throws Exception;
|
||||
|
||||
JukeboxStatus setJukeboxGain(float gain, Context context, ProgressListener progressListener) throws Exception;
|
||||
|
||||
List<Share> getShares(Context context, ProgressListener progressListener) throws Exception;
|
||||
|
||||
List<ChatMessage> getChatMessages(Long since, Context context, ProgressListener progressListener) throws Exception;
|
||||
|
||||
void addChatMessage(String message, Context context, ProgressListener progressListener) throws Exception;
|
||||
JukeboxStatus setJukeboxGain(float gain, Context context, ProgressListener progressListener) throws Exception;
|
||||
|
||||
List<Share> getShares(Context context, ProgressListener progressListener) throws Exception;
|
||||
|
||||
List<ChatMessage> getChatMessages(Long since, Context context, ProgressListener progressListener) throws Exception;
|
||||
|
||||
void addChatMessage(String message, Context context, ProgressListener progressListener) throws Exception;
|
||||
|
||||
List<Bookmark> getBookmarks(Context context, ProgressListener progressListener) throws Exception;
|
||||
|
||||
void deleteBookmark(String id, Context context, ProgressListener progressListener) throws Exception;
|
||||
|
||||
void createBookmark(String id, int position, Context context, ProgressListener progressListener) throws Exception;
|
||||
|
||||
|
||||
MusicDirectory getVideos(boolean refresh, Context context, ProgressListener progressListener) throws Exception;
|
||||
}
|
|
@ -19,18 +19,20 @@
|
|||
package com.thejoshwa.ultrasonic.androidapp.service;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.thejoshwa.ultrasonic.androidapp.util.Util;
|
||||
|
||||
/**
|
||||
* @author Sindre Mehus
|
||||
* @version $Id$
|
||||
*/
|
||||
public class MusicServiceFactory {
|
||||
public class MusicServiceFactory
|
||||
{
|
||||
private static final MusicService REST_MUSIC_SERVICE = new CachedMusicService(new RESTMusicService());
|
||||
private static final MusicService OFFLINE_MUSIC_SERVICE = new OfflineMusicService();
|
||||
|
||||
private static final MusicService REST_MUSIC_SERVICE = new CachedMusicService(new RESTMusicService());
|
||||
private static final MusicService OFFLINE_MUSIC_SERVICE = new OfflineMusicService();
|
||||
|
||||
public static MusicService getMusicService(Context context) {
|
||||
return Util.isOffline(context) ? OFFLINE_MUSIC_SERVICE : REST_MUSIC_SERVICE;
|
||||
}
|
||||
public static MusicService getMusicService(Context context)
|
||||
{
|
||||
return Util.isOffline(context) ? OFFLINE_MUSIC_SERVICE : REST_MUSIC_SERVICE;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,14 +24,12 @@ package com.thejoshwa.ultrasonic.androidapp.service;
|
|||
* @author Sindre Mehus
|
||||
* @version $Id$
|
||||
*/
|
||||
public class OfflineException extends Exception {
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class OfflineException extends Exception
|
||||
{
|
||||
private static final long serialVersionUID = -4479642294747429444L;
|
||||
|
||||
public OfflineException(String message) {
|
||||
super(message);
|
||||
}
|
||||
public OfflineException(String message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -2,6 +2,7 @@ package com.thejoshwa.ultrasonic.androidapp.service;
|
|||
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
import com.thejoshwa.ultrasonic.androidapp.util.Util;
|
||||
|
||||
/**
|
||||
|
@ -10,43 +11,59 @@ import com.thejoshwa.ultrasonic.androidapp.util.Util;
|
|||
* @author Sindre Mehus
|
||||
* @version $Id$
|
||||
*/
|
||||
public class Scrobbler {
|
||||
public class Scrobbler
|
||||
{
|
||||
|
||||
private static final String TAG = Scrobbler.class.getSimpleName();
|
||||
private static final String TAG = Scrobbler.class.getSimpleName();
|
||||
|
||||
private String lastSubmission;
|
||||
private String lastNowPlaying;
|
||||
private String lastSubmission;
|
||||
private String lastNowPlaying;
|
||||
|
||||
public void scrobble(final Context context, final DownloadFile song, final boolean submission) {
|
||||
if (song == null || !Util.isScrobblingEnabled(context)) {
|
||||
return;
|
||||
}
|
||||
final String id = song.getSong().getId();
|
||||
public void scrobble(final Context context, final DownloadFile song, final boolean submission)
|
||||
{
|
||||
if (song == null || !Util.isScrobblingEnabled(context))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Avoid duplicate registrations.
|
||||
if (submission && id.equals(lastSubmission)) {
|
||||
return;
|
||||
}
|
||||
if (!submission && id.equals(lastNowPlaying)) {
|
||||
return;
|
||||
}
|
||||
if (submission) {
|
||||
lastSubmission = id;
|
||||
} else {
|
||||
lastNowPlaying = id;
|
||||
}
|
||||
final String id = song.getSong().getId();
|
||||
|
||||
new Thread("Scrobble " + song) {
|
||||
@Override
|
||||
public void run() {
|
||||
MusicService service = MusicServiceFactory.getMusicService(context);
|
||||
try {
|
||||
service.scrobble(id, submission, context, null);
|
||||
Log.i(TAG, "Scrobbled '" + (submission ? "submission" : "now playing") + "' for " + song);
|
||||
} catch (Exception x) {
|
||||
Log.i(TAG, "Failed to scrobble'" + (submission ? "submission" : "now playing") + "' for " + song, x);
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
// Avoid duplicate registrations.
|
||||
if (submission && id.equals(lastSubmission))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!submission && id.equals(lastNowPlaying))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (submission)
|
||||
{
|
||||
lastSubmission = id;
|
||||
}
|
||||
else
|
||||
{
|
||||
lastNowPlaying = id;
|
||||
}
|
||||
|
||||
new Thread(String.format("Scrobble %s", song))
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
MusicService service = MusicServiceFactory.getMusicService(context);
|
||||
try
|
||||
{
|
||||
service.scrobble(id, submission, context, null);
|
||||
Log.i(TAG, String.format("Scrobbled '%s' for %s", submission ? "submission" : "now playing", song));
|
||||
}
|
||||
catch (Exception x)
|
||||
{
|
||||
Log.i(TAG, String.format("Failed to scrobble'%s' for %s", submission ? "submission" : "now playing", song), x);
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,25 +24,25 @@ package com.thejoshwa.ultrasonic.androidapp.service;
|
|||
* @author Sindre Mehus
|
||||
* @version $Id$
|
||||
*/
|
||||
public class ServerTooOldException extends Exception {
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class ServerTooOldException extends Exception
|
||||
{
|
||||
private static final long serialVersionUID = -7955245839000220002L;
|
||||
|
||||
public ServerTooOldException(String text) {
|
||||
super(createMessage(text));
|
||||
}
|
||||
public ServerTooOldException(String text)
|
||||
{
|
||||
super(createMessage(text));
|
||||
}
|
||||
|
||||
private static String createMessage(String text) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
if (text != null) {
|
||||
builder.append(text).append(" ");
|
||||
}
|
||||
private static String createMessage(String text)
|
||||
{
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
builder.append("Subsonic server version is too old. Please upgrade.");
|
||||
return builder.toString();
|
||||
}
|
||||
if (text != null)
|
||||
{
|
||||
builder.append(text).append(' ');
|
||||
}
|
||||
|
||||
builder.append("Subsonic server version is too old. Please upgrade.");
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,126 +18,150 @@
|
|||
*/
|
||||
package com.thejoshwa.ultrasonic.androidapp.service.parser;
|
||||
|
||||
import java.io.Reader;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Xml;
|
||||
|
||||
import com.thejoshwa.ultrasonic.androidapp.R;
|
||||
import com.thejoshwa.ultrasonic.androidapp.domain.Version;
|
||||
import com.thejoshwa.ultrasonic.androidapp.util.ProgressListener;
|
||||
import com.thejoshwa.ultrasonic.androidapp.util.Util;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
|
||||
import java.io.Reader;
|
||||
|
||||
/**
|
||||
* @author Sindre Mehus
|
||||
*/
|
||||
public abstract class AbstractParser {
|
||||
public abstract class AbstractParser
|
||||
{
|
||||
|
||||
private final Context context;
|
||||
private XmlPullParser parser;
|
||||
private boolean rootElementFound;
|
||||
private final Context context;
|
||||
private XmlPullParser parser;
|
||||
private boolean rootElementFound;
|
||||
|
||||
public AbstractParser(Context context) {
|
||||
this.context = context;
|
||||
}
|
||||
public AbstractParser(Context context)
|
||||
{
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
protected Context getContext() {
|
||||
return context;
|
||||
}
|
||||
protected Context getContext()
|
||||
{
|
||||
return context;
|
||||
}
|
||||
|
||||
protected void handleError() throws Exception {
|
||||
int code = getInteger("code");
|
||||
String message;
|
||||
switch (code) {
|
||||
case 20:
|
||||
message = context.getResources().getString(R.string.parser_upgrade_client);
|
||||
break;
|
||||
case 30:
|
||||
message = context.getResources().getString(R.string.parser_upgrade_server);
|
||||
break;
|
||||
case 40:
|
||||
message = context.getResources().getString(R.string.parser_not_authenticated);
|
||||
break;
|
||||
case 50:
|
||||
message = context.getResources().getString(R.string.parser_not_authorized);
|
||||
break;
|
||||
default:
|
||||
message = get("message");
|
||||
break;
|
||||
}
|
||||
throw new SubsonicRESTException(code, message);
|
||||
}
|
||||
protected void handleError() throws Exception
|
||||
{
|
||||
int code = getInteger("code");
|
||||
String message;
|
||||
switch (code)
|
||||
{
|
||||
case 20:
|
||||
message = context.getResources().getString(R.string.parser_upgrade_client);
|
||||
break;
|
||||
case 30:
|
||||
message = context.getResources().getString(R.string.parser_upgrade_server);
|
||||
break;
|
||||
case 40:
|
||||
message = context.getResources().getString(R.string.parser_not_authenticated);
|
||||
break;
|
||||
case 50:
|
||||
message = context.getResources().getString(R.string.parser_not_authorized);
|
||||
break;
|
||||
default:
|
||||
message = get("message");
|
||||
break;
|
||||
}
|
||||
throw new SubsonicRESTException(code, message);
|
||||
}
|
||||
|
||||
protected void updateProgress(ProgressListener progressListener, int messageId) {
|
||||
if (progressListener != null) {
|
||||
progressListener.updateProgress(messageId);
|
||||
}
|
||||
}
|
||||
protected void updateProgress(ProgressListener progressListener, int messageId)
|
||||
{
|
||||
if (progressListener != null)
|
||||
{
|
||||
progressListener.updateProgress(messageId);
|
||||
}
|
||||
}
|
||||
|
||||
protected void updateProgress(ProgressListener progressListener, String message) {
|
||||
if (progressListener != null) {
|
||||
progressListener.updateProgress(message);
|
||||
}
|
||||
}
|
||||
protected void updateProgress(ProgressListener progressListener, String message)
|
||||
{
|
||||
if (progressListener != null)
|
||||
{
|
||||
progressListener.updateProgress(message);
|
||||
}
|
||||
}
|
||||
|
||||
protected String getText() {
|
||||
return parser.getText();
|
||||
}
|
||||
protected String getText()
|
||||
{
|
||||
return parser.getText();
|
||||
}
|
||||
|
||||
protected String get(String name) {
|
||||
return parser.getAttributeValue(null, name);
|
||||
}
|
||||
protected String get(String name)
|
||||
{
|
||||
return parser.getAttributeValue(null, name);
|
||||
}
|
||||
|
||||
protected boolean getBoolean(String name) {
|
||||
return "true".equals(get(name));
|
||||
}
|
||||
|
||||
protected boolean getValueExists(String name) {
|
||||
String value = get(name);
|
||||
return value != null && !value.isEmpty();
|
||||
}
|
||||
protected boolean getBoolean(String name)
|
||||
{
|
||||
return "true".equals(get(name));
|
||||
}
|
||||
|
||||
protected Integer getInteger(String name) {
|
||||
String s = get(name);
|
||||
return s == null ? null : Integer.valueOf(s);
|
||||
}
|
||||
protected boolean getValueExists(String name)
|
||||
{
|
||||
String value = get(name);
|
||||
return value != null && !value.isEmpty();
|
||||
}
|
||||
|
||||
protected Long getLong(String name) {
|
||||
String s = get(name);
|
||||
return s == null ? null : Long.valueOf(s);
|
||||
}
|
||||
protected Integer getInteger(String name)
|
||||
{
|
||||
String s = get(name);
|
||||
return s == null ? null : Integer.valueOf(s);
|
||||
}
|
||||
|
||||
protected Float getFloat(String name) {
|
||||
String s = get(name);
|
||||
return s == null ? null : Float.valueOf(s);
|
||||
}
|
||||
protected Long getLong(String name)
|
||||
{
|
||||
String s = get(name);
|
||||
return s == null ? null : Long.valueOf(s);
|
||||
}
|
||||
|
||||
protected void init(Reader reader) throws Exception {
|
||||
parser = Xml.newPullParser();
|
||||
parser.setInput(reader);
|
||||
rootElementFound = false;
|
||||
}
|
||||
protected Float getFloat(String name)
|
||||
{
|
||||
String s = get(name);
|
||||
return s == null ? null : Float.valueOf(s);
|
||||
}
|
||||
|
||||
protected int nextParseEvent() throws Exception {
|
||||
return parser.next();
|
||||
}
|
||||
protected void init(Reader reader) throws Exception
|
||||
{
|
||||
parser = Xml.newPullParser();
|
||||
parser.setInput(reader);
|
||||
rootElementFound = false;
|
||||
}
|
||||
|
||||
protected String getElementName() {
|
||||
String name = parser.getName();
|
||||
if ("subsonic-response".equals(name)) {
|
||||
rootElementFound = true;
|
||||
String version = get("version");
|
||||
if (version != null) {
|
||||
Util.setServerRestVersion(context, new Version(version));
|
||||
}
|
||||
}
|
||||
return name;
|
||||
}
|
||||
protected int nextParseEvent() throws Exception
|
||||
{
|
||||
return parser.next();
|
||||
}
|
||||
|
||||
protected void validate() throws Exception {
|
||||
if (!rootElementFound) {
|
||||
throw new Exception(context.getResources().getString(R.string.background_task_parse_error));
|
||||
}
|
||||
}
|
||||
protected String getElementName()
|
||||
{
|
||||
String name = parser.getName();
|
||||
if ("subsonic-response".equals(name))
|
||||
{
|
||||
rootElementFound = true;
|
||||
String version = get("version");
|
||||
if (version != null)
|
||||
{
|
||||
Util.setServerRestVersion(context, new Version(version));
|
||||
}
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
protected void validate() throws Exception
|
||||
{
|
||||
if (!rootElementFound)
|
||||
{
|
||||
throw new Exception(context.getResources().getString(R.string.background_task_parse_error));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -19,9 +19,11 @@
|
|||
package com.thejoshwa.ultrasonic.androidapp.service.parser;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.thejoshwa.ultrasonic.androidapp.R;
|
||||
import com.thejoshwa.ultrasonic.androidapp.domain.MusicDirectory;
|
||||
import com.thejoshwa.ultrasonic.androidapp.util.ProgressListener;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
|
||||
import java.io.Reader;
|
||||
|
@ -29,34 +31,41 @@ import java.io.Reader;
|
|||
/**
|
||||
* @author Sindre Mehus
|
||||
*/
|
||||
public class AlbumListParser extends MusicDirectoryEntryParser {
|
||||
public class AlbumListParser extends MusicDirectoryEntryParser
|
||||
{
|
||||
public AlbumListParser(Context context)
|
||||
{
|
||||
super(context);
|
||||
}
|
||||
|
||||
public AlbumListParser(Context context) {
|
||||
super(context);
|
||||
}
|
||||
public MusicDirectory parse(Reader reader, ProgressListener progressListener, boolean useId3) throws Exception
|
||||
{
|
||||
|
||||
public MusicDirectory parse(Reader reader, ProgressListener progressListener, boolean useId3) throws Exception {
|
||||
updateProgress(progressListener, R.string.parser_reading);
|
||||
init(reader);
|
||||
|
||||
updateProgress(progressListener, R.string.parser_reading);
|
||||
init(reader);
|
||||
MusicDirectory dir = new MusicDirectory();
|
||||
int eventType;
|
||||
do
|
||||
{
|
||||
eventType = nextParseEvent();
|
||||
if (eventType == XmlPullParser.START_TAG)
|
||||
{
|
||||
String name = getElementName();
|
||||
if ("album".equals(name))
|
||||
{
|
||||
dir.addChild(parseEntry("", useId3, 0));
|
||||
}
|
||||
else if ("error".equals(name))
|
||||
{
|
||||
handleError();
|
||||
}
|
||||
}
|
||||
} while (eventType != XmlPullParser.END_DOCUMENT);
|
||||
|
||||
MusicDirectory dir = new MusicDirectory();
|
||||
int eventType;
|
||||
do {
|
||||
eventType = nextParseEvent();
|
||||
if (eventType == XmlPullParser.START_TAG) {
|
||||
String name = getElementName();
|
||||
if ("album".equals(name)) {
|
||||
dir.addChild(parseEntry("", useId3, 0));
|
||||
} else if ("error".equals(name)) {
|
||||
handleError();
|
||||
}
|
||||
}
|
||||
} while (eventType != XmlPullParser.END_DOCUMENT);
|
||||
validate();
|
||||
updateProgress(progressListener, R.string.parser_reading_done);
|
||||
|
||||
validate();
|
||||
updateProgress(progressListener, R.string.parser_reading_done);
|
||||
|
||||
return dir;
|
||||
}
|
||||
return dir;
|
||||
}
|
||||
}
|
|
@ -1,10 +1,13 @@
|
|||
package com.thejoshwa.ultrasonic.androidapp.service.parser;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.thejoshwa.ultrasonic.androidapp.R;
|
||||
import com.thejoshwa.ultrasonic.androidapp.domain.Bookmark;
|
||||
import com.thejoshwa.ultrasonic.androidapp.util.ProgressListener;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
|
||||
import java.io.Reader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
@ -12,48 +15,59 @@ import java.util.List;
|
|||
/**
|
||||
* @author Joshua Bahnsen
|
||||
*/
|
||||
public class BookmarkParser extends MusicDirectoryEntryParser {
|
||||
public class BookmarkParser extends MusicDirectoryEntryParser
|
||||
{
|
||||
|
||||
public BookmarkParser(Context context) {
|
||||
super(context);
|
||||
}
|
||||
public BookmarkParser(Context context)
|
||||
{
|
||||
super(context);
|
||||
}
|
||||
|
||||
public List<Bookmark> parse(Reader reader, ProgressListener progressListener) throws Exception {
|
||||
public List<Bookmark> parse(Reader reader, ProgressListener progressListener) throws Exception
|
||||
{
|
||||
|
||||
updateProgress(progressListener, R.string.parser_reading);
|
||||
init(reader);
|
||||
updateProgress(progressListener, R.string.parser_reading);
|
||||
init(reader);
|
||||
|
||||
List<Bookmark> dir = new ArrayList<Bookmark>();
|
||||
Bookmark bookmark = null;
|
||||
int eventType;
|
||||
|
||||
do {
|
||||
eventType = nextParseEvent();
|
||||
|
||||
if (eventType == XmlPullParser.START_TAG) {
|
||||
String name = getElementName();
|
||||
|
||||
if ("bookmark".equals(name)) {
|
||||
bookmark = new Bookmark();
|
||||
bookmark.setChanged(get("changed"));
|
||||
bookmark.setCreated(get("created"));
|
||||
bookmark.setComment(get("comment"));
|
||||
bookmark.setPosition(getInteger("position"));
|
||||
bookmark.setUsername(get("username"));
|
||||
} else if ("entry".equals(name)) {
|
||||
if (bookmark != null) {
|
||||
bookmark.setEntry(parseEntry(null, false, bookmark.getPosition()));
|
||||
dir.add(bookmark);
|
||||
}
|
||||
} else if ("error".equals(name)) {
|
||||
handleError();
|
||||
}
|
||||
}
|
||||
} while (eventType != XmlPullParser.END_DOCUMENT);
|
||||
List<Bookmark> dir = new ArrayList<Bookmark>();
|
||||
Bookmark bookmark = null;
|
||||
int eventType;
|
||||
|
||||
validate();
|
||||
updateProgress(progressListener, R.string.parser_reading_done);
|
||||
do
|
||||
{
|
||||
eventType = nextParseEvent();
|
||||
|
||||
return dir;
|
||||
}
|
||||
if (eventType == XmlPullParser.START_TAG)
|
||||
{
|
||||
String name = getElementName();
|
||||
|
||||
if ("bookmark".equals(name))
|
||||
{
|
||||
bookmark = new Bookmark();
|
||||
bookmark.setChanged(get("changed"));
|
||||
bookmark.setCreated(get("created"));
|
||||
bookmark.setComment(get("comment"));
|
||||
bookmark.setPosition(getInteger("position"));
|
||||
bookmark.setUsername(get("username"));
|
||||
}
|
||||
else if ("entry".equals(name))
|
||||
{
|
||||
if (bookmark != null)
|
||||
{
|
||||
bookmark.setEntry(parseEntry(null, false, bookmark.getPosition()));
|
||||
dir.add(bookmark);
|
||||
}
|
||||
}
|
||||
else if ("error".equals(name))
|
||||
{
|
||||
handleError();
|
||||
}
|
||||
}
|
||||
} while (eventType != XmlPullParser.END_DOCUMENT);
|
||||
|
||||
validate();
|
||||
updateProgress(progressListener, R.string.parser_reading_done);
|
||||
|
||||
return dir;
|
||||
}
|
||||
}
|
|
@ -1,9 +1,11 @@
|
|||
package com.thejoshwa.ultrasonic.androidapp.service.parser;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.thejoshwa.ultrasonic.androidapp.R;
|
||||
import com.thejoshwa.ultrasonic.androidapp.domain.ChatMessage;
|
||||
import com.thejoshwa.ultrasonic.androidapp.util.ProgressListener;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
|
||||
import java.io.Reader;
|
||||
|
@ -13,37 +15,45 @@ import java.util.List;
|
|||
/**
|
||||
* @author Joshua Bahnsen
|
||||
*/
|
||||
public class ChatMessageParser extends AbstractParser {
|
||||
public class ChatMessageParser extends AbstractParser
|
||||
{
|
||||
|
||||
public ChatMessageParser(Context context) {
|
||||
super(context);
|
||||
}
|
||||
public ChatMessageParser(Context context)
|
||||
{
|
||||
super(context);
|
||||
}
|
||||
|
||||
public List<ChatMessage> parse(Reader reader, ProgressListener progressListener) throws Exception {
|
||||
updateProgress(progressListener, R.string.parser_reading);
|
||||
init(reader);
|
||||
List<ChatMessage> result = new ArrayList<ChatMessage>();
|
||||
int eventType;
|
||||
|
||||
do {
|
||||
eventType = nextParseEvent();
|
||||
if (eventType == XmlPullParser.START_TAG) {
|
||||
String name = getElementName();
|
||||
if ("chatMessage".equals(name)) {
|
||||
ChatMessage chatMessage = new ChatMessage();
|
||||
chatMessage.setUsername(get("username"));
|
||||
chatMessage.setTime(getLong("time"));
|
||||
chatMessage.setMessage(get("message"));
|
||||
result.add(chatMessage);
|
||||
} else if ("error".equals(name)) {
|
||||
handleError();
|
||||
}
|
||||
}
|
||||
} while (eventType != XmlPullParser.END_DOCUMENT);
|
||||
public List<ChatMessage> parse(Reader reader, ProgressListener progressListener) throws Exception
|
||||
{
|
||||
updateProgress(progressListener, R.string.parser_reading);
|
||||
init(reader);
|
||||
List<ChatMessage> result = new ArrayList<ChatMessage>();
|
||||
int eventType;
|
||||
|
||||
validate();
|
||||
updateProgress(progressListener, R.string.parser_reading_done);
|
||||
|
||||
return result;
|
||||
}
|
||||
do
|
||||
{
|
||||
eventType = nextParseEvent();
|
||||
if (eventType == XmlPullParser.START_TAG)
|
||||
{
|
||||
String name = getElementName();
|
||||
if ("chatMessage".equals(name))
|
||||
{
|
||||
ChatMessage chatMessage = new ChatMessage();
|
||||
chatMessage.setUsername(get("username"));
|
||||
chatMessage.setTime(getLong("time"));
|
||||
chatMessage.setMessage(get("message"));
|
||||
result.add(chatMessage);
|
||||
}
|
||||
else if ("error".equals(name))
|
||||
{
|
||||
handleError();
|
||||
}
|
||||
}
|
||||
} while (eventType != XmlPullParser.END_DOCUMENT);
|
||||
|
||||
validate();
|
||||
updateProgress(progressListener, R.string.parser_reading_done);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
package com.thejoshwa.ultrasonic.androidapp.service.parser;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
|
||||
import java.io.Reader;
|
||||
|
@ -26,24 +27,29 @@ import java.io.Reader;
|
|||
/**
|
||||
* @author Sindre Mehus
|
||||
*/
|
||||
public class ErrorParser extends AbstractParser {
|
||||
public class ErrorParser extends AbstractParser
|
||||
{
|
||||
|
||||
public ErrorParser(Context context) {
|
||||
super(context);
|
||||
}
|
||||
public ErrorParser(Context context)
|
||||
{
|
||||
super(context);
|
||||
}
|
||||
|
||||
public void parse(Reader reader) throws Exception {
|
||||
public void parse(Reader reader) throws Exception
|
||||
{
|
||||
|
||||
init(reader);
|
||||
init(reader);
|
||||
|
||||
int eventType;
|
||||
do {
|
||||
eventType = nextParseEvent();
|
||||
if (eventType == XmlPullParser.START_TAG && "error".equals(getElementName())) {
|
||||
handleError();
|
||||
}
|
||||
} while (eventType != XmlPullParser.END_DOCUMENT);
|
||||
int eventType;
|
||||
do
|
||||
{
|
||||
eventType = nextParseEvent();
|
||||
if (eventType == XmlPullParser.START_TAG && "error".equals(getElementName()))
|
||||
{
|
||||
handleError();
|
||||
}
|
||||
} while (eventType != XmlPullParser.END_DOCUMENT);
|
||||
|
||||
validate();
|
||||
}
|
||||
validate();
|
||||
}
|
||||
}
|
|
@ -24,6 +24,7 @@ import android.util.Log;
|
|||
import com.thejoshwa.ultrasonic.androidapp.R;
|
||||
import com.thejoshwa.ultrasonic.androidapp.domain.Genre;
|
||||
import com.thejoshwa.ultrasonic.androidapp.util.ProgressListener;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
|
@ -32,95 +33,122 @@ import java.io.Reader;
|
|||
import java.io.StringReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* @author Joshua Bahnsen
|
||||
*/
|
||||
public class GenreParser extends AbstractParser {
|
||||
public class GenreParser extends AbstractParser
|
||||
{
|
||||
|
||||
private static final String TAG = GenreParser.class.getSimpleName();
|
||||
|
||||
public GenreParser(Context context) {
|
||||
super(context);
|
||||
}
|
||||
private static final Pattern COMPILE = Pattern.compile("(?:&)(amp;|lt;|gt;|#37;|apos;)");
|
||||
private static final Pattern PATTERN = Pattern.compile("&(?!amp;|lt;|gt;|#37;|apos;)");
|
||||
private static final Pattern COMPILE1 = Pattern.compile("%");
|
||||
private static final Pattern COMPILE2 = Pattern.compile("'");
|
||||
|
||||
public List<Genre> parse(Reader reader, ProgressListener progressListener) throws Exception {
|
||||
updateProgress(progressListener, R.string.parser_reading);
|
||||
|
||||
List<Genre> result = new ArrayList<Genre>();
|
||||
StringReader sr = null;
|
||||
|
||||
try {
|
||||
BufferedReader br = new BufferedReader(reader);
|
||||
String xml = null;
|
||||
String line;
|
||||
|
||||
while ((line = br.readLine()) != null) {
|
||||
if (xml == null) {
|
||||
xml = line;
|
||||
} else {
|
||||
xml += line;
|
||||
}
|
||||
}
|
||||
br.close();
|
||||
public GenreParser(Context context)
|
||||
{
|
||||
super(context);
|
||||
}
|
||||
|
||||
// Replace possible unescaped XML characters
|
||||
// No replacements for <> at this time
|
||||
if (xml != null) {
|
||||
// Replace double escaped ampersand (&apos;)
|
||||
xml = xml.replaceAll("(?:&)(amp;|lt;|gt;|#37;|apos;)", "&$1");
|
||||
public List<Genre> parse(Reader reader, ProgressListener progressListener) throws Exception
|
||||
{
|
||||
updateProgress(progressListener, R.string.parser_reading);
|
||||
|
||||
// Replace unescaped ampersand
|
||||
xml = xml.replaceAll("&(?!amp;|lt;|gt;|#37;|apos;)", "&");
|
||||
List<Genre> result = new ArrayList<Genre>();
|
||||
StringReader sr = null;
|
||||
|
||||
// Replace unescaped percent symbol
|
||||
xml = xml.replaceAll("%", "%");
|
||||
try
|
||||
{
|
||||
BufferedReader br = new BufferedReader(reader);
|
||||
String xml = null;
|
||||
String line;
|
||||
|
||||
// Replace unescaped apostrophe
|
||||
xml = xml.replaceAll("'", "'");
|
||||
}
|
||||
while ((line = br.readLine()) != null)
|
||||
{
|
||||
if (xml == null)
|
||||
{
|
||||
xml = line;
|
||||
}
|
||||
else
|
||||
{
|
||||
xml += line;
|
||||
}
|
||||
}
|
||||
br.close();
|
||||
|
||||
sr = new StringReader(xml);
|
||||
} catch (IOException ioe) {
|
||||
Log.e(TAG, "Error parsing Genre XML", ioe);
|
||||
}
|
||||
// Replace possible unescaped XML characters
|
||||
// No replacements for <> at this time
|
||||
if (xml != null)
|
||||
{
|
||||
// Replace double escaped ampersand (&apos;)
|
||||
xml = COMPILE.matcher(xml).replaceAll("&$1");
|
||||
|
||||
if (sr == null) {
|
||||
Log.w(TAG, "Unable to parse Genre XML, returning empty list");
|
||||
return result;
|
||||
}
|
||||
|
||||
init(sr);
|
||||
// Replace unescaped ampersand
|
||||
xml = PATTERN.matcher(xml).replaceAll("&");
|
||||
|
||||
Genre genre = null;
|
||||
|
||||
int eventType;
|
||||
do {
|
||||
eventType = nextParseEvent();
|
||||
if (eventType == XmlPullParser.START_TAG) {
|
||||
String name = getElementName();
|
||||
if ("genre".equals(name)) {
|
||||
genre = new Genre();
|
||||
} else if ("error".equals(name)) {
|
||||
handleError();
|
||||
} else {
|
||||
genre = null;
|
||||
}
|
||||
} else if (eventType == XmlPullParser.TEXT) {
|
||||
if (genre != null) {
|
||||
String value = getText();
|
||||
// Replace unescaped percent symbol
|
||||
xml = COMPILE1.matcher(xml).replaceAll("%");
|
||||
|
||||
genre.setName(value);
|
||||
genre.setIndex(value.substring(0, 1));
|
||||
result.add(genre);
|
||||
genre = null;
|
||||
}
|
||||
}
|
||||
} while (eventType != XmlPullParser.END_DOCUMENT);
|
||||
// Replace unescaped apostrophe
|
||||
xml = COMPILE2.matcher(xml).replaceAll("'");
|
||||
}
|
||||
|
||||
validate();
|
||||
updateProgress(progressListener, R.string.parser_reading_done);
|
||||
|
||||
return result;
|
||||
}
|
||||
sr = new StringReader(xml);
|
||||
}
|
||||
catch (IOException ioe)
|
||||
{
|
||||
Log.e(TAG, "Error parsing Genre XML", ioe);
|
||||
}
|
||||
|
||||
if (sr == null)
|
||||
{
|
||||
Log.w(TAG, "Unable to parse Genre XML, returning empty list");
|
||||
return result;
|
||||
}
|
||||
|
||||
init(sr);
|
||||
|
||||
Genre genre = null;
|
||||
|
||||
int eventType;
|
||||
do
|
||||
{
|
||||
eventType = nextParseEvent();
|
||||
if (eventType == XmlPullParser.START_TAG)
|
||||
{
|
||||
String name = getElementName();
|
||||
if ("genre".equals(name))
|
||||
{
|
||||
genre = new Genre();
|
||||
}
|
||||
else if ("error".equals(name))
|
||||
{
|
||||
handleError();
|
||||
}
|
||||
else
|
||||
{
|
||||
genre = null;
|
||||
}
|
||||
}
|
||||
else if (eventType == XmlPullParser.TEXT)
|
||||
{
|
||||
if (genre != null)
|
||||
{
|
||||
String value = getText();
|
||||
|
||||
genre.setName(value);
|
||||
genre.setIndex(value.substring(0, 1));
|
||||
result.add(genre);
|
||||
genre = null;
|
||||
}
|
||||
}
|
||||
} while (eventType != XmlPullParser.END_DOCUMENT);
|
||||
|
||||
validate();
|
||||
updateProgress(progressListener, R.string.parser_reading_done);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,84 +25,102 @@ import java.util.ArrayList;
|
|||
import org.xmlpull.v1.XmlPullParser;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.thejoshwa.ultrasonic.androidapp.R;
|
||||
import com.thejoshwa.ultrasonic.androidapp.domain.Artist;
|
||||
import com.thejoshwa.ultrasonic.androidapp.domain.Indexes;
|
||||
import com.thejoshwa.ultrasonic.androidapp.util.ProgressListener;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* @author Sindre Mehus
|
||||
*/
|
||||
public class IndexesParser extends AbstractParser {
|
||||
private static final String TAG = IndexesParser.class.getSimpleName();
|
||||
public class IndexesParser extends AbstractParser
|
||||
{
|
||||
private static final String TAG = IndexesParser.class.getSimpleName();
|
||||
|
||||
public IndexesParser(Context context) {
|
||||
super(context);
|
||||
}
|
||||
public IndexesParser(Context context)
|
||||
{
|
||||
super(context);
|
||||
}
|
||||
|
||||
public Indexes parse(Reader reader, ProgressListener progressListener) throws Exception {
|
||||
public Indexes parse(Reader reader, ProgressListener progressListener) throws Exception
|
||||
{
|
||||
|
||||
long t0 = System.currentTimeMillis();
|
||||
updateProgress(progressListener, R.string.parser_reading);
|
||||
init(reader);
|
||||
long t0 = System.currentTimeMillis();
|
||||
updateProgress(progressListener, R.string.parser_reading);
|
||||
init(reader);
|
||||
|
||||
List<Artist> artists = new ArrayList<Artist>();
|
||||
List<Artist> shortcuts = new ArrayList<Artist>();
|
||||
Long lastModified = null;
|
||||
String ignoredArticles = null;
|
||||
int eventType;
|
||||
String index = "#";
|
||||
boolean changed = false;
|
||||
List<Artist> artists = new ArrayList<Artist>();
|
||||
List<Artist> shortcuts = new ArrayList<Artist>();
|
||||
Long lastModified = null;
|
||||
String ignoredArticles = null;
|
||||
int eventType;
|
||||
String index = "#";
|
||||
boolean changed = false;
|
||||
|
||||
do {
|
||||
eventType = nextParseEvent();
|
||||
if (eventType == XmlPullParser.START_TAG) {
|
||||
String name = getElementName();
|
||||
if ("indexes".equals(name) || "artists".equals(name)) {
|
||||
changed = true;
|
||||
lastModified = getLong("lastModified");
|
||||
ignoredArticles = get("ignoredArticles");
|
||||
} else if ("index".equals(name)) {
|
||||
index = get("name");
|
||||
do
|
||||
{
|
||||
eventType = nextParseEvent();
|
||||
if (eventType == XmlPullParser.START_TAG)
|
||||
{
|
||||
String name = getElementName();
|
||||
if ("indexes".equals(name) || "artists".equals(name))
|
||||
{
|
||||
changed = true;
|
||||
lastModified = getLong("lastModified");
|
||||
ignoredArticles = get("ignoredArticles");
|
||||
}
|
||||
else if ("index".equals(name))
|
||||
{
|
||||
index = get("name");
|
||||
|
||||
} else if ("artist".equals(name)) {
|
||||
Artist artist = new Artist();
|
||||
artist.setId(get("id"));
|
||||
artist.setName(get("name"));
|
||||
artist.setCoverArt(get("coverArt"));
|
||||
artist.setAlbumCount(getLong("albumCount"));
|
||||
artist.setIndex(index);
|
||||
artists.add(artist);
|
||||
}
|
||||
else if ("artist".equals(name))
|
||||
{
|
||||
Artist artist = new Artist();
|
||||
artist.setId(get("id"));
|
||||
artist.setName(get("name"));
|
||||
artist.setCoverArt(get("coverArt"));
|
||||
artist.setAlbumCount(getLong("albumCount"));
|
||||
artist.setIndex(index);
|
||||
artists.add(artist);
|
||||
|
||||
if (artists.size() % 10 == 0) {
|
||||
String msg = getContext().getResources().getString(R.string.parser_artist_count, artists.size());
|
||||
updateProgress(progressListener, msg);
|
||||
}
|
||||
} else if ("shortcut".equals(name)) {
|
||||
Artist shortcut = new Artist();
|
||||
shortcut.setId(get("id"));
|
||||
shortcut.setName(get("name"));
|
||||
shortcut.setIndex("*");
|
||||
shortcuts.add(shortcut);
|
||||
} else if ("error".equals(name)) {
|
||||
handleError();
|
||||
}
|
||||
}
|
||||
} while (eventType != XmlPullParser.END_DOCUMENT);
|
||||
if (artists.size() % 10 == 0)
|
||||
{
|
||||
String msg = getContext().getResources().getString(R.string.parser_artist_count, artists.size());
|
||||
updateProgress(progressListener, msg);
|
||||
}
|
||||
}
|
||||
else if ("shortcut".equals(name))
|
||||
{
|
||||
Artist shortcut = new Artist();
|
||||
shortcut.setId(get("id"));
|
||||
shortcut.setName(get("name"));
|
||||
shortcut.setIndex("*");
|
||||
shortcuts.add(shortcut);
|
||||
}
|
||||
else if ("error".equals(name))
|
||||
{
|
||||
handleError();
|
||||
}
|
||||
}
|
||||
} while (eventType != XmlPullParser.END_DOCUMENT);
|
||||
|
||||
validate();
|
||||
validate();
|
||||
|
||||
if (!changed) {
|
||||
return null;
|
||||
}
|
||||
if (!changed)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
long t1 = System.currentTimeMillis();
|
||||
Log.d(TAG, "Got " + artists.size() + " artist(s) in " + (t1 - t0) + "ms.");
|
||||
long t1 = System.currentTimeMillis();
|
||||
Log.d(TAG, "Got " + artists.size() + " artist(s) in " + (t1 - t0) + "ms.");
|
||||
|
||||
String msg = getContext().getResources().getString(R.string.parser_artist_count, artists.size());
|
||||
updateProgress(progressListener, msg);
|
||||
String msg = getContext().getResources().getString(R.string.parser_artist_count, artists.size());
|
||||
updateProgress(progressListener, msg);
|
||||
|
||||
return new Indexes(lastModified == null ? 0L : lastModified, shortcuts, artists);
|
||||
}
|
||||
return new Indexes(lastModified == null ? 0L : lastModified, shortcuts, artists);
|
||||
}
|
||||
}
|
|
@ -18,45 +18,54 @@
|
|||
*/
|
||||
package com.thejoshwa.ultrasonic.androidapp.service.parser;
|
||||
|
||||
import java.io.Reader;
|
||||
import android.content.Context;
|
||||
|
||||
import com.thejoshwa.ultrasonic.androidapp.domain.JukeboxStatus;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
|
||||
import android.content.Context;
|
||||
import com.thejoshwa.ultrasonic.androidapp.domain.JukeboxStatus;
|
||||
import java.io.Reader;
|
||||
|
||||
/**
|
||||
* @author Sindre Mehus
|
||||
*/
|
||||
public class JukeboxStatusParser extends AbstractParser {
|
||||
public class JukeboxStatusParser extends AbstractParser
|
||||
{
|
||||
|
||||
public JukeboxStatusParser(Context context) {
|
||||
super(context);
|
||||
}
|
||||
public JukeboxStatusParser(Context context)
|
||||
{
|
||||
super(context);
|
||||
}
|
||||
|
||||
public JukeboxStatus parse(Reader reader) throws Exception {
|
||||
public JukeboxStatus parse(Reader reader) throws Exception
|
||||
{
|
||||
|
||||
init(reader);
|
||||
init(reader);
|
||||
|
||||
JukeboxStatus jukeboxStatus = new JukeboxStatus();
|
||||
int eventType;
|
||||
do {
|
||||
eventType = nextParseEvent();
|
||||
if (eventType == XmlPullParser.START_TAG) {
|
||||
String name = getElementName();
|
||||
if ("jukeboxPlaylist".equals(name) || "jukeboxStatus".equals(name)) {
|
||||
jukeboxStatus.setPositionSeconds(getInteger("position"));
|
||||
jukeboxStatus.setCurrentIndex(getInteger("currentIndex"));
|
||||
jukeboxStatus.setPlaying(getBoolean("playing"));
|
||||
jukeboxStatus.setGain(getFloat("gain"));
|
||||
} else if ("error".equals(name)) {
|
||||
handleError();
|
||||
}
|
||||
}
|
||||
} while (eventType != XmlPullParser.END_DOCUMENT);
|
||||
JukeboxStatus jukeboxStatus = new JukeboxStatus();
|
||||
int eventType;
|
||||
do
|
||||
{
|
||||
eventType = nextParseEvent();
|
||||
if (eventType == XmlPullParser.START_TAG)
|
||||
{
|
||||
String name = getElementName();
|
||||
if ("jukeboxPlaylist".equals(name) || "jukeboxStatus".equals(name))
|
||||
{
|
||||
jukeboxStatus.setPositionSeconds(getInteger("position"));
|
||||
jukeboxStatus.setCurrentIndex(getInteger("currentIndex"));
|
||||
jukeboxStatus.setPlaying(getBoolean("playing"));
|
||||
jukeboxStatus.setGain(getFloat("gain"));
|
||||
}
|
||||
else if ("error".equals(name))
|
||||
{
|
||||
handleError();
|
||||
}
|
||||
}
|
||||
} while (eventType != XmlPullParser.END_DOCUMENT);
|
||||
|
||||
validate();
|
||||
validate();
|
||||
|
||||
return jukeboxStatus;
|
||||
}
|
||||
return jukeboxStatus;
|
||||
}
|
||||
}
|
|
@ -19,6 +19,7 @@
|
|||
package com.thejoshwa.ultrasonic.androidapp.service.parser;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
|
||||
import java.io.Reader;
|
||||
|
@ -29,34 +30,44 @@ import com.thejoshwa.ultrasonic.androidapp.domain.Version;
|
|||
/**
|
||||
* @author Sindre Mehus
|
||||
*/
|
||||
public class LicenseParser extends AbstractParser {
|
||||
public class LicenseParser extends AbstractParser
|
||||
{
|
||||
|
||||
public LicenseParser(Context context) {
|
||||
super(context);
|
||||
}
|
||||
public LicenseParser(Context context)
|
||||
{
|
||||
super(context);
|
||||
}
|
||||
|
||||
public ServerInfo parse(Reader reader) throws Exception {
|
||||
public ServerInfo parse(Reader reader) throws Exception
|
||||
{
|
||||
|
||||
init(reader);
|
||||
init(reader);
|
||||
|
||||
ServerInfo serverInfo = new ServerInfo();
|
||||
int eventType;
|
||||
do {
|
||||
eventType = nextParseEvent();
|
||||
if (eventType == XmlPullParser.START_TAG) {
|
||||
String name = getElementName();
|
||||
if ("subsonic-response".equals(name)) {
|
||||
serverInfo.setRestVersion(new Version(get("version")));
|
||||
} else if ("license".equals(name)) {
|
||||
serverInfo.setLicenseValid(getBoolean("valid"));
|
||||
} else if ("error".equals(name)) {
|
||||
handleError();
|
||||
}
|
||||
}
|
||||
} while (eventType != XmlPullParser.END_DOCUMENT);
|
||||
ServerInfo serverInfo = new ServerInfo();
|
||||
int eventType;
|
||||
do
|
||||
{
|
||||
eventType = nextParseEvent();
|
||||
if (eventType == XmlPullParser.START_TAG)
|
||||
{
|
||||
String name = getElementName();
|
||||
if ("subsonic-response".equals(name))
|
||||
{
|
||||
serverInfo.setRestVersion(new Version(get("version")));
|
||||
}
|
||||
else if ("license".equals(name))
|
||||
{
|
||||
serverInfo.setLicenseValid(getBoolean("valid"));
|
||||
}
|
||||
else if ("error".equals(name))
|
||||
{
|
||||
handleError();
|
||||
}
|
||||
}
|
||||
} while (eventType != XmlPullParser.END_DOCUMENT);
|
||||
|
||||
validate();
|
||||
validate();
|
||||
|
||||
return serverInfo;
|
||||
}
|
||||
return serverInfo;
|
||||
}
|
||||
}
|
|
@ -19,9 +19,11 @@
|
|||
package com.thejoshwa.ultrasonic.androidapp.service.parser;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.thejoshwa.ultrasonic.androidapp.R;
|
||||
import com.thejoshwa.ultrasonic.androidapp.domain.Lyrics;
|
||||
import com.thejoshwa.ultrasonic.androidapp.util.ProgressListener;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
|
||||
import java.io.Reader;
|
||||
|
@ -29,37 +31,48 @@ import java.io.Reader;
|
|||
/**
|
||||
* @author Sindre Mehus
|
||||
*/
|
||||
public class LyricsParser extends AbstractParser {
|
||||
public class LyricsParser extends AbstractParser
|
||||
{
|
||||
|
||||
public LyricsParser(Context context) {
|
||||
super(context);
|
||||
}
|
||||
public LyricsParser(Context context)
|
||||
{
|
||||
super(context);
|
||||
}
|
||||
|
||||
public Lyrics parse(Reader reader, ProgressListener progressListener) throws Exception {
|
||||
updateProgress(progressListener, R.string.parser_reading);
|
||||
init(reader);
|
||||
public Lyrics parse(Reader reader, ProgressListener progressListener) throws Exception
|
||||
{
|
||||
updateProgress(progressListener, R.string.parser_reading);
|
||||
init(reader);
|
||||
|
||||
Lyrics lyrics = null;
|
||||
int eventType;
|
||||
do {
|
||||
eventType = nextParseEvent();
|
||||
if (eventType == XmlPullParser.START_TAG) {
|
||||
String name = getElementName();
|
||||
if ("lyrics".equals(name)) {
|
||||
lyrics = new Lyrics();
|
||||
lyrics.setArtist(get("artist"));
|
||||
lyrics.setTitle(get("title"));
|
||||
} else if ("error".equals(name)) {
|
||||
handleError();
|
||||
}
|
||||
} else if (eventType == XmlPullParser.TEXT) {
|
||||
if (lyrics != null && lyrics.getText() == null) {
|
||||
lyrics.setText(getText());
|
||||
}
|
||||
}
|
||||
} while (eventType != XmlPullParser.END_DOCUMENT);
|
||||
Lyrics lyrics = null;
|
||||
int eventType;
|
||||
do
|
||||
{
|
||||
eventType = nextParseEvent();
|
||||
if (eventType == XmlPullParser.START_TAG)
|
||||
{
|
||||
String name = getElementName();
|
||||
if ("lyrics".equals(name))
|
||||
{
|
||||
lyrics = new Lyrics();
|
||||
lyrics.setArtist(get("artist"));
|
||||
lyrics.setTitle(get("title"));
|
||||
}
|
||||
else if ("error".equals(name))
|
||||
{
|
||||
handleError();
|
||||
}
|
||||
}
|
||||
else if (eventType == XmlPullParser.TEXT)
|
||||
{
|
||||
if (lyrics != null && lyrics.getText() == null)
|
||||
{
|
||||
lyrics.setText(getText());
|
||||
}
|
||||
}
|
||||
} while (eventType != XmlPullParser.END_DOCUMENT);
|
||||
|
||||
validate();
|
||||
return lyrics;
|
||||
}
|
||||
validate();
|
||||
return lyrics;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,52 +19,59 @@
|
|||
package com.thejoshwa.ultrasonic.androidapp.service.parser;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.thejoshwa.ultrasonic.androidapp.domain.MusicDirectory;
|
||||
import com.thejoshwa.ultrasonic.androidapp.util.Constants;
|
||||
|
||||
/**
|
||||
* @author Sindre Mehus
|
||||
*/
|
||||
public class MusicDirectoryEntryParser extends AbstractParser {
|
||||
public class MusicDirectoryEntryParser extends AbstractParser
|
||||
{
|
||||
|
||||
public MusicDirectoryEntryParser(Context context) {
|
||||
super(context);
|
||||
}
|
||||
public MusicDirectoryEntryParser(Context context)
|
||||
{
|
||||
super(context);
|
||||
}
|
||||
|
||||
protected MusicDirectory.Entry parseEntry(String artist, boolean isAlbum, int bookmarkPosition) {
|
||||
MusicDirectory.Entry entry = new MusicDirectory.Entry();
|
||||
entry.setId(get("id"));
|
||||
entry.setParent(get("parent"));
|
||||
entry.setTitle(isAlbum ? get("name") : get("title"));
|
||||
entry.setIsDirectory(getBoolean("isDir") || isAlbum);
|
||||
entry.setCoverArt(get("coverArt"));
|
||||
entry.setArtist(get("artist"));
|
||||
entry.setArtistId(get("artistId"));
|
||||
entry.setYear(getInteger("year"));
|
||||
entry.setCreated(get("created"));
|
||||
entry.setStarred(getValueExists(Constants.STARRED));
|
||||
protected MusicDirectory.Entry parseEntry(String artist, boolean isAlbum, int bookmarkPosition)
|
||||
{
|
||||
MusicDirectory.Entry entry = new MusicDirectory.Entry();
|
||||
entry.setId(get("id"));
|
||||
entry.setParent(get("parent"));
|
||||
entry.setTitle(isAlbum ? get("name") : get("title"));
|
||||
entry.setIsDirectory(getBoolean("isDir") || isAlbum);
|
||||
entry.setCoverArt(get("coverArt"));
|
||||
entry.setArtist(get("artist"));
|
||||
entry.setArtistId(get("artistId"));
|
||||
entry.setYear(getInteger("year"));
|
||||
entry.setCreated(get("created"));
|
||||
entry.setStarred(getValueExists(Constants.STARRED));
|
||||
|
||||
if (!entry.isDirectory()) {
|
||||
entry.setAlbum(get("album"));
|
||||
entry.setAlbumId(get("albumId"));
|
||||
entry.setTrack(getInteger("track"));
|
||||
entry.setGenre(get("genre"));
|
||||
entry.setContentType(get("contentType"));
|
||||
entry.setSuffix(get("suffix"));
|
||||
entry.setTranscodedContentType(get("transcodedContentType"));
|
||||
entry.setTranscodedSuffix(get("transcodedSuffix"));
|
||||
entry.setSize(getLong("size"));
|
||||
entry.setDuration(getInteger("duration"));
|
||||
entry.setBitRate(getInteger("bitRate"));
|
||||
entry.setPath(get("path"));
|
||||
entry.setIsVideo(getBoolean("isVideo"));
|
||||
entry.setDiscNumber(getInteger("discNumber"));
|
||||
entry.setType(get("type"));
|
||||
entry.setBookmarkPosition(bookmarkPosition);
|
||||
} else if(!"".equals(artist)) {
|
||||
entry.setPath(artist + "/" + entry.getTitle());
|
||||
if (!entry.isDirectory())
|
||||
{
|
||||
entry.setAlbum(get("album"));
|
||||
entry.setAlbumId(get("albumId"));
|
||||
entry.setTrack(getInteger("track"));
|
||||
entry.setGenre(get("genre"));
|
||||
entry.setContentType(get("contentType"));
|
||||
entry.setSuffix(get("suffix"));
|
||||
entry.setTranscodedContentType(get("transcodedContentType"));
|
||||
entry.setTranscodedSuffix(get("transcodedSuffix"));
|
||||
entry.setSize(getLong("size"));
|
||||
entry.setDuration(getInteger("duration"));
|
||||
entry.setBitRate(getInteger("bitRate"));
|
||||
entry.setPath(get("path"));
|
||||
entry.setIsVideo(getBoolean("isVideo"));
|
||||
entry.setDiscNumber(getInteger("discNumber"));
|
||||
entry.setType(get("type"));
|
||||
entry.setBookmarkPosition(bookmarkPosition);
|
||||
}
|
||||
|
||||
return entry;
|
||||
}
|
||||
else if (!"".equals(artist))
|
||||
{
|
||||
entry.setPath(String.format("%s/%s", artist, entry.getTitle()));
|
||||
}
|
||||
|
||||
return entry;
|
||||
}
|
||||
}
|
|
@ -20,54 +20,69 @@ package com.thejoshwa.ultrasonic.androidapp.service.parser;
|
|||
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
import com.thejoshwa.ultrasonic.androidapp.R;
|
||||
import com.thejoshwa.ultrasonic.androidapp.domain.MusicDirectory;
|
||||
import com.thejoshwa.ultrasonic.androidapp.util.ProgressListener;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
|
||||
import java.io.Reader;
|
||||
|
||||
/**
|
||||
* @author Sindre Mehus
|
||||
*/
|
||||
public class MusicDirectoryParser extends MusicDirectoryEntryParser {
|
||||
public class MusicDirectoryParser extends MusicDirectoryEntryParser
|
||||
{
|
||||
|
||||
private static final String TAG = MusicDirectoryParser.class.getSimpleName();
|
||||
private static final String TAG = MusicDirectoryParser.class.getSimpleName();
|
||||
|
||||
public MusicDirectoryParser(Context context) {
|
||||
super(context);
|
||||
}
|
||||
public MusicDirectoryParser(Context context)
|
||||
{
|
||||
super(context);
|
||||
}
|
||||
|
||||
public MusicDirectory parse(String artist, Reader reader, ProgressListener progressListener, boolean isAlbum) throws Exception {
|
||||
public MusicDirectory parse(String artist, Reader reader, ProgressListener progressListener, boolean isAlbum) throws Exception
|
||||
{
|
||||
|
||||
long t0 = System.currentTimeMillis();
|
||||
updateProgress(progressListener, R.string.parser_reading);
|
||||
init(reader);
|
||||
long t0 = System.currentTimeMillis();
|
||||
updateProgress(progressListener, R.string.parser_reading);
|
||||
init(reader);
|
||||
|
||||
MusicDirectory dir = new MusicDirectory();
|
||||
int eventType;
|
||||
do {
|
||||
eventType = nextParseEvent();
|
||||
if (eventType == XmlPullParser.START_TAG) {
|
||||
String name = getElementName();
|
||||
|
||||
if ("child".equals(name) || "song".equals(name) || "video".equals(name)) {
|
||||
dir.addChild(parseEntry(artist, false, 0));
|
||||
} else if ("album".equals(name) && !isAlbum) {
|
||||
dir.addChild(parseEntry(artist, true, 0));
|
||||
} else if ("directory".equals(name) || "artist".equals(name)) {
|
||||
dir.setName(get("name"));
|
||||
} else if ("error".equals(name)) {
|
||||
handleError();
|
||||
}
|
||||
}
|
||||
} while (eventType != XmlPullParser.END_DOCUMENT);
|
||||
MusicDirectory dir = new MusicDirectory();
|
||||
int eventType;
|
||||
do
|
||||
{
|
||||
eventType = nextParseEvent();
|
||||
if (eventType == XmlPullParser.START_TAG)
|
||||
{
|
||||
String name = getElementName();
|
||||
|
||||
validate();
|
||||
updateProgress(progressListener, R.string.parser_reading_done);
|
||||
if ("child".equals(name) || "song".equals(name) || "video".equals(name))
|
||||
{
|
||||
dir.addChild(parseEntry(artist, false, 0));
|
||||
}
|
||||
else if ("album".equals(name) && !isAlbum)
|
||||
{
|
||||
dir.addChild(parseEntry(artist, true, 0));
|
||||
}
|
||||
else if ("directory".equals(name) || "artist".equals(name))
|
||||
{
|
||||
dir.setName(get("name"));
|
||||
}
|
||||
else if ("error".equals(name))
|
||||
{
|
||||
handleError();
|
||||
}
|
||||
}
|
||||
} while (eventType != XmlPullParser.END_DOCUMENT);
|
||||
|
||||
long t1 = System.currentTimeMillis();
|
||||
Log.d(TAG, "Got music directory in " + (t1 - t0) + "ms.");
|
||||
validate();
|
||||
updateProgress(progressListener, R.string.parser_reading_done);
|
||||
|
||||
return dir;
|
||||
}
|
||||
long t1 = System.currentTimeMillis();
|
||||
Log.d(TAG, "Got music directory in " + (t1 - t0) + "ms.");
|
||||
|
||||
return dir;
|
||||
}
|
||||
}
|
|
@ -25,6 +25,7 @@ import java.util.List;
|
|||
import org.xmlpull.v1.XmlPullParser;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.thejoshwa.ultrasonic.androidapp.R;
|
||||
import com.thejoshwa.ultrasonic.androidapp.domain.MusicFolder;
|
||||
import com.thejoshwa.ultrasonic.androidapp.util.ProgressListener;
|
||||
|
@ -32,37 +33,45 @@ import com.thejoshwa.ultrasonic.androidapp.util.ProgressListener;
|
|||
/**
|
||||
* @author Sindre Mehus
|
||||
*/
|
||||
public class MusicFoldersParser extends AbstractParser {
|
||||
public class MusicFoldersParser extends AbstractParser
|
||||
{
|
||||
|
||||
public MusicFoldersParser(Context context) {
|
||||
super(context);
|
||||
}
|
||||
public MusicFoldersParser(Context context)
|
||||
{
|
||||
super(context);
|
||||
}
|
||||
|
||||
public List<MusicFolder> parse(Reader reader, ProgressListener progressListener) throws Exception {
|
||||
public List<MusicFolder> parse(Reader reader, ProgressListener progressListener) throws Exception
|
||||
{
|
||||
|
||||
updateProgress(progressListener, R.string.parser_reading);
|
||||
init(reader);
|
||||
updateProgress(progressListener, R.string.parser_reading);
|
||||
init(reader);
|
||||
|
||||
List<MusicFolder> result = new ArrayList<MusicFolder>();
|
||||
int eventType;
|
||||
do {
|
||||
eventType = nextParseEvent();
|
||||
if (eventType == XmlPullParser.START_TAG) {
|
||||
String tag = getElementName();
|
||||
if ("musicFolder".equals(tag)) {
|
||||
String id = get("id");
|
||||
String name = get("name");
|
||||
result.add(new MusicFolder(id, name));
|
||||
} else if ("error".equals(tag)) {
|
||||
handleError();
|
||||
}
|
||||
}
|
||||
} while (eventType != XmlPullParser.END_DOCUMENT);
|
||||
List<MusicFolder> result = new ArrayList<MusicFolder>();
|
||||
int eventType;
|
||||
do
|
||||
{
|
||||
eventType = nextParseEvent();
|
||||
if (eventType == XmlPullParser.START_TAG)
|
||||
{
|
||||
String tag = getElementName();
|
||||
if ("musicFolder".equals(tag))
|
||||
{
|
||||
String id = get("id");
|
||||
String name = get("name");
|
||||
result.add(new MusicFolder(id, name));
|
||||
}
|
||||
else if ("error".equals(tag))
|
||||
{
|
||||
handleError();
|
||||
}
|
||||
}
|
||||
} while (eventType != XmlPullParser.END_DOCUMENT);
|
||||
|
||||
validate();
|
||||
updateProgress(progressListener, R.string.parser_reading_done);
|
||||
validate();
|
||||
updateProgress(progressListener, R.string.parser_reading_done);
|
||||
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
|
@ -19,9 +19,11 @@
|
|||
package com.thejoshwa.ultrasonic.androidapp.service.parser;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.thejoshwa.ultrasonic.androidapp.R;
|
||||
import com.thejoshwa.ultrasonic.androidapp.domain.MusicDirectory;
|
||||
import com.thejoshwa.ultrasonic.androidapp.util.ProgressListener;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
|
||||
import java.io.Reader;
|
||||
|
@ -29,34 +31,42 @@ import java.io.Reader;
|
|||
/**
|
||||
* @author Sindre Mehus
|
||||
*/
|
||||
public class PlaylistParser extends MusicDirectoryEntryParser {
|
||||
public class PlaylistParser extends MusicDirectoryEntryParser
|
||||
{
|
||||
|
||||
public PlaylistParser(Context context) {
|
||||
super(context);
|
||||
}
|
||||
public PlaylistParser(Context context)
|
||||
{
|
||||
super(context);
|
||||
}
|
||||
|
||||
public MusicDirectory parse(Reader reader, ProgressListener progressListener) throws Exception {
|
||||
updateProgress(progressListener, R.string.parser_reading);
|
||||
init(reader);
|
||||
public MusicDirectory parse(Reader reader, ProgressListener progressListener) throws Exception
|
||||
{
|
||||
updateProgress(progressListener, R.string.parser_reading);
|
||||
init(reader);
|
||||
|
||||
MusicDirectory dir = new MusicDirectory();
|
||||
int eventType;
|
||||
do {
|
||||
eventType = nextParseEvent();
|
||||
if (eventType == XmlPullParser.START_TAG) {
|
||||
String name = getElementName();
|
||||
if ("entry".equals(name)) {
|
||||
dir.addChild(parseEntry("", false, 0));
|
||||
} else if ("error".equals(name)) {
|
||||
handleError();
|
||||
}
|
||||
}
|
||||
} while (eventType != XmlPullParser.END_DOCUMENT);
|
||||
MusicDirectory dir = new MusicDirectory();
|
||||
int eventType;
|
||||
do
|
||||
{
|
||||
eventType = nextParseEvent();
|
||||
if (eventType == XmlPullParser.START_TAG)
|
||||
{
|
||||
String name = getElementName();
|
||||
if ("entry".equals(name))
|
||||
{
|
||||
dir.addChild(parseEntry("", false, 0));
|
||||
}
|
||||
else if ("error".equals(name))
|
||||
{
|
||||
handleError();
|
||||
}
|
||||
}
|
||||
} while (eventType != XmlPullParser.END_DOCUMENT);
|
||||
|
||||
validate();
|
||||
updateProgress(progressListener, R.string.parser_reading_done);
|
||||
validate();
|
||||
updateProgress(progressListener, R.string.parser_reading_done);
|
||||
|
||||
return dir;
|
||||
}
|
||||
return dir;
|
||||
}
|
||||
|
||||
}
|
|
@ -19,6 +19,7 @@
|
|||
package com.thejoshwa.ultrasonic.androidapp.service.parser;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.thejoshwa.ultrasonic.androidapp.R;
|
||||
import com.thejoshwa.ultrasonic.androidapp.domain.Playlist;
|
||||
import com.thejoshwa.ultrasonic.androidapp.util.ProgressListener;
|
||||
|
@ -33,42 +34,50 @@ import java.util.List;
|
|||
/**
|
||||
* @author Sindre Mehus
|
||||
*/
|
||||
public class PlaylistsParser extends AbstractParser {
|
||||
public class PlaylistsParser extends AbstractParser
|
||||
{
|
||||
|
||||
public PlaylistsParser(Context context) {
|
||||
super(context);
|
||||
}
|
||||
public PlaylistsParser(Context context)
|
||||
{
|
||||
super(context);
|
||||
}
|
||||
|
||||
public List<Playlist> parse(Reader reader, ProgressListener progressListener) throws Exception {
|
||||
public List<Playlist> parse(Reader reader, ProgressListener progressListener) throws Exception
|
||||
{
|
||||
|
||||
updateProgress(progressListener, R.string.parser_reading);
|
||||
init(reader);
|
||||
updateProgress(progressListener, R.string.parser_reading);
|
||||
init(reader);
|
||||
|
||||
List<Playlist> result = new ArrayList<Playlist>();
|
||||
int eventType;
|
||||
do {
|
||||
eventType = nextParseEvent();
|
||||
if (eventType == XmlPullParser.START_TAG) {
|
||||
String tag = getElementName();
|
||||
if ("playlist".equals(tag)) {
|
||||
String id = get("id");
|
||||
String name = get("name");
|
||||
List<Playlist> result = new ArrayList<Playlist>();
|
||||
int eventType;
|
||||
do
|
||||
{
|
||||
eventType = nextParseEvent();
|
||||
if (eventType == XmlPullParser.START_TAG)
|
||||
{
|
||||
String tag = getElementName();
|
||||
if ("playlist".equals(tag))
|
||||
{
|
||||
String id = get("id");
|
||||
String name = get("name");
|
||||
String owner = get("owner");
|
||||
String comment = get("comment");
|
||||
String songCount = get("songCount");
|
||||
String created = get("created");
|
||||
String pub = get("public");
|
||||
result.add(new Playlist(id, name, owner, comment, songCount, created, pub));
|
||||
} else if ("error".equals(tag)) {
|
||||
handleError();
|
||||
}
|
||||
}
|
||||
} while (eventType != XmlPullParser.END_DOCUMENT);
|
||||
result.add(new Playlist(id, name, owner, comment, songCount, created, pub));
|
||||
}
|
||||
else if ("error".equals(tag))
|
||||
{
|
||||
handleError();
|
||||
}
|
||||
}
|
||||
} while (eventType != XmlPullParser.END_DOCUMENT);
|
||||
|
||||
validate();
|
||||
updateProgress(progressListener, R.string.parser_reading_done);
|
||||
validate();
|
||||
updateProgress(progressListener, R.string.parser_reading_done);
|
||||
|
||||
return PlaylistAdapter.PlaylistComparator.sort(result);
|
||||
}
|
||||
return PlaylistAdapter.PlaylistComparator.sort(result);
|
||||
}
|
||||
|
||||
}
|
|
@ -19,9 +19,11 @@
|
|||
package com.thejoshwa.ultrasonic.androidapp.service.parser;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.thejoshwa.ultrasonic.androidapp.R;
|
||||
import com.thejoshwa.ultrasonic.androidapp.domain.MusicDirectory;
|
||||
import com.thejoshwa.ultrasonic.androidapp.util.ProgressListener;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
|
||||
import java.io.Reader;
|
||||
|
@ -29,34 +31,42 @@ import java.io.Reader;
|
|||
/**
|
||||
* @author Sindre Mehus
|
||||
*/
|
||||
public class RandomSongsParser extends MusicDirectoryEntryParser {
|
||||
public class RandomSongsParser extends MusicDirectoryEntryParser
|
||||
{
|
||||
|
||||
public RandomSongsParser(Context context) {
|
||||
super(context);
|
||||
}
|
||||
public RandomSongsParser(Context context)
|
||||
{
|
||||
super(context);
|
||||
}
|
||||
|
||||
public MusicDirectory parse(Reader reader, ProgressListener progressListener) throws Exception {
|
||||
updateProgress(progressListener, R.string.parser_reading);
|
||||
init(reader);
|
||||
public MusicDirectory parse(Reader reader, ProgressListener progressListener) throws Exception
|
||||
{
|
||||
updateProgress(progressListener, R.string.parser_reading);
|
||||
init(reader);
|
||||
|
||||
MusicDirectory dir = new MusicDirectory();
|
||||
int eventType;
|
||||
do {
|
||||
eventType = nextParseEvent();
|
||||
if (eventType == XmlPullParser.START_TAG) {
|
||||
String name = getElementName();
|
||||
if ("song".equals(name)) {
|
||||
dir.addChild(parseEntry("", false, 0));
|
||||
} else if ("error".equals(name)) {
|
||||
handleError();
|
||||
}
|
||||
}
|
||||
} while (eventType != XmlPullParser.END_DOCUMENT);
|
||||
MusicDirectory dir = new MusicDirectory();
|
||||
int eventType;
|
||||
do
|
||||
{
|
||||
eventType = nextParseEvent();
|
||||
if (eventType == XmlPullParser.START_TAG)
|
||||
{
|
||||
String name = getElementName();
|
||||
if ("song".equals(name))
|
||||
{
|
||||
dir.addChild(parseEntry("", false, 0));
|
||||
}
|
||||
else if ("error".equals(name))
|
||||
{
|
||||
handleError();
|
||||
}
|
||||
}
|
||||
} while (eventType != XmlPullParser.END_DOCUMENT);
|
||||
|
||||
validate();
|
||||
updateProgress(progressListener, R.string.parser_reading_done);
|
||||
validate();
|
||||
updateProgress(progressListener, R.string.parser_reading_done);
|
||||
|
||||
return dir;
|
||||
}
|
||||
return dir;
|
||||
}
|
||||
|
||||
}
|
|
@ -19,11 +19,13 @@
|
|||
package com.thejoshwa.ultrasonic.androidapp.service.parser;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.thejoshwa.ultrasonic.androidapp.R;
|
||||
import com.thejoshwa.ultrasonic.androidapp.domain.MusicDirectory;
|
||||
import com.thejoshwa.ultrasonic.androidapp.domain.SearchResult;
|
||||
import com.thejoshwa.ultrasonic.androidapp.domain.Artist;
|
||||
import com.thejoshwa.ultrasonic.androidapp.util.ProgressListener;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
|
||||
import java.io.Reader;
|
||||
|
@ -33,43 +35,55 @@ import java.util.ArrayList;
|
|||
/**
|
||||
* @author Sindre Mehus
|
||||
*/
|
||||
public class SearchResult2Parser extends MusicDirectoryEntryParser {
|
||||
public class SearchResult2Parser extends MusicDirectoryEntryParser
|
||||
{
|
||||
|
||||
public SearchResult2Parser(Context context) {
|
||||
super(context);
|
||||
}
|
||||
public SearchResult2Parser(Context context)
|
||||
{
|
||||
super(context);
|
||||
}
|
||||
|
||||
public SearchResult parse(Reader reader, ProgressListener progressListener, boolean useId3) throws Exception {
|
||||
updateProgress(progressListener, R.string.parser_reading);
|
||||
init(reader);
|
||||
public SearchResult parse(Reader reader, ProgressListener progressListener, boolean useId3) throws Exception
|
||||
{
|
||||
updateProgress(progressListener, R.string.parser_reading);
|
||||
init(reader);
|
||||
|
||||
List<Artist> artists = new ArrayList<Artist>();
|
||||
List<MusicDirectory.Entry> albums = new ArrayList<MusicDirectory.Entry>();
|
||||
List<MusicDirectory.Entry> songs = new ArrayList<MusicDirectory.Entry>();
|
||||
int eventType;
|
||||
do {
|
||||
eventType = nextParseEvent();
|
||||
if (eventType == XmlPullParser.START_TAG) {
|
||||
String name = getElementName();
|
||||
if ("artist".equals(name)) {
|
||||
Artist artist = new Artist();
|
||||
artist.setId(get("id"));
|
||||
artist.setName(get("name"));
|
||||
artists.add(artist);
|
||||
} else if ("album".equals(name)) {
|
||||
albums.add(parseEntry("", useId3, 0));
|
||||
} else if ("song".equals(name)) {
|
||||
songs.add(parseEntry("", false, 0));
|
||||
} else if ("error".equals(name)) {
|
||||
handleError();
|
||||
}
|
||||
}
|
||||
} while (eventType != XmlPullParser.END_DOCUMENT);
|
||||
List<Artist> artists = new ArrayList<Artist>();
|
||||
List<MusicDirectory.Entry> albums = new ArrayList<MusicDirectory.Entry>();
|
||||
List<MusicDirectory.Entry> songs = new ArrayList<MusicDirectory.Entry>();
|
||||
int eventType;
|
||||
do
|
||||
{
|
||||
eventType = nextParseEvent();
|
||||
if (eventType == XmlPullParser.START_TAG)
|
||||
{
|
||||
String name = getElementName();
|
||||
if ("artist".equals(name))
|
||||
{
|
||||
Artist artist = new Artist();
|
||||
artist.setId(get("id"));
|
||||
artist.setName(get("name"));
|
||||
artists.add(artist);
|
||||
}
|
||||
else if ("album".equals(name))
|
||||
{
|
||||
albums.add(parseEntry("", useId3, 0));
|
||||
}
|
||||
else if ("song".equals(name))
|
||||
{
|
||||
songs.add(parseEntry("", false, 0));
|
||||
}
|
||||
else if ("error".equals(name))
|
||||
{
|
||||
handleError();
|
||||
}
|
||||
}
|
||||
} while (eventType != XmlPullParser.END_DOCUMENT);
|
||||
|
||||
validate();
|
||||
updateProgress(progressListener, R.string.parser_reading_done);
|
||||
validate();
|
||||
updateProgress(progressListener, R.string.parser_reading_done);
|
||||
|
||||
return new SearchResult(artists, albums, songs);
|
||||
}
|
||||
return new SearchResult(artists, albums, songs);
|
||||
}
|
||||
|
||||
}
|
|
@ -19,11 +19,13 @@
|
|||
package com.thejoshwa.ultrasonic.androidapp.service.parser;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.thejoshwa.ultrasonic.androidapp.R;
|
||||
import com.thejoshwa.ultrasonic.androidapp.domain.MusicDirectory;
|
||||
import com.thejoshwa.ultrasonic.androidapp.domain.SearchResult;
|
||||
import com.thejoshwa.ultrasonic.androidapp.domain.Artist;
|
||||
import com.thejoshwa.ultrasonic.androidapp.util.ProgressListener;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
|
||||
import java.io.Reader;
|
||||
|
@ -34,34 +36,42 @@ import java.util.ArrayList;
|
|||
/**
|
||||
* @author Sindre Mehus
|
||||
*/
|
||||
public class SearchResultParser extends MusicDirectoryEntryParser {
|
||||
public class SearchResultParser extends MusicDirectoryEntryParser
|
||||
{
|
||||
|
||||
public SearchResultParser(Context context) {
|
||||
super(context);
|
||||
}
|
||||
public SearchResultParser(Context context)
|
||||
{
|
||||
super(context);
|
||||
}
|
||||
|
||||
public SearchResult parse(Reader reader, ProgressListener progressListener) throws Exception {
|
||||
updateProgress(progressListener, R.string.parser_reading);
|
||||
init(reader);
|
||||
public SearchResult parse(Reader reader, ProgressListener progressListener) throws Exception
|
||||
{
|
||||
updateProgress(progressListener, R.string.parser_reading);
|
||||
init(reader);
|
||||
|
||||
List<MusicDirectory.Entry> songs = new ArrayList<MusicDirectory.Entry>();
|
||||
int eventType;
|
||||
do {
|
||||
eventType = nextParseEvent();
|
||||
if (eventType == XmlPullParser.START_TAG) {
|
||||
String name = getElementName();
|
||||
if ("match".equals(name)) {
|
||||
songs.add(parseEntry("", false, 0));
|
||||
} else if ("error".equals(name)) {
|
||||
handleError();
|
||||
}
|
||||
}
|
||||
} while (eventType != XmlPullParser.END_DOCUMENT);
|
||||
List<MusicDirectory.Entry> songs = new ArrayList<MusicDirectory.Entry>();
|
||||
int eventType;
|
||||
do
|
||||
{
|
||||
eventType = nextParseEvent();
|
||||
if (eventType == XmlPullParser.START_TAG)
|
||||
{
|
||||
String name = getElementName();
|
||||
if ("match".equals(name))
|
||||
{
|
||||
songs.add(parseEntry("", false, 0));
|
||||
}
|
||||
else if ("error".equals(name))
|
||||
{
|
||||
handleError();
|
||||
}
|
||||
}
|
||||
} while (eventType != XmlPullParser.END_DOCUMENT);
|
||||
|
||||
validate();
|
||||
updateProgress(progressListener, R.string.parser_reading_done);
|
||||
validate();
|
||||
updateProgress(progressListener, R.string.parser_reading_done);
|
||||
|
||||
return new SearchResult(Collections.<Artist>emptyList(), Collections.<MusicDirectory.Entry>emptyList(), songs);
|
||||
}
|
||||
return new SearchResult(Collections.<Artist>emptyList(), Collections.<MusicDirectory.Entry>emptyList(), songs);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
package com.thejoshwa.ultrasonic.androidapp.service.parser;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.thejoshwa.ultrasonic.androidapp.R;
|
||||
import com.thejoshwa.ultrasonic.androidapp.domain.Share;
|
||||
import com.thejoshwa.ultrasonic.androidapp.util.ProgressListener;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
|
||||
import java.io.Reader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
@ -12,50 +15,61 @@ import java.util.List;
|
|||
/**
|
||||
* @author Joshua Bahnsen
|
||||
*/
|
||||
public class ShareParser extends MusicDirectoryEntryParser {
|
||||
public class ShareParser extends MusicDirectoryEntryParser
|
||||
{
|
||||
|
||||
public ShareParser(Context context) {
|
||||
super(context);
|
||||
}
|
||||
public ShareParser(Context context)
|
||||
{
|
||||
super(context);
|
||||
}
|
||||
|
||||
public List<Share> parse(Reader reader, ProgressListener progressListener) throws Exception {
|
||||
public List<Share> parse(Reader reader, ProgressListener progressListener) throws Exception
|
||||
{
|
||||
|
||||
updateProgress(progressListener, R.string.parser_reading);
|
||||
init(reader);
|
||||
updateProgress(progressListener, R.string.parser_reading);
|
||||
init(reader);
|
||||
|
||||
List<Share> dir = new ArrayList<Share>();
|
||||
Share share = null;
|
||||
int eventType;
|
||||
|
||||
do {
|
||||
eventType = nextParseEvent();
|
||||
|
||||
if (eventType == XmlPullParser.START_TAG) {
|
||||
String name = getElementName();
|
||||
|
||||
if ("share".equals(name)) {
|
||||
share = new Share();
|
||||
share.setCreated(get("created"));
|
||||
share.setDescription(get("description"));
|
||||
share.setExpires(get("expires"));
|
||||
share.setId(get("id"));
|
||||
share.setLastVisited(get("lastVisited"));
|
||||
share.setUrl(get("url"));
|
||||
share.setUsername(get("username"));
|
||||
share.setVisitCount(getLong("visitCount"));
|
||||
} else if ("entry".equals(name)) {
|
||||
if (share != null) {
|
||||
share.addEntry(parseEntry(null, false, 0));
|
||||
}
|
||||
} else if ("error".equals(name)) {
|
||||
handleError();
|
||||
}
|
||||
}
|
||||
} while (eventType != XmlPullParser.END_DOCUMENT);
|
||||
List<Share> dir = new ArrayList<Share>();
|
||||
Share share = null;
|
||||
int eventType;
|
||||
|
||||
validate();
|
||||
updateProgress(progressListener, R.string.parser_reading_done);
|
||||
do
|
||||
{
|
||||
eventType = nextParseEvent();
|
||||
|
||||
return dir;
|
||||
}
|
||||
if (eventType == XmlPullParser.START_TAG)
|
||||
{
|
||||
String name = getElementName();
|
||||
|
||||
if ("share".equals(name))
|
||||
{
|
||||
share = new Share();
|
||||
share.setCreated(get("created"));
|
||||
share.setDescription(get("description"));
|
||||
share.setExpires(get("expires"));
|
||||
share.setId(get("id"));
|
||||
share.setLastVisited(get("lastVisited"));
|
||||
share.setUrl(get("url"));
|
||||
share.setUsername(get("username"));
|
||||
share.setVisitCount(getLong("visitCount"));
|
||||
}
|
||||
else if ("entry".equals(name))
|
||||
{
|
||||
if (share != null)
|
||||
{
|
||||
share.addEntry(parseEntry(null, false, 0));
|
||||
}
|
||||
}
|
||||
else if ("error".equals(name))
|
||||
{
|
||||
handleError();
|
||||
}
|
||||
}
|
||||
} while (eventType != XmlPullParser.END_DOCUMENT);
|
||||
|
||||
validate();
|
||||
updateProgress(progressListener, R.string.parser_reading_done);
|
||||
|
||||
return dir;
|
||||
}
|
||||
}
|
|
@ -4,20 +4,23 @@ package com.thejoshwa.ultrasonic.androidapp.service.parser;
|
|||
* @author Sindre Mehus
|
||||
* @version $Id$
|
||||
*/
|
||||
public class SubsonicRESTException extends Exception {
|
||||
public class SubsonicRESTException extends Exception
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 859440717343258203L;
|
||||
private final int code;
|
||||
|
||||
public SubsonicRESTException(int code, String message) {
|
||||
super(message);
|
||||
this.code = code;
|
||||
}
|
||||
public SubsonicRESTException(int code, String message)
|
||||
{
|
||||
super(message);
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public int getCode() {
|
||||
return code;
|
||||
}
|
||||
public int getCode()
|
||||
{
|
||||
return code;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,20 +28,24 @@ import java.util.regex.Pattern;
|
|||
/**
|
||||
* @author Sindre Mehus
|
||||
*/
|
||||
public class VersionParser {
|
||||
public class VersionParser
|
||||
{
|
||||
|
||||
public Version parse(Reader reader) throws Exception {
|
||||
public static Version parse(Reader reader) throws Exception
|
||||
{
|
||||
|
||||
BufferedReader bufferedReader = new BufferedReader(reader);
|
||||
Pattern pattern = Pattern.compile("SUBSONIC_ANDROID_VERSION_BEGIN(.*)SUBSONIC_ANDROID_VERSION_END");
|
||||
String line = bufferedReader.readLine();
|
||||
while (line != null) {
|
||||
Matcher finalMatcher = pattern.matcher(line);
|
||||
if (finalMatcher.find()) {
|
||||
return new Version(finalMatcher.group(1));
|
||||
}
|
||||
line = bufferedReader.readLine();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
BufferedReader bufferedReader = new BufferedReader(reader);
|
||||
Pattern pattern = Pattern.compile("SUBSONIC_ANDROID_VERSION_BEGIN(.*)SUBSONIC_ANDROID_VERSION_END");
|
||||
String line = bufferedReader.readLine();
|
||||
while (line != null)
|
||||
{
|
||||
Matcher finalMatcher = pattern.matcher(line);
|
||||
if (finalMatcher.find())
|
||||
{
|
||||
return new Version(finalMatcher.group(1));
|
||||
}
|
||||
line = bufferedReader.readLine();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -67,7 +67,7 @@ import javax.net.ssl.X509TrustManager;
|
|||
* server attempts to authenticate itself with a non-trusted certificate.
|
||||
* <p>
|
||||
* Use JDK keytool utility to import a trusted certificate and generate a trust-store file:
|
||||
* <pre>
|
||||
* <pre>
|
||||
* keytool -import -alias "my server cert" -file server.crt -keystore my.truststore
|
||||
* </pre>
|
||||
* <p>
|
||||
|
@ -78,8 +78,8 @@ import javax.net.ssl.X509TrustManager;
|
|||
* The following parameters can be used to customize the behavior of this
|
||||
* class:
|
||||
* <ul>
|
||||
* <li>{@link org.apache.http.params.CoreConnectionPNames#CONNECTION_TIMEOUT}</li>
|
||||
* <li>{@link org.apache.http.params.CoreConnectionPNames#SO_TIMEOUT}</li>
|
||||
* <li>{@link org.apache.http.params.CoreConnectionPNames#CONNECTION_TIMEOUT}</li>
|
||||
* <li>{@link org.apache.http.params.CoreConnectionPNames#SO_TIMEOUT}</li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* SSLSocketFactory will enable client authentication when supplied with
|
||||
|
@ -92,245 +92,282 @@ import javax.net.ssl.X509TrustManager;
|
|||
* <p>
|
||||
* Use the following sequence of actions to generate a key-store file
|
||||
* </p>
|
||||
* <ul>
|
||||
* <li>
|
||||
* <p>
|
||||
* Use JDK keytool utility to generate a new key
|
||||
* <pre>keytool -genkey -v -alias "my client key" -validity 365 -keystore my.keystore</pre>
|
||||
* For simplicity use the same password for the key as that of the key-store
|
||||
* </p>
|
||||
* </li>
|
||||
* <li>
|
||||
* <p>
|
||||
* Issue a certificate signing request (CSR)
|
||||
* <pre>keytool -certreq -alias "my client key" -file mycertreq.csr -keystore my.keystore</pre>
|
||||
* </p>
|
||||
* </li>
|
||||
* <li>
|
||||
* <p>
|
||||
* Send the certificate request to the trusted Certificate Authority for signature.
|
||||
* One may choose to act as her own CA and sign the certificate request using a PKI
|
||||
* tool, such as OpenSSL.
|
||||
* </p>
|
||||
* </li>
|
||||
* <li>
|
||||
* <p>
|
||||
* Import the trusted CA root certificate
|
||||
* <pre>keytool -import -alias "my trusted ca" -file caroot.crt -keystore my.keystore</pre>
|
||||
* </p>
|
||||
* </li>
|
||||
* <li>
|
||||
* <p>
|
||||
* Import the PKCS#7 file containg the complete certificate chain
|
||||
* <pre>keytool -import -alias "my client key" -file mycert.p7 -keystore my.keystore</pre>
|
||||
* </p>
|
||||
* </li>
|
||||
* <li>
|
||||
* <p>
|
||||
* Verify the content the resultant keystore file
|
||||
* <pre>keytool -list -v -keystore my.keystore</pre>
|
||||
* </p>
|
||||
* </li>
|
||||
* </ul>
|
||||
* <ul>
|
||||
* <li>
|
||||
* <p>
|
||||
* Use JDK keytool utility to generate a new key
|
||||
* <pre>keytool -genkey -v -alias "my client key" -validity 365 -keystore my.keystore</pre>
|
||||
* For simplicity use the same password for the key as that of the key-store
|
||||
* </p>
|
||||
* </li>
|
||||
* <li>
|
||||
* <p>
|
||||
* Issue a certificate signing request (CSR)
|
||||
* <pre>keytool -certreq -alias "my client key" -file mycertreq.csr -keystore my.keystore</pre>
|
||||
* </p>
|
||||
* </li>
|
||||
* <li>
|
||||
* <p>
|
||||
* Send the certificate request to the trusted Certificate Authority for signature.
|
||||
* One may choose to act as her own CA and sign the certificate request using a PKI
|
||||
* tool, such as OpenSSL.
|
||||
* </p>
|
||||
* </li>
|
||||
* <li>
|
||||
* <p>
|
||||
* Import the trusted CA root certificate
|
||||
* <pre>keytool -import -alias "my trusted ca" -file caroot.crt -keystore my.keystore</pre>
|
||||
* </p>
|
||||
* </li>
|
||||
* <li>
|
||||
* <p>
|
||||
* Import the PKCS#7 file containg the complete certificate chain
|
||||
* <pre>keytool -import -alias "my client key" -file mycert.p7 -keystore my.keystore</pre>
|
||||
* </p>
|
||||
* </li>
|
||||
* <li>
|
||||
* <p>
|
||||
* Verify the content the resultant keystore file
|
||||
* <pre>keytool -list -v -keystore my.keystore</pre>
|
||||
* </p>
|
||||
* </li>
|
||||
* </ul>
|
||||
*
|
||||
* @since 4.0
|
||||
*/
|
||||
public class SSLSocketFactory implements LayeredSocketFactory {
|
||||
public class SSLSocketFactory implements LayeredSocketFactory
|
||||
{
|
||||
|
||||
public static final String TLS = "TLS";
|
||||
public static final X509HostnameVerifier ALLOW_ALL_HOSTNAME_VERIFIER = new AllowAllHostnameVerifier();
|
||||
public static final String TLS = "TLS";
|
||||
public static final X509HostnameVerifier ALLOW_ALL_HOSTNAME_VERIFIER = new AllowAllHostnameVerifier();
|
||||
|
||||
/**
|
||||
* The default factory using the default JVM settings for secure connections.
|
||||
*/
|
||||
private final javax.net.ssl.SSLSocketFactory socketFactory;
|
||||
private final HostNameResolver nameResolver;
|
||||
private volatile X509HostnameVerifier hostnameVerifier;
|
||||
/**
|
||||
* The default factory using the default JVM settings for secure connections.
|
||||
*/
|
||||
private final javax.net.ssl.SSLSocketFactory socketFactory;
|
||||
private final HostNameResolver nameResolver;
|
||||
private volatile X509HostnameVerifier hostnameVerifier;
|
||||
|
||||
private static SSLContext createSSLContext(String algorithm, final KeyStore keystore, final String keyStorePassword, final SecureRandom random, final TrustStrategy trustStrategy) throws NoSuchAlgorithmException, KeyStoreException, UnrecoverableKeyException, KeyManagementException {
|
||||
if (algorithm == null) {
|
||||
algorithm = TLS;
|
||||
}
|
||||
private static SSLContext createSSLContext(String algorithm, final KeyStore keystore, final String keyStorePassword, final SecureRandom random, final TrustStrategy trustStrategy) throws NoSuchAlgorithmException, KeyStoreException, UnrecoverableKeyException, KeyManagementException
|
||||
{
|
||||
if (algorithm == null)
|
||||
{
|
||||
algorithm = TLS;
|
||||
}
|
||||
|
||||
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
|
||||
keyManagerFactory.init(keystore, keyStorePassword != null ? keyStorePassword.toCharArray() : null);
|
||||
KeyManager[] keyManagers = keyManagerFactory.getKeyManagers();
|
||||
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
|
||||
trustManagerFactory.init(keystore);
|
||||
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
|
||||
keyManagerFactory.init(keystore, keyStorePassword != null ? keyStorePassword.toCharArray() : null);
|
||||
KeyManager[] keyManagers = keyManagerFactory.getKeyManagers();
|
||||
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
|
||||
trustManagerFactory.init(keystore);
|
||||
|
||||
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
|
||||
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
|
||||
|
||||
if (trustManagers != null && trustStrategy != null) {
|
||||
for (int i = 0; i < trustManagers.length; i++) {
|
||||
TrustManager tm = trustManagers[i];
|
||||
if (trustManagers != null && trustStrategy != null)
|
||||
{
|
||||
for (int i = 0; i < trustManagers.length; i++)
|
||||
{
|
||||
TrustManager tm = trustManagers[i];
|
||||
|
||||
if (tm instanceof X509TrustManager) {
|
||||
trustManagers[i] = new TrustManagerDecorator((X509TrustManager) tm, trustStrategy);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (tm instanceof X509TrustManager)
|
||||
{
|
||||
trustManagers[i] = new TrustManagerDecorator((X509TrustManager) tm, trustStrategy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SSLContext sslcontext = SSLContext.getInstance(algorithm);
|
||||
sslcontext.init(keyManagers, trustManagers, random);
|
||||
SSLContext sslcontext = SSLContext.getInstance(algorithm);
|
||||
sslcontext.init(keyManagers, trustManagers, random);
|
||||
|
||||
return sslcontext;
|
||||
}
|
||||
return sslcontext;
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 4.1
|
||||
*/
|
||||
public SSLSocketFactory(String algorithm, final KeyStore keystore, final String keyStorePassword, final SecureRandom random, final TrustStrategy trustStrategy, final X509HostnameVerifier hostnameVerifier) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
|
||||
this(createSSLContext(algorithm, keystore, keyStorePassword, random, trustStrategy), hostnameVerifier);
|
||||
}
|
||||
/**
|
||||
* @since 4.1
|
||||
*/
|
||||
public SSLSocketFactory(String algorithm, final KeyStore keystore, final String keyStorePassword, final SecureRandom random, final TrustStrategy trustStrategy, final X509HostnameVerifier hostnameVerifier) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException
|
||||
{
|
||||
this(createSSLContext(algorithm, keystore, keyStorePassword, random, trustStrategy), hostnameVerifier);
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 4.1
|
||||
*/
|
||||
public SSLSocketFactory(final TrustStrategy trustStrategy, final X509HostnameVerifier hostnameVerifier) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
|
||||
this(TLS, null, null, null, trustStrategy, hostnameVerifier);
|
||||
}
|
||||
/**
|
||||
* @since 4.1
|
||||
*/
|
||||
public SSLSocketFactory(final TrustStrategy trustStrategy, final X509HostnameVerifier hostnameVerifier) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException
|
||||
{
|
||||
this(TLS, null, null, null, trustStrategy, hostnameVerifier);
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 4.1
|
||||
*/
|
||||
public SSLSocketFactory(final SSLContext sslContext, final X509HostnameVerifier hostnameVerifier) {
|
||||
super();
|
||||
this.socketFactory = sslContext.getSocketFactory();
|
||||
this.hostnameVerifier = hostnameVerifier;
|
||||
this.nameResolver = null;
|
||||
}
|
||||
/**
|
||||
* @since 4.1
|
||||
*/
|
||||
public SSLSocketFactory(final SSLContext sslContext, final X509HostnameVerifier hostnameVerifier)
|
||||
{
|
||||
super();
|
||||
this.socketFactory = sslContext.getSocketFactory();
|
||||
this.hostnameVerifier = hostnameVerifier;
|
||||
this.nameResolver = null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("cast")
|
||||
public Socket createSocket() throws IOException {
|
||||
// the cast makes sure that the factory is working as expected
|
||||
return this.socketFactory.createSocket();
|
||||
}
|
||||
@SuppressWarnings("cast")
|
||||
public Socket createSocket() throws IOException
|
||||
{
|
||||
// the cast makes sure that the factory is working as expected
|
||||
return this.socketFactory.createSocket();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 4.1
|
||||
*/
|
||||
public Socket connectSocket(final Socket sock, final InetSocketAddress remoteAddress, final InetSocketAddress localAddress, final HttpParams params) throws IOException {
|
||||
if (remoteAddress == null) {
|
||||
throw new IllegalArgumentException("Remote address may not be null");
|
||||
}
|
||||
/**
|
||||
* @since 4.1
|
||||
*/
|
||||
public Socket connectSocket(final Socket sock, final InetSocketAddress remoteAddress, final InetSocketAddress localAddress, final HttpParams params) throws IOException
|
||||
{
|
||||
if (remoteAddress == null)
|
||||
{
|
||||
throw new IllegalArgumentException("Remote address may not be null");
|
||||
}
|
||||
|
||||
if (params == null) {
|
||||
throw new IllegalArgumentException("HTTP parameters may not be null");
|
||||
}
|
||||
if (params == null)
|
||||
{
|
||||
throw new IllegalArgumentException("HTTP parameters may not be null");
|
||||
}
|
||||
|
||||
SSLSocket sslSocket = (SSLSocket) (sock != null ? sock : createSocket());
|
||||
SSLSocket sslSocket = (SSLSocket) (sock != null ? sock : createSocket());
|
||||
|
||||
if (localAddress != null) {
|
||||
// sslSocket.setReuseAddress(HttpConnectionParams.getSoReuseaddr(params));
|
||||
sslSocket.bind(localAddress);
|
||||
}
|
||||
if (localAddress != null)
|
||||
{
|
||||
// sslSocket.setReuseAddress(HttpConnectionParams.getSoReuseaddr(params));
|
||||
sslSocket.bind(localAddress);
|
||||
}
|
||||
|
||||
int connTimeout = HttpConnectionParams.getConnectionTimeout(params);
|
||||
int soTimeout = HttpConnectionParams.getSoTimeout(params);
|
||||
int connTimeout = HttpConnectionParams.getConnectionTimeout(params);
|
||||
int soTimeout = HttpConnectionParams.getSoTimeout(params);
|
||||
|
||||
try {
|
||||
sslSocket.connect(remoteAddress, connTimeout);
|
||||
} catch (SocketTimeoutException ex) {
|
||||
throw new ConnectTimeoutException("Connect to " + remoteAddress.getHostName() + "/" + remoteAddress.getAddress() + " timed out");
|
||||
}
|
||||
try
|
||||
{
|
||||
sslSocket.connect(remoteAddress, connTimeout);
|
||||
}
|
||||
catch (SocketTimeoutException ex)
|
||||
{
|
||||
throw new ConnectTimeoutException(String.format("Connect to %s/%s timed out", remoteAddress.getHostName(), remoteAddress.getAddress()));
|
||||
}
|
||||
|
||||
sslSocket.setSoTimeout(soTimeout);
|
||||
sslSocket.setSoTimeout(soTimeout);
|
||||
|
||||
if (this.hostnameVerifier != null) {
|
||||
try {
|
||||
this.hostnameVerifier.verify(remoteAddress.getHostName(), sslSocket);
|
||||
// verifyHostName() didn't blowup - good!
|
||||
} catch (IOException iox) {
|
||||
// close the socket before re-throwing the exception
|
||||
try { sslSocket.close(); } catch (Exception x) { /*ignore*/ }
|
||||
throw iox;
|
||||
}
|
||||
}
|
||||
if (this.hostnameVerifier != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
this.hostnameVerifier.verify(remoteAddress.getHostName(), sslSocket);
|
||||
// verifyHostName() didn't blowup - good!
|
||||
}
|
||||
catch (IOException iox)
|
||||
{
|
||||
// close the socket before re-throwing the exception
|
||||
try
|
||||
{
|
||||
sslSocket.close();
|
||||
}
|
||||
catch (Exception x)
|
||||
{ /*ignore*/ }
|
||||
throw iox;
|
||||
}
|
||||
}
|
||||
|
||||
return sslSocket;
|
||||
}
|
||||
return sslSocket;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks whether a socket connection is secure.
|
||||
* This factory creates TLS/SSL socket connections
|
||||
* which, by default, are considered secure.
|
||||
* <br/>
|
||||
* Derived classes may override this method to perform
|
||||
* runtime checks, for example based on the cypher suite.
|
||||
*
|
||||
* @param sock the connected socket
|
||||
*
|
||||
* @return <code>true</code>
|
||||
*
|
||||
* @throws IllegalArgumentException if the argument is invalid
|
||||
*/
|
||||
public boolean isSecure(final Socket sock) throws IllegalArgumentException {
|
||||
if (sock == null) {
|
||||
throw new IllegalArgumentException("Socket may not be null");
|
||||
}
|
||||
/**
|
||||
* Checks whether a socket connection is secure.
|
||||
* This factory creates TLS/SSL socket connections
|
||||
* which, by default, are considered secure.
|
||||
* <br/>
|
||||
* Derived classes may override this method to perform
|
||||
* runtime checks, for example based on the cypher suite.
|
||||
*
|
||||
* @param sock the connected socket
|
||||
* @return <code>true</code>
|
||||
* @throws IllegalArgumentException if the argument is invalid
|
||||
*/
|
||||
public boolean isSecure(final Socket sock) throws IllegalArgumentException
|
||||
{
|
||||
if (sock == null)
|
||||
{
|
||||
throw new IllegalArgumentException("Socket may not be null");
|
||||
}
|
||||
|
||||
// This instanceof check is in line with createSocket() above.
|
||||
if (!(sock instanceof SSLSocket)) {
|
||||
throw new IllegalArgumentException("Socket not created by this factory");
|
||||
}
|
||||
// This instanceof check is in line with createSocket() above.
|
||||
if (!(sock instanceof SSLSocket))
|
||||
{
|
||||
throw new IllegalArgumentException("Socket not created by this factory");
|
||||
}
|
||||
|
||||
// This check is performed last since it calls the argument object.
|
||||
if (sock.isClosed()) {
|
||||
throw new IllegalArgumentException("Socket is closed");
|
||||
}
|
||||
// This check is performed last since it calls the argument object.
|
||||
if (sock.isClosed())
|
||||
{
|
||||
throw new IllegalArgumentException("Socket is closed");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 4.1
|
||||
*/
|
||||
public Socket createLayeredSocket(final Socket socket, final String host, final int port, final boolean autoClose) throws IOException {
|
||||
SSLSocket sslSocket = (SSLSocket) this.socketFactory.createSocket(socket, host, port, autoClose);
|
||||
/**
|
||||
* @since 4.1
|
||||
*/
|
||||
public Socket createLayeredSocket(final Socket socket, final String host, final int port, final boolean autoClose) throws IOException
|
||||
{
|
||||
SSLSocket sslSocket = (SSLSocket) this.socketFactory.createSocket(socket, host, port, autoClose);
|
||||
|
||||
if (this.hostnameVerifier != null) {
|
||||
this.hostnameVerifier.verify(host, sslSocket);
|
||||
}
|
||||
if (this.hostnameVerifier != null)
|
||||
{
|
||||
this.hostnameVerifier.verify(host, sslSocket);
|
||||
}
|
||||
|
||||
// verifyHostName() didn't blowup - good!
|
||||
return sslSocket;
|
||||
}
|
||||
// verifyHostName() didn't blowup - good!
|
||||
return sslSocket;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #connectSocket(Socket, InetSocketAddress, InetSocketAddress, HttpParams)}
|
||||
*/
|
||||
@Deprecated
|
||||
public Socket connectSocket(final Socket socket, final String host, int port, final InetAddress localAddress, int localPort, final HttpParams params) throws IOException {
|
||||
InetSocketAddress local = null;
|
||||
/**
|
||||
* @deprecated Use {@link #connectSocket(Socket, InetSocketAddress, InetSocketAddress, HttpParams)}
|
||||
*/
|
||||
@Deprecated
|
||||
public Socket connectSocket(final Socket socket, final String host, int port, final InetAddress localAddress, int localPort, final HttpParams params) throws IOException
|
||||
{
|
||||
InetSocketAddress local = null;
|
||||
|
||||
if (localAddress != null || localPort > 0) {
|
||||
// we need to bind explicitly
|
||||
if (localPort < 0) {
|
||||
localPort = 0; // indicates "any"
|
||||
}
|
||||
if (localAddress != null || localPort > 0)
|
||||
{
|
||||
// we need to bind explicitly
|
||||
if (localPort < 0)
|
||||
{
|
||||
localPort = 0; // indicates "any"
|
||||
}
|
||||
|
||||
local = new InetSocketAddress(localAddress, localPort);
|
||||
}
|
||||
local = new InetSocketAddress(localAddress, localPort);
|
||||
}
|
||||
|
||||
InetAddress remoteAddress;
|
||||
InetAddress remoteAddress;
|
||||
|
||||
if (this.nameResolver != null) {
|
||||
remoteAddress = this.nameResolver.resolve(host);
|
||||
} else {
|
||||
remoteAddress = InetAddress.getByName(host);
|
||||
}
|
||||
if (this.nameResolver != null)
|
||||
{
|
||||
remoteAddress = this.nameResolver.resolve(host);
|
||||
}
|
||||
else
|
||||
{
|
||||
remoteAddress = InetAddress.getByName(host);
|
||||
}
|
||||
|
||||
InetSocketAddress remote = new InetSocketAddress(remoteAddress, port);
|
||||
InetSocketAddress remote = new InetSocketAddress(remoteAddress, port);
|
||||
|
||||
return connectSocket(socket, remote, local, params);
|
||||
}
|
||||
return connectSocket(socket, remote, local, params);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #createLayeredSocket(Socket, String, int, boolean)}
|
||||
*/
|
||||
@Deprecated
|
||||
public Socket createSocket(final Socket socket, final String host, int port, boolean autoClose) throws IOException {
|
||||
return createLayeredSocket(socket, host, port, autoClose);
|
||||
}
|
||||
/**
|
||||
* @deprecated Use {@link #createLayeredSocket(Socket, String, int, boolean)}
|
||||
*/
|
||||
@Deprecated
|
||||
public Socket createSocket(final Socket socket, final String host, int port, boolean autoClose) throws IOException
|
||||
{
|
||||
return createLayeredSocket(socket, host, port, autoClose);
|
||||
}
|
||||
}
|
|
@ -34,28 +34,37 @@ import javax.net.ssl.X509TrustManager;
|
|||
/**
|
||||
* @since 4.1
|
||||
*/
|
||||
class TrustManagerDecorator implements X509TrustManager {
|
||||
class TrustManagerDecorator implements X509TrustManager
|
||||
{
|
||||
|
||||
private final X509TrustManager trustManager;
|
||||
private final TrustStrategy trustStrategy;
|
||||
private final X509TrustManager trustManager;
|
||||
private final TrustStrategy trustStrategy;
|
||||
|
||||
TrustManagerDecorator(final X509TrustManager trustManager, final TrustStrategy trustStrategy) {
|
||||
super();
|
||||
this.trustManager = trustManager;
|
||||
this.trustStrategy = trustStrategy;
|
||||
}
|
||||
TrustManagerDecorator(final X509TrustManager trustManager, final TrustStrategy trustStrategy)
|
||||
{
|
||||
super();
|
||||
this.trustManager = trustManager;
|
||||
this.trustStrategy = trustStrategy;
|
||||
}
|
||||
|
||||
public void checkClientTrusted(final X509Certificate[] chain, final String authType) throws CertificateException {
|
||||
this.trustManager.checkClientTrusted(chain, authType);
|
||||
}
|
||||
@Override
|
||||
public void checkClientTrusted(final X509Certificate[] chain, final String authType) throws CertificateException
|
||||
{
|
||||
this.trustManager.checkClientTrusted(chain, authType);
|
||||
}
|
||||
|
||||
public void checkServerTrusted(final X509Certificate[] chain, final String authType) throws CertificateException {
|
||||
if (!this.trustStrategy.isTrusted(chain, authType)) {
|
||||
this.trustManager.checkServerTrusted(chain, authType);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void checkServerTrusted(final X509Certificate[] chain, final String authType) throws CertificateException
|
||||
{
|
||||
if (!this.trustStrategy.isTrusted(chain, authType))
|
||||
{
|
||||
this.trustManager.checkServerTrusted(chain, authType);
|
||||
}
|
||||
}
|
||||
|
||||
public X509Certificate[] getAcceptedIssuers() {
|
||||
return this.trustManager.getAcceptedIssuers();
|
||||
}
|
||||
@Override
|
||||
public X509Certificate[] getAcceptedIssuers()
|
||||
{
|
||||
return this.trustManager.getAcceptedIssuers();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,10 +35,12 @@ import java.security.cert.X509Certificate;
|
|||
*
|
||||
* @since 4.1
|
||||
*/
|
||||
public class TrustSelfSignedStrategy implements TrustStrategy {
|
||||
|
||||
public boolean isTrusted(final X509Certificate[] chain, final String authType) throws CertificateException {
|
||||
return true;
|
||||
}
|
||||
public class TrustSelfSignedStrategy implements TrustStrategy
|
||||
{
|
||||
@Override
|
||||
public boolean isTrusted(final X509Certificate[] chain, final String authType) throws CertificateException
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -36,22 +36,23 @@ import java.security.cert.X509Certificate;
|
|||
*
|
||||
* @since 4.1
|
||||
*/
|
||||
public interface TrustStrategy {
|
||||
public interface TrustStrategy
|
||||
{
|
||||
|
||||
/**
|
||||
* Determines whether the certificate chain can be trusted without consulting the trust manager
|
||||
* configured in the actual SSL context. This method can be used to override the standard JSSE
|
||||
* certificate verification process.
|
||||
* <p>
|
||||
* Please note that, if this method returns <code>false</code>, the trust manager configured
|
||||
* in the actual SSL context can still clear the certificate as trusted.
|
||||
*
|
||||
* @param chain the peer certificate chain
|
||||
* @param authType the authentication type based on the client certificate
|
||||
* @return <code>true</code> if the certificate can be trusted without verification by
|
||||
* the trust manager, <code>false</code> otherwise.
|
||||
* @throws CertificateException thrown if the certificate is not trusted or invalid.
|
||||
*/
|
||||
boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException;
|
||||
/**
|
||||
* Determines whether the certificate chain can be trusted without consulting the trust manager
|
||||
* configured in the actual SSL context. This method can be used to override the standard JSSE
|
||||
* certificate verification process.
|
||||
* <p/>
|
||||
* Please note that, if this method returns <code>false</code>, the trust manager configured
|
||||
* in the actual SSL context can still clear the certificate as trusted.
|
||||
*
|
||||
* @param chain the peer certificate chain
|
||||
* @param authType the authentication type based on the client certificate
|
||||
* @return <code>true</code> if the certificate can be trusted without verification by
|
||||
* the trust manager, <code>false</code> otherwise.
|
||||
* @throws CertificateException thrown if the certificate is not trusted or invalid.
|
||||
*/
|
||||
boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException;
|
||||
|
||||
}
|
||||
|
|
|
@ -5,81 +5,97 @@ import android.content.Context;
|
|||
import com.thejoshwa.ultrasonic.androidapp.domain.MusicDirectory;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class AlbumHeader {
|
||||
private boolean isAllVideo;
|
||||
private long totalDuration;
|
||||
private Set<String> artists;
|
||||
private Set<String> grandParents;
|
||||
private Set<String> genres;
|
||||
public class AlbumHeader
|
||||
{
|
||||
private boolean isAllVideo;
|
||||
private long totalDuration;
|
||||
private Set<String> artists;
|
||||
private Set<String> grandParents;
|
||||
private Set<String> genres;
|
||||
|
||||
public boolean getIsAllVideo() {
|
||||
return isAllVideo;
|
||||
}
|
||||
public boolean getIsAllVideo()
|
||||
{
|
||||
return isAllVideo;
|
||||
}
|
||||
|
||||
public long getTotalDuration() {
|
||||
return totalDuration;
|
||||
}
|
||||
public long getTotalDuration()
|
||||
{
|
||||
return totalDuration;
|
||||
}
|
||||
|
||||
public Set<String> getArtists () {
|
||||
return artists;
|
||||
}
|
||||
public Set<String> getArtists()
|
||||
{
|
||||
return artists;
|
||||
}
|
||||
|
||||
public Set<String> getGrandParents () {
|
||||
return this.grandParents;
|
||||
}
|
||||
public Set<String> getGrandParents()
|
||||
{
|
||||
return this.grandParents;
|
||||
}
|
||||
|
||||
public Set<String> getGenres () {
|
||||
return this.genres;
|
||||
}
|
||||
public Set<String> getGenres()
|
||||
{
|
||||
return this.genres;
|
||||
}
|
||||
|
||||
public AlbumHeader() {
|
||||
this.artists = new HashSet<String>();
|
||||
this.grandParents = new HashSet<String>();
|
||||
this.genres = new HashSet<String>();
|
||||
this.isAllVideo = true;
|
||||
this.totalDuration = 0;
|
||||
}
|
||||
public AlbumHeader()
|
||||
{
|
||||
this.artists = new HashSet<String>();
|
||||
this.grandParents = new HashSet<String>();
|
||||
this.genres = new HashSet<String>();
|
||||
this.isAllVideo = true;
|
||||
this.totalDuration = 0;
|
||||
}
|
||||
|
||||
public static AlbumHeader processEntries(Context context, List<MusicDirectory.Entry> entries) {
|
||||
AlbumHeader albumHeader = new AlbumHeader();
|
||||
public static AlbumHeader processEntries(Context context, Iterable<MusicDirectory.Entry> entries)
|
||||
{
|
||||
AlbumHeader albumHeader = new AlbumHeader();
|
||||
|
||||
for (MusicDirectory.Entry entry : entries) {
|
||||
if (!entry.isVideo()) {
|
||||
albumHeader.isAllVideo = false;
|
||||
}
|
||||
for (MusicDirectory.Entry entry : entries)
|
||||
{
|
||||
if (!entry.isVideo())
|
||||
{
|
||||
albumHeader.isAllVideo = false;
|
||||
}
|
||||
|
||||
if (!entry.isDirectory()) {
|
||||
if (Util.shouldUseFolderForArtistName(context)) {
|
||||
albumHeader.processGrandParents(entry);
|
||||
}
|
||||
if (!entry.isDirectory())
|
||||
{
|
||||
if (Util.shouldUseFolderForArtistName(context))
|
||||
{
|
||||
albumHeader.processGrandParents(entry);
|
||||
}
|
||||
|
||||
if (entry.getArtist() != null) {
|
||||
Integer duration = entry.getDuration();
|
||||
if (entry.getArtist() != null)
|
||||
{
|
||||
Integer duration = entry.getDuration();
|
||||
|
||||
if (duration != null) {
|
||||
albumHeader.totalDuration += duration;
|
||||
}
|
||||
if (duration != null)
|
||||
{
|
||||
albumHeader.totalDuration += duration;
|
||||
}
|
||||
|
||||
albumHeader.artists.add(entry.getArtist());
|
||||
}
|
||||
albumHeader.artists.add(entry.getArtist());
|
||||
}
|
||||
|
||||
if (entry.getGenre() != null) {
|
||||
albumHeader.genres.add(entry.getGenre());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (entry.getGenre() != null)
|
||||
{
|
||||
albumHeader.genres.add(entry.getGenre());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return albumHeader;
|
||||
}
|
||||
return albumHeader;
|
||||
}
|
||||
|
||||
private void processGrandParents(MusicDirectory.Entry entry) {
|
||||
String grandParent = Util.getGrandparent(entry.getPath());
|
||||
private void processGrandParents(MusicDirectory.Entry entry)
|
||||
{
|
||||
String grandParent = Util.getGrandparent(entry.getPath());
|
||||
|
||||
if (grandParent != null) {
|
||||
this.grandParents.add(grandParent);
|
||||
}
|
||||
}
|
||||
if (grandParent != null)
|
||||
{
|
||||
this.grandParents.add(grandParent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,79 +18,92 @@
|
|||
*/
|
||||
package com.thejoshwa.ultrasonic.androidapp.util;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Handler;
|
||||
import android.util.Log;
|
||||
|
||||
import com.thejoshwa.ultrasonic.androidapp.R;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* @author Sindre Mehus
|
||||
*/
|
||||
public abstract class BackgroundTask<T> implements ProgressListener {
|
||||
public abstract class BackgroundTask<T> implements ProgressListener
|
||||
{
|
||||
|
||||
private static final String TAG = BackgroundTask.class.getSimpleName();
|
||||
private final Activity activity;
|
||||
private final Handler handler;
|
||||
private static final String TAG = BackgroundTask.class.getSimpleName();
|
||||
private final Activity activity;
|
||||
private final Handler handler;
|
||||
|
||||
public BackgroundTask(Activity activity) {
|
||||
this.activity = activity;
|
||||
handler = new Handler();
|
||||
}
|
||||
public BackgroundTask(Activity activity)
|
||||
{
|
||||
this.activity = activity;
|
||||
handler = new Handler();
|
||||
}
|
||||
|
||||
protected Activity getActivity() {
|
||||
return activity;
|
||||
}
|
||||
protected Activity getActivity()
|
||||
{
|
||||
return activity;
|
||||
}
|
||||
|
||||
protected Handler getHandler() {
|
||||
return handler;
|
||||
}
|
||||
protected Handler getHandler()
|
||||
{
|
||||
return handler;
|
||||
}
|
||||
|
||||
public abstract void execute();
|
||||
public abstract void execute();
|
||||
|
||||
protected abstract T doInBackground() throws Throwable;
|
||||
protected abstract T doInBackground() throws Throwable;
|
||||
|
||||
protected abstract void done(T result);
|
||||
protected abstract void done(T result);
|
||||
|
||||
protected void error(Throwable error) {
|
||||
Log.w(TAG, "Got exception: " + error, error);
|
||||
new ErrorDialog(activity, getErrorMessage(error), true);
|
||||
}
|
||||
protected void error(Throwable error)
|
||||
{
|
||||
Log.w(TAG, String.format("Got exception: %s", error), error);
|
||||
new ErrorDialog(activity, getErrorMessage(error), true);
|
||||
}
|
||||
|
||||
protected String getErrorMessage(Throwable error) {
|
||||
protected String getErrorMessage(Throwable error)
|
||||
{
|
||||
|
||||
if (error instanceof IOException && !Util.isNetworkConnected(activity)) {
|
||||
return activity.getResources().getString(R.string.background_task_no_network);
|
||||
}
|
||||
if (error instanceof IOException && !Util.isNetworkConnected(activity))
|
||||
{
|
||||
return activity.getResources().getString(R.string.background_task_no_network);
|
||||
}
|
||||
|
||||
if (error instanceof FileNotFoundException) {
|
||||
return activity.getResources().getString(R.string.background_task_not_found);
|
||||
}
|
||||
if (error instanceof FileNotFoundException)
|
||||
{
|
||||
return activity.getResources().getString(R.string.background_task_not_found);
|
||||
}
|
||||
|
||||
if (error instanceof IOException) {
|
||||
return activity.getResources().getString(R.string.background_task_network_error);
|
||||
}
|
||||
if (error instanceof IOException)
|
||||
{
|
||||
return activity.getResources().getString(R.string.background_task_network_error);
|
||||
}
|
||||
|
||||
if (error instanceof XmlPullParserException) {
|
||||
return activity.getResources().getString(R.string.background_task_parse_error);
|
||||
}
|
||||
if (error instanceof XmlPullParserException)
|
||||
{
|
||||
return activity.getResources().getString(R.string.background_task_parse_error);
|
||||
}
|
||||
|
||||
String message = error.getMessage();
|
||||
if (message != null) {
|
||||
return message;
|
||||
}
|
||||
return error.getClass().getSimpleName();
|
||||
}
|
||||
String message = error.getMessage();
|
||||
if (message != null)
|
||||
{
|
||||
return message;
|
||||
}
|
||||
return error.getClass().getSimpleName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract void updateProgress(final String message);
|
||||
@Override
|
||||
public abstract void updateProgress(final String message);
|
||||
|
||||
@Override
|
||||
public void updateProgress(int messageId) {
|
||||
updateProgress(activity.getResources().getString(messageId));
|
||||
}
|
||||
@Override
|
||||
public void updateProgress(int messageId)
|
||||
{
|
||||
updateProgress(activity.getResources().getString(messageId));
|
||||
}
|
||||
}
|
|
@ -1,7 +1,17 @@
|
|||
package com.thejoshwa.ultrasonic.androidapp.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.StatFs;
|
||||
import android.util.Log;
|
||||
|
||||
import com.thejoshwa.ultrasonic.androidapp.domain.Playlist;
|
||||
import com.thejoshwa.ultrasonic.androidapp.service.DownloadFile;
|
||||
import com.thejoshwa.ultrasonic.androidapp.service.DownloadService;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashSet;
|
||||
|
@ -9,172 +19,202 @@ import java.util.List;
|
|||
import java.util.Set;
|
||||
import java.util.SortedSet;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.StatFs;
|
||||
|
||||
import com.thejoshwa.ultrasonic.androidapp.domain.Playlist;
|
||||
import com.thejoshwa.ultrasonic.androidapp.service.DownloadFile;
|
||||
import com.thejoshwa.ultrasonic.androidapp.service.DownloadService;
|
||||
|
||||
/**
|
||||
* @author Sindre Mehus
|
||||
* @version $Id$
|
||||
*/
|
||||
public class CacheCleaner {
|
||||
public class CacheCleaner
|
||||
{
|
||||
|
||||
private static final String TAG = CacheCleaner.class.getSimpleName();
|
||||
private static final String TAG = CacheCleaner.class.getSimpleName();
|
||||
private static final long MIN_FREE_SPACE = 500 * 1024L * 1024L;
|
||||
|
||||
private final Context context;
|
||||
private final DownloadService downloadService;
|
||||
private final Context context;
|
||||
private final DownloadService downloadService;
|
||||
|
||||
public CacheCleaner(Context context, DownloadService downloadService) {
|
||||
this.context = context;
|
||||
this.downloadService = downloadService;
|
||||
}
|
||||
|
||||
public void clean() {
|
||||
new BackgroundCleanup().execute();
|
||||
}
|
||||
|
||||
public void cleanSpace() {
|
||||
new BackgroundSpaceCleanup().execute();
|
||||
public CacheCleaner(Context context, DownloadService downloadService)
|
||||
{
|
||||
this.context = context;
|
||||
this.downloadService = downloadService;
|
||||
}
|
||||
|
||||
public void cleanPlaylists(List<Playlist> playlists) {
|
||||
|
||||
public void clean()
|
||||
{
|
||||
new BackgroundCleanup().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}
|
||||
|
||||
public void cleanSpace()
|
||||
{
|
||||
new BackgroundSpaceCleanup().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}
|
||||
|
||||
public void cleanPlaylists(List<Playlist> playlists)
|
||||
{
|
||||
new BackgroundPlaylistsCleanup().execute(playlists);
|
||||
}
|
||||
|
||||
private void deleteEmptyDirs(List<File> dirs, Set<File> undeletable) {
|
||||
for (File dir : dirs) {
|
||||
if (undeletable.contains(dir)) {
|
||||
continue;
|
||||
}
|
||||
private static void deleteEmptyDirs(Iterable<File> dirs, Collection<File> undeletable)
|
||||
{
|
||||
for (File dir : dirs)
|
||||
{
|
||||
if (undeletable.contains(dir))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
File[] children = dir.listFiles();
|
||||
File[] children = dir.listFiles();
|
||||
|
||||
if (children != null) {
|
||||
// No songs left in the folder
|
||||
if (children.length == 1 && children[0].getPath().equals(FileUtil.getAlbumArtFile(dir).getPath())) {
|
||||
Util.delete(FileUtil.getAlbumArtFile(dir));
|
||||
children = dir.listFiles();
|
||||
}
|
||||
if (children != null)
|
||||
{
|
||||
// No songs left in the folder
|
||||
if (children.length == 1 && children[0].getPath().equals(FileUtil.getAlbumArtFile(dir).getPath()))
|
||||
{
|
||||
Util.delete(FileUtil.getAlbumArtFile(dir));
|
||||
children = dir.listFiles();
|
||||
}
|
||||
|
||||
// Delete empty directory
|
||||
if (children != null && children.length == 0) {
|
||||
Util.delete(dir);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private long getMinimumDelete(List<File> files) {
|
||||
if(files.size() == 0) {
|
||||
// Delete empty directory
|
||||
if (children != null && children.length == 0)
|
||||
{
|
||||
Util.delete(dir);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private long getMinimumDelete(List<File> files)
|
||||
{
|
||||
if (files.size() == 0)
|
||||
{
|
||||
return 0L;
|
||||
}
|
||||
|
||||
|
||||
long cacheSizeBytes = Util.getCacheSizeMB(context) * 1024L * 1024L;
|
||||
|
||||
long bytesUsedBySubsonic = 0L;
|
||||
for (File file : files) {
|
||||
bytesUsedBySubsonic += file.length();
|
||||
}
|
||||
|
||||
|
||||
long bytesUsedBySubsonic = 0L;
|
||||
for (File file : files)
|
||||
{
|
||||
bytesUsedBySubsonic += file.length();
|
||||
}
|
||||
|
||||
// Ensure that file system is not more than 95% full.
|
||||
StatFs stat = new StatFs(files.get(0).getPath());
|
||||
long bytesTotalFs = (long) stat.getBlockCount() * (long) stat.getBlockSize();
|
||||
long bytesAvailableFs = (long) stat.getAvailableBlocks() * (long) stat.getBlockSize();
|
||||
long bytesUsedFs = bytesTotalFs - bytesAvailableFs;
|
||||
long minFsAvailability = bytesTotalFs - MIN_FREE_SPACE;
|
||||
StatFs stat = new StatFs(files.get(0).getPath());
|
||||
long bytesTotalFs = (long) stat.getBlockCount() * (long) stat.getBlockSize();
|
||||
long bytesAvailableFs = (long) stat.getAvailableBlocks() * (long) stat.getBlockSize();
|
||||
long bytesUsedFs = bytesTotalFs - bytesAvailableFs;
|
||||
long minFsAvailability = bytesTotalFs - MIN_FREE_SPACE;
|
||||
|
||||
long bytesToDeleteCacheLimit = Math.max(bytesUsedBySubsonic - cacheSizeBytes, 0L);
|
||||
long bytesToDeleteFsLimit = Math.max(bytesUsedFs - minFsAvailability, 0L);
|
||||
long bytesToDelete = Math.max(bytesToDeleteCacheLimit, bytesToDeleteFsLimit);
|
||||
long bytesToDeleteCacheLimit = Math.max(bytesUsedBySubsonic - cacheSizeBytes, 0L);
|
||||
long bytesToDeleteFsLimit = Math.max(bytesUsedFs - minFsAvailability, 0L);
|
||||
long bytesToDelete = Math.max(bytesToDeleteCacheLimit, bytesToDeleteFsLimit);
|
||||
|
||||
Log.i(TAG, String.format("File system : %s of %s available", Util.formatBytes(bytesAvailableFs), Util.formatBytes(bytesTotalFs)));
|
||||
Log.i(TAG, String.format("Cache limit : %s", Util.formatBytes(cacheSizeBytes)));
|
||||
Log.i(TAG, String.format("Cache size before : %s", Util.formatBytes(bytesUsedBySubsonic)));
|
||||
Log.i(TAG, String.format("Minimum to delete : %s", Util.formatBytes(bytesToDelete)));
|
||||
|
||||
Log.i(TAG, "File system : " + Util.formatBytes(bytesAvailableFs) + " of " + Util.formatBytes(bytesTotalFs) + " available");
|
||||
Log.i(TAG, "Cache limit : " + Util.formatBytes(cacheSizeBytes));
|
||||
Log.i(TAG, "Cache size before : " + Util.formatBytes(bytesUsedBySubsonic));
|
||||
Log.i(TAG, "Minimum to delete : " + Util.formatBytes(bytesToDelete));
|
||||
|
||||
return bytesToDelete;
|
||||
}
|
||||
|
||||
private void deleteFiles(List<File> files, Set<File> undeletable, long bytesToDelete, boolean deletePartials) {
|
||||
if (files.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
private static void deleteFiles(Collection<File> files, Collection<File> undeletable, long bytesToDelete, boolean deletePartials)
|
||||
{
|
||||
if (files.isEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
long bytesDeleted = 0L;
|
||||
for (File file : files) {
|
||||
if(!deletePartials && bytesDeleted > bytesToDelete) break;
|
||||
long bytesDeleted = 0L;
|
||||
for (File file : files)
|
||||
{
|
||||
if (!deletePartials && bytesDeleted > bytesToDelete) break;
|
||||
|
||||
if (bytesToDelete > bytesDeleted || (deletePartials && (file.getName().endsWith(".partial") || file.getName().contains(".partial.")))) {
|
||||
if (!undeletable.contains(file) && !file.getName().equals(Constants.ALBUM_ART_FILE)) {
|
||||
long size = file.length();
|
||||
if (Util.delete(file)) {
|
||||
bytesDeleted += size;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (bytesToDelete > bytesDeleted || (deletePartials && (file.getName().endsWith(".partial") || file.getName().contains(".partial."))))
|
||||
{
|
||||
if (!undeletable.contains(file) && !file.getName().equals(Constants.ALBUM_ART_FILE))
|
||||
{
|
||||
long size = file.length();
|
||||
if (Util.delete(file))
|
||||
{
|
||||
bytesDeleted += size;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Log.i(TAG, "Deleted : " + Util.formatBytes(bytesDeleted));
|
||||
}
|
||||
Log.i(TAG, String.format("Deleted : %s", Util.formatBytes(bytesDeleted)));
|
||||
}
|
||||
|
||||
private void findCandidatesForDeletion(File file, List<File> files, List<File> dirs) {
|
||||
if (file.isFile()) {
|
||||
String name = file.getName();
|
||||
boolean isCacheFile = name.endsWith(".partial") || name.contains(".partial.") || name.endsWith(".complete") || name.contains(".complete.");
|
||||
if (isCacheFile) {
|
||||
files.add(file);
|
||||
}
|
||||
} else {
|
||||
// Depth-first
|
||||
for (File child : FileUtil.listFiles(file)) {
|
||||
findCandidatesForDeletion(child, files, dirs);
|
||||
}
|
||||
dirs.add(file);
|
||||
}
|
||||
}
|
||||
private static void findCandidatesForDeletion(File file, List<File> files, List<File> dirs)
|
||||
{
|
||||
if (file.isFile())
|
||||
{
|
||||
String name = file.getName();
|
||||
boolean isCacheFile = name.endsWith(".partial") || name.contains(".partial.") || name.endsWith(".complete") || name.contains(".complete.");
|
||||
if (isCacheFile)
|
||||
{
|
||||
files.add(file);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Depth-first
|
||||
for (File child : FileUtil.listFiles(file))
|
||||
{
|
||||
findCandidatesForDeletion(child, files, dirs);
|
||||
}
|
||||
dirs.add(file);
|
||||
}
|
||||
}
|
||||
|
||||
private void sortByAscendingModificationTime(List<File> files) {
|
||||
Collections.sort(files, new Comparator<File>() {
|
||||
@Override
|
||||
public int compare(File a, File b) {
|
||||
if (a.lastModified() < b.lastModified()) {
|
||||
return -1;
|
||||
}
|
||||
if (a.lastModified() > b.lastModified()) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
}
|
||||
private static void sortByAscendingModificationTime(List<File> files)
|
||||
{
|
||||
Collections.sort(files, new Comparator<File>()
|
||||
{
|
||||
@Override
|
||||
public int compare(File a, File b)
|
||||
{
|
||||
if (a.lastModified() < b.lastModified())
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
private Set<File> findUndeletableFiles() {
|
||||
Set<File> undeletable = new HashSet<File>(5);
|
||||
if (a.lastModified() > b.lastModified())
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (DownloadFile downloadFile : downloadService.getDownloads()) {
|
||||
undeletable.add(downloadFile.getPartialFile());
|
||||
undeletable.add(downloadFile.getCompleteFile());
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
undeletable.add(FileUtil.getMusicDirectory(context));
|
||||
return undeletable;
|
||||
}
|
||||
private Set<File> findUndeletableFiles()
|
||||
{
|
||||
Set<File> undeletable = new HashSet<File>(5);
|
||||
|
||||
private class BackgroundCleanup extends AsyncTask<Void, Void, Void> {
|
||||
for (DownloadFile downloadFile : downloadService.getDownloads())
|
||||
{
|
||||
undeletable.add(downloadFile.getPartialFile());
|
||||
undeletable.add(downloadFile.getCompleteFile());
|
||||
}
|
||||
|
||||
undeletable.add(FileUtil.getMusicDirectory(context));
|
||||
return undeletable;
|
||||
}
|
||||
|
||||
private class BackgroundCleanup extends AsyncTask<Void, Void, Void>
|
||||
{
|
||||
@Override
|
||||
protected Void doInBackground(Void... params) {
|
||||
if (downloadService == null) {
|
||||
protected Void doInBackground(Void... params)
|
||||
{
|
||||
if (downloadService == null)
|
||||
{
|
||||
Log.e(TAG, "DownloadService not set. Aborting cache cleaning.");
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
try
|
||||
{
|
||||
List<File> files = new ArrayList<File>();
|
||||
List<File> dirs = new ArrayList<File>();
|
||||
|
||||
|
@ -185,7 +225,9 @@ public class CacheCleaner {
|
|||
|
||||
deleteFiles(files, undeletable, getMinimumDelete(files), true);
|
||||
deleteEmptyDirs(dirs, undeletable);
|
||||
} catch (RuntimeException x) {
|
||||
}
|
||||
catch (RuntimeException x)
|
||||
{
|
||||
Log.e(TAG, "Error in cache cleaning.", x);
|
||||
}
|
||||
|
||||
|
@ -193,26 +235,33 @@ public class CacheCleaner {
|
|||
}
|
||||
}
|
||||
|
||||
private class BackgroundSpaceCleanup extends AsyncTask<Void, Void, Void> {
|
||||
private class BackgroundSpaceCleanup extends AsyncTask<Void, Void, Void>
|
||||
{
|
||||
@Override
|
||||
protected Void doInBackground(Void... params) {
|
||||
if (downloadService == null) {
|
||||
protected Void doInBackground(Void... params)
|
||||
{
|
||||
if (downloadService == null)
|
||||
{
|
||||
Log.e(TAG, "DownloadService not set. Aborting cache cleaning.");
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
try
|
||||
{
|
||||
List<File> files = new ArrayList<File>();
|
||||
List<File> dirs = new ArrayList<File>();
|
||||
findCandidatesForDeletion(FileUtil.getMusicDirectory(context), files, dirs);
|
||||
|
||||
long bytesToDelete = getMinimumDelete(files);
|
||||
if(bytesToDelete > 0L) {
|
||||
if (bytesToDelete > 0L)
|
||||
{
|
||||
sortByAscendingModificationTime(files);
|
||||
Set<File> undeletable = findUndeletableFiles();
|
||||
deleteFiles(files, undeletable, bytesToDelete, false);
|
||||
}
|
||||
} catch (RuntimeException x) {
|
||||
}
|
||||
catch (RuntimeException x)
|
||||
{
|
||||
Log.e(TAG, "Error in cache cleaning.", x);
|
||||
}
|
||||
|
||||
|
@ -220,21 +269,28 @@ public class CacheCleaner {
|
|||
}
|
||||
}
|
||||
|
||||
private class BackgroundPlaylistsCleanup extends AsyncTask<List<Playlist>, Void, Void> {
|
||||
private class BackgroundPlaylistsCleanup extends AsyncTask<List<Playlist>, Void, Void>
|
||||
{
|
||||
@Override
|
||||
protected Void doInBackground(List<Playlist>... params) {
|
||||
try {
|
||||
protected Void doInBackground(List<Playlist>... params)
|
||||
{
|
||||
try
|
||||
{
|
||||
String server = Util.getServerName(context);
|
||||
SortedSet<File> playlistFiles = FileUtil.listFiles(FileUtil.getPlaylistDirectory(server));
|
||||
List<Playlist> playlists = params[0];
|
||||
for (Playlist playlist : playlists) {
|
||||
for (Playlist playlist : playlists)
|
||||
{
|
||||
playlistFiles.remove(FileUtil.getPlaylistFile(server, playlist.getName()));
|
||||
}
|
||||
|
||||
for(File playlist : playlistFiles) {
|
||||
for (File playlist : playlistFiles)
|
||||
{
|
||||
playlist.delete();
|
||||
}
|
||||
} catch (RuntimeException x) {
|
||||
}
|
||||
catch (RuntimeException x)
|
||||
{
|
||||
Log.e(TAG, "Error in playlist cache cleaning.", x);
|
||||
}
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue