org.xbmc.kore.ui.MediaFileListFragment.java Source code

Java tutorial

Introduction

Here is the source code for org.xbmc.kore.ui.MediaFileListFragment.java

Source

/*
 * Copyright 2015 DanhDroid. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.xbmc.kore.ui;

import android.content.Context;
import android.content.res.Resources;
import android.os.Bundle;
import android.os.Handler;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.v4.app.Fragment;
import android.support.v4.widget.SwipeRefreshLayout;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.ListAdapter;
import android.widget.PopupMenu;
import android.widget.TextView;
import android.widget.Toast;

import org.xbmc.kore.R;
import org.xbmc.kore.host.HostManager;
import org.xbmc.kore.jsonrpc.ApiCallback;
import org.xbmc.kore.jsonrpc.HostConnection;
import org.xbmc.kore.jsonrpc.method.Files;
import org.xbmc.kore.jsonrpc.method.Player;
import org.xbmc.kore.jsonrpc.method.Playlist;
import org.xbmc.kore.jsonrpc.type.ItemType;
import org.xbmc.kore.jsonrpc.type.ListType;
import org.xbmc.kore.jsonrpc.type.PlayerType;
import org.xbmc.kore.jsonrpc.type.PlaylistType;
import org.xbmc.kore.utils.LogUtils;
import org.xbmc.kore.utils.UIUtils;
import org.xbmc.kore.utils.Utils;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

import butterknife.ButterKnife;
import butterknife.InjectView;

/**
 * Presents a list of files of different types (Video/Music)
 */
public class MediaFileListFragment extends Fragment {
    private static final String TAG = LogUtils.makeLogTag(MediaFileListFragment.class);

    public static final String MEDIA_TYPE = "mediaType";
    public static final String PATH_CONTENTS = "pathContents";
    public static final String ROOT_PATH_CONTENTS = "rootPathContents";
    public static final String ROOT_VISITED = "rootVisited";
    private static final String ADDON_SOURCE = "addons:";

    private HostManager hostManager;
    /**
     * Handler on which to post RPC callbacks
     */
    private Handler callbackHandler = new Handler();

    String mediaType = Files.Media.MUSIC;
    String parentDirectory = null;
    int playlistId = PlaylistType.MUSIC_PLAYLISTID; // this is the ID of the music player
    private MediaFileListAdapter adapter = null;
    boolean browseRootAlready = false;

    ArrayList<FileLocation> rootFileLocation = new ArrayList<FileLocation>();
    Queue<FileLocation> mediaQueueFileLocation = new LinkedList<>();

    @InjectView(R.id.list)
    GridView folderGridView;
    @InjectView(R.id.swipe_refresh_layout)
    SwipeRefreshLayout swipeRefreshLayout;
    @InjectView(android.R.id.empty)
    TextView emptyView;

