Skip to content

Commit 9f4d37b

Browse files
committed
Implement audio playback.
1 parent f77de2a commit 9f4d37b

File tree

30 files changed

+982
-282
lines changed

30 files changed

+982
-282
lines changed

org.monte.demo.aviwriter/src/main/java/org.monte.demo.aviwriter/org/monte/demo/aviwriter/Main.java

+16-16
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
import java.awt.Graphics2D;
1919
import java.awt.RenderingHints;
2020
import java.awt.Stroke;
21-
import java.awt.geom.Line2D;
21+
import java.awt.geom.AffineTransform;
2222
import java.awt.image.BufferedImage;
2323
import java.awt.image.IndexColorModel;
2424
import java.io.File;
@@ -84,18 +84,16 @@ private static void drawAnimationFrame(BufferedImage img, Graphics2D g, double s
8484
g.drawString("Frame " + (frameIndex + 1) + " of " + frameCount, 473, 24);
8585
}
8686

87-
private static void drawClock(Graphics2D g, int cx, int cy, int radius, double seconds) {
87+
private static void drawClock(Graphics2D g, int cx, int cy, int radius, double timeInSeconds) {
8888
g.setPaint(Color.WHITE);
8989
g.fillOval(cx - radius, cy - radius, radius * 2, radius * 2);
9090

91-
92-
double minutes = seconds / 60.0;
93-
double hours = minutes / 60.0;
94-
drawClockHand(g, cx, cy, -10, radius / 2, new BasicStroke(20, BasicStroke.CAP_ROUND, BasicStroke.JOIN_BEVEL), Color.BLACK, (hours) * (Math.PI * 2.0 / 12.0));
95-
drawClockHand(g, cx, cy, -10, radius - 20, new BasicStroke(20, BasicStroke.CAP_ROUND, BasicStroke.JOIN_BEVEL), new Color(0x1a1a1a), (minutes) * (Math.PI * 2.0 / 60.0));
96-
drawClockHand(g, cx, cy, -64, radius - 1, new BasicStroke(6, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL), Color.RED, (seconds) * (Math.PI * 2.0 / +60.0));
97-
drawClockHand(g, cx, cy, -64, radius - 1, new BasicStroke(20, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_BEVEL, 4f, new float[]{20f, radius * 2}, 0f), Color.RED, (seconds) * (Math.PI * 2.0 / +60.0));
98-
91+
double timeInMinutes = timeInSeconds / 60.0;
92+
double timeInHours = timeInMinutes / 60.0;
93+
drawClockHand(g, cx, cy, -10, radius / 2, new BasicStroke(20, BasicStroke.CAP_ROUND, BasicStroke.JOIN_BEVEL), Color.BLACK, (timeInHours) * (Math.PI * 2.0 / 12.0));
94+
drawClockHand(g, cx, cy, -10, radius - 20, new BasicStroke(20, BasicStroke.CAP_ROUND, BasicStroke.JOIN_BEVEL), new Color(0x1a1a1a), (timeInMinutes) * (Math.PI * 2.0 / 60.0));
95+
drawClockHand(g, cx, cy, -64, radius - 1, new BasicStroke(6, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL), Color.RED, (timeInSeconds) * (Math.PI * 2.0 / +60.0));
96+
drawClockHand(g, cx, cy, -64, -24, new BasicStroke(20, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL), Color.RED, (timeInSeconds) * (Math.PI * 2.0 / +60.0));
9997
// Draw plug
10098
int plugRadius = 12;
10199
g.setPaint(Color.WHITE);
@@ -105,13 +103,15 @@ private static void drawClock(Graphics2D g, int cx, int cy, int radius, double s
105103
g.drawOval(cx - plugRadius, cy - plugRadius, plugRadius * 2, plugRadius * 2);
106104
}
107105

108-
private static void drawClockHand(Graphics2D g, int cx, int cy, int radius1, int radius2, Stroke stroke, Color color, double angle) {
109-
angle = angle % (Math.PI * 2);
110-
double sin = Math.sin(angle);
111-
double cos = Math.cos(angle);
112-
g.setPaint(color);
106+
private static void drawClockHand(Graphics2D g, int cx, int cy, int radius1, int radius2, Stroke stroke, Color color, double theta) {
107+
AffineTransform tx = new AffineTransform();
108+
tx.setToRotation(theta % (Math.PI * 2), cx, cy);
109+
g.setTransform(tx);
110+
g.setColor(color);
113111
g.setStroke(stroke);
114-
g.draw(new Line2D.Double(cx + radius1 * sin, cy - radius1 * cos, cx + radius2 * sin, cy - radius2 * cos));
112+
g.drawLine(cx, cy - radius1, cx, cy - radius2);
113+
tx.setToIdentity();
114+
g.setTransform(tx);
115115
}
116116

117117
/**

org.monte.demo.javafx.movieplayer/src/main/java/org.monte.demo.javafx.movieplayer/org/monte/demo/javafx/movieplayer/Main.java

+7-3
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,13 @@ public void start(Stage stage) throws Exception {
2727
MainWindowController controller = loader.getController();
2828

2929

30-
stage.titleProperty().bind(controller.fileProperty().map(f ->
31-
labels.getString("application.name") + (f == null ? "" : ": " + f.getName())
32-
));
30+
controller.fileProperty().addListener((o, oldv, f) ->
31+
stage.setTitle((f == null ? labels.getString("file.noFile") : f.getName()))
32+
);
33+
stage.setOnHidden(event -> controller.close(null));
34+
35+
36+
stage.setTitle(labels.getString("file.noFile"));
3337
Scene scene = new Scene(root);
3438
scene.getStylesheets().add(getClass().getResource("controls.css").toString());
3539
stage.setScene(scene);

org.monte.demo.javafx.movieplayer/src/main/java/org.monte.demo.javafx.movieplayer/org/monte/demo/javafx/movieplayer/MainWindowController.java

+77-16
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import javafx.scene.control.Alert;
1717
import javafx.scene.control.ButtonType;
1818
import javafx.scene.control.Label;
19+
import javafx.scene.layout.AnchorPane;
1920
import javafx.scene.layout.BorderPane;
2021
import javafx.scene.layout.HBox;
2122
import javafx.scene.layout.StackPane;
@@ -49,12 +50,10 @@ enum Mode {
4950
@FXML // URL location of the FXML file that was given to the FXMLLoader
5051
private URL location;
5152

52-
@FXML
53-
private StackPane stackPane; // Value injected by FXMLLoader
54-
55-
5653
@FXML // fx:id="rootPane"
5754
private BorderPane rootPane; // Value injected by FXMLLoader
55+
@FXML // fx:id="rootPane"
56+
private StackPane stackPane; // Value injected by FXMLLoader
5857
private FileChooser fileChooser;
5958

6059
@FXML
@@ -71,6 +70,12 @@ void about(ActionEvent event) {
7170

7271
@FXML
7372
void close(ActionEvent event) {
73+
MediaPlayerInterface p = player.get();
74+
if (p != null) {
75+
p.dispose();
76+
player.set(null);
77+
stackPane.getChildren().clear();
78+
}
7479
getStage().close();
7580
}
7681

@@ -87,6 +92,51 @@ private Stage getStage() {
8792
return scene == null ? null : (Stage) scene.getWindow();
8893
}
8994

95+
@FXML
96+
void zoomIn(ActionEvent event) {
97+
zoomTo((Math.round(getZoomPower() + 1)));
98+
}
99+
100+
@FXML
101+
void zoomOut(ActionEvent event) {
102+
zoomTo((Math.round(getZoomPower() - 1)));
103+
}
104+
105+
@FXML
106+
void zoomToActualSize(ActionEvent event) {
107+
zoomTo(0);
108+
}
109+
110+
void zoomTo(double power) {
111+
MediaInterface media = getPlayer() instanceof MediaPlayerInterface p ? p.getMedia() : null;
112+
if (media == null) {
113+
return;
114+
}
115+
double factor = Math.pow(2, power);
116+
stackPane.setPrefWidth(media.getWidth() * factor);
117+
stackPane.setPrefHeight(media.getHeight() * factor);
118+
getStage().sizeToScene();
119+
}
120+
121+
private MediaPlayerInterface getPlayer() {
122+
return player.get();
123+
}
124+
125+
private double getZoomPower() {
126+
MediaInterface media = getPlayer() instanceof MediaPlayerInterface p ? p.getMedia() : null;
127+
if (media == null) {
128+
return 1;
129+
}
130+
double factor = stackPane.getWidth() / media.getWidth();
131+
double power = Math.log(factor) / Math.log(2);
132+
return power;
133+
}
134+
135+
@FXML
136+
void zoomToFit(ActionEvent event) {
137+
zoomTo(getZoomPower());
138+
}
139+
90140
@FXML
91141
// This method is called by the FXMLLoader when initialization is complete
92142
void initialize() {
@@ -148,21 +198,23 @@ private void createMoviePlayer(int retries) {
148198
};
149199

150200
if (player == null || player.getError() != null) {
151-
retryCreateMoviePlayer(retries);
201+
retryCreateMoviePlayer(retries, player == null ? null : player.getError());
152202
} else {
153-
player.setOnError(() -> retryCreateMoviePlayer(retries));
203+
this.player.set(player);
204+
player.setOnError(() -> retryCreateMoviePlayer(retries, player.getError()));
154205
}
155206
}
156207

157-
private void retryCreateMoviePlayer(int retries) {
208+
private void retryCreateMoviePlayer(int retries, Throwable error) {
158209
Mode[] values = Mode.values();
159210
if (retries < values.length) {
160211
mode.set(values[(mode.get().ordinal() + 1) % values.length]);
161212
createMoviePlayer(retries + 1);
162213
} else {
163214
ObservableList<Node> c = stackPane.getChildren();
164215
c.clear();
165-
c.add(new Label(resources.getString("error.creatingPlayer")));
216+
c.add(new Label(resources.getString("error.creatingPlayer") + "\n" + error));
217+
error.printStackTrace();
166218
}
167219
}
168220

@@ -174,9 +226,9 @@ private MediaPlayerInterface createMonteMediaPlayer() {
174226
}
175227
MonteMedia movie = new MonteMedia(mediaFile);
176228
MonteMediaPlayer player = new MonteMediaPlayer(movie);
177-
MonteMediaView monteMediaView = MonteMediaView.newVideoView();
229+
MonteMediaView monteMediaView = MonteMediaView.newMonteMediaView();
178230
monteMediaView.setMedia(movie);
179-
ControlsController playerController = createPlayerController();
231+
PlayerControlsController playerController = createPlayerController();
180232
playerController.setPlayer(player);
181233
showPlayer(monteMediaView.getRoot(), player, movie, playerController);
182234
return player;
@@ -201,15 +253,22 @@ private MediaPlayerInterface createFXMoviePlayer() {
201253
mediaPlayer.dispose();
202254
return null;
203255
}
204-
ControlsController playerController = createPlayerController();
256+
PlayerControlsController playerController = createPlayerController();
205257
FXMediaPlayer p = new FXMediaPlayer(mediaPlayer);
206258
player.set(p);
207259
playerController.setPlayer(p);
208260
mediaPlayer.setAutoPlay(true);
209261
mediaView = new MediaView(mediaPlayer);
210262

263+
264+
mediaView.fitWidthProperty().bind(stackPane.widthProperty());
265+
mediaView.fitHeightProperty().bind(stackPane.heightProperty());
266+
mediaView.setManaged(false);
267+
268+
mediaView.setPreserveRatio(false);
269+
270+
211271
showPlayer(mediaView, p, new FXMedia(media), playerController);
212-
//mediaView.setOnError(t -> leftStatusLabel.setText(resources.getString("error") + t.toString()));
213272

214273
return p;
215274
} catch (Exception mediaException) {
@@ -218,19 +277,21 @@ private MediaPlayerInterface createFXMoviePlayer() {
218277
return null;
219278
}
220279

221-
222-
private void showPlayer(Node mediaView, MediaPlayerInterface mediaPlayer, MediaInterface media, ControlsController playerController) {
280+
private void showPlayer(Node mediaView, MediaPlayerInterface mediaPlayer, MediaInterface media, PlayerControlsController playerController) {
223281
mediaPlayer.setOnReady(() -> {
282+
stackPane.setPrefWidth(media.getWidth());
283+
stackPane.setPrefHeight(media.getHeight());
224284
sizeStageToScene();
225285
});
226286

227287
stackPane.getChildren().addAll(mediaView, playerController.getRoot());
228288
}
229289

230-
private ControlsController createPlayerController() {
290+
private PlayerControlsController createPlayerController() {
231291
try {
232-
FXMLLoader loader = new FXMLLoader(getClass().getResource("Controls.fxml"));
292+
FXMLLoader loader = new FXMLLoader(getClass().getResource("PlayerControls.fxml"));
233293
ResourceBundle labels = ResourceBundle.getBundle("org.monte.demo.javafx.movieplayer.Labels");
294+
loader.setRoot(new AnchorPane());
234295
loader.setResources(labels);
235296
loader.load();
236297
return loader.getController();

0 commit comments

Comments
 (0)