private void setActionBarTitle() {
   MySong currentSong = App.mClementine.getCurrentSong();
   if (currentSong == null) {
     mActionBar.setTitle(getString(R.string.player_nosong));
     mActionBar.setSubtitle("");
   } else {
     mActionBar.setTitle(currentSong.getArtist());
     mActionBar.setSubtitle(currentSong.getTitle());
   }
 }
  /** Update the notification with the new track info */
  private void updateNotification() {
    if (mLastSong != null) {
      Bitmap scaledArt =
          Bitmap.createScaledBitmap(
              mLastSong.getArt(), mNotificationWidth, mNotificationHeight, false);
      mNotifyBuilder.setLargeIcon(scaledArt);
      mNotifyBuilder.setContentTitle(mLastSong.getArtist());
      mNotifyBuilder.setContentText(mLastSong.getTitle() + " / " + mLastSong.getAlbum());
    } else {
      mNotifyBuilder.setContentTitle(App.mApp.getString(R.string.app_name));
      mNotifyBuilder.setContentText(App.mApp.getString(R.string.player_nosong));
    }

    mNotificationManager.notify(App.NOTIFY_ID, mNotifyBuilder.build());
  }
  @Override
  protected void onProgressUpdate(Integer... progress) {
    mBuilder.setProgress(100, progress[0], false);
    StringBuilder sb = new StringBuilder();

    switch (mItem) {
      case APlaylist:
        sb.append(mContext.getString(R.string.download_noti_title_playlist));
        sb.append(" ");
        sb.append(mPlaylistName);
        break;
      case CurrentItem:
        sb.append(mContext.getString(R.string.download_noti_title_song));
        sb.append(" ");
        sb.append(mCurrentSong.getTitle());
        break;
      case ItemAlbum:
        sb.append(mContext.getString(R.string.download_noti_title_album));
        sb.append(" ");
        sb.append(mCurrentSong.getAlbum());
        break;
    }

    mTitle = sb.toString();

    sb = new StringBuilder();

    if (mCurrentSong.equals(new MySong())) {
      sb.append(mContext.getString(R.string.connectdialog_connecting));
    } else {
      sb.append("(");
      sb.append(mCurrentFile);
      sb.append("/");
      sb.append(mFileCount);
      sb.append(") ");
      sb.append(mCurrentSong.getArtist());
      sb.append(" - ");
      sb.append(mCurrentSong.getTitle());
    }

    mSubtitle = sb.toString();

    mBuilder.setContentTitle(mTitle);
    mBuilder.setContentText(mSubtitle);

    // Displays the progress bar for the first time.
    mNotifyManager.notify(mId, mBuilder.build());
  }
  /** Update the RemoteControlClient */
  private void updateRemoteControlClient() {
    // Update playstate
    if (App.mClementine.getState() == Clementine.State.PLAY) {
      mRcClient.setPlaybackState(RemoteControlClient.PLAYSTATE_PLAYING);
    } else {
      mRcClient.setPlaybackState(RemoteControlClient.PLAYSTATE_PAUSED);
    }

    // Get the metadata editor
    if (mLastSong != null && mLastSong.getArt() != null) {
      RemoteControlClient.MetadataEditor editor = mRcClient.editMetadata(false);
      editor.putBitmap(MetadataEditor.BITMAP_KEY_ARTWORK, mLastSong.getArt());

      // The RemoteControlClients displays the following info:
      // METADATA_KEY_TITLE (white) - METADATA_KEY_ALBUMARTIST (grey) - METADATA_KEY_ALBUM (grey)
      //
      // So i put the metadata not in the "correct" fields to display artist, track and album
      // TODO: Fix it when changed in newer android versions
      editor.putString(MediaMetadataRetriever.METADATA_KEY_ALBUM, mLastSong.getAlbum());
      editor.putString(MediaMetadataRetriever.METADATA_KEY_TITLE, mLastSong.getArtist());
      editor.putString(MediaMetadataRetriever.METADATA_KEY_ALBUMARTIST, mLastSong.getTitle());
      editor.apply();
    }
  }
  /** Start the Downlaod */
  private DownloaderResult startDownloading(ClementineMessage clementineMessage) {
    boolean downloadFinished = false;
    DownloaderResult result = new DownloaderResult(DownloadResult.SUCCESSFUL);
    File f = null;
    FileOutputStream fo = null;

    // Do we have a playlist?
    mIsPlaylist =
        (clementineMessage.getMessage().getRequestDownloadSongs().getDownloadItem()
            == DownloadItem.APlaylist);
    if (mIsPlaylist) {
      int id = clementineMessage.getMessage().getRequestDownloadSongs().getPlaylistId();
      mPlaylistName = App.mClementine.getPlaylistManager().getPlaylist(id).getName();
    }

    publishProgress(0);

    // Now request the songs
    mClient.sendRequest(clementineMessage);

    while (!downloadFinished) {
      // Check if the user canceled the process
      if (isCancelled()) {
        // Close the stream and delete the incomplete file
        try {
          if (fo != null) {
            fo.flush();
            fo.close();
          }
          if (f != null) {
            f.delete();
          }
        } catch (IOException e) {
        }

        break;
      }

      // Get the raw protocol buffer
      ClementineMessage message = mClient.getProtoc();

      // Check if an error occured
      if (message == null || message.isErrorMessage()) {
        result = new DownloaderResult(DownloadResult.CONNECTION_ERROR);
        break;
      }

      // Is the download forbidden?
      if (message.getMessageType() == MsgType.DISCONNECT) {
        result = new DownloaderResult(DownloadResult.FOBIDDEN);
        break;
      }

      // Download finished?
      if (message.getMessageType() == MsgType.DOWNLOAD_QUEUE_EMPTY) {
        break;
      }

      // Ignore other elements!
      if (message.getMessageType() != MsgType.SONG_FILE_CHUNK) {
        continue;
      }

      ResponseSongFileChunk chunk = message.getMessage().getResponseSongFileChunk();

      // If we received chunk no 0, then we have to decide wether to
      // accept the song offered or not
      if (chunk.getChunkNumber() == 0) {
        processSongOffer(chunk);

        // Update progress here to. If the first (and only) file exists and shall not be
        // overriten, the notification bar shows NULL.
        mCurrentSong = MySong.fromProtocolBuffer(chunk.getSongMetadata());
        publishProgress(mCurrentProgress);
        continue;
      }

      try {
        // Check if we need to create a new file
        if (f == null) {
          // Check if we have enougth free space
          if (chunk.getSize() > Utilities.getFreeSpaceExternal()) {
            result = new DownloaderResult(DownloadResult.INSUFFIANT_SPACE);
            break;
          }

          File dir = new File(BuildDirPath(chunk));
          f = new File(BuildFilePath(chunk));

          // User wants to override files, so delete it here!
          // The check was already done in processSongOffer()
          if (f.exists()) {
            f.delete();
          }

          dir.mkdirs();
          f.createNewFile();
          fo = new FileOutputStream(f);

          // File for download fragment
          mFileUri = Uri.fromFile(f);
        }

        // Write chunk to sdcard
        fo.write(chunk.getData().toByteArray());

        // Have we downloaded all chunks?
        if (chunk.getChunkCount() == chunk.getChunkNumber()) {
          // Index file
          MediaScannerConnection.scanFile(mContext, new String[] {f.getAbsolutePath()}, null, null);
          fo.flush();
          fo.close();
          f = null;
        }

        // Update notification
        updateProgress(chunk);
      } catch (IOException e) {
        result = new DownloaderResult(DownloaderResult.DownloadResult.NOT_MOUNTED);
        break;
      }
    }

    // Disconnect at the end
    mClient.disconnect(ClementineMessage.getMessage(MsgType.DISCONNECT));

    return result;
  }