    public static MediaFileListFragment newInstance(final String media) {
        MediaFileListFragment fragment = new MediaFileListFragment();
        Bundle args = new Bundle();
        args.putString(MEDIA_TYPE, media);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putString(MEDIA_TYPE, mediaType);
        try {
            outState.putParcelableArrayList(PATH_CONTENTS, (ArrayList<FileLocation>) adapter.getFileItemList());
        } catch (NullPointerException npe) {
            // adapter is null probably nothing was save in bundle because the directory is empty
            // ignore this so that the empty message would display later on
        }
        outState.putParcelableArrayList(ROOT_PATH_CONTENTS, rootFileLocation);
        outState.putBoolean(ROOT_VISITED, browseRootAlready);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        Bundle args = getArguments();
        if (args != null) {
            mediaType = args.getString(MEDIA_TYPE, Files.Media.MUSIC);
            if (mediaType.equalsIgnoreCase(Files.Media.VIDEO)) {
                playlistId = PlaylistType.VIDEO_PLAYLISTID;
            } else if (mediaType.equalsIgnoreCase(Files.Media.PICTURES)) {
                playlistId = PlaylistType.PICTURE_PLAYLISTID;
            }
        }
        ViewGroup root = (ViewGroup) inflater.inflate(R.layout.fragment_generic_media_list, container, false);
        ButterKnife.inject(this, root);

        hostManager = HostManager.getInstance(getActivity());
        swipeRefreshLayout.setEnabled(false);

        emptyView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                browseSources();
            }
        });
        folderGridView.setEmptyView(emptyView);
        folderGridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                handleFileSelect(adapter.getItem(position));
            }
        });

        if (adapter == null) {
            adapter = new MediaFileListAdapter(getActivity(), R.layout.grid_item_file);
        }
        folderGridView.setAdapter(adapter);
        if (savedInstanceState != null) {
            mediaType = savedInstanceState.getString(MEDIA_TYPE);
            //currentPath = savedInstanceState.getString(CURRENT_PATH);
            if (mediaType.equalsIgnoreCase(Files.Media.VIDEO)) {
                playlistId = PlaylistType.VIDEO_PLAYLISTID;
            } else if (mediaType.equalsIgnoreCase(Files.Media.PICTURES)) {
                playlistId = PlaylistType.PICTURE_PLAYLISTID;
            }
            ArrayList<FileLocation> list = savedInstanceState.getParcelableArrayList(PATH_CONTENTS);
            rootFileLocation = savedInstanceState.getParcelableArrayList(ROOT_PATH_CONTENTS);
            browseRootAlready = savedInstanceState.getBoolean(ROOT_VISITED);
            adapter.setFilelistItems(list);
        } else {
            browseSources();
        }
        return root;
    }

    void handleFileSelect(FileLocation f) {
        // if selection is a directory, browse the the level below
        if (f.isDirectory) {
            // a directory - store the path of this directory so that we can reverse travel if
            // we want to
            if (f.isRootDir()) {
                if (browseRootAlready)
                    browseDirectory(f);
                else {
                    browseSources();
                }
            } else {
                browseDirectory(f);
            }
        } else {
            playMediaFile(f.file);
        }
    }

    public void onBackPressed() {
        // Emulate a click on ..
        handleFileSelect(adapter.getItem(0));
    }

    public boolean atRootDirectory() {
        if (adapter.getCount() == 0)
            return true;
        FileLocation fl = adapter.getItem(0);
        if (fl == null)
            return true;
        else
            // if we still see "..", it is not the real root directory
            return fl.isRootDir() && (fl.title.contentEquals("..") == false);
    }

    /**
     * Gets and presents the list of media sources
     */
    private void browseSources() {
        Files.GetSources action = new Files.GetSources(mediaType);
        action.execute(hostManager.getConnection(), new ApiCallback<List<ItemType.Source>>() {
            @Override
            public void onSuccess(List<ItemType.Source> result) {
                if (!isAdded())
                    return;

                // save this to compare when the user select a node
                rootFileLocation.clear();
                FileLocation fl;
                for (ItemType.Source item : result) {
                    if (!item.file.contains(ADDON_SOURCE)) {
                        fl = new FileLocation(item.label, item.file, true);
                        fl.setRootDir(true);
                        rootFileLocation.add(fl);
                    }
                }

                browseRootAlready = true;
                emptyView.setText(getString(R.string.source_empty));
                adapter.setFilelistItems(rootFileLocation);
            }

            @Override
            public void onError(int errorCode, String description) {
                if (!isAdded())
                    return;

                Toast.makeText(getActivity(),
                        String.format(getString(R.string.error_getting_source_info), description),
                        Toast.LENGTH_SHORT).show();
            }
        }, callbackHandler);
    }

    /**
     * Gets and presents the files of the specified directory
     * @param dir Directory to browse
     */
    private void browseDirectory(final FileLocation dir) {
        if (dir.isRootDir()) {
            // this is a root directory
            parentDirectory = dir.file;
        } else {
            // check to make sure that this is not our root path
            String rootPath = null;
            String path;
            for (FileLocation fl : rootFileLocation) {
                path = fl.file;
                if (dir.file.contentEquals(path)) {
                    rootPath = fl.file;
                    break;
                }
            }
            if (rootPath != null) {
                parentDirectory = rootPath;
                dir.setRootDir(true);
            } else {
                parentDirectory = getParentDirectory(dir.file);
            }
        }

        String[] properties = new String[] { ListType.FieldsFiles.TITLE, ListType.FieldsFiles.ARTIST,
                //ListType.FieldsFiles.ALBUMARTIST, ListType.FieldsFiles.GENRE,
                //ListType.FieldsFiles.YEAR, ListType.FieldsFiles.RATING,
                ListType.FieldsFiles.ALBUM, ListType.FieldsFiles.TRACK, ListType.FieldsFiles.DURATION,
                //ListType.FieldsFiles.COMMENT,
                //ListType.FieldsFiles.LYRICS, ListType.FieldsFiles.MUSICBRAINZTRACKID,
                //ListType.FieldsFiles.MUSICBRAINZARTISTID, ListType.FieldsFiles.MUSICBRAINZALBUMID,
                //ListType.FieldsFiles.MUSICBRAINZALBUMARTISTID, ListType.FieldsFiles.PLAYCOUNT,
                //ListType.FieldsFiles.FANART,
                //ListType.FieldsFiles.DIRECTOR, ListType.FieldsFiles.TRAILER,
                ListType.FieldsFiles.TAGLINE,
                //ListType.FieldsFiles.PLOT, ListType.FieldsFiles.PLOTOUTLINE, ListType.FieldsFiles.ORIGINALTITLE,
                //ListType.FieldsFiles.LASTPLAYED, ListType.FieldsFiles.WRITER, ListType.FieldsFiles.STUDIO,
                //ListType.FieldsFiles.MPAA, ListType.FieldsFiles.CAST, ListType.FieldsFiles.COUNTRY,
                //ListType.FieldsFiles.IMDBNUMBER, ListType.FieldsFiles.PREMIERED,
                //ListType.FieldsFiles.PRODUCTIONCODE,
                ListType.FieldsFiles.RUNTIME,
                //ListType.FieldsFiles.SET,
                //ListType.FieldsFiles.SHOWLINK, ListType.FieldsFiles.STREAMDETAILS,
                //ListType.FieldsFiles.TOP250, ListType.FieldsFiles.VOTES,
                //ListType.FieldsFiles.FIRSTAIRED,
                ListType.FieldsFiles.SEASON, ListType.FieldsFiles.EPISODE, ListType.FieldsFiles.SHOWTITLE,
                ListType.FieldsFiles.THUMBNAIL, ListType.FieldsFiles.FILE,
                //ListType.FieldsFiles.RESUME, ListType.FieldsFiles.ARTISTID, ListType.FieldsFiles.ALBUMID,
                //ListType.FieldsFiles.TVSHOWID, ListType.FieldsFiles.SETID, ListType.FieldsFiles.WATCHEDEPISODES,
                //ListType.FieldsFiles.DISC, ListType.FieldsFiles.TAG, ListType.FieldsFiles.ART,
                //ListType.FieldsFiles.GENREID,
                ListType.FieldsFiles.DISPLAYARTIST,
                //ListType.FieldsFiles.ALBUMARTISTID, ListType.FieldsFiles.DESCRIPTION, ListType.FieldsFiles.THEME,
                //ListType.FieldsFiles.MOOD, ListType.FieldsFiles.STYLE, ListType.FieldsFiles.ALBUMLABEL,
                //ListType.FieldsFiles.SORTTITLE, ListType.FieldsFiles.EPISODEGUIDE,
                //ListType.FieldsFiles.UNIQUEID, ListType.FieldsFiles.DATEADDED,
                ListType.FieldsFiles.SIZE, ListType.FieldsFiles.LASTMODIFIED, ListType.FieldsFiles.MIMETYPE };

        Files.GetDirectory action = new Files.GetDirectory(dir.file, mediaType,
                new ListType.Sort(ListType.Sort.SORT_METHOD_LABEL, true, true), properties);
        action.execute(hostManager.getConnection(), new ApiCallback<List<ListType.ItemFile>>() {
            @Override
            public void onSuccess(List<ListType.ItemFile> result) {
                if (!isAdded())
                    return;

                ArrayList<FileLocation> flList = new ArrayList<FileLocation>();

                // insert the parent directory as the first item in the list
                FileLocation fl = new FileLocation("..", parentDirectory, true);
                fl.setRootDir(dir.isRootDir());
                flList.add(0, fl);

                for (ListType.ItemFile i : result) {
                    flList.add(FileLocation.newInstanceFromItemFile(getActivity(), i));
                }
                adapter.setFilelistItems(flList);
                browseRootAlready = false;
            }

            @Override
            public void onError(int errorCode, String description) {
                if (!isAdded())
                    return;

                Toast.makeText(getActivity(),
                        String.format(getString(R.string.error_getting_source_info), description),
                        Toast.LENGTH_SHORT).show();
            }
        }, callbackHandler);

    }

    /**
     * Starts playing the given media file
     * @param filename Filename to start playing
     */
    private void playMediaFile(final String filename) {
        PlaylistType.Item item = new PlaylistType.Item();
        item.file = filename;
        Player.Open action = new Player.Open(item);
        action.execute(hostManager.getConnection(), new ApiCallback<String>() {
            @Override
            public void onSuccess(String result) {
                while (mediaQueueFileLocation.size() > 0) {
                    queueMediaFile(mediaQueueFileLocation.poll().file);
                }
            }

            @Override
            public void onError(int errorCode, String description) {
                if (!isAdded())
                    return;
                Toast.makeText(getActivity(), String.format(getString(R.string.error_play_media_file), description),
                        Toast.LENGTH_SHORT).show();
            }
        }, callbackHandler);
    }

    /**
     * Queues the given media file on the active playlist, and starts it if nothing is playing
     * @param filename File to queue
     */
    private void queueMediaFile(final String filename) {
        final HostConnection connection = hostManager.getConnection();
        PlaylistType.Item item = new PlaylistType.Item();
        item.file = filename;
        Playlist.Add action = new Playlist.Add(playlistId, item);
        action.execute(connection, new ApiCallback<String>() {
            @Override
            public void onSuccess(String result) {
                startPlaylistIfNoActivePlayers(connection, playlistId, callbackHandler);
            }

            @Override
            public void onError(int errorCode, String description) {
                if (!isAdded())
                    return;
                Toast.makeText(getActivity(),
                        String.format(getString(R.string.error_queue_media_file), description), Toast.LENGTH_SHORT)
                        .show();
            }
        }, callbackHandler);
    }

    /**
     * Starts a playlist if no active players are playing
     * @param connection Host connection
     * @param playlistId PlaylistId to start
     * @param callbackHandler Handler on which to post method callbacks
     */
    private void startPlaylistIfNoActivePlayers(final HostConnection connection, final int playlistId,
            final Handler callbackHandler) {
        Player.GetActivePlayers action = new Player.GetActivePlayers();
        action.execute(connection, new ApiCallback<ArrayList<PlayerType.GetActivePlayersReturnType>>() {
            @Override
            public void onSuccess(ArrayList<PlayerType.GetActivePlayersReturnType> result) {
                // find out if any player is running. If it is not, start one
                if (result.isEmpty()) {
                    Player.Open action = new Player.Open(Player.Open.TYPE_PLAYLIST, playlistId);
                    action.execute(connection, new ApiCallback<String>() {
                        @Override
                        public void onSuccess(String result) {
                        }

                        @Override
                        public void onError(int errorCode, String description) {
                            if (!isAdded())
                                return;
                            Toast.makeText(getActivity(),
                                    String.format(getString(R.string.error_play_media_file), description),
                                    Toast.LENGTH_SHORT).show();
                        }
                    }, callbackHandler);
                }
            }

            @Override
            public void onError(int errorCode, String description) {
                if (!isAdded())
                    return;
                Toast.makeText(getActivity(),
                        String.format(getString(R.string.error_get_active_player), description), Toast.LENGTH_SHORT)
                        .show();
            }
        }, callbackHandler);

    }

    /**
     * return the path of the parent based on path
     * @param path of the current media file
     * @return path of the parent
     */
    public static String getParentDirectory(final String path) {
        String p = path;
        String pathSymbol = "/"; // unix style
        if (path.contains("\\")) {
            pathSymbol = "\\"; // windows style
        }

        // if path ends with /, remove it before removing the directory name
        if (path.endsWith(pathSymbol)) {
            p = path.substring(0, path.length() - 1);
        }

        if (p.lastIndexOf(pathSymbol) != -1) {
            p = p.substring(0, p.lastIndexOf(pathSymbol));
        }
        p = p + pathSymbol; // add it back to make it look like path
        return p;
    }

    private class MediaFileListAdapter extends BaseAdapter implements ListAdapter {

        Context ctx;
        int resource;
        List<FileLocation> fileLocationItems = null;

        int artWidth;
        int artHeight;

        private View.OnClickListener itemMenuClickListener = new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                final int position = (Integer) v.getTag();
                if (fileLocationItems != null) {
                    final FileLocation loc = fileLocationItems.get(position);
                    if (!loc.isDirectory) {
                        final PopupMenu popupMenu = new PopupMenu(getActivity(), v);
                        popupMenu.getMenuInflater().inflate(R.menu.filelist_item, popupMenu.getMenu());
                        popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
                            @Override
                            public boolean onMenuItemClick(MenuItem item) {

                                switch (item.getItemId()) {
                                case R.id.action_queue_item:
                                    queueMediaFile(loc.file);
                                    return true;
                                case R.id.action_play_item:
                                    playMediaFile(loc.file);
                                    return true;
                                case R.id.action_play_from_this_item:
                                    mediaQueueFileLocation.clear();
                                    FileLocation fl;
                                    for (int i = position + 1; i < fileLocationItems.size(); i++) {
                                        fl = fileLocationItems.get(i);
                                        if (!fl.isDirectory) {
                                            mediaQueueFileLocation.add(fl);
                                        }
                                    }
                                    // start playing the selected one, then queue the rest make sure to queue
                                    // the selected on last so the it does not lose its place in the queue
                                    mediaQueueFileLocation.add(loc);
                                    playMediaFile(loc.file);
                                    return true;
                                }
                                return false;
                            }
                        });
                        popupMenu.show();
                    }
                }
            }
        };

        public MediaFileListAdapter(Context context, int resource) {
            super();
            this.ctx = context;
            this.resource = resource;
            this.fileLocationItems = null;

            // Get the art dimensions
            Resources resources = context.getResources();
            artWidth = (int) (resources.getDimension(R.dimen.filelist_art_width) / UIUtils.IMAGE_RESIZE_FACTOR);
            artHeight = (int) (resources.getDimension(R.dimen.filelist_art_heigth) / UIUtils.IMAGE_RESIZE_FACTOR);

        }

        /**
         * Manually set the items on the adapter
         * Calls notifyDataSetChanged()
         *
         * @param items list of files/directories
         */
        public void setFilelistItems(List<FileLocation> items) {
            this.fileLocationItems = items;
            notifyDataSetChanged();
        }

        public List<FileLocation> getFileItemList() {
            if (fileLocationItems == null)
                return new ArrayList<FileLocation>();
            return new ArrayList<FileLocation>(fileLocationItems);
        }

        @Override
        public int getCount() {
            if (fileLocationItems == null) {
                return 0;
            } else {
                return fileLocationItems.size();
            }
        }

        @Override
        public FileLocation getItem(int position) {
            if (fileLocationItems == null) {
                return null;
            } else {
                return fileLocationItems.get(position);
            }
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public int getViewTypeCount() {
            return 1;
        }

        /** {@inheritDoc} */
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder viewHolder;
            if (convertView == null) {
                convertView = LayoutInflater.from(ctx).inflate(resource, parent, false);

                // Setup View holder pattern
                viewHolder = new ViewHolder();
                viewHolder.art = (ImageView) convertView.findViewById(R.id.art);
                viewHolder.title = (TextView) convertView.findViewById(R.id.title);
                viewHolder.details = (TextView) convertView.findViewById(R.id.details);
                viewHolder.contextMenu = (ImageView) convertView.findViewById(R.id.list_context_menu);
                viewHolder.sizeDuration = (TextView) convertView.findViewById(R.id.size_duration);

                convertView.setTag(viewHolder);
            }

            viewHolder = (ViewHolder) convertView.getTag();
            FileLocation fileLocation = this.getItem(position);

            //            if (fileLocation.isDirectory) {
            //                viewHolder.title.setText(fileLocation.title);
            //                viewHolder.details.setText("");
            //            } else {
            //                viewHolder.title.setText("");
            //                viewHolder.details.setText(fileLocation.title);
            //            }
            viewHolder.title.setText(fileLocation.title);
            viewHolder.details.setText(fileLocation.details);
            viewHolder.sizeDuration.setText(fileLocation.sizeDuration);

            UIUtils.loadImageWithCharacterAvatar(getActivity(), hostManager, fileLocation.artUrl,
                    fileLocation.title, viewHolder.art, artWidth, artHeight);
            // For the popup menu
            if (fileLocation.isDirectory) {
                viewHolder.contextMenu.setVisibility(View.GONE);
            } else {
                viewHolder.contextMenu.setVisibility(View.VISIBLE);
                viewHolder.contextMenu.setTag(position);
                viewHolder.contextMenu.setOnClickListener(itemMenuClickListener);
            }

            return convertView;
        }
    }

    /**
     * View holder pattern
     */
    private static class ViewHolder {
        ImageView art;
        TextView title;
        TextView details;
        TextView sizeDuration;
        ImageView contextMenu;
    }

    public static class FileLocation implements Parcelable {
        public final String title;
        public final String details;
        public final String sizeDuration;
        public final String artUrl;

        public final String file;
        public final boolean isDirectory;
        private boolean isRoot;

        public boolean isRootDir() {
            return this.isRoot;
        }

        public void setRootDir(boolean root) {
            this.isRoot = root;
        }

        public FileLocation(String title, String path, boolean isDir) {
            this(title, path, isDir, null, null, null);
        }

        public FileLocation(String title, String path, boolean isDir, String details, String sizeDuration,
                String artUrl) {
            this.title = title;
            this.file = path;
            this.isDirectory = isDir;
            this.isRoot = false;

            this.details = details;
            this.sizeDuration = sizeDuration;
            this.artUrl = artUrl;
        }

        public static FileLocation newInstanceFromItemFile(Context context, ListType.ItemFile itemFile) {
            String title, details, sizeDuration, artUrl;

            switch (itemFile.type) {
            case ListType.ItemBase.TYPE_MOVIE:
                title = itemFile.title;
                details = itemFile.tagline;
                sizeDuration = UIUtils.formatTime(itemFile.runtime);
                artUrl = itemFile.thumbnail;
                break;
            case ListType.ItemBase.TYPE_EPISODE:
                title = itemFile.title;
                details = String.format(context.getString(R.string.season_episode), itemFile.season,
                        itemFile.episode);
                sizeDuration = UIUtils.formatTime(itemFile.runtime);
                artUrl = itemFile.thumbnail;
                break;
            case ListType.ItemBase.TYPE_MUSIC_VIDEO:
                title = itemFile.title;
                details = Utils.listStringConcat(itemFile.artist, ", ") + " | " + itemFile.album;
                sizeDuration = UIUtils.formatTime(itemFile.runtime);
                artUrl = itemFile.thumbnail;
                break;
            case ListType.ItemBase.TYPE_ALBUM:
            case ListType.ItemBase.TYPE_SONG:
                title = itemFile.title;
                details = itemFile.displayartist + " | " + itemFile.album;
                artUrl = itemFile.thumbnail;
                sizeDuration = UIUtils.formatTime(itemFile.duration);
                break;
            case ListType.ItemBase.TYPE_PICTURE:
            default:
                title = itemFile.label;
                details = null;
                artUrl = itemFile.thumbnail;
                sizeDuration = UIUtils.formatFileSize(itemFile.size);
                break;
            }

            return new FileLocation(title, itemFile.file,
                    itemFile.filetype.equalsIgnoreCase(ListType.ItemFile.FILETYPE_DIRECTORY), details, sizeDuration,
                    artUrl);
        }

        private FileLocation(Parcel in) {
            this.title = in.readString();
            this.file = in.readString();
            this.isDirectory = (in.readInt() != 0);
            this.isRoot = (in.readInt() != 0);

            this.details = in.readString();
            this.sizeDuration = in.readString();
            this.artUrl = in.readString();
        }

        public int describeContents() {
            return 0;
        }

        public void writeToParcel(Parcel out, int flags) {
            out.writeString(title);
            out.writeString(file);
            out.writeInt(isDirectory ? 1 : 0);
            out.writeInt(isRoot ? 1 : 0);

            out.writeString(details);
            out.writeString(sizeDuration);
            out.writeString(artUrl);
        }

        public static final Parcelable.Creator<FileLocation> CREATOR = new Parcelable.Creator<FileLocation>() {
            public FileLocation createFromParcel(Parcel in) {
                return new FileLocation(in);
            }

            public FileLocation[] newArray(int size) {
                return new FileLocation[size];
            }
        };
    }
}