/*
* Copyright © 2023 Dean Lee
*/
package alarm;
import java.lang.Error;
import javax.swing.Timer;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.util.Calendar;
import java.net.URL;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.Clip;
/**
*
* @author dean
*/
public class Alarm extends javax.swing.JFrame implements ActionListener {
private Audio audio = new Audio();
private boolean audioPlaying = false;
private boolean alarmEnabled = true;
private Calendar previousTime = captureTime();
private Calendar currentTime;
private Calendar alarmTime = Calendar.getInstance();
/**
* Creates new form Alarm
*/
public Alarm() {
initComponents();
initAlarm();
initTimer();
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// //GEN-BEGIN:initComponents
private void initComponents() {
timeDisplay = new javax.swing.JLabel();
message = new javax.swing.JLabel();
alarmDisplay = new javax.swing.JLabel();
dateDisplay = new javax.swing.JLabel();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
setTitle("Alarm");
addKeyListener(new java.awt.event.KeyAdapter() {
public void keyPressed(java.awt.event.KeyEvent evt) {
formKeyPressed(evt);
}
});
timeDisplay.setFont(new java.awt.Font("Dialog", 1, 48)); // NOI18N
timeDisplay.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
timeDisplay.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
message.setFont(new java.awt.Font("Dialog", 1, 18)); // NOI18N
message.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
message.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
alarmDisplay.setFont(new java.awt.Font("Dialog", 1, 36)); // NOI18N
alarmDisplay.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
alarmDisplay.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
dateDisplay.setFont(new java.awt.Font("Dialog", 1, 36)); // NOI18N
dateDisplay.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
dateDisplay.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(183, 183, 183)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(alarmDisplay, javax.swing.GroupLayout.PREFERRED_SIZE, 225, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(dateDisplay, javax.swing.GroupLayout.PREFERRED_SIZE, 225, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(timeDisplay, javax.swing.GroupLayout.PREFERRED_SIZE, 225, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addGroup(layout.createSequentialGroup()
.addGap(61, 61, 61)
.addComponent(message, javax.swing.GroupLayout.PREFERRED_SIZE, 463, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addContainerGap(76, Short.MAX_VALUE))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(message, javax.swing.GroupLayout.PREFERRED_SIZE, 46, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(70, 70, 70)
.addComponent(timeDisplay, javax.swing.GroupLayout.PREFERRED_SIZE, 82, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(dateDisplay, javax.swing.GroupLayout.PREFERRED_SIZE, 42, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 46, Short.MAX_VALUE)
.addComponent(alarmDisplay, javax.swing.GroupLayout.PREFERRED_SIZE, 46, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap())
);
pack();
}// //GEN-END:initComponents
private void formKeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_formKeyPressed
if (audioPlaying)
alarmOff();
else
handleSpecificKey(evt);
}//GEN-LAST:event_formKeyPressed
private void handleSpecificKey(java.awt.event.KeyEvent evt) {
switch(evt.getKeyCode()) {
case KeyEvent.VK_PERIOD:
alarmTime.roll(Calendar.HOUR_OF_DAY, 1);
break;
case KeyEvent.VK_COMMA:
alarmTime.roll(Calendar.HOUR_OF_DAY, -1);
break;
case KeyEvent.VK_K:
alarmTime.roll(Calendar.MINUTE, -1);
break;
case KeyEvent.VK_L:
alarmTime.roll(Calendar.MINUTE, 1);
break;
case KeyEvent.VK_SEMICOLON:
alarmTime.roll(Calendar.MINUTE, 10);
break;
case KeyEvent.VK_J:
alarmTime.roll(Calendar.MINUTE, -10);
break;
case KeyEvent.VK_SLASH:
alarmTime.set(Calendar.HOUR_OF_DAY, 12);
break;
case KeyEvent.VK_M:
alarmTime.set(Calendar.HOUR_OF_DAY, 0);
break;
case KeyEvent.VK_SPACE:
toggleAlarmEnabled();
break;
};
updateAlarmDisplay();
}
// basically the "ticking" method.
public void actionPerformed(ActionEvent e) {
setTime();
handleTimeChange();
previousTime = currentTime;
}
private void alarmOff() {
if (audioPlaying)
audio.stop();
audioPlaying = false;
setAlarmMessage();
}
private void alarmOn() {
if (!audioPlaying)
audio.play();
audioPlaying = true;
message.setText("Press any key to stop audio.");
}
private void toggleAlarmEnabled() {
if (alarmEnabled)
alarmEnabled = false;
else
alarmEnabled = true;
setAlarmMessage();
}
private void setAlarmMessage() {
if (alarmEnabled)
message.setText("Alarm enabled. Press space bar to disable.");
else
message.setText("Alarm disabled. Press space bar to enable.");
}
private void updateAlarmDisplay() {
alarmDisplay.setText(String.format("%tR", alarmTime));
}
private Calendar captureTime() {
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(System.currentTimeMillis());
return cal;
}
private void setTime() {
currentTime = captureTime();
timeDisplay.setText(String.format("%tR", currentTime));
dateDisplay.setText(String.format("%tD", currentTime));
}
private boolean timesMatch(Calendar timeA, Calendar timeB) {
return (timeA.get(Calendar.HOUR_OF_DAY) == timeB.get(Calendar.HOUR_OF_DAY)) && (timeA.get(Calendar.MINUTE) == timeB.get(Calendar.MINUTE));
}
private boolean timeChanging() {
return !timesMatch(previousTime, currentTime);
}
private boolean alarmMatching() {
return timesMatch(currentTime, alarmTime);
}
private void handleAlarmMatch() {
if (alarmEnabled && alarmMatching())
alarmOn();
}
private void handleTimeChange() {
if (timeChanging())
handleAlarmMatch();
}
private void initAlarm() {
alarmTime.set(Calendar.HOUR_OF_DAY, 0);
alarmTime.set(Calendar.MINUTE, 0);
updateAlarmDisplay();
setAlarmMessage();
}
private void initTimer() {
timer = new Timer(1000, this);
timer.setInitialDelay(0);
timer.start();
}
/**
* @param args the command line arguments
*/
public static void main(String args[]) {
/* Set the Nimbus look and feel */
//
/* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
* For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
*/
try {
for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException ex) {
java.util.logging.Logger.getLogger(Alarm.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (InstantiationException ex) {
java.util.logging.Logger.getLogger(Alarm.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
java.util.logging.Logger.getLogger(Alarm.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (javax.swing.UnsupportedLookAndFeelException ex) {
java.util.logging.Logger.getLogger(Alarm.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
//
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new Alarm().setVisible(true);
}
});
}
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JLabel alarmDisplay;
private javax.swing.JLabel dateDisplay;
private javax.swing.JLabel message;
private javax.swing.JLabel timeDisplay;
// End of variables declaration//GEN-END:variables
// Manually declared variables - can modify!
private Timer timer;
}
class Audio {
private Clip clip;
public Audio() {
init();
}
private void init() {
try {
URL url = getClass().getResource("/resources/wakeupkorn.wav");
AudioInputStream stream = AudioSystem.getAudioInputStream(url);
AudioFormat format = stream.getFormat();
DataLine.Info info = new DataLine.Info(Clip.class, format);
Clip line = (Clip) AudioSystem.getLine(info);
line.open(stream);
line.setLoopPoints(0, -1);
clip = line;
}
catch (Throwable e) {
throw new Error(e.getMessage());
}
}
public void play() {
clip.loop(Clip.LOOP_CONTINUOUSLY);
}
public void stop() {
clip.stop();
clip.setFramePosition(0);
}
}