2018-05-02 05:21:44 +03:00
package mplayer4anime ;
import javafx.application.HostServices ;
import javafx.application.Platform ;
2018-11-25 18:13:09 +03:00
import javafx.event.ActionEvent ;
import javafx.event.EventHandler ;
2018-05-02 05:21:44 +03:00
import javafx.fxml.FXML ;
import javafx.fxml.Initializable ;
import javafx.scene.control.* ;
2018-11-25 18:13:09 +03:00
import javafx.stage.Stage ;
2018-05-02 05:21:44 +03:00
import mplayer4anime.About.AboutWindow ;
2018-11-25 18:13:09 +03:00
import mplayer4anime.Playlists.JsonStorage ;
import mplayer4anime.Playlists.Playlists ;
2018-05-02 05:21:44 +03:00
import mplayer4anime.Settings.SettingsWindow ;
2018-11-28 07:10:35 +03:00
import mplayer4anime.appPanes.ControllerPane ;
2018-05-02 05:21:44 +03:00
import mplayer4anime.appPanes.ControllerSUB ;
import java.io.* ;
import java.net.URL ;
2018-11-25 18:13:09 +03:00
import java.util.ListIterator ;
2018-05-02 05:21:44 +03:00
import java.util.ResourceBundle ;
public class Controller implements Initializable {
@FXML
2018-11-28 07:10:35 +03:00
private ControllerPane mkvPaneController ;
2018-05-02 05:21:44 +03:00
@FXML
2018-11-28 07:10:35 +03:00
private ControllerPane mkaPaneController ;
2018-05-02 05:21:44 +03:00
@FXML
2018-11-28 07:10:35 +03:00
private ControllerSUB subPaneController ;
2018-11-25 18:13:09 +03:00
@FXML
private Label statusLbl ;
@FXML
private Menu recentlyOpenedMenu ;
2018-05-02 05:21:44 +03:00
// Get preferences
private AppPreferences appPreferences = new AppPreferences ( ) ;
private ResourceBundle resourceBundle ;
2018-05-02 15:28:32 +03:00
@FXML
private CheckMenuItem fullScreen ;
// Get host services for opening URLs etc.
private HostServices hostServices ;
@FXML
private TabPane tabPane ;
2018-05-08 01:43:01 +03:00
@FXML
private CheckMenuItem subsHide ;
2018-11-25 18:13:09 +03:00
private String currentPlaylistLocation = null ; //TODO: move to the constructor?
2018-05-02 05:21:44 +03:00
@Override
public void initialize ( URL url , ResourceBundle rb ) {
2018-11-28 07:10:35 +03:00
mkvPaneController . setPaneType ( " Video " ) ;
mkaPaneController . setPaneType ( " Audio " ) ;
subPaneController . setPaneType ( " Subtitles " ) ;
2018-05-02 05:21:44 +03:00
// Register this controller in mediator
MediatorControl . getInstance ( ) . registerMainController ( this ) ;
resourceBundle = rb ;
2018-11-25 18:13:09 +03:00
// Set default list of encodings of the subtitles files:
subPaneController . setEncoding ( appPreferences . getSubsEncodingList ( ) , appPreferences . getLastTimeUsedSubsEncoding ( ) ) ;
2018-05-02 05:21:44 +03:00
// If subtitles should be opened first, per user's settings let's show it first
if ( appPreferences . getSubtilesFirst ( ) ) {
tabPane . getSelectionModel ( ) . select ( 1 ) ; // 0 is mka 1 is subs
}
fullScreen . setSelected ( appPreferences . getFullScreenSelected ( ) ) ;
2018-05-08 01:43:01 +03:00
subsHide . setSelected ( appPreferences . getSubtitlesHideSelected ( ) ) ;
2018-11-25 18:13:09 +03:00
String [ ] recentPlaylists = appPreferences . getRecentPlaylists ( ) ;
for ( int i = recentPlaylists . length - 1 ; i > = 0 ; i - - )
if ( ! recentPlaylists [ i ] . isEmpty ( ) )
addRecentlyOpened ( recentPlaylists [ i ] ) ;
2018-05-02 05:21:44 +03:00
}
public void setHostServices ( HostServices hostServices ) {
this . hostServices = hostServices ;
}
2018-11-25 18:13:09 +03:00
/* PLAYER COMMANDS */
2018-05-02 05:21:44 +03:00
private boolean playerSingleCommand ( String command ) {
if ( player ! = null & & player . isAlive ( ) ) {
playerIn . print ( command ) ;
playerIn . print ( " \ n " ) ;
playerIn . flush ( ) ;
return true ;
} else { return false ; }
}
2018-05-08 01:43:01 +03:00
@FXML
private void subsTriggerBtn ( ) {
2018-11-25 18:13:09 +03:00
if ( playerSingleCommand ( " get_sub_visibility " ) ) {
String returnedStr ;
int returnedInt = 1 ;
try {
while ( ( returnedStr = playerOutErr . readLine ( ) ) ! = null ) {
//System.out.println(returnedStr);
if ( returnedStr . startsWith ( " ANS_SUB_VISIBILITY= " ) ) {
returnedInt = Integer . parseInt ( returnedStr . substring ( " ANS_SUB_VISIBILITY= " . length ( ) ) ) ;
break ;
}
2018-05-08 01:43:01 +03:00
}
2018-11-25 18:13:09 +03:00
} catch ( IOException e ) {
System . out . println ( " Can't determine whether subtitles enabled or disabled " ) ;
2018-05-08 01:43:01 +03:00
}
2018-11-25 18:13:09 +03:00
if ( returnedInt = = 1 )
playerSingleCommand ( " sub_visibility 0 " ) ;
else
playerSingleCommand ( " sub_visibility 1 " ) ;
}
2018-05-08 01:43:01 +03:00
}
2018-05-02 05:21:44 +03:00
@FXML
private void fullscreenBtn ( ) { playerSingleCommand ( " vo_fullscreen " ) ; }
@FXML
private void muteBtn ( ) { playerSingleCommand ( " mute " ) ; }
@FXML
private void playPrevTrackBtn ( ) {
if ( player ! = null & & player . isAlive ( ) ) {
playerSingleCommand ( " quit " ) ;
while ( player . isAlive ( ) ) ; // TODO: remove crutch, implement bike
}
int index ;
2018-11-25 18:13:09 +03:00
index = mkvPaneController . getElementSelectedIndex ( ) ;
2018-05-02 05:21:44 +03:00
if ( index > 0 ) {
2018-11-25 18:13:09 +03:00
mkvPaneController . setElementSelectedByIndex ( index - 1 ) ; // .selectNext / .selectPrevious
2018-05-02 05:21:44 +03:00
playBtn ( ) ;
}
}
@FXML
private void playNextTrackBtn ( ) {
if ( player ! = null & & player . isAlive ( ) ) {
playerSingleCommand ( " quit " ) ;
while ( player . isAlive ( ) ) ; // TODO: remove crutch, implement bike
}
int index ;
2018-11-25 18:13:09 +03:00
index = mkvPaneController . getElementSelectedIndex ( ) ;
if ( index + 1 < mkvPaneController . getElementsCount ( ) ) {
mkvPaneController . setElementSelectedByIndex ( index + 1 ) ;
2018-05-02 05:21:44 +03:00
playBtn ( ) ;
}
}
private Process player ;
private PrintStream playerIn ;
private BufferedReader playerOutErr ;
@FXML
private void playBtn ( ) {
2018-11-25 18:13:09 +03:00
if ( mkvPaneController . getElementSelected ( ) ! = null ) {
boolean Audio = ! mkaPaneController . isElementsListEmpty ( ) & & mkvPaneController . getElementSelectedIndex ( ) < mkaPaneController . getElementsCount ( ) ;
boolean Subtitles = ! subPaneController . isElementsListEmpty ( ) & & mkvPaneController . getElementSelectedIndex ( ) < subPaneController . getElementsCount ( ) ;
boolean SubEncodingDefault = subPaneController . getSelectedEncoding ( ) . equals ( " default " ) ;
2018-05-02 05:21:44 +03:00
try {
if ( player = = null | | ! player . isAlive ( ) ) {
player = new ProcessBuilder ( // FUCKING MAGIC! DON'T CHANGE SEQUENCE
appPreferences . getPath ( ) , // It's a chance for Windows ;)
" -slave " ,
Audio ? " -audiofile " : " " ,
2018-11-25 18:13:09 +03:00
Audio ? mkaPaneController . getElementSelected ( ) : " " ,
2018-05-02 05:21:44 +03:00
" -quiet " ,
fullScreen . isSelected ( ) ? " -fs " : " " ,
2018-11-25 18:13:09 +03:00
mkvPaneController . getElementSelected ( ) ,
2018-05-08 01:43:01 +03:00
subsHide . isSelected ( ) | | Subtitles ? " -nosub " : " " , // Turn off subtitles embedded into MKV file (and replace by localy-stored subs file if needed)
2018-05-02 05:21:44 +03:00
Subtitles ? " -sub " : " " ,
2018-11-25 18:13:09 +03:00
Subtitles ? subPaneController . getElementSelected ( ) : " " ,
Subtitles ? SubEncodingDefault ? " " : " -subcp " : " " , // Use subtitles -> YES -> Check if we need encoding
Subtitles ? SubEncodingDefault ? " " : subPaneController . getSelectedEncoding ( ) : " "
2018-05-02 05:21:44 +03:00
) . start ( ) ;
PipedInputStream readFrom = new PipedInputStream ( 256 * 1024 ) ;
PipedOutputStream writeTo = new PipedOutputStream ( readFrom ) ;
playerOutErr = new BufferedReader ( new InputStreamReader ( readFrom ) ) ;
new LineRedirecter ( player . getInputStream ( ) , writeTo ) . start ( ) ;
new LineRedirecter ( player . getErrorStream ( ) , writeTo ) . start ( ) ;
playerIn = new PrintStream ( player . getOutputStream ( ) ) ;
2018-05-08 01:43:01 +03:00
/ * If user desired to disable subtitles but populated the list in the SUB pane , then load them and disable visibility .
* It ' s should be done this way because if we won ' t pass them to mplayer during start them user won ' t be able to enable them later on .
* There is another bike could be implemented such as passing input file during load but it ' s far more dumb idea then current implementation .
* /
if ( subsHide . isSelected ( ) )
playerSingleCommand ( " sub_visibility 0 " ) ;
2018-05-02 05:21:44 +03:00
} else {
playerIn . print ( " pause " ) ;
playerIn . print ( " \ n " ) ;
playerIn . flush ( ) ;
}
} catch ( IOException e ) {
2018-11-25 18:13:09 +03:00
ServiceWindow . getErrorNotification ( resourceBundle . getString ( " Error " ) , resourceBundle . getString ( " ErrorUnableToStartMplayer " ) ) ;
2018-05-02 05:21:44 +03:00
}
} else { System . out . println ( " File not selected " ) ; }
}
@FXML
private void stopBtn ( ) { playerSingleCommand ( " stop " ) ; }
@FXML
private void volumeUpBtn ( ) { playerSingleCommand ( " volume +1 0 " ) ; }
@FXML
private void volumeDownBtn ( ) { playerSingleCommand ( " volume -1 0 " ) ; }
2018-11-25 18:13:09 +03:00
@FXML
private void closeBtn ( ) {
Stage currentStage = ( Stage ) tabPane . getScene ( ) . getWindow ( ) ;
currentStage . close ( ) ;
}
2018-05-02 05:21:44 +03:00
// Will be used to store lists previously opened.
// Linkage established by ohHidden in Main.java class
2018-11-25 18:13:09 +03:00
void shutdown ( ) {
appPreferences . setLastTimeUsedSubsEncoding ( subPaneController . getSelectedEncoding ( ) ) ;
2018-05-02 05:21:44 +03:00
appPreferences . setFullScreenSelected ( fullScreen . isSelected ( ) ) ;
2018-05-08 01:43:01 +03:00
appPreferences . setSubtitlesHideSelected ( subsHide . isSelected ( ) ) ;
2018-05-02 05:21:44 +03:00
2018-11-25 18:13:09 +03:00
String [ ] storeRecentArr = new String [ 10 ] ;
for ( int i = 0 ; i < recentlyOpenedMenu . getItems ( ) . size ( ) - 2 & & ! ( i > 9 ) ; i + + ) { // Don't take separator and Clean button
storeRecentArr [ i ] = ( String ) recentlyOpenedMenu . getItems ( ) . get ( i ) . getUserData ( ) ;
}
appPreferences . setRecentPlaylists ( storeRecentArr ) ;
2018-05-02 05:21:44 +03:00
Platform . exit ( ) ;
}
@FXML
2018-11-25 18:13:09 +03:00
private void infoBtn ( ) { new AboutWindow ( this . hostServices ) ; } // TODO: fix this shit with hostSerivces that doesn't work @ linux
2018-05-02 05:21:44 +03:00
/** SETTINGS HANDLE */
@FXML
private void settingsBtn ( ) { new SettingsWindow ( ) ; }
// Get event that notify application in case some settings has been changed
// This function called from MediatorControl after mediator receives request form SettingsController indicating that user updated some required fields.
2018-11-25 18:13:09 +03:00
void updateAfterSettingsChanged ( ) {
/* update list of encoding */
subPaneController . setEncoding ( appPreferences . getSubsEncodingList ( ) , null ) ;
2018-05-02 05:21:44 +03:00
// In case of application failure should be better to save this immediately
2018-11-25 18:13:09 +03:00
appPreferences . setLastTimeUsedSubsEncoding ( subPaneController . getSelectedEncoding ( ) ) ;
}
@FXML
private void openBtn ( ) {
JsonStorage jsonStorage = Playlists . Read ( resourceBundle ) ;
2018-11-28 07:10:35 +03:00
setAllLists ( jsonStorage ) ;
}
private void setAllLists ( JsonStorage jsonStorage ) {
2018-11-25 18:13:09 +03:00
if ( jsonStorage ! = null ) {
2018-11-28 07:10:35 +03:00
mkvPaneController . cleanList ( ) ;
mkaPaneController . cleanList ( ) ;
subPaneController . cleanList ( ) ;
2018-11-25 18:13:09 +03:00
mkvPaneController . setFilesFromList ( jsonStorage . getVideo ( ) ) ;
mkaPaneController . setFilesFromList ( jsonStorage . getAudio ( ) ) ;
subPaneController . setFilesFromList ( jsonStorage . getSubs ( ) ) ;
subPaneController . selectEncodingValue ( jsonStorage . getSubEncoding ( ) , appPreferences ) ;
2018-11-28 07:10:35 +03:00
currentPlaylistLocation = Playlists . getPlaylistLocation ( ) ; // TODO: Implement listener? mmm...
statusLbl . setText ( currentPlaylistLocation ) ;
2018-11-25 18:13:09 +03:00
addRecentlyOpened ( currentPlaylistLocation ) ;
}
}
@FXML
private void saveBtn ( ) {
if ( mkvPaneController . getElementsCount ( ) = = 0 )
ServiceWindow . getErrorNotification ( resourceBundle . getString ( " Error " ) , resourceBundle . getString ( " ErrorUnableToSaveEmptyPlaylist " ) ) ;
else {
JsonStorage jsonStorage = new JsonStorage ( mkvPaneController . getElementsAll ( ) , mkaPaneController . getElementsAll ( ) , subPaneController . getElementsAll ( ) , subPaneController . getSelectedEncoding ( ) ) ;
if ( Playlists . SaveCurrent ( resourceBundle , jsonStorage ) ) {
this . currentPlaylistLocation = Playlists . getPlaylistLocation ( ) ;
this . statusLbl . setText ( currentPlaylistLocation ) ; //TODO: update header of the application to include this?
addRecentlyOpened ( currentPlaylistLocation ) ;
}
}
}
@FXML
private void saveAsBtn ( ) {
if ( mkvPaneController . getElementsCount ( ) = = 0 )
ServiceWindow . getErrorNotification ( resourceBundle . getString ( " Error " ) , resourceBundle . getString ( " ErrorUnableToSaveEmptyPlaylist " ) ) ;
else {
JsonStorage jsonStorage = new JsonStorage ( mkvPaneController . getElementsAll ( ) , mkaPaneController . getElementsAll ( ) , subPaneController . getElementsAll ( ) , subPaneController . getSelectedEncoding ( ) ) ;
if ( Playlists . SaveAs ( resourceBundle , jsonStorage ) ) {
this . currentPlaylistLocation = Playlists . getPlaylistLocation ( ) ;
this . statusLbl . setText ( currentPlaylistLocation ) ; //TODO: update header of the application to include this?
addRecentlyOpened ( currentPlaylistLocation ) ;
}
}
}
@FXML
private void cleanAllRecentlyOpened ( ) {
recentlyOpenedMenu . getItems ( ) . remove ( 0 , recentlyOpenedMenu . getItems ( ) . size ( ) - 2 ) ;
2018-05-02 05:21:44 +03:00
}
2018-11-25 18:13:09 +03:00
private void addRecentlyOpened ( String playlistPath ) {
ListIterator < MenuItem > iteratorItem = recentlyOpenedMenu . getItems ( ) . listIterator ( ) ;
while ( iteratorItem . hasNext ( ) ) {
MenuItem mi = iteratorItem . next ( ) ;
if ( mi . getUserData ( ) ! = null & & mi . getUserData ( ) . equals ( playlistPath ) ) {
recentlyOpenedMenu . getItems ( ) . remove ( mi ) ;
recentlyOpenedMenu . getItems ( ) . add ( 0 , mi ) ;
return ;
}
}
MenuItem menuItem = new MenuItem ( ) ;
String fileNameOnly ;
if ( playlistPath . contains ( " / " ) ) { // Unix
fileNameOnly = playlistPath . substring ( playlistPath . lastIndexOf ( " / " ) + 1 , playlistPath . length ( ) ) ;
menuItem . setText ( fileNameOnly ) ;
}
else if ( playlistPath . contains ( " \\ " ) ) { // Windows
fileNameOnly = playlistPath . substring ( playlistPath . lastIndexOf ( " \\ " ) + 1 , playlistPath . length ( ) ) ;
menuItem . setText ( fileNameOnly ) ;
}
else { // Other o_0
menuItem . setText ( playlistPath ) ;
}
menuItem . setUserData ( playlistPath ) ;
menuItem . setOnAction ( new EventHandler < ActionEvent > ( ) {
@Override
public void handle ( ActionEvent actionEvent ) {
JsonStorage jsonStorage = Playlists . ReadByPath ( resourceBundle , new File ( playlistPath ) ) ;
2018-11-28 07:10:35 +03:00
setAllLists ( jsonStorage ) ;
2018-11-25 18:13:09 +03:00
}
} ) ;
// Limit list to 13 elements (2 in the end are separator and clear button)
if ( recentlyOpenedMenu . getItems ( ) . size ( ) > = 11 )
recentlyOpenedMenu . getItems ( ) . remove ( 9 , recentlyOpenedMenu . getItems ( ) . size ( ) - 2 ) ;
recentlyOpenedMenu . getItems ( ) . add ( 0 , menuItem ) ;
}
2018-05-02 05:21:44 +03:00
}
2018-11-25 18:13:09 +03:00