/**
   * Try to connect to Clementine
   *
   * @param message The Request Object. Stores the ip to connect to.
   */
  public boolean createConnection(ClementineMessage message) {
    SocketAddress socketAddress = new InetSocketAddress(message.getIp(), message.getPort());
    mSocket = new Socket();
    try {
      mSocket.connect(socketAddress, 3000);
      mIn = new DataInputStream(mSocket.getInputStream());
      mOut = new DataOutputStream(mSocket.getOutputStream());

      // Send the connect request to clementine
      sendRequest(message);
    } catch (IOException e) {
      return false;
    }

    return true;
  }
예제 #2
0
 @Override
 public void MessageFromClementine(ClementineMessage clementineMessage) {
   switch (clementineMessage.getMessageType()) {
     case CURRENT_METAINFO:
       setActionBarTitle();
       break;
     default:
       break;
   }
 }
  @SuppressLint({"InlinedApi", "NewApi"})
  public void startDownload(ClementineMessage message) {
    mItem = message.getMessage().getRequestDownloadSongs().getDownloadItem();

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
      this.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, message);
    } else {
      this.execute(message);
    }
  }
  @Override
  public void onReceive(Context context, Intent intent) {
    // Check if we have an media button intent
    if (Intent.ACTION_MEDIA_BUTTON.equals(intent.getAction())) {

      // Get the key event and obtain a new message
      KeyEvent event = intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
      Message msg = Message.obtain();

      // Only on KeyDown
      if (event.getAction() == KeyEvent.ACTION_UP) {
        // Check which key was pressed
        switch (event.getKeyCode()) {
          case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
            msg.obj = ClementineMessage.getMessage(MsgType.PLAYPAUSE);
            break;
          case KeyEvent.KEYCODE_MEDIA_NEXT:
            msg.obj = ClementineMessage.getMessage(MsgType.NEXT);
            break;
          case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
            msg.obj = ClementineMessage.getMessage(MsgType.PREVIOUS);
            break;
          case KeyEvent.KEYCODE_VOLUME_DOWN:
            msg.obj = ClementineMessageFactory.buildVolumeMessage(App.mClementine.getVolume() - 10);
            break;
          case KeyEvent.KEYCODE_VOLUME_UP:
            msg.obj = ClementineMessageFactory.buildVolumeMessage(App.mClementine.getVolume() + 10);
            break;
          default:
            msg = null;
            break;
        }

        // Now send the message
        if (msg != null && App.mClementineConnection != null) {
          App.mClementineConnection.mHandler.sendMessage(msg);
        }
      }
    }
  }
