From a182ff8e851e7b11c1ff26a97b19ebe666a20a2a Mon Sep 17 00:00:00 2001 From: eluchsinger Date: Tue, 12 Apr 2016 22:22:49 +0200 Subject: [PATCH 01/24] MainWindowViewModel code review and better documentation. --- .../java/viewmodels/MainWindowViewModel.java | 131 +++++++++++++----- gradle/wrapper/gradle-wrapper.properties | 4 +- 2 files changed, 99 insertions(+), 36 deletions(-) diff --git a/Server/src/main/java/viewmodels/MainWindowViewModel.java b/Server/src/main/java/viewmodels/MainWindowViewModel.java index 0ab9a4f..e1ca039 100644 --- a/Server/src/main/java/viewmodels/MainWindowViewModel.java +++ b/Server/src/main/java/viewmodels/MainWindowViewModel.java @@ -37,6 +37,7 @@ * Created by Esteban Luchsinger on 30.11.2015. */ public class MainWindowViewModel { + //region Members private final Logger logger; private MediaPlayer mediaPlayer; @@ -45,49 +46,100 @@ public class MainWindowViewModel { private TCPSocketServer tcpServer; private ClientController clientController; + //endregion Members - // Properties + //region Properties + /** + * Property containing the path to the song folder. + */ private StringProperty pathToFolder; + + /** + * List containing the songs. + */ private ObservableList songObservableList; + //endregion Properties - /* Elements */ + //region Elements + /** + * The search button provides the user with an option to search for his music. + */ @FXML private Button buttonSearch; + /** + * Play and Pause button (Function changes depending on MediaPlayer state). + */ @FXML private ToggleButton buttonPlayPause; + /** + * Button to skip to the next song. + */ @FXML private Button buttonSkipNext; + /** + * Button to play the previous song. + */ @FXML private Button buttonSkipPrevious; + /** + * The textfield containing the song folder. + */ @FXML private TextField textFieldFolder; - @FXML - private ListView listViewClients; - + /** + * The table view containing the songs. + */ @FXML private TableView tableViewSongs; + /** + * The column of the song table containing the title of the song. + */ @FXML private TableColumn tableColumnTitle; + /** + * The column of the song table containing the artist. + */ @FXML private TableColumn tableColumnArtist; + /** + * The ListView showing the clients (right now: Speakers) connected to this server instance. + */ + @FXML + private ListView listViewClients; + + /** + * The slider that changes the volume (loudness) of the MediaPlayer. + */ @FXML private Slider sliderVolume; + /** + * The slider that tracks the song's current playtime. + */ @FXML private Slider songTrackerSlider; + /** + * A label describing the current time in the currently playing song. + */ @FXML private Label labelCurrentDuration; + + /** + * (Workaround) + * This is the stage (the window / View) of this ViewModel. + */ private Stage stage; + //endregion //region Constructor public MainWindowViewModel() { @@ -98,32 +150,7 @@ public MainWindowViewModel() { } //endregion Constructor - /** - * Is called, when the window has been initialized. - */ - @FXML - protected void initialize() throws IOException { - - this.songObservableList = FXCollections.observableArrayList(); - - // Init Media Player - this.mediaPlayer = new AudioPlayer(this.songObservableList); - this.mediaPlayer.isPlayingProperty().addListener((observable, oldValue, newValue) -> this.onIsPlayingChanged()); - - this.tcpServer = new TCPSocketServer(); - this.clientController = new ClientController(this.tcpServer); - - this.tcpServer.start(); - - this.initializeTable(); - this.initializeClientListView(); - this.initializeBindings(); - this.initializeDiscoveryService(); - - this.musicStreamController = new TCPMusicStreamController(this.clientController); - } - - /* Properties */ + //region Getters & Setters public final String getPathToFolder() { return this.pathToFolder.get(); } @@ -191,6 +218,8 @@ public void setStage(Stage stage) { } } + //endregion Getters & Setters + //region Events @FXML @@ -214,33 +243,42 @@ public void onSearchButtonClicked() { @FXML public void onButtonPlayPauseClicked() { + // Pause if the pause button was clicked. if (this.mediaPlayer.isPlaying()) { this.mediaPlayer.pause(); this.musicStreamController.stop(); } else if (this.getSelectedSong() != null) { + // Play if the play button was clicked. this.startPlaying(this.getSelectedSong()); } } @FXML public void onButtonSkipPreviousClicked(){ - // First check, if there are items on the list. - if(this.songObservableList.size() > 1){ + if(this.songObservableList != null && this.songObservableList.size() > 1){ Song previous = this.mediaPlayer.getPreviousTrack(); if(previous != null){ this.mediaPlayer.play(previous); } + } else { + // Error is either null or it's the size. + String error = (this.songObservableList == null) ? "not initialized" : Integer.toString(this.songObservableList.size()); + this.logger.warn("Tried to skip to the previous song, but the song list is currently " + error); } } @FXML public void onButtonSkipNextClicked(){ - if(this.songObservableList.size() > 1){ + if(this.songObservableList != null && this.songObservableList.size() > 1){ Song next = this.mediaPlayer.getNextTrack(); if(next != null){ this.mediaPlayer.play(next); } + } else { + // Error is either null or it's the size. + String error = (this.songObservableList == null) ? "not initialized" : Integer.toString(this.songObservableList.size()); + this.logger.warn("Tried to skip to the next song, but the song list is currently " + error); } } @@ -284,6 +322,31 @@ private void startPlaying(Song song) { //region initialization + /** + * Is called, when the window has been initialized. + */ + @FXML + protected void initialize() throws IOException { + + this.songObservableList = FXCollections.observableArrayList(); + + // Init Media Player + this.mediaPlayer = new AudioPlayer(this.songObservableList); + this.mediaPlayer.isPlayingProperty().addListener((observable, oldValue, newValue) -> this.onIsPlayingChanged()); + + this.tcpServer = new TCPSocketServer(); + this.clientController = new ClientController(this.tcpServer); + + this.tcpServer.start(); + + this.initializeTable(); + this.initializeClientListView(); + this.initializeBindings(); + this.initializeDiscoveryService(); + + this.musicStreamController = new TCPMusicStreamController(this.clientController); + } + private void initializeDiscoveryService() { this.serverDiscoveryService = new ServerDiscoveryService(); diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 0248557..67e20dd 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Wed Apr 06 21:20:32 CEST 2016 +#Thu Apr 07 20:45:15 CEST 2016 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.12-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-2.12-bin.zip From d26fafd04ed314d19d938f039ab82d9357b70efa Mon Sep 17 00:00:00 2001 From: eluchsinger Date: Tue, 12 Apr 2016 22:59:20 +0200 Subject: [PATCH 02/24] Deleted unused classes. Tries to guess the name of the songs folder. --- .../clients/NetworkClientStringConverter.java | 34 ---------- .../main/java/viewmodels/ClientListCell.java | 63 ------------------- .../java/viewmodels/MainWindowViewModel.java | 54 +++++++++++++--- 3 files changed, 44 insertions(+), 107 deletions(-) delete mode 100644 Server/src/main/java/controllers/clients/NetworkClientStringConverter.java delete mode 100644 Server/src/main/java/viewmodels/ClientListCell.java diff --git a/Server/src/main/java/controllers/clients/NetworkClientStringConverter.java b/Server/src/main/java/controllers/clients/NetworkClientStringConverter.java deleted file mode 100644 index 49f47e2..0000000 --- a/Server/src/main/java/controllers/clients/NetworkClientStringConverter.java +++ /dev/null @@ -1,34 +0,0 @@ -package controllers.clients; - -import javafx.util.StringConverter; -import models.networking.clients.NetworkClient; - -import java.util.Optional; - -/** - * Created by Esteban on 02.04.2016. - * Converts the NetworkClient to a String and gets the NetworkClient from a String. - */ -public class NetworkClientStringConverter extends StringConverter { - - private final ClientController clientController; - - public NetworkClientStringConverter(ClientController controller) { - this.clientController = controller; - } - - @Override - public String toString(NetworkClient object) { - return object.toString(); - } - - @Override - public NetworkClient fromString(String string) { - Optional optional = this.clientController.getClients() - .stream() - .filter(nc -> nc.toString().equals(string)) - .findFirst(); - - return optional.orElse(null); - } -} diff --git a/Server/src/main/java/viewmodels/ClientListCell.java b/Server/src/main/java/viewmodels/ClientListCell.java deleted file mode 100644 index c05b599..0000000 --- a/Server/src/main/java/viewmodels/ClientListCell.java +++ /dev/null @@ -1,63 +0,0 @@ -package viewmodels; - -import javafx.scene.control.ContentDisplay; -import javafx.scene.control.ListCell; -import javafx.scene.control.TextField; -import javafx.scene.input.KeyCode; -import javafx.scene.input.KeyEvent; -import models.networking.clients.NetworkClient; - -/** - * Created by Esteban Luchsinger on 06.04.2016. - */ -public class ClientListCell extends ListCell { - - private final TextField textField = new TextField(); - - public ClientListCell() { - textField.addEventFilter(KeyEvent.KEY_PRESSED, e -> { - if(e.getCode() == KeyCode.ESCAPE){ - cancelEdit(); - } - }); - - textField.setOnAction(e -> { - getItem().setName(textField.getText()); - setText(textField.getText()); - setContentDisplay(ContentDisplay.TEXT_ONLY); - }); - } - - @Override - protected void updateItem(NetworkClient client, boolean empty) { - super.updateItem(client, empty); - - if(isEditing()) { - textField.setText(client.getName()); - setContentDisplay(ContentDisplay.GRAPHIC_ONLY); - } else { - setContentDisplay(ContentDisplay.TEXT_ONLY); - if(empty) { - setText(null); - } else { - setText(client.getName()); - } - } - } - - @Override - public void startEdit() { - super.startEdit(); - textField.setText(getItem().getName()); - setContentDisplay(ContentDisplay.GRAPHIC_ONLY); - textField.requestFocus(); - textField.selectAll(); - } - - @Override - public void cancelEdit() { - super.cancelEdit(); - setText(getItem().getName()); - setContentDisplay(ContentDisplay.TEXT_ONLY); - } -} diff --git a/Server/src/main/java/viewmodels/MainWindowViewModel.java b/Server/src/main/java/viewmodels/MainWindowViewModel.java index e1ca039..60f8b3b 100644 --- a/Server/src/main/java/viewmodels/MainWindowViewModel.java +++ b/Server/src/main/java/viewmodels/MainWindowViewModel.java @@ -30,6 +30,8 @@ import java.io.Closeable; import java.io.File; import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.List; import java.util.Optional; @@ -155,8 +157,14 @@ public final String getPathToFolder() { return this.pathToFolder.get(); } - public final void setPathToFolder(String path) { - this.pathToFolder.set(path); + public final void setPathToFolder(File file) { + this.pathToFolder.set(file.getAbsolutePath()); + + + // Loads the songs. + SongsHandler handler = new SongsHandler(); + List songs = handler.loadSongsFromDir(file.getPath()); + this.songObservableList.setAll(songs); } public StringProperty getPathToFolderProperty() { @@ -229,14 +237,7 @@ public void onSearchButtonClicked() { File file = directoryChooser.showDialog(this.buttonSearch.getScene().getWindow()); if (file != null) { - - // Sets the property for the textBox. - this.setPathToFolder(file.getPath()); - - // Loads the songs. - SongsHandler handler = new SongsHandler(); - List songs = handler.loadSongsFromDir(file.getPath()); - this.songObservableList.setAll(songs); + this.setPathToFolder(file); } } @@ -345,6 +346,11 @@ protected void initialize() throws IOException { this.initializeDiscoveryService(); this.musicStreamController = new TCPMusicStreamController(this.clientController); + + File file = this.guessSongsFolder(); + if(file != null) { + this.setPathToFolder(file); + } } private void initializeDiscoveryService() { @@ -455,7 +461,35 @@ private void initializeClientListView() { }); } + /** + * Guesses the song folder. May return the folder or may not. + * @return Returns the songs folder or null, if it was not found. + */ + private File guessSongsFolder() { + File file = null; + try { + String userFolder = System.getProperty("user.home"); + Path path = Paths.get(userFolder, "Music"); + file = path.toFile(); + + if(file != null) { + + if(file.exists()) { + this.logger.info("Music folder in " + file.getAbsolutePath() + " was not found."); + } else { + this.logger.info("Music Folder (in " + file.getAbsolutePath() + ") was found."); + } + } else { + throw new Exception("The path returned was null"); + } + + } + catch(Exception ex) { + this.logger.warn("Failed guessing the users song folder", ex); + } + return file; + } //endregion } From 0a26f288f483a52cc7678f95a22fc5b24c180af8 Mon Sep 17 00:00:00 2001 From: eluchsinger Date: Tue, 12 Apr 2016 23:03:12 +0200 Subject: [PATCH 03/24] Renamed a property for better readability and maintainability. --- .../java/viewmodels/MainWindowViewModel.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Server/src/main/java/viewmodels/MainWindowViewModel.java b/Server/src/main/java/viewmodels/MainWindowViewModel.java index 60f8b3b..48dd057 100644 --- a/Server/src/main/java/viewmodels/MainWindowViewModel.java +++ b/Server/src/main/java/viewmodels/MainWindowViewModel.java @@ -54,7 +54,7 @@ public class MainWindowViewModel { /** * Property containing the path to the song folder. */ - private StringProperty pathToFolder; + private StringProperty pathToSongFolder; /** * List containing the songs. @@ -153,12 +153,12 @@ public MainWindowViewModel() { //endregion Constructor //region Getters & Setters - public final String getPathToFolder() { - return this.pathToFolder.get(); + public final String getPathToSongFolder() { + return this.pathToSongFolder.get(); } - public final void setPathToFolder(File file) { - this.pathToFolder.set(file.getAbsolutePath()); + public final void setPathToSongFolder(File file) { + this.pathToSongFolder.set(file.getAbsolutePath()); // Loads the songs. @@ -168,7 +168,7 @@ public final void setPathToFolder(File file) { } public StringProperty getPathToFolderProperty() { - return this.pathToFolder; + return this.pathToSongFolder; } /** @@ -237,7 +237,7 @@ public void onSearchButtonClicked() { File file = directoryChooser.showDialog(this.buttonSearch.getScene().getWindow()); if (file != null) { - this.setPathToFolder(file); + this.setPathToSongFolder(file); } } @@ -349,7 +349,7 @@ protected void initialize() throws IOException { File file = this.guessSongsFolder(); if(file != null) { - this.setPathToFolder(file); + this.setPathToSongFolder(file); } } @@ -396,7 +396,7 @@ private void initializeTable() { */ private void initializeBindings(){ // Do binding for the music folder. - this.pathToFolder = new SimpleStringProperty(); + this.pathToSongFolder = new SimpleStringProperty(); this.textFieldFolder.textProperty().bindBidirectional(this.getPathToFolderProperty()); // Bind Slider to Volume property From f74f198a95a9dbf4a09e05f2c28544997ad3962d Mon Sep 17 00:00:00 2001 From: Esteban Luchsinger Date: Wed, 13 Apr 2016 19:36:56 +0200 Subject: [PATCH 04/24] Started adding NetworkAudioPlayer implementation. --- Client/build.gradle | 25 +-- Client/src/main/java/controllers/MainApp.java | 2 +- Client/src/main/resources/libs/jl1.0.1.jar | Bin 0 -> 105363 bytes Server/build.gradle | 1 + .../java/controllers/media/MediaPlayer.java | 53 ++++++ .../media/music/NetworkAudioPlayer.java | 170 ++++++++++++++++++ ...udioPlayer.java => SimpleAudioPlayer.java} | 12 +- .../java/viewmodels/MainWindowViewModel.java | 4 +- gradle/wrapper/gradle-wrapper.properties | 4 +- 9 files changed, 240 insertions(+), 31 deletions(-) create mode 100644 Client/src/main/resources/libs/jl1.0.1.jar create mode 100644 Server/src/main/java/controllers/media/music/NetworkAudioPlayer.java rename Server/src/main/java/controllers/media/music/{AudioPlayer.java => SimpleAudioPlayer.java} (96%) diff --git a/Client/build.gradle b/Client/build.gradle index 0605f42..dcadd08 100644 --- a/Client/build.gradle +++ b/Client/build.gradle @@ -1,37 +1,22 @@ plugins { - id 'maven-publish' id 'java' // or 'groovy' Must be explicitly applied id 'application' - id 'com.github.johnrengelman.shadow' version '1.2.3' } repositories { mavenCentral() -} - -mainClassName = "controllers.MainApp" -shadowJar { - baseName = 'wss-client-all' - classifier = '' -} - -publishing { - publications { - shadow(MavenPublication) { - from components.shadow - artifactId = 'wss-client-all' - } + flatDir { + dirs 'resources/libs' } } -task executeClient(type: JavaExec){ - main = "controllers.Main" - classpath = sourceSets.main.runtimeClasspath -} +mainClassName = "controllers.MainApp" +version = 0.2 dependencies { testCompile group: 'junit', name: 'junit', version: '4.11' + compile files('resources/libs/jl1.0.1.jar') compile group: 'org.slf4j', name: 'slf4j-api', version: '1.7.+' compile group: 'ch.qos.logback', name: 'logback-classic', version: '1.+' compile project (':shared') diff --git a/Client/src/main/java/controllers/MainApp.java b/Client/src/main/java/controllers/MainApp.java index 21bdf51..2098a6d 100644 --- a/Client/src/main/java/controllers/MainApp.java +++ b/Client/src/main/java/controllers/MainApp.java @@ -16,7 +16,7 @@ public void start(Stage primaryStage) throws Exception{ FXMLLoader loader = new FXMLLoader(getClass().getResource("/views/ClientWindow.fxml")); Parent root = loader.load(); - + // Add Stage object to the client window view model. Object o = loader.getController(); if(ClientWindowViewModel.class == o.getClass()){ diff --git a/Client/src/main/resources/libs/jl1.0.1.jar b/Client/src/main/resources/libs/jl1.0.1.jar new file mode 100644 index 0000000000000000000000000000000000000000..bd5fb8b8eb28746e4a3d7cfee2b54c4fd54f5043 GIT binary patch literal 105363 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

(H>r|Sz$es;n6q4t!9osGU^)b#AiEhi^s}TD` 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

W(94n+m(@89xah6`eR%%`DDLQJ z@Aw-tzAuT|%L0%GK<*i@V2Akr4eM@f3U;=%2Sy>6YsHYQLyEK|Z8bpL11_>F}YRuJ#JGFcwh-A`V6?P`n%x%Z*Y#rY~0twp7PN3*a12I3Y5yr*v}s+&yP&# zdYIT>-6EwD$Pr}w8(TVd>&T)3#c>M-GRIRQf23Zo`6c~Y#_&1s||(pA8~*3 zH#28kbvgk20OTI1CqGl3AHU3>p?~%^eue<^AV9+d*vvnvm*t&I?s~4cgA2&U($mzD zQe0WW#m@NmC5hTx`!yd>GqZpW@@ieWC;u<(>n+>%lU>h*s|M9D?t~>iW#je6v|d1&9s6 zb+vIi{ZG{2RHz)qO?*4R3K@VEt~O5drvIkwpNlI~wVO%^pzLJ;_|>`#acVut_owv?%mQkhV3n_!p>}v!%^%jDUDUniLKw{dqv?zkE9TBjx$I+g?xo?k(vb zEtZOlkrBwwH8o_YNTLDy^l$qz=Z2x#V>0@Kv1(~W13{se_|_;;VMUoS(v(ILJLu#g=v zA`|~57?pf!^x6apPaLUHYdO6%py{b3mX@NKXu4zX2E96*NNae?*%(gN%MRwX#Ln zM4bT8^gy|~I(Kt^_TTX4j(?fvHw_`Ffyo*HAYc->u1;u^>i?SnXH#3Sy(7rd@i&8Z zrykQ_MPN&K=aE` z53(!1MP0ofD-W^*ng4Fa7Khs^nF^qAfWm$ihqQJ*?vE2dT3f%31pvkN|7zs=`fqS9 z&cJX+)B2MXNPQ5^i+>#2XO42b+;s(P|+jc^Xw@A5RJJ6G%& z_U<>#KMc0+Gt#8C;6Ong0lm=GVNo|w%&v2`iie%Eg{hOJ6R@HI^l;ZZyW!OO-5ns~ zguq2|Maf=h=xebc7k1#F%FB}iA={f|vHPEI17j=B4#Qi~UngEcQXx+}`bB*q|8LYQJA)y?kVoqL0@o^D z3%>S%9Y`wV(Hg&~(5lx`Wqy0m1|%ACd-N}KlJye&wkP`%>WUo3JHgdkNgEM0iJ367xW3{UzcK*aUm1zg`JK*mS>V&ZsS%lsKFp(G0nOyi)SRDgfygiuhx J<3Ql2{{u2lHQE3G literal 0 HcmV?d00001 diff --git a/Server/build.gradle b/Server/build.gradle index 8760d89..f0c754b 100644 --- a/Server/build.gradle +++ b/Server/build.gradle @@ -8,6 +8,7 @@ repositories { } mainClassName = "controllers.Main" +version = 0.2 task executeServer(type: JavaExec){ main = "controllers.Main" diff --git a/Server/src/main/java/controllers/media/MediaPlayer.java b/Server/src/main/java/controllers/media/MediaPlayer.java index 507df61..ad2fc18 100644 --- a/Server/src/main/java/controllers/media/MediaPlayer.java +++ b/Server/src/main/java/controllers/media/MediaPlayer.java @@ -8,10 +8,27 @@ /** * Created by Esteban Luchsinger on 01.12.2015. + * A media player interface built to handle different types of media (music/video). */ public interface MediaPlayer { + + /** + * Plays a track and tries to resume it, if desired. + * @param track Track to play. + * @param tryResume Set this true, if the track should be resumed (only if possible). + */ void play(T track, boolean tryResume); + + /** + * Plays a track. + * @param track The track to play. + */ void play(T track); + + /** + * Pauses the currently played track. + * If there is no currently playing track, doesn't do anything. + */ void pause(); /** @@ -19,7 +36,16 @@ public interface MediaPlayer { * Can be used always, without checking the status. */ void stop(); + + /** + * @return Returns true if the player is currently playing. + */ boolean isPlaying(); + + /** + * Property to bind the isPlaying value. + * @return Returns the property to the corresponding isPlaying field. + */ BooleanProperty isPlayingProperty(); /** @@ -46,13 +72,40 @@ default void togglePlay(){ */ T getPreviousTrack(); + /** + * @return Returns the current track. + */ T getCurrentTrack(); + + /** + * @return Returns the property with the value of the current track. + */ SimpleObjectProperty currentTrackProperty(); + /** + * @return Returns the current media time ObjectProperty. This property shows the current progress of the currently playing track. + */ ObjectProperty currentMediaTime(); + + /** + * @return Returns the total duration of the currently playing media. + */ ObjectProperty totalMediaDuration(); + /** + * @return Returns the current volume value. + */ double getVolume(); + + /** + * Sets the current volume value. + * Bigger value = Louder! + * @param value New Value + */ void setVolume(double value); + + /** + * @return Returns the property containing the current volume. (Write and read possible!) + */ DoubleProperty volumeProperty(); } diff --git a/Server/src/main/java/controllers/media/music/NetworkAudioPlayer.java b/Server/src/main/java/controllers/media/music/NetworkAudioPlayer.java new file mode 100644 index 0000000..65c4c42 --- /dev/null +++ b/Server/src/main/java/controllers/media/music/NetworkAudioPlayer.java @@ -0,0 +1,170 @@ +package controllers.media.music; + +import controllers.clients.ClientController; +import controllers.media.MediaPlayer; +import javafx.beans.property.BooleanProperty; +import javafx.beans.property.DoubleProperty; +import javafx.beans.property.ObjectProperty; +import javafx.beans.property.SimpleObjectProperty; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import javafx.util.Duration; +import models.songs.Song; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Created by Esteban Luchsinger on 13.04.2016. + * The simple audio player enhanced for use in network. + */ +public class NetworkAudioPlayer implements MediaPlayer { + private final Logger logger; + + private final ClientController clientController; + + public NetworkAudioPlayer(ClientController clientController) { + this(FXCollections.observableArrayList(), clientController); + } + + public NetworkAudioPlayer(ObservableList songs, ClientController clientController) { + this.logger = LoggerFactory.getLogger(this.getClass()); + + this.clientController = clientController; + } + + /** + * Plays a track and tries to resume it, if desired. + * + * @param track Track to play. + * @param tryResume Set this true, if the track should be resumed (only if possible). + */ + @Override + public void play(Song track, boolean tryResume) { + + } + + /** + * Plays a track. + * + * @param track The track to play. + */ + @Override + public void play(Song track) { + + } + + /** + * Pauses the currently played track. + * If there is no currently playing track, doesn't do anything. + */ + @Override + public void pause() { + + } + + /** + * Stops and disposes the player, regardless of the current status. + * Can be used always, without checking the status. + */ + @Override + public void stop() { + + } + + /** + * @return Returns true if the player is currently playing. + */ + @Override + public boolean isPlaying() { + return false; + } + + /** + * Property to bind the isPlaying value. + * + * @return Returns the property to the corresponding isPlaying field. + */ + @Override + public BooleanProperty isPlayingProperty() { + return null; + } + + /** + * Tries to find the next track. + * + * @return Returns the next track on the playlist, or null if it wasn't found. + */ + @Override + public Song getNextTrack() { + return null; + } + + /** + * Tries to find the previous track. + * + * @return Returns the previous track on the playlist, or null if it wasn't found. + */ + @Override + public Song getPreviousTrack() { + return null; + } + + /** + * @return Returns the current track. + */ + @Override + public Song getCurrentTrack() { + return null; + } + + /** + * @return Returns the property with the value of the current track. + */ + @Override + public SimpleObjectProperty currentTrackProperty() { + return null; + } + + /** + * @return Returns the current media time ObjectProperty. This property shows the current progress of the currently playing track. + */ + @Override + public ObjectProperty currentMediaTime() { + return null; + } + + /** + * @return Returns the total duration of the currently playing media. + */ + @Override + public ObjectProperty totalMediaDuration() { + return null; + } + + /** + * @return Returns the current volume value. + */ + @Override + public double getVolume() { + return 0; + } + + /** + * Sets the current volume value. + * Bigger value = Louder! + * + * @param value New Value + */ + @Override + public void setVolume(double value) { + + } + + /** + * @return Returns the property containing the current volume. (Write and read possible!) + */ + @Override + public DoubleProperty volumeProperty() { + return null; + } +} diff --git a/Server/src/main/java/controllers/media/music/AudioPlayer.java b/Server/src/main/java/controllers/media/music/SimpleAudioPlayer.java similarity index 96% rename from Server/src/main/java/controllers/media/music/AudioPlayer.java rename to Server/src/main/java/controllers/media/music/SimpleAudioPlayer.java index 9d3b2cf..b9b21b7 100644 --- a/Server/src/main/java/controllers/media/music/AudioPlayer.java +++ b/Server/src/main/java/controllers/media/music/SimpleAudioPlayer.java @@ -14,9 +14,10 @@ import java.util.Optional; /** - * Created by eluch on 01.12.2015. + * Created by Esteban Luchsinger on 01.12.2015. + * This is a simple audio player designed to handle the music playing. */ -public class AudioPlayer implements controllers.media.MediaPlayer { +public class SimpleAudioPlayer implements controllers.media.MediaPlayer { private final Logger logger; /** @@ -33,12 +34,12 @@ public class AudioPlayer implements controllers.media.MediaPlayer { private ObservableList playlist; private Song lastPlayed; - public AudioPlayer() { + public SimpleAudioPlayer() { // Call parameterized constructor with a new list. this(FXCollections.observableArrayList()); } - public AudioPlayer(ObservableList songs) { + public SimpleAudioPlayer(ObservableList songs) { this.logger = LoggerFactory.getLogger(this.getClass()); this.playlist = songs; @@ -50,8 +51,7 @@ public AudioPlayer(ObservableList songs) { } /** - * Plays the selected trackc, if found. - * + * Plays the selected track if found and / or resumes it. * @param track The track that should be played. (Must not be the same reference as in the playlist). * @param tryResume Tries to resume the song, if it is paused. */ diff --git a/Server/src/main/java/viewmodels/MainWindowViewModel.java b/Server/src/main/java/viewmodels/MainWindowViewModel.java index 48dd057..96b0692 100644 --- a/Server/src/main/java/viewmodels/MainWindowViewModel.java +++ b/Server/src/main/java/viewmodels/MainWindowViewModel.java @@ -3,7 +3,7 @@ import controllers.clients.ClientController; import controllers.io.SongsHandler; import controllers.media.MediaPlayer; -import controllers.media.music.AudioPlayer; +import controllers.media.music.SimpleAudioPlayer; import controllers.networking.discovery.ServerDiscoveryService; import controllers.networking.streaming.music.MusicStreamController; import controllers.networking.streaming.music.tcp.TCPMusicStreamController; @@ -332,7 +332,7 @@ protected void initialize() throws IOException { this.songObservableList = FXCollections.observableArrayList(); // Init Media Player - this.mediaPlayer = new AudioPlayer(this.songObservableList); + this.mediaPlayer = new SimpleAudioPlayer(this.songObservableList); this.mediaPlayer.isPlayingProperty().addListener((observable, oldValue, newValue) -> this.onIsPlayingChanged()); this.tcpServer = new TCPSocketServer(); diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 67e20dd..a5fee37 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Thu Apr 07 20:45:15 CEST 2016 +#Wed Apr 13 10:02:42 CEST 2016 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.12-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-2.12-all.zip From 44b11c4cf79fa97e7f1d4892d4bb659879c6effd Mon Sep 17 00:00:00 2001 From: Esteban Luchsinger Date: Fri, 15 Apr 2016 10:43:13 +0200 Subject: [PATCH 05/24] Started JavaDoc for Shared module. --- .../src/main/java/models/clients/Server.java | 2 +- .../java/models/networking/SongCache.java | 4 +- .../java/models/networking/SongDatagram.java | 2 + .../networking/clients/NetworkClient.java | 4 +- .../networking/messages/StreamingMessage.java | 44 ++++++++++++++----- Shared/src/main/java/models/songs/Song.java | 4 +- .../src/main/java/utils/media/SongUtils.java | 2 + .../main/java/utils/networking/NetUtil.java | 3 +- 8 files changed, 47 insertions(+), 18 deletions(-) diff --git a/Shared/src/main/java/models/clients/Server.java b/Shared/src/main/java/models/clients/Server.java index 32682c2..3cad5d4 100644 --- a/Shared/src/main/java/models/clients/Server.java +++ b/Shared/src/main/java/models/clients/Server.java @@ -106,7 +106,7 @@ public int hashCode() { /** * Creates a string with representing the server Object. - * @return String: " (Port: )" + * @return String: "<HostAddress< (Port: <Port<)" */ @Override public String toString() { diff --git a/Shared/src/main/java/models/networking/SongCache.java b/Shared/src/main/java/models/networking/SongCache.java index 660a9f4..4d061d0 100644 --- a/Shared/src/main/java/models/networking/SongCache.java +++ b/Shared/src/main/java/models/networking/SongCache.java @@ -13,8 +13,10 @@ import java.util.stream.IntStream; /** + *

  * Created by Esteban Luchsinger on 18.12.2015.
  * The cache stores the Songs inside a TreeSet.
+ * 
*/ public class SongCache { private Set cache; @@ -72,7 +74,7 @@ public int getExpectedCacheSize() { * Gets the missing sequence numbers. * @return List of the missing sequence numbers. If there are no missing numbers, * returns an empty list. - * If there are no missing datagrams, returns an empty List. + * If there are no missing datagrams, returns an empty List<Integer>. */ public List getMissingSequenceNumbers() throws Exception /*throws CacheOverflowException */{ diff --git a/Shared/src/main/java/models/networking/SongDatagram.java b/Shared/src/main/java/models/networking/SongDatagram.java index cdbd362..9a562ca 100644 --- a/Shared/src/main/java/models/networking/SongDatagram.java +++ b/Shared/src/main/java/models/networking/SongDatagram.java @@ -10,10 +10,12 @@ import java.util.Objects; /** + *
  * Created by Esteban Luchsinger on 16.12.2015.
  * This datagram contains a part of the complete song.
  * It is only some bytes long and a song is usually composed by
  * hundreds or thousands of SongDatagrams.
+ * 
*/ public class SongDatagram implements Comparable{ diff --git a/Shared/src/main/java/models/networking/clients/NetworkClient.java b/Shared/src/main/java/models/networking/clients/NetworkClient.java index 7c7b2c3..c23c1f2 100644 --- a/Shared/src/main/java/models/networking/clients/NetworkClient.java +++ b/Shared/src/main/java/models/networking/clients/NetworkClient.java @@ -4,7 +4,6 @@ import models.networking.clients.callbacks.OnDisconnected; import java.io.Closeable; -import java.io.IOException; import java.net.Socket; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; @@ -28,7 +27,6 @@ public interface NetworkClient extends Closeable { /** * Sends an object to the connected socket. * @param object Object to send. Must implement the serializable interface. - * @throws IOException */ void send(Object object); @@ -59,7 +57,7 @@ public interface NetworkClient extends Closeable { String getName(); /** - * @return Sets the name of the Network Client. + * Sets the name of the Network Client. */ void setName(String name); diff --git a/Shared/src/main/java/models/networking/messages/StreamingMessage.java b/Shared/src/main/java/models/networking/messages/StreamingMessage.java index b67e42d..dcf7ed8 100644 --- a/Shared/src/main/java/models/networking/messages/StreamingMessage.java +++ b/Shared/src/main/java/models/networking/messages/StreamingMessage.java @@ -1,37 +1,61 @@ package models.networking.messages; -import java.util.*; -import java.util.regex.MatchResult; +import java.util.ArrayList; +import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; -import java.util.stream.Stream; /** + *
  * Created by Esteban Luchsinger on 18.12.2015.
  * This class contains static messages used for the streaming network protocols
  *
  * Change 04.03.2016 (ELU):
- * Changed the messages to be used in a continuous stream. (TCP is continious, UDP is Datagram-oriented).
+ * Changed the messages to be used in a continuous stream. (TCP is continuous, UDP is Datagram-oriented).
+ * 
*/ public final class StreamingMessage { // INITIALIZATION example: + /** + * The initial bracket for the stream initialization message. + */ public final static String STREAMING_INITIALIZATION_MESSAGE = ""; + + /** + * The length attribute for the initialization message. + */ public final static String STREAMING_INITIALIZATION_LENGTH_ATTRIBUTE = "length"; + + /** + * The acknowledge message for a streaming initialization message (The response from the client to the server). + */ public final static String STREAMING_INITIALIZATION_ACKNOWLEDGED_MESSAGE = "stream"; // QUALITY + /** + * This message is sent when there are packages missing. + * This is the starting bracket. + */ public final static String MISSING_PACKETS_MESSAGE = ""; + + /** + * This message is sent when there are packages missing. + * This is the closing bracket of the MISSING_PACKETS MESSAGE. + */ public final static String MISSING_PACKETS_CLOSE = ""; // FINALIZATION + /** + * The stream finalization message is sent when the stream is finished. + */ public final static String STREAMING_FINALIZATION_MESSAGE = ""; //region Initialization /** * The Streaming Initialization Message is sent before the server starts streaming a song. * It contains the amount of packets for UDP and bytes for TCP that are going to be sent. - * Example: + * Example: {@code } * @param amountOfPackets Amount of packets that are going to be sent in the stream. * @return Returns the correct message corresponding with the parameters. */ @@ -43,7 +67,7 @@ public static String initializationMessage(int amountOfPackets) { /** * The message sent when the streaming finished. - * Example: + * Example: {@code } * @return */ public static String streamingEndedMessage() { @@ -88,10 +112,10 @@ public static String setAttribute(String tag, String attribute, String value) { /** * Returns a string list with all attributes (with values) in the tag. * Example: - * Input: - * Output: ["length=100", "size=300"] - * @param tag - * @return + * Input: {@code } + * Output: {@code {"length=100", "size=300"}} + * @param tag The tag you want to check. (Complete tag with brackets) + * @return Returns a list of strings with the attributes and corresponding values in the tag. */ public static List getAttributes(String tag){ Pattern pattern = Pattern.compile("(?[a-zA-Z]*=(?[0-9]*))"); diff --git a/Shared/src/main/java/models/songs/Song.java b/Shared/src/main/java/models/songs/Song.java index 38a8453..77a5cf4 100644 --- a/Shared/src/main/java/models/songs/Song.java +++ b/Shared/src/main/java/models/songs/Song.java @@ -1,7 +1,7 @@ package models.songs; /** - * Created by eluch on 30.11.2015. + * Created by Esteban Luchsinger on 30.11.2015. */ public interface Song extends Comparable { /** @@ -18,7 +18,7 @@ public interface Song extends Comparable { /** * Returns the file extension without the dot. - * @return i.e. MP3 --> "mp3" + * @return i.e. MP3 --> "mp3" */ String getExtension(); diff --git a/Shared/src/main/java/utils/media/SongUtils.java b/Shared/src/main/java/utils/media/SongUtils.java index 08ca7ab..e670d8c 100644 --- a/Shared/src/main/java/utils/media/SongUtils.java +++ b/Shared/src/main/java/utils/media/SongUtils.java @@ -23,4 +23,6 @@ public static byte[] getSongData(Song song) throws IOException { File songFile = new File(song.getPath()); return Files.readAllBytes(songFile.toPath()); } + + } diff --git a/Shared/src/main/java/utils/networking/NetUtil.java b/Shared/src/main/java/utils/networking/NetUtil.java index 84d4a7c..f9fcfaa 100644 --- a/Shared/src/main/java/utils/networking/NetUtil.java +++ b/Shared/src/main/java/utils/networking/NetUtil.java @@ -9,8 +9,10 @@ import java.util.Enumeration; /** + *
  * Created by Esteban Luchsinger on 03.12.2015.
  * Provides some basic functionality.
+ * 
*/ public class NetUtil { private static InetAddress broadcastAddress; @@ -78,7 +80,6 @@ public static InetAddress getLocalAddress4(){ * * Threadsafe. * @return - * @throws SocketException */ public static InetAddress getBroadcastAddress4() { return broadcastAddress; From f95f1f33783328e0ea3a3b66a74a9654dac4ee39 Mon Sep 17 00:00:00 2001 From: Esteban Luchsinger Date: Fri, 15 Apr 2016 11:00:54 +0200 Subject: [PATCH 06/24] Added NetworkAudioPlayer (implementation status: Unfinished). Added JavaDoc for Server module. --- Server/src/main/java/controllers/Main.java | 4 + .../controllers/clients/ClientController.java | 3 +- .../java/controllers/io/SongsHandler.java | 2 + .../java/controllers/media/MediaPlayer.java | 2 + .../media/music/BaseAudioPlayer.java | 86 +++++++++++++++++++ .../media/music/NetworkAudioPlayer.java | 83 ++++++++++++++++-- .../media/music/SimpleAudioPlayer.java | 2 + .../controllers/networking/NetworkStream.java | 2 + .../discovery/ServerDiscoveryService.java | 2 + .../music/MusicStreamController.java | 2 + 10 files changed, 178 insertions(+), 10 deletions(-) create mode 100644 Server/src/main/java/controllers/media/music/BaseAudioPlayer.java diff --git a/Server/src/main/java/controllers/Main.java b/Server/src/main/java/controllers/Main.java index f2b0e29..ed6f212 100644 --- a/Server/src/main/java/controllers/Main.java +++ b/Server/src/main/java/controllers/Main.java @@ -8,6 +8,10 @@ import javafx.stage.Stage; import viewmodels.MainWindowViewModel; +/** + * Main Class. + * This class starts the JavaFX application. + */ public class Main extends Application { @Override diff --git a/Server/src/main/java/controllers/clients/ClientController.java b/Server/src/main/java/controllers/clients/ClientController.java index 162a7bf..9d5fb52 100644 --- a/Server/src/main/java/controllers/clients/ClientController.java +++ b/Server/src/main/java/controllers/clients/ClientController.java @@ -11,10 +11,11 @@ import java.io.Closeable; import java.io.IOException; - /** + *
  * Created by Esteban Luchsinger on 26.03.2016.
  * This controller handles the clients connected to the server.
+ * 
*/ public class ClientController implements Closeable{ private final Logger logger; diff --git a/Server/src/main/java/controllers/io/SongsHandler.java b/Server/src/main/java/controllers/io/SongsHandler.java index 32c716f..48c26ff 100644 --- a/Server/src/main/java/controllers/io/SongsHandler.java +++ b/Server/src/main/java/controllers/io/SongsHandler.java @@ -10,8 +10,10 @@ import java.util.List; /** + *
  * Created by Esteban on 30.11.2015.
  * Handles songs (ie: Reading songs from files)
+ * 
*/ public class SongsHandler { diff --git a/Server/src/main/java/controllers/media/MediaPlayer.java b/Server/src/main/java/controllers/media/MediaPlayer.java index ad2fc18..f12ecaf 100644 --- a/Server/src/main/java/controllers/media/MediaPlayer.java +++ b/Server/src/main/java/controllers/media/MediaPlayer.java @@ -7,8 +7,10 @@ import javafx.util.Duration; /** + *
  * Created by Esteban Luchsinger on 01.12.2015.
  * A media player interface built to handle different types of media (music/video).
+ * 
*/ public interface MediaPlayer { diff --git a/Server/src/main/java/controllers/media/music/BaseAudioPlayer.java b/Server/src/main/java/controllers/media/music/BaseAudioPlayer.java new file mode 100644 index 0000000..a1e0e97 --- /dev/null +++ b/Server/src/main/java/controllers/media/music/BaseAudioPlayer.java @@ -0,0 +1,86 @@ +package controllers.media.music; + +import javafx.beans.property.*; +import javafx.scene.media.MediaPlayer; +import javafx.util.Duration; +import models.songs.Song; + +/** + * Created by Esteban Luchsinger on 14.04.2016. + * This is a base class for an audio player. It provides the needed properties. + */ +public abstract class BaseAudioPlayer implements controllers.media.MediaPlayer { + + private BooleanProperty isPlaying; + private ObjectProperty currentMediaTime; + private StringProperty currentMediaTimeString; + private ObjectProperty totalMediaDuration; + private DoubleProperty volume; + + private MediaPlayer mediaPlayer; + + public BaseAudioPlayer() { + + // Init properties + this.isPlaying = new SimpleBooleanProperty(); + this.currentMediaTime = new SimpleObjectProperty<>(); + this.currentMediaTimeString = new SimpleStringProperty(); + this.totalMediaDuration = new SimpleObjectProperty<>(); + this.volume = new SimpleDoubleProperty(); + } + + public boolean getIsPlaying() { + return isPlaying.get(); + } + + @Override + public BooleanProperty isPlayingProperty() { + return isPlaying; + } + + protected void setIsPlaying(boolean isPlaying) { + this.isPlaying.set(isPlaying); + } + + public Duration getCurrentMediaTime() { + return currentMediaTime.get(); + } + + public ObjectProperty currentMediaTimeProperty() { + return currentMediaTime; + } + + public String getCurrentMediaTimeString() { + return currentMediaTimeString.get(); + } + + public StringProperty currentMediaTimeStringProperty() { + return currentMediaTimeString; + } + + public Duration getTotalMediaDuration() { + return totalMediaDuration.get(); + } + + public ObjectProperty totalMediaDurationProperty() { + return totalMediaDuration; + } + + public void setTotalMediaDuration(Duration totalMediaDuration) { + this.totalMediaDuration.set(totalMediaDuration); + } + + @Override + public double getVolume() { + return volume.get(); + } + + @Override + public DoubleProperty volumeProperty() { + return volume; + } + + public void setVolume(double volume) { + this.volume.set(volume); + } +} diff --git a/Server/src/main/java/controllers/media/music/NetworkAudioPlayer.java b/Server/src/main/java/controllers/media/music/NetworkAudioPlayer.java index 65c4c42..b6e0e02 100644 --- a/Server/src/main/java/controllers/media/music/NetworkAudioPlayer.java +++ b/Server/src/main/java/controllers/media/music/NetworkAudioPlayer.java @@ -1,37 +1,96 @@ package controllers.media.music; -import controllers.clients.ClientController; -import controllers.media.MediaPlayer; +import controllers.networking.streaming.music.MusicStreamController; import javafx.beans.property.BooleanProperty; import javafx.beans.property.DoubleProperty; import javafx.beans.property.ObjectProperty; import javafx.beans.property.SimpleObjectProperty; import javafx.collections.FXCollections; import javafx.collections.ObservableList; +import javafx.scene.media.Media; +import javafx.scene.media.MediaPlayer; import javafx.util.Duration; import models.songs.Song; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.io.File; + /** * Created by Esteban Luchsinger on 13.04.2016. * The simple audio player enhanced for use in network. + * The network clients are controlled by the required music stream controller. */ -public class NetworkAudioPlayer implements MediaPlayer { +public class NetworkAudioPlayer implements controllers.media.MediaPlayer { + //region Members private final Logger logger; - private final ClientController clientController; + private final MusicStreamController musicStreamController; + private MediaPlayer mediaPlayer; + + //endregion Members - public NetworkAudioPlayer(ClientController clientController) { - this(FXCollections.observableArrayList(), clientController); + //region Constructors + + public NetworkAudioPlayer(MusicStreamController musicStreamController) { + this(FXCollections.observableArrayList(), musicStreamController); } - public NetworkAudioPlayer(ObservableList songs, ClientController clientController) { + public NetworkAudioPlayer(ObservableList songs, MusicStreamController musicStreamController) { this.logger = LoggerFactory.getLogger(this.getClass()); - this.clientController = clientController; + this.musicStreamController = musicStreamController; } + //endregion Constructors + + //region Getters & Setters + + /** + * Initializes the media player for the song in the parameters. + * If the current MediaPlayer already uses the song in the parameters, it wont be reinitialized. + * If the current MediaPlayer is playing, it will be stopped and disposed. + * @param song Song for the MediaPlayer + * @return the MediaPlayer for the desired song. + */ + private MediaPlayer getMediaPlayer(Song song) { + if(this.mediaPlayer == null) { + this.mediaPlayer = new MediaPlayer(this.createMediaFromSong(song)); + } + + return this.mediaPlayer; + } + + /** + * Retrieves the current MediaPlayer with whatever song it may have initialized (null possible). + * @return Current MediaPlayer (null possible). + */ + private MediaPlayer getCurrentMediaPlayer() { + return this.mediaPlayer; + } + + //endregion Getters & Setters + + //region Private methods + + /** + * Creates a JavaFX Media Object from a Song object. + * This method is not in the shared code module, because it uses JavaFX. + * @param song The song object containing the path. + * @return Returns a Media object with the Song. + */ + private Media createMediaFromSong(Song song) { + + // Have to create a temporary file to convert the path to a URI. + File tempFile = new File(song.getPath()); + + Media media = new Media(tempFile.toURI().toString()); + return media; + } + + //endregion Private methods + + //region MediaPlayer Interface /** * Plays a track and tries to resume it, if desired. * @@ -50,7 +109,6 @@ public void play(Song track, boolean tryResume) { */ @Override public void play(Song track) { - } /** @@ -69,6 +127,11 @@ public void pause() { @Override public void stop() { + // Check, if the MediaPlayer needs to get disposed first. + if (this.mediaPlayer != null) { + this.mediaPlayer.dispose(); + this.mediaPlayer = null; + } } /** @@ -167,4 +230,6 @@ public void setVolume(double value) { public DoubleProperty volumeProperty() { return null; } + + //endregion MediaPlayer Interface } diff --git a/Server/src/main/java/controllers/media/music/SimpleAudioPlayer.java b/Server/src/main/java/controllers/media/music/SimpleAudioPlayer.java index b9b21b7..ac6d7bb 100644 --- a/Server/src/main/java/controllers/media/music/SimpleAudioPlayer.java +++ b/Server/src/main/java/controllers/media/music/SimpleAudioPlayer.java @@ -14,8 +14,10 @@ import java.util.Optional; /** + *
  * Created by Esteban Luchsinger on 01.12.2015.
  * This is a simple audio player designed to handle the music playing.
+ * 
*/ public class SimpleAudioPlayer implements controllers.media.MediaPlayer { diff --git a/Server/src/main/java/controllers/networking/NetworkStream.java b/Server/src/main/java/controllers/networking/NetworkStream.java index f11f466..5c9b5fc 100644 --- a/Server/src/main/java/controllers/networking/NetworkStream.java +++ b/Server/src/main/java/controllers/networking/NetworkStream.java @@ -1,7 +1,9 @@ package controllers.networking; /** + *
  * Created by Esteban Luchsinger on 03.12.2015.
+ * 
*/ public interface NetworkStream { void startStream(T data); diff --git a/Server/src/main/java/controllers/networking/discovery/ServerDiscoveryService.java b/Server/src/main/java/controllers/networking/discovery/ServerDiscoveryService.java index ae3a2c5..7fb9d4c 100644 --- a/Server/src/main/java/controllers/networking/discovery/ServerDiscoveryService.java +++ b/Server/src/main/java/controllers/networking/discovery/ServerDiscoveryService.java @@ -14,9 +14,11 @@ import java.util.concurrent.TimeUnit; /** + *
  * Created by Esteban Luchsinger on 04.12.2015.
  * Discovery Service Handler.
  * Sends out beacons in an interval.
+ * 
*/ public class ServerDiscoveryService implements Closeable { diff --git a/Server/src/main/java/controllers/networking/streaming/music/MusicStreamController.java b/Server/src/main/java/controllers/networking/streaming/music/MusicStreamController.java index da7a070..3733334 100644 --- a/Server/src/main/java/controllers/networking/streaming/music/MusicStreamController.java +++ b/Server/src/main/java/controllers/networking/streaming/music/MusicStreamController.java @@ -5,8 +5,10 @@ import java.io.IOException; /** + *
  * Created by Esteban Luchsinger on 16.12.2015.
  * This interface controls the song streaming.
+ * 
*/ public interface MusicStreamController { From 4851500b6ff5fad72e09bc8c6f6d17c502143a24 Mon Sep 17 00:00:00 2001 From: Esteban Luchsinger Date: Fri, 15 Apr 2016 11:20:43 +0200 Subject: [PATCH 07/24] Testing new .gitIgnore settings to make more IntelliJ Settings project-wide. --- .gitignore | 11 ++++++++++- .idea/.name | 1 + .idea/copyright/profiles_settings.xml | 3 +++ .idea/encodings.xml | 6 ++++++ .idea/file.template.settings.xml | 8 ++++++++ .idea/fileTemplates/includes/File Header.java | 5 +++++ .idea/inspectionProfiles/Project_Default.xml | 19 +++++++++++++++++++ .../inspectionProfiles/profiles_settings.xml | 7 +++++++ 8 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 .idea/.name create mode 100644 .idea/copyright/profiles_settings.xml create mode 100644 .idea/encodings.xml create mode 100644 .idea/file.template.settings.xml create mode 100644 .idea/fileTemplates/includes/File Header.java create mode 100644 .idea/inspectionProfiles/Project_Default.xml create mode 100644 .idea/inspectionProfiles/profiles_settings.xml diff --git a/.gitignore b/.gitignore index dbf2f68..288e3f8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,15 @@ #Idea Projects **/.idea/workspace.xml **/.idea/tasks.xml -**/.idea +**/.idea/modules +**/.idea/libraries +**/.idea/compiler.xml +**/.idea/gradle.xml +**/.idea/misc.xml +**/.idea/modules.xml +**/.idea/vcs.xml +**/.idea/uiDesigner.xml + #WirelessSoundSystem.iml # Windows image file caches @@ -11,6 +19,7 @@ ehthumbs.db # Folder config file Desktop.ini + # Recycle Bin used on file shares $RECYCLE.BIN/ diff --git a/.idea/.name b/.idea/.name new file mode 100644 index 0000000..c73e2ed --- /dev/null +++ b/.idea/.name @@ -0,0 +1 @@ +WirelessSoundSystem \ No newline at end of file diff --git a/.idea/copyright/profiles_settings.xml b/.idea/copyright/profiles_settings.xml new file mode 100644 index 0000000..e7bedf3 --- /dev/null +++ b/.idea/copyright/profiles_settings.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 0000000..97626ba --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/file.template.settings.xml b/.idea/file.template.settings.xml new file mode 100644 index 0000000..d8cf7e7 --- /dev/null +++ b/.idea/file.template.settings.xml @@ -0,0 +1,8 @@ + + + + +