Adds an export service
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" type="JAVA_MODULE" version="4">
|
||||
<module external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" external.system.module.group="" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
|
||||
<component name="FacetManager">
|
||||
<facet type="java-gradle" name="Java-Gradle">
|
||||
<configuration>
|
||||
|
@ -7,9 +7,7 @@
|
|||
</configuration>
|
||||
</facet>
|
||||
</component>
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="false">
|
||||
<output url="file://$MODULE_DIR$/build/classes/main" />
|
||||
<output-test url="file://$MODULE_DIR$/build/classes/test" />
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<excludeFolder url="file://$MODULE_DIR$/.gradle" />
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/.." external.system.id="GRADLE" type="JAVA_MODULE" version="4">
|
||||
<module external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/.." external.system.id="GRADLE" external.system.module.group="PlayMusicExporterGit" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
|
||||
<component name="FacetManager">
|
||||
<facet type="android-gradle" name="Android-Gradle">
|
||||
<configuration>
|
||||
|
@ -9,6 +9,7 @@
|
|||
<facet type="android" name="Android">
|
||||
<configuration>
|
||||
<option name="SELECTED_BUILD_VARIANT" value="debug" />
|
||||
<option name="SELECTED_TEST_ARTIFACT" value="_android_test_" />
|
||||
<option name="ASSEMBLE_TASK_NAME" value="assembleDebug" />
|
||||
<option name="COMPILE_JAVA_TASK_NAME" value="compileDebugSources" />
|
||||
<option name="ASSEMBLE_TEST_TASK_NAME" value="assembleDebugTest" />
|
||||
|
@ -25,6 +26,7 @@
|
|||
</component>
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="false">
|
||||
<output url="file://$MODULE_DIR$/build/intermediates/classes/debug" />
|
||||
<output-test url="file://$MODULE_DIR$/build/intermediates/classes/test/debug" />
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/debug" isTestSource="false" generated="true" />
|
||||
|
|
|
@ -32,7 +32,7 @@ public class AppSettings {
|
|||
/**
|
||||
* The default settings file
|
||||
*/
|
||||
private static final String DEFAULT_SETTINGS_FILENAME = "app_settings";
|
||||
public static final String DEFAULT_SETTINGS_FILENAME = "app_settings";
|
||||
|
||||
/**
|
||||
* The preferences
|
||||
|
@ -105,6 +105,26 @@ public class AppSettings {
|
|||
return mSharedPreferences.getLong(key, defValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an enum value from the settings
|
||||
* @param key Key of the setting
|
||||
* @param defValue Default value which is returned if the key doesn't exists
|
||||
* @param <E> The enum type
|
||||
* @return Value
|
||||
*/
|
||||
public <E extends Enum<E>> E getEnum(String key, E defValue) {
|
||||
String value = mSharedPreferences.getString(key, defValue.name());
|
||||
|
||||
// Checks all enum values
|
||||
for (E constant : ((Class<E>)defValue.getClass()).getEnumConstants()) {
|
||||
if (value.equals(constant.name()))
|
||||
return constant;
|
||||
}
|
||||
|
||||
// Return default
|
||||
return defValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the settings contains a specific key
|
||||
* @param key Key of the setting
|
||||
|
@ -126,7 +146,7 @@ public class AppSettings {
|
|||
editor.remove(key);
|
||||
|
||||
// Commits the change
|
||||
editor.apply();
|
||||
editor.commit();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -141,7 +161,7 @@ public class AppSettings {
|
|||
editor.putString(key, value);
|
||||
|
||||
// Commits the change
|
||||
editor.apply();
|
||||
editor.commit();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -156,7 +176,7 @@ public class AppSettings {
|
|||
editor.putBoolean(key, value);
|
||||
|
||||
// Commits the change
|
||||
editor.apply();
|
||||
editor.commit();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -171,7 +191,7 @@ public class AppSettings {
|
|||
editor.putFloat(key, value);
|
||||
|
||||
// Commits the change
|
||||
editor.apply();
|
||||
editor.commit();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -186,7 +206,7 @@ public class AppSettings {
|
|||
editor.putInt(key, value);
|
||||
|
||||
// Commits the change
|
||||
editor.apply();
|
||||
editor.commit();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -201,9 +221,22 @@ public class AppSettings {
|
|||
editor.putLong(key, value);
|
||||
|
||||
// Commits the change
|
||||
editor.apply();
|
||||
editor.commit();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Saves an enum value to the settings
|
||||
* @param key Key of the setting
|
||||
* @param value Value
|
||||
*/
|
||||
public <E extends Enum<E>> void setEnum(String key, E value) {
|
||||
// Opens the editor
|
||||
SharedPreferences.Editor editor = mSharedPreferences.edit();
|
||||
|
||||
editor.putString(key, value.name());
|
||||
|
||||
// Commits the change
|
||||
editor.commit();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/.." external.system.id="GRADLE" type="JAVA_MODULE" version="4">
|
||||
<module external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/.." external.system.id="GRADLE" external.system.module.group="PlayMusicExporterGit" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
|
||||
<component name="FacetManager">
|
||||
<facet type="android-gradle" name="Android-Gradle">
|
||||
<configuration>
|
||||
|
@ -9,6 +9,7 @@
|
|||
<facet type="android" name="Android">
|
||||
<configuration>
|
||||
<option name="SELECTED_BUILD_VARIANT" value="debug" />
|
||||
<option name="SELECTED_TEST_ARTIFACT" value="_android_test_" />
|
||||
<option name="ASSEMBLE_TASK_NAME" value="assembleDebug" />
|
||||
<option name="COMPILE_JAVA_TASK_NAME" value="compileDebugSources" />
|
||||
<option name="ASSEMBLE_TEST_TASK_NAME" value="assembleDebugTest" />
|
||||
|
@ -24,6 +25,7 @@
|
|||
</component>
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="false">
|
||||
<output url="file://$MODULE_DIR$/build/intermediates/classes/debug" />
|
||||
<output-test url="file://$MODULE_DIR$/build/intermediates/classes/test/debug" />
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/debug" isTestSource="false" generated="true" />
|
||||
|
|
|
@ -48,6 +48,15 @@
|
|||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value=".activitys.MusicTrackListActivity" />
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".activitys.SettingsActivity"
|
||||
android:label="@string/title_settings"
|
||||
android:parentActivityName=".activitys.MusicTrackListActivity" >
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value=".activitys.MusicTrackListActivity" />
|
||||
</activity>
|
||||
<service android:name="de.arcus.playmusicexporter2.services.ExportService"/>
|
||||
|
||||
<meta-data android:name="crashhandler.email" android:value="mail@david-schulte.de" />
|
||||
<meta-data android:name="crashhandler.supporturl" android:value="http://www.david-schulte.de/" />
|
||||
|
|
|
@ -28,6 +28,7 @@ import android.support.v7.app.ActionBarActivity;
|
|||
import android.support.v4.app.NavUtils;
|
||||
import android.view.MenuItem;
|
||||
|
||||
import de.arcus.framework.crashhandler.CrashHandler;
|
||||
import de.arcus.playmusicexporter2.R;
|
||||
import de.arcus.playmusicexporter2.fragments.MusicTrackDetailFragment;
|
||||
|
||||
|
@ -48,6 +49,9 @@ public class MusicTrackDetailActivity extends ActionBarActivity {
|
|||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_track_detail);
|
||||
|
||||
// Adds the crash handler to this class
|
||||
CrashHandler.addCrashHandler(this);
|
||||
|
||||
// Show the Up button in the action bar.
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
|
||||
|
|
|
@ -140,9 +140,8 @@ public class MusicTrackListActivity extends ActionBarActivity
|
|||
}
|
||||
}
|
||||
|
||||
loadList(NavigationDrawerFragment.ViewType.Album);
|
||||
|
||||
|
||||
// Loads the list
|
||||
loadList(mNavigationDrawerFragment.getViewType());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Copyright (c) 2015 David Schulte
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package de.arcus.playmusicexporter2.activitys;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceActivity;
|
||||
import android.preference.PreferenceManager;
|
||||
|
||||
import de.arcus.playmusicexporter2.R;
|
||||
import de.arcus.playmusicexporter2.settings.PlayMusicExporterSettings;
|
||||
|
||||
/**
|
||||
* The preference activity
|
||||
*/
|
||||
public class SettingsActivity extends PreferenceActivity {
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
// Setup the default shared preference
|
||||
PreferenceManager prefMgr = getPreferenceManager();
|
||||
prefMgr.setSharedPreferencesName(PlayMusicExporterSettings.DEFAULT_SETTINGS_FILENAME);
|
||||
prefMgr.setSharedPreferencesMode(MODE_WORLD_READABLE);
|
||||
|
||||
// Loads the preference xml
|
||||
addPreferencesFromResource(R.xml.preferences);
|
||||
}
|
||||
}
|
|
@ -29,7 +29,6 @@ import android.view.View;
|
|||
import android.view.ViewGroup;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -48,7 +47,8 @@ public class MusicTrackAdapter extends ArrayAdapter<MusicTrack> {
|
|||
private Context mContext;
|
||||
|
||||
/**
|
||||
* If this is set the music track shows it artwork instead of the track number
|
||||
* If this is set the music track shows it artwork instead of the track number.
|
||||
* Used for playlists.
|
||||
*/
|
||||
private boolean mShowArtworks = true;
|
||||
|
||||
|
@ -92,7 +92,6 @@ public class MusicTrackAdapter extends ArrayAdapter<MusicTrack> {
|
|||
view = inflater.inflate(R.layout.adapter_music_track, parent, false);
|
||||
}
|
||||
|
||||
|
||||
TextView textView;
|
||||
|
||||
// Sets the track number
|
||||
|
@ -106,6 +105,7 @@ public class MusicTrackAdapter extends ArrayAdapter<MusicTrack> {
|
|||
textView.setText("" + trackPosition);
|
||||
else
|
||||
textView.setText("");
|
||||
|
||||
textView.setTextColor(mContext.getResources().getColor(musicTrack.isOfflineAvailable() ? R.color.text_music_number : R.color.text_music_disable_number));
|
||||
|
||||
// Sets the disc number
|
||||
|
@ -116,6 +116,7 @@ public class MusicTrackAdapter extends ArrayAdapter<MusicTrack> {
|
|||
textView.setVisibility(View.VISIBLE);
|
||||
else
|
||||
textView.setVisibility(View.GONE);
|
||||
|
||||
textView.setTextColor(mContext.getResources().getColor(musicTrack.isOfflineAvailable() ? R.color.text_music_disc_number : R.color.text_music_disable_disc_number));
|
||||
|
||||
|
||||
|
@ -127,6 +128,7 @@ public class MusicTrackAdapter extends ArrayAdapter<MusicTrack> {
|
|||
view.findViewById(R.id.relative_layout_artwork).setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
// Shows the artwork
|
||||
if (mShowArtworks) {
|
||||
ImageView imageView = (ImageView) view.findViewById(R.id.image_music_track_artwork);
|
||||
imageView.setImageResource(R.drawable.cd_case);
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
package de.arcus.playmusicexporter2.fragments;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.support.v4.app.Fragment;
|
||||
|
@ -35,6 +36,7 @@ import android.widget.TextView;
|
|||
|
||||
import de.arcus.playmusicexporter2.R;
|
||||
import de.arcus.playmusicexporter2.adapter.MusicTrackAdapter;
|
||||
import de.arcus.playmusicexporter2.services.ExportService;
|
||||
import de.arcus.playmusicexporter2.utils.ImageViewLoader;
|
||||
import de.arcus.playmusicexporter2.utils.MusicPathBuilder;
|
||||
import de.arcus.playmusiclib.PlayMusicManager;
|
||||
|
@ -149,11 +151,17 @@ public class MusicTrackDetailFragment extends Fragment {
|
|||
// Path to the public music folder
|
||||
path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC) + "/" + path;
|
||||
|
||||
PlayMusicManager playMusicManager = PlayMusicManager.getInstance();
|
||||
|
||||
if (playMusicManager != null) {
|
||||
playMusicManager.exportMusicTrack(musicTrack, path);
|
||||
}
|
||||
Intent intent = new Intent(MusicTrackDetailFragment.this.getActivity(), ExportService.class);
|
||||
|
||||
// Puts the export parameter
|
||||
intent.putExtra(ExportService.ARG_EXPORT_TRACK_ID, musicTrack.getId());
|
||||
intent.putExtra(ExportService.ARG_EXPORT_PATH, path);
|
||||
|
||||
// Starts the service
|
||||
MusicTrackDetailFragment.this.getActivity().startService(intent);
|
||||
//playMusicManager.exportMusicTrack(musicTrack, path);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -109,6 +109,7 @@ public class MusicTrackListFragment extends ListFragment {
|
|||
// Set the list in the adapter
|
||||
mMusicTrackListAdapter.setList(newList);
|
||||
getListView().invalidateViews();
|
||||
getListView().setSelection(0);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -23,11 +23,10 @@
|
|||
package de.arcus.playmusicexporter2.fragments;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.view.GravityCompat;
|
||||
import android.support.v4.widget.DrawerLayout;
|
||||
|
@ -43,7 +42,10 @@ import android.view.ViewGroup;
|
|||
import android.widget.Button;
|
||||
|
||||
|
||||
import de.arcus.framework.settings.AppSettings;
|
||||
import de.arcus.playmusicexporter2.R;
|
||||
import de.arcus.playmusicexporter2.activitys.SettingsActivity;
|
||||
import de.arcus.playmusicexporter2.settings.PlayMusicExporterSettings;
|
||||
|
||||
/**
|
||||
* Fragment used for managing interactions for and presentation of a navigation drawer.
|
||||
|
@ -51,18 +53,6 @@ import de.arcus.playmusicexporter2.R;
|
|||
* design guidelines</a> for a complete explanation of the behaviors implemented here.
|
||||
*/
|
||||
public class NavigationDrawerFragment extends Fragment {
|
||||
|
||||
/**
|
||||
* Remember the position of the selected item.
|
||||
*/
|
||||
private static final String STATE_SELECTED_POSITION = "selected_navigation_drawer_position";
|
||||
|
||||
/**
|
||||
* Per the design guidelines, you should show the drawer on launch until the user manually
|
||||
* expands it. This shared preference tracks this.
|
||||
*/
|
||||
private static final String PREF_USER_LEARNED_DRAWER = "navigation_drawer_learned";
|
||||
|
||||
/**
|
||||
* A pointer to the current callbacks instance (the Activity).
|
||||
*/
|
||||
|
@ -76,8 +66,6 @@ public class NavigationDrawerFragment extends Fragment {
|
|||
private DrawerLayout mDrawerLayout;
|
||||
private View mFragmentContainerView;
|
||||
|
||||
private int mCurrentSelectedPosition = 0;
|
||||
private boolean mFromSavedInstanceState;
|
||||
private boolean mUserLearnedDrawer;
|
||||
|
||||
private Button mButtonTypeAlbum;
|
||||
|
@ -109,11 +97,16 @@ public class NavigationDrawerFragment extends Fragment {
|
|||
setButtonActive(mButtonTypePlaylist, viewType == ViewType.Playlist);
|
||||
setButtonActive(mButtonTypeRated, viewType == ViewType.Rated);
|
||||
|
||||
// Callback the parent activity
|
||||
if (viewType != mViewType)
|
||||
if (mCallbacks != null) mCallbacks.onViewTypeChanged(viewType);
|
||||
|
||||
mViewType = viewType;
|
||||
|
||||
// Save the selection
|
||||
PlayMusicExporterSettings appSettings = new PlayMusicExporterSettings(getActivity());
|
||||
appSettings.setEnum(PlayMusicExporterSettings.PREF_DRAWER_SELECTED_TYPE, viewType);
|
||||
|
||||
// Close the drawer
|
||||
if (mDrawerLayout != null)
|
||||
mDrawerLayout.closeDrawers();
|
||||
|
@ -126,15 +119,11 @@ public class NavigationDrawerFragment extends Fragment {
|
|||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
// Read in the flag indicating whether or not the user has demonstrated awareness of the
|
||||
// drawer. See PREF_USER_LEARNED_DRAWER for details.
|
||||
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getActivity());
|
||||
mUserLearnedDrawer = sp.getBoolean(PREF_USER_LEARNED_DRAWER, false);
|
||||
// Load the settings
|
||||
PlayMusicExporterSettings appSettings = new PlayMusicExporterSettings(getActivity());
|
||||
mUserLearnedDrawer = appSettings.getBoolean(PlayMusicExporterSettings.PREF_DRAWER_LEARNED, false);
|
||||
mViewType = appSettings.getEnum(PlayMusicExporterSettings.PREF_DRAWER_SELECTED_TYPE, ViewType.Album);
|
||||
|
||||
if (savedInstanceState != null) {
|
||||
mCurrentSelectedPosition = savedInstanceState.getInt(STATE_SELECTED_POSITION);
|
||||
mFromSavedInstanceState = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -160,7 +149,7 @@ public class NavigationDrawerFragment extends Fragment {
|
|||
mButtonSettings = (Button)view.findViewById(R.id.button_setting);
|
||||
|
||||
// Set the default
|
||||
setViewType(ViewType.Album);
|
||||
setViewType(mViewType);
|
||||
|
||||
// Click on album
|
||||
mButtonTypeAlbum.setOnClickListener(new View.OnClickListener() {
|
||||
|
@ -194,6 +183,18 @@ public class NavigationDrawerFragment extends Fragment {
|
|||
}
|
||||
});
|
||||
|
||||
// Click on settings
|
||||
mButtonSettings.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Intent intentSettings = new Intent(getActivity(), SettingsActivity.class);
|
||||
startActivity(intentSettings);
|
||||
|
||||
// Close the drawer
|
||||
mDrawerLayout.closeDrawers();
|
||||
}
|
||||
});
|
||||
|
||||
// Color the settings button
|
||||
setButtonActive(mButtonSettings, false);
|
||||
|
||||
|
@ -284,9 +285,8 @@ public class NavigationDrawerFragment extends Fragment {
|
|||
// The user manually opened the drawer; store this flag to prevent auto-showing
|
||||
// the navigation drawer automatically in the future.
|
||||
mUserLearnedDrawer = true;
|
||||
SharedPreferences sp = PreferenceManager
|
||||
.getDefaultSharedPreferences(getActivity());
|
||||
sp.edit().putBoolean(PREF_USER_LEARNED_DRAWER, true).commit();
|
||||
PlayMusicExporterSettings appSettings = new PlayMusicExporterSettings(getActivity());
|
||||
appSettings.setBoolean(PlayMusicExporterSettings.PREF_DRAWER_LEARNED, mUserLearnedDrawer);
|
||||
}
|
||||
|
||||
getActivity().supportInvalidateOptionsMenu(); // calls onPrepareOptionsMenu()
|
||||
|
@ -295,7 +295,7 @@ public class NavigationDrawerFragment extends Fragment {
|
|||
|
||||
// If the user hasn't 'learned' about the drawer, open it to introduce them to the drawer,
|
||||
// per the navigation drawer design guidelines.
|
||||
if (!mUserLearnedDrawer && !mFromSavedInstanceState) {
|
||||
if (!mUserLearnedDrawer) {
|
||||
mDrawerLayout.openDrawer(mFragmentContainerView);
|
||||
}
|
||||
|
||||
|
@ -326,12 +326,6 @@ public class NavigationDrawerFragment extends Fragment {
|
|||
mCallbacks = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
outState.putInt(STATE_SELECTED_POSITION, mCurrentSelectedPosition);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfigurationChanged(Configuration newConfig) {
|
||||
super.onConfigurationChanged(newConfig);
|
||||
|
|
|
@ -0,0 +1,217 @@
|
|||
/*
|
||||
* Copyright (c) 2015 David Schulte
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package de.arcus.playmusicexporter2.services;
|
||||
|
||||
import android.app.IntentService;
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationManager;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.NotificationCompat;
|
||||
|
||||
import de.arcus.framework.logger.Logger;
|
||||
import de.arcus.playmusicexporter2.R;
|
||||
import de.arcus.playmusiclib.PlayMusicManager;
|
||||
import de.arcus.playmusiclib.datasources.MusicTrackDataSource;
|
||||
import de.arcus.playmusiclib.items.MusicTrack;
|
||||
|
||||
/**
|
||||
* The export service
|
||||
*/
|
||||
public class ExportService extends IntentService {
|
||||
/**
|
||||
* Constants for the server instance
|
||||
*/
|
||||
public static final String ARG_EXPORT_TRACK_ID = "track_id";
|
||||
public static final String ARG_EXPORT_PATH = "path";
|
||||
|
||||
/**
|
||||
* Notification id
|
||||
*/
|
||||
public static final int NOTIFICATION_ID = 1;
|
||||
|
||||
/**
|
||||
* The export notification
|
||||
*/
|
||||
protected NotificationCompat.Builder mNotificationBuilder;
|
||||
|
||||
/**
|
||||
* The number of tracks that needs to be exported
|
||||
*/
|
||||
protected int mTracksTotal;
|
||||
|
||||
/**
|
||||
* The number of tracks that were exported
|
||||
*/
|
||||
protected int mTracksDone;
|
||||
|
||||
/**
|
||||
* The number of tracks that were not exported
|
||||
*/
|
||||
protected int mTracksFailed;
|
||||
|
||||
/**
|
||||
* The current track we are exporting
|
||||
*/
|
||||
protected MusicTrack mTrackCurrent;
|
||||
|
||||
/**
|
||||
* The export finished
|
||||
*/
|
||||
protected boolean mFinished;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new export service
|
||||
*/
|
||||
public ExportService() {
|
||||
super("ExportService");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
|
||||
Logger.getInstance().logDebug("ExportService", "Start");
|
||||
|
||||
// Creates a notification builder
|
||||
mNotificationBuilder = new NotificationCompat.Builder(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
|
||||
// Finish
|
||||
Logger.getInstance().logDebug("ExportService", "End");
|
||||
mFinished = true;
|
||||
|
||||
updateNotification();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
// Count
|
||||
mTracksTotal++;
|
||||
|
||||
return super.onStartCommand(intent, flags, startId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the notification.
|
||||
* Sets the data in {@link this.mNotificationBuilder}
|
||||
*/
|
||||
protected void updateNotification() {
|
||||
// Gets the notification manager
|
||||
NotificationManager notificationManager =
|
||||
(NotificationManager) getSystemService(NOTIFICATION_SERVICE);
|
||||
|
||||
if (mFinished) {
|
||||
// Clear the progress
|
||||
mNotificationBuilder.setProgress(0, 0, false);
|
||||
|
||||
mNotificationBuilder.setSmallIcon(R.drawable.ic_action_accept);
|
||||
mNotificationBuilder.setAutoCancel(false);
|
||||
|
||||
mNotificationBuilder.setContentTitle(getString(R.string.notification_export_finished_title));
|
||||
|
||||
if (mTracksTotal == 1) {
|
||||
mNotificationBuilder.setContentText(getString(R.string.notification_export_finished_single_summery));
|
||||
} else {
|
||||
mNotificationBuilder.setContentText(getString(R.string.notification_export_finished_summery, mTracksDone, mTracksTotal));
|
||||
}
|
||||
} else {
|
||||
// Sets the progress
|
||||
mNotificationBuilder.setProgress(mTracksTotal, mTracksDone, false);
|
||||
|
||||
mNotificationBuilder.setSmallIcon(R.drawable.ic_action_download);
|
||||
mNotificationBuilder.setAutoCancel(true);
|
||||
|
||||
if (mTrackCurrent != null) {
|
||||
// Sets the title
|
||||
mNotificationBuilder.setContentTitle(mTrackCurrent.getTitle());
|
||||
|
||||
if (mTracksTotal == 1) {
|
||||
mNotificationBuilder.setContentText(getString(R.string.notification_export_working_single_summery));
|
||||
} else {
|
||||
mNotificationBuilder.setContentText(getString(R.string.notification_export_working_summery, mTracksDone, mTracksTotal));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Build the notification
|
||||
Notification notification = mNotificationBuilder.build();
|
||||
|
||||
// Show the notification and replace the older once with the same id
|
||||
notificationManager.notify(NOTIFICATION_ID, notification);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* New service request
|
||||
* @param intent Data for the exporter
|
||||
*/
|
||||
@Override
|
||||
protected void onHandleIntent(Intent intent) {
|
||||
// Get the parameter
|
||||
Bundle bundle = intent.getExtras();
|
||||
|
||||
// Gets the track information
|
||||
long trackID = bundle.getLong(ARG_EXPORT_TRACK_ID);
|
||||
String path = bundle.getString(ARG_EXPORT_PATH);
|
||||
|
||||
PlayMusicManager playMusicManager = PlayMusicManager.getInstance();
|
||||
|
||||
if (playMusicManager != null) {
|
||||
// Creates a new data source to get the selected track
|
||||
MusicTrackDataSource musicTrackDataSource = new MusicTrackDataSource(playMusicManager);
|
||||
|
||||
// Gets the track
|
||||
mTrackCurrent = musicTrackDataSource.getById(trackID);
|
||||
if (mTrackCurrent != null) {
|
||||
// Updates the notification
|
||||
updateNotification();
|
||||
|
||||
// Exports the song
|
||||
if(!playMusicManager.exportMusicTrack(mTrackCurrent, path)) {
|
||||
// Export failed
|
||||
mTracksFailed ++;
|
||||
}
|
||||
} else {
|
||||
// Export failed
|
||||
mTracksFailed ++;
|
||||
}
|
||||
} else {
|
||||
// Export failed
|
||||
mTracksFailed ++;
|
||||
}
|
||||
|
||||
mTracksDone ++;
|
||||
|
||||
// Updates the notification
|
||||
updateNotification();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* Copyright (c) 2015 David Schulte
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package de.arcus.playmusicexporter2.settings;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Environment;
|
||||
|
||||
import de.arcus.framework.settings.AppSettings;
|
||||
|
||||
/**
|
||||
* Helper class to read and write app settings without to care about to open and close an editor
|
||||
*/
|
||||
public class PlayMusicExporterSettings extends AppSettings {
|
||||
/**
|
||||
* The default settings file
|
||||
*/
|
||||
public static final String DEFAULT_SETTINGS_FILENAME = "play_music_exporter";
|
||||
|
||||
// Preference constants
|
||||
public static final String PREF_ID3 = "pref_id3";
|
||||
public static final String PREF_EXPORT_PATH = "pref_export_path";
|
||||
public static final String PREF_STRUCTURE_ALBUMS = "pref_structure_albums";
|
||||
public static final String PREF_STRUCTURE_GROUPS = "pref_structure_groups";
|
||||
public static final String PREF_DRAWER_LEARNED = "pref_drawer_learned";
|
||||
public static final String PREF_DRAWER_SELECTED_TYPE = "pref_drawer_selected_type";
|
||||
|
||||
/**
|
||||
* Creates a new instance of PlayMusicExporterSettings that access to the default settings file
|
||||
* @param context Context of the app
|
||||
*/
|
||||
public PlayMusicExporterSettings(Context context) {
|
||||
super(context, DEFAULT_SETTINGS_FILENAME);
|
||||
|
||||
// Init the default values
|
||||
|
||||
// ID3 settings
|
||||
if (!contains(PREF_ID3))
|
||||
setString(PREF_ID3, "id3_with_cover");
|
||||
|
||||
// Export path
|
||||
if (!contains(PREF_EXPORT_PATH))
|
||||
setString(PREF_EXPORT_PATH, Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC).getAbsolutePath());
|
||||
}
|
||||
|
||||
|
||||
}
|
After Width: | Height: | Size: 401 B |
After Width: | Height: | Size: 363 B |
After Width: | Height: | Size: 246 B |
After Width: | Height: | Size: 313 B |
After Width: | Height: | Size: 475 B |
After Width: | Height: | Size: 470 B |
After Width: | Height: | Size: 619 B |
After Width: | Height: | Size: 574 B |
|
@ -32,4 +32,22 @@
|
|||
<string name="navigation_drawer_open">Drawer öffnen</string>
|
||||
<string name="title_track_detail">Titeldetails</string>
|
||||
<string name="title_settings">Einstellungen</string>
|
||||
<string name="settings_category_about_me">Über mich</string>
|
||||
<string name="settings_category_export">Export-Einstellungen</string>
|
||||
<string name="settings_category_extra">Extras</string>
|
||||
<string name="settings_category_thanks">Dank an</string>
|
||||
<string name="settings_donation_summery">Spende über PayPal</string>
|
||||
<string name="settings_donation_title">Unterstützt mich</string>
|
||||
<string name="settings_export_path">Speicherort</string>
|
||||
<string name="settings_export_structure_albums">Verzeichnisbaum für Alben</string>
|
||||
<string name="settings_export_structure_groups">Verzeichnisbaum für Playlists</string>
|
||||
<string name="settings_export_id3">MP3 Metadaten</string>
|
||||
<string name="settings_export_id3_disabled">Ohne Metadaten</string>
|
||||
<string name="settings_export_id3_with_cover">Metadaten mit Bild</string>
|
||||
<string name="settings_export_id3_without_cover">Metadaten ohne Bild</string>
|
||||
<string name="notification_export_finished_single_summery">Der Titel wurde erfolgreich exportiert!</string>
|
||||
<string name="notification_export_working_single_summery">Titel wird exportiert…</string>
|
||||
<string name="notification_export_working_summery">Titel %1$d von %2$d wird exportiert…</string>
|
||||
<string name="notification_export_finished_summery">%1$d Titel wurden erfolgreich exportiert!</string>
|
||||
<string name="notification_export_finished_title">Export abgeschlossen!</string>
|
||||
</resources>
|
|
@ -36,4 +36,47 @@
|
|||
<string name="title_view_rated">Good rated</string>
|
||||
|
||||
<string name="title_settings">Settings</string>
|
||||
|
||||
<string name="notification_export_working_summery">Export track %1$d of %2$d…</string>
|
||||
<string name="notification_export_working_single_summery">Export track…</string>
|
||||
|
||||
<string name="notification_export_finished_title">Export finished!</string>
|
||||
<string name="notification_export_finished_summery">%1$d tracks were exported successfully!</string>
|
||||
<string name="notification_export_finished_single_summery">Track was exported successfully!</string>
|
||||
|
||||
<string name="settings_category_export">Export settings</string>
|
||||
<string name="settings_category_extra">Extras</string>
|
||||
<string name="settings_category_about_me">About me</string>
|
||||
<string name="settings_category_thanks">Thanks to</string>
|
||||
|
||||
<string name="settings_export_path">Location</string>
|
||||
<string name="settings_export_structure_albums">Subdirectory structure for albums</string>
|
||||
<string name="settings_export_structure_groups">Subdirectory structure for playlists</string>
|
||||
|
||||
<string name="settings_export_id3">MP3 metadata</string>
|
||||
<string name="settings_export_id3_with_cover">Metadata with cover</string>
|
||||
<string name="settings_export_id3_without_cover">Metadata without cover</string>
|
||||
<string name="settings_export_id3_disabled">No metadata</string>
|
||||
|
||||
<string-array name="settings_export_id3_value_names">
|
||||
<item>@string/settings_export_id3_with_cover</item>
|
||||
<item>@string/settings_export_id3_without_cover</item>
|
||||
<item>@string/settings_export_id3_disabled</item>
|
||||
</string-array>
|
||||
<string-array name="settings_export_id3_values">
|
||||
<item>id3_with_cover</item>
|
||||
<item>id3_without_cover</item>
|
||||
<item>id3_disabled</item>
|
||||
</string-array>
|
||||
|
||||
<string name="settings_open_homepage_title" translatable="false">David-Schulte.de</string>
|
||||
<string name="settings_open_homepage_url" translatable="false"><![CDATA[http://www.david-schulte.de/]]></string>
|
||||
|
||||
<string name="settings_mp3agic_title" translatable="false">Mp3agic ID3 Libary</string>
|
||||
<string name="settings_mp3agic_summery" translatable="false">Michael Patricios © 2006–2013</string>
|
||||
<string name="settings_mp3agic_url" translatable="false"><![CDATA[https://github.com/mpatric/mp3agic]]></string>
|
||||
|
||||
<string name="settings_donation_title">Support me</string>
|
||||
<string name="settings_donation_summery">Donate to me via PayPal</string>
|
||||
<string name="settings_donation_url" translatable="false"><![CDATA[https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A2VD24Z5E32RU]]></string>
|
||||
</resources>
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
|
||||
<!-- Customize your theme here. -->
|
||||
<item name="colorPrimary">@color/application_main</item>
|
||||
<item name="colorAccent">@color/application_main</item>
|
||||
<item name="colorPrimaryDark">@color/application_main_dark</item>
|
||||
<item name="actionBarStyle">@style/AppTheme.ActionBar</item>
|
||||
</style>
|
||||
|
|
76
playmusicexporter/src/main/res/xml/preferences.xml
Normal file
|
@ -0,0 +1,76 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (c) 2015 David Schulte
|
||||
~
|
||||
~ Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
~ of this software and associated documentation files (the "Software"), to deal
|
||||
~ in the Software without restriction, including without limitation the rights
|
||||
~ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
~ copies of the Software, and to permit persons to whom the Software is
|
||||
~ furnished to do so, subject to the following conditions:
|
||||
~
|
||||
~ The above copyright notice and this permission notice shall be included in
|
||||
~ all copies or substantial portions of the Software.
|
||||
~
|
||||
~ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
~ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
~ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
~ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
~ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
~ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
~ THE SOFTWARE.
|
||||
-->
|
||||
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<!-- Export settings -->
|
||||
<PreferenceCategory android:title="@string/settings_category_export">
|
||||
<!-- Export path -->
|
||||
<Preference android:title="@string/settings_export_path"
|
||||
android:key="preference_export_path"/>
|
||||
|
||||
<!-- Path structure for albums -->
|
||||
<Preference android:title="@string/settings_export_structure_albums"
|
||||
android:key="preference_structure_albums"
|
||||
/>
|
||||
|
||||
<!-- Path structure for groups -->
|
||||
<Preference android:title="@string/settings_export_structure_groups"
|
||||
android:key="preference_structure_groups"
|
||||
/>
|
||||
|
||||
<!-- ID3 settings -->
|
||||
<ListPreference android:title="@string/settings_export_id3"
|
||||
android:key="preference_id3"
|
||||
android:defaultValue="id3_with_cover"
|
||||
android:entries="@array/settings_export_id3_value_names"
|
||||
android:entryValues="@array/settings_export_id3_values"
|
||||
/>
|
||||
</PreferenceCategory>
|
||||
|
||||
<!-- Thanks to -->
|
||||
<PreferenceCategory android:title="@string/settings_category_thanks">
|
||||
<!-- Mp3agic -->
|
||||
<Preference android:title="@string/settings_mp3agic_title"
|
||||
android:summary="@string/settings_mp3agic_summery">
|
||||
<intent android:action="android.intent.action.VIEW"
|
||||
android:data="@string/settings_mp3agic_url" />
|
||||
</Preference>
|
||||
</PreferenceCategory>
|
||||
|
||||
<!-- About me -->
|
||||
<PreferenceCategory android:title="@string/settings_category_about_me">
|
||||
<!-- Homepage -->
|
||||
<Preference android:title="@string/settings_open_homepage_title"
|
||||
android:summary="@string/settings_open_homepage_url">
|
||||
<intent android:action="android.intent.action.VIEW"
|
||||
android:data="@string/settings_open_homepage_url" />
|
||||
</Preference>
|
||||
|
||||
<!-- Donation -->
|
||||
<Preference android:title="@string/settings_donation_title"
|
||||
android:summary="@string/settings_donation_summery">
|
||||
<intent android:action="android.intent.action.VIEW"
|
||||
android:data="@string/settings_donation_url" />
|
||||
</Preference>
|
||||
</PreferenceCategory>
|
||||
</PreferenceScreen>
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/.." external.system.id="GRADLE" type="JAVA_MODULE" version="4">
|
||||
<module external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/.." external.system.id="GRADLE" external.system.module.group="PlayMusicExporterGit" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
|
||||
<component name="FacetManager">
|
||||
<facet type="android-gradle" name="Android-Gradle">
|
||||
<configuration>
|
||||
|
@ -9,6 +9,7 @@
|
|||
<facet type="android" name="Android">
|
||||
<configuration>
|
||||
<option name="SELECTED_BUILD_VARIANT" value="debug" />
|
||||
<option name="SELECTED_TEST_ARTIFACT" value="_android_test_" />
|
||||
<option name="ASSEMBLE_TASK_NAME" value="assembleDebug" />
|
||||
<option name="COMPILE_JAVA_TASK_NAME" value="compileDebugSources" />
|
||||
<option name="ASSEMBLE_TEST_TASK_NAME" value="assembleDebugTest" />
|
||||
|
@ -25,6 +26,7 @@
|
|||
</component>
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="false">
|
||||
<output url="file://$MODULE_DIR$/build/intermediates/classes/debug" />
|
||||
<output-test url="file://$MODULE_DIR$/build/intermediates/classes/test/debug" />
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/debug" isTestSource="false" generated="true" />
|
||||
|
|