예제 #5
0
        @Override
        public void onClick(View v) {
          Message msg = Message.obtain();

          switch (v.getId()) {
            case R.id.btnNext:
              msg.obj = ClementineMessage.getMessage(MsgType.NEXT);
              break;
            case R.id.btnPrev:
              msg.obj = ClementineMessage.getMessage(MsgType.PREVIOUS);
              break;
            case R.id.btnPlaypause:
              msg.obj = ClementineMessage.getMessage(MsgType.PLAYPAUSE);
              break;
            default:
              break;
          }
          // Send the request to the thread
          if (msg.obj != null) {
            App.mClementineConnection.mHandler.sendMessage(msg);
          }
        }
 /**
  * Send a request to clementine
  *
  * @param message The request as a RequestToThread object
  * @return true if data was sent, false if not
  */
 public boolean sendRequest(ClementineMessage message) {
   // Create the protocolbuffer
   byte[] data = message.getMessage().toByteArray();
   try {
     mOut.writeInt(data.length);
     mOut.write(data);
     mOut.flush();
   } catch (Exception e) {
     // Try to reconnect
     closeSocket();
     return false;
   }
   return true;
 }
  /**
   * Process the received protocol buffer
   *
   * @param clementineMessage The Message received from Clementine
   */
  private void processProtocolBuffer(ClementineMessage clementineMessage) {
    // Close the connection if we have an old proto verion
    if (clementineMessage.isErrorMessage()) {
      closeConnection(clementineMessage);
    } else if (clementineMessage.getTypeGroup() == MessageGroup.GUI_RELOAD) {
      sendUiMessage(clementineMessage);

      // Now update the notification and the remote control client
      if (App.mClementine.getCurrentSong() != mLastSong) {
        mLastSong = App.mClementine.getCurrentSong();
        updateNotification();
        updateRemoteControlClient();
        mPebble.sendMusicUpdateToPebble();
      }
      if (App.mClementine.getState() != mLastState) {
        mLastState = App.mClementine.getState();
        updateRemoteControlClient();
      }
    } else if (clementineMessage.getMessageType() == MsgType.DISCONNECT) {
      closeConnection(clementineMessage);
    } else {
      sendUiMessage(clementineMessage);
    }
  }
  /**
   * Disconnect from Clementine
   *
   * @param message The RequestDisconnect Object
   */
  public void disconnect(ClementineMessage message) {
    if (isConnected()) {
      // Send the disconnect message to clementine
      byte[] data = message.getMessage().toByteArray();

      try {
        // Now send the data
        mOut.writeInt(data.length);
        mOut.write(data);
        mOut.flush();

        closeSocket();
      } catch (IOException e) {
      }
    }
  }
예제 #9
0
  @Override
  public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
      case R.id.library_menu_refresh:
        mAdapters.clear();
        showList();

        App.libraryDownloader = new ClementineLibraryDownloader(getActivity());
        App.libraryDownloader.addOnLibraryDownloadListener(mOnLibraryDownloadListener);
        App.libraryDownloader.startDownload(ClementineMessage.getMessage(MsgType.GET_LIBRARY));

        createDownloadProgressDialog();
        break;
      default:
        return super.onOptionsItemSelected(item);
    }

    return true;
  }
예제 #10
0
        @Override
        public boolean onLongClick(View v) {
          boolean ret = false;
          Message msg = Message.obtain();

          switch (v.getId()) {
            case R.id.btnPlaypause:
              Toast.makeText(getActivity(), R.string.player_stop_after_current, Toast.LENGTH_SHORT)
                  .show();
              msg.obj = ClementineMessage.getMessage(MsgType.STOP_AFTER);
              ret = true;
              break;
            default:
              break;
          }

          App.mClementineConnection.mHandler.sendMessage(msg);
          return ret;
        }
  /**
   * Send a request to clementine
   *
   * @param message The request as a RequestToThread object
   * @return true if data was sent, false if not
   */
  @Override
  public boolean sendRequest(ClementineMessage message) {
    // Send the request to Clementine
    boolean ret = super.sendRequest(message);

    // If we lost connection, try to reconnect
    if (!ret) {
      //
      if (mRequestConnect != null) {
        ret = super.createConnection(mRequestConnect);
      }
      if (!ret) {
        // Failed. Close connection
        Builder builder = ClementineMessage.getMessageBuilder(MsgType.DISCONNECT);
        ResponseDisconnect.Builder disc = builder.getResponseDisconnectBuilder();
        disc.setReasonDisconnect(ReasonDisconnect.Server_Shutdown);
        builder.setResponseDisconnect(disc);
        closeConnection(new ClementineMessage(builder));
      }
    }

    return ret;
  }
