void addToPlaylist(List<File> files, Playlist p) {
   if (interfaceDisabled) return;
   new Thread(
           () -> {
             setInterfaceDisabled(true);
             int total = files.size();
             AtomicInteger current = new AtomicInteger(0);
             Cache.pushToPlaylist(
                 files,
                 p,
                 (Track t) -> {
                   Platform.runLater(
                       () -> {
                         infoLabel.setText(
                             String.format(
                                 res.getString("processed"),
                                 current.incrementAndGet(),
                                 total,
                                 t.getTitle()));
                         if (p == getSelectedPlaylist()) {
                           tracksView.getItems().remove(t);
                           tracksView.getItems().add(0, t);
                         }
                       });
                 });
             setInterfaceDisabled(false);
           })
       .start();
   if (p == getSelectedPlaylist()) {
     Platform.runLater(
         () -> {
           loadSelectedPlaylist();
         });
   }
 }
  void renameTrack() {
    if (interfaceDisabled) return;
    Playlist p = getSelectedPlaylist();
    if (p == null) return;
    Track t = getSelectedTrack();
    if (t == null) return;

    TextInputDialog dialog = new TextInputDialog(t.getTitle());
    dialog.setTitle(res.getString("rename_track"));
    dialog.setHeaderText(res.getString("rename_track"));
    dialog.setContentText(res.getString("enter_new_title"));
    dialog.getDialogPane().getStylesheets().add("/styles/dialogs.css");
    ((Stage) dialog.getDialogPane().getScene().getWindow()).getIcons().addAll(logoImages);
    Optional<String> result = dialog.showAndWait();
    result.ifPresent(
        title -> {
          if (StringUtils.isEmpty(title)) {
            return;
          }
          Cache.renameTrack(t, p, title);
          Platform.runLater(
              () -> {
                loadSelectedPlaylist();
              });
        });
  }
 void addToPlaylist(Track t, Playlist p) {
   if (interfaceDisabled) return;
   Cache.pushToPlaylist(t, p);
   if (p == getSelectedPlaylist()) {
     Platform.runLater(
         () -> {
           loadSelectedPlaylist();
         });
   }
 }
 void deleteDeadFromOfflinePlaylist(Playlist p) {
   if (interfaceDisabled) return;
   infoLabel.setText(res.getString("deleting_dead_items"));
   log.info("Deleting dead items from " + p.getTitle());
   Integer deleted = Cache.deleteDead(p);
   infoLabel.setText(String.format(res.getString("deleted_dead_items"), deleted));
   log.info("Deleted dead items from " + p.getTitle() + ": " + deleted);
   Platform.runLater(
       () -> {
         loadSelectedPlaylist();
       });
 }
 void updatePlaylists() {
   if (interfaceDisabled) return;
   final ObservableList<Playlist> items = playlistsView.getItems();
   items.clear();
   items.addAll(Cache.playlists());
   if (Settings.rememberedPlaylistId != null)
     for (Playlist p : items) {
       if (p.getId().equals(Settings.rememberedPlaylistId)) {
         rememberedPlaylist = p;
         break;
       }
     }
 }
 void addToRememberedPlaylist(Track t) {
   if (interfaceDisabled) return;
   if (t == null) return;
   if (rememberedPlaylist != null) {
     Cache.pushToPlaylist(t, rememberedPlaylist);
     infoAndAnnounce(
         String.format(
             res.getString("track_added_to_playlist"),
             rememberedPlaylist.getTitle(),
             t.getTitle()));
     if (rememberedPlaylist == getSelectedPlaylist()) loadSelectedPlaylist();
   } else {
     infoAndAnnounce(res.getString("remembered_not_yet"));
   }
 }
 @FXML
 void search() {
   searching = true;
   new Thread(
           () -> {
             List<Track> tracks = Cache.search(searchText.getText());
             tracksView.setPlaceholder(searchPlaceholder);
             Platform.runLater(
                 () -> {
                   if (tracksView.getItems().size() > 0) {
                     tracksView.scrollTo(0);
                   }
                   tracksView.getItems().clear();
                   tracksView.getItems().addAll(tracks.toArray());
                 });
           })
       .start();
 }
  @FXML
  void refreshPlaylists() {
    infoLabel.setText(res.getString("refreshing"));
    log.info("Refreshing playlists");

    ObservableList<Playlist> items = playlistsView.getItems();
    items.clear();
    items.addAll(Cache.playlists());

    if (Settings.rememberedPlaylistId != null)
      for (Playlist p : items) {
        if (p.getId().equals(Settings.rememberedPlaylistId)) {
          rememberedPlaylist = p;
          break;
        }
      }

    infoLabel.setText(res.getString("playlists_refreshed"));
    log.info("Playlists refreshed");
  }
 void createOfflinePlaylist() {
   if (interfaceDisabled) return;
   TextInputDialog dialog = new TextInputDialog(res.getString("new_offline_playlist"));
   dialog.setTitle(res.getString("create_new_offline_playlist"));
   dialog.setHeaderText(res.getString("create_new_playlist"));
   dialog.setContentText(res.getString("enter_playlist_name"));
   dialog.getDialogPane().getStylesheets().add("/styles/dialogs.css");
   ((Stage) dialog.getDialogPane().getScene().getWindow()).getIcons().addAll(logoImages);
   Optional<String> result = dialog.showAndWait();
   result.ifPresent(
       title -> {
         Platform.runLater(
             () -> {
               Playlist newPlaylist = Cache.createPlaylist(title);
               Platform.runLater(
                   () -> {
                     playlistsView.getItems().add(newPlaylist);
                     playlistsView.getSelectionModel().select(newPlaylist);
                   });
             });
       });
 }
  void deletePlaylist() {
    if (interfaceDisabled) return;
    Playlist p = getSelectedPlaylist();
    if (p == null) return;
    Alert alert = new Alert(AlertType.CONFIRMATION);
    ButtonType btYes = new ButtonType(res.getString("yes"), ButtonBar.ButtonData.YES);
    ButtonType btCancel =
        new ButtonType(res.getString("cancel"), ButtonBar.ButtonData.CANCEL_CLOSE);
    alert.getButtonTypes().setAll(btYes, btCancel);
    alert.setTitle(res.getString("delete_playlist"));
    alert.setHeaderText(res.getString("delete_playlist"));
    alert.setContentText(String.format(res.getString("delete_confirm"), p.getTitle()));
    alert.getDialogPane().getStylesheets().add("/styles/dialogs.css");
    ((Stage) alert.getDialogPane().getScene().getWindow()).getIcons().addAll(logoImages);

    Optional<ButtonType> result = alert.showAndWait();
    if (result.get() == btYes) {
      Cache.deletePlaylist(p);
      Platform.runLater(
          () -> {
            updatePlaylists();
          });
    }
  }
  @FXML
  void playTrack(Track t) {
    if (tweenBlock) return;
    tweenBlock = true;
    stop(
        () -> {
          currentPlaylist = (Playlist) playlistsView.getSelectionModel().getSelectedItem();
          currentTrack = t;
          if (player != null) {
            player.dispose();
          }
          if (t == null) {
            return;
          }
          timeUpdate = 9;
          if (currentPlaylist != null) {
            Tray.announce("[" + currentPlaylist.getTitle() + "] " + t.getTitle());
          }

          Platform.runLater(
              () -> {
                infoLabel.setText(res.getString("playing_offline") + t.getTitle());
                log.info("Playing offline: " + t.getTitle());
              });
          try {
            Media media = new Media(Cache.getContent(t).toURI().toString());
            player = new MediaPlayer(media);
            player.setVolume(Settings.currentVolume);
            player.play();
          } catch (MediaException ex) {
            Platform.runLater(
                () -> {
                  infoLabel.setText(
                      String.format(res.getString("cant_play_offline_not_exist"), t.getTitle()));
                  log.error("Can't play: seems that track does not exist - " + t.getTitle());
                });
          }

          if (player != null) {
            pushToPlayStack(getSelectedPlaylist(), t);
            player.setOnEndOfMedia(
                () -> {
                  String mode = Settings.currentMode;
                  if (mode.equals(Settings.MODE_NEXT)) {
                    playNext();
                  } else if (mode.equals(Settings.MODE_RANDOM)) {
                    playRandom();
                  } else if (mode.equals(Settings.MODE_SAME)) {
                    playSame();
                  }
                });
          }

          Platform.runLater(
              () -> {
                isPlaying = true;
                tweenBlock = false;
                titleLabel.setText(t.getTitle());
                stateButton.setGraphic(imagePause);
              });
        });
  }
 void deleteFromOfflinePlaylist(Track t, Playlist p) {
   if (interfaceDisabled) return;
   tracksView.getItems().remove(t);
   Cache.deleteFromPlaylist(t, p);
 }