예제 #12
0
  @Override
  public void MessageFromClementine(ClementineMessage clementineMessage) {
    switch (clementineMessage.getMessageType()) {
      case PLAY:
      case PAUSE:
      case STOP:
        stateChanged();
        break;
      case CURRENT_METAINFO:
        metadataChanged();
      default:
        break;
    }

    if (mPlayerPageFragment.isAdded()) {
      mPlayerPageFragment.MessageFromClementine(clementineMessage);
    }
    if (mSongDetailFragment.isAdded()) {
      mSongDetailFragment.MessageFromClementine(clementineMessage);
    }
    if (mConnectionFragment.isAdded()) {
      mConnectionFragment.MessageFromClementine(clementineMessage);
    }
  }
  /**
   * Try to connect to Clementine
   *
   * @param message The Request Object. Stores the ip to connect to.
   */
  @Override
  public boolean createConnection(ClementineMessage message) {
    boolean connected = false;
    // Reset the connected flag
    mLastKeepAlive = 0;

    // Now try to connect and set the input and output streams
    connected = super.createConnection(message);

    // Check if Clementine dropped the connection.
    // Is possible when we connect from a public ip and clementine rejects it
    if (connected && !mSocket.isClosed()) {
      // Enter the main loop in the thread
      Message msg = Message.obtain();
      msg.arg1 = CHECK_FOR_DATA_ARG;
      mHandler.sendMessage(msg);

      // Now we are connected
      mLastSong = null;
      mLastState = App.mClementine.getState();

      // Setup the MediaButtonReceiver and the RemoteControlClient
      registerRemoteControlClient();

      // Register MediaButtonReceiver
      IntentFilter filter = new IntentFilter(Intent.ACTION_MEDIA_BUTTON);
      App.mApp.registerReceiver(mMediaButtonBroadcastReceiver, filter);

      updateNotification();

      // The device shall be awake
      mWakeLock.acquire();

      // We can now reconnect MAX_RECONNECTS times when
      // we get a keep alive timeout
      mLeftReconnects = MAX_RECONNECTS;

      // Set the current time to last keep alive
      setLastKeepAlive(System.currentTimeMillis());

      // Until we get a new connection request from ui,
      // don't request the first data a second time
      mRequestConnect =
          ClementineMessageFactory.buildConnectMessage(
              message.getIp(),
              message.getPort(),
              message.getMessage().getRequestConnect().getAuthCode(),
              false,
              message.getMessage().getRequestConnect().getDownloader());

      // Save started transmitted bytes
      int uid = App.mApp.getApplicationInfo().uid;
      mStartTx = TrafficStats.getUidTxBytes(uid);
      mStartRx = TrafficStats.getUidRxBytes(uid);

      mStartTime = new Date().getTime();
    } else {
      sendUiMessage(new ClementineMessage(ErrorMessage.NO_CONNECTION));
    }

    return connected;
  }
  /** Start the Download */
  private DownloaderResult startDownloading(ClementineMessage clementineMessage) {
    boolean downloadFinished = false;
    DownloaderResult result = new DownloaderResult(DownloadResult.SUCCESSFUL);
    File f = null;
    FileOutputStream fo = null;

    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) {
        }
        Log.d(TAG, "isCancelled");
        break;
      }

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

      if (message.isErrorMessage()) {
        result = new DownloaderResult(DownloadResult.CONNECTION_ERROR);
        break;
      }

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

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

      ResponseLibraryChunk chunk = message.getMessage().getResponseLibraryChunk();

      try {
        // Check if we need to create a new file
        if (f == null) {
          // Check if we have enougth free space
          // size times 2, because we optimise the table later and
          // need space for that too!
          if ((chunk.getSize() * 2) > Utilities.getFreeSpaceExternal()) {
            result = new DownloaderResult(DownloadResult.INSUFFIANT_SPACE);
            break;
          }
          f = mLibrary.getLibraryDb();

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

          f.createNewFile();
          fo = new FileOutputStream(f);
        }

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

        // Have we downloaded all chunks?
        if (chunk.getChunkCount() == chunk.getChunkNumber()) {
          fo.flush();
          fo.close();
          f = null;
          downloadFinished = true;
        }

        // 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));

    // Optimize library table
    if (mLibrary.getLibraryDb().exists()) {
      mLibrary.optimizeTable();
    }

    return result;
  }
  /** 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;